File:  [NetBSD Developer Wiki] / wikisrc / users / mlelstv / disk-driver-template.mdwn
Revision 1.9: download - view: text, annotated - select for diffs
Mon Nov 28 06:12:12 2016 UTC (4 years, 5 months ago) by mlelstv
Branches: MAIN
CVS tags: HEAD
also to the ops vector

    1: **Contents**
    2: 
    3: [[!toc levels=2]]
    4: 
    5: # Disk driver template when using dksubr library
    6: 
    7: ## Declaration
    8: 
    9: <pre><code>
   10: static dev_type_open(xxxopen);
   11: static dev_type_close(xxxclose);
   12: static dev_type_read(xxxread);
   13: static dev_type_write(xxxwrite);
   14: static dev_type_ioctl(xxxioctl);
   15: static dev_type_strategy(xxxstrategy);
   16: static dev_type_dump(xxxdump);
   17: static dev_type_size(xxxsize);
   18: static dev_type_discard(xxxdiscard);
   19: 
   20: const struct bdevsw xxx_bdevsww= {
   21: 	.d_open = xxxopen,
   22: 	.d_close = xxxclose,
   23: 	.d_strategy = xxxstrategy,
   24: 	.d_ioctl = xxxioctl,
   25: 	.d_dump = xxxdump,
   26: 	.d_psize = xxxsize,
   27: 	.d_discard = xxxdiscard,
   28: 	.d_flag = D_DISK
   29: };
   30: 
   31: const struct cdevsw xxx_cdevsw = {
   32: 	.d_open = xxxopen,
   33: 	.d_close = xxxclose,
   34: 	.d_read = xxxread,
   35: 	.d_write = xxxwrite,
   36: 	.d_ioctl = xxxioctl,
   37: 	.d_stop = nostop,
   38: 	.d_tty = notty,
   39: 	.d_poll = nopoll,
   40: 	.d_mmap = nommap,
   41: 	.d_kqfilter = nokqfilter,
   42: 	.d_discard = xxxdiscard,
   43: 	.d_flag = D_DISK
   44: };
   45: 
   46: static void     xxxminphys(struct buf *bp);
   47: static int      xxxdiskstart(device_t, struct buf *bp);
   48: static void     xxx_iosize(device_t, int *);
   49: static int      xxx_dumpblocks(device_t, void *, daddr_t, int);
   50: static int      xxx_lastclose(device_t);
   51: static int      xxx_discard(device_t, off_t, off_t);
   52: 
   53: static const struct dkdriver xxxdkdriver = {
   54: 	.d_open = xxxopen,
   55: 	.d_close = xxxclose,
   56: 	.d_strategy = xxxstrategy,
   57: 	.d_iosize = xxx_iosize,
   58: 	.d_minphys  = xxxminphys,
   59: 	.d_diskstart = xxx_diskstart,
   60: 	.d_dumpblocks = xxx_dumpblocks,
   61: 	.d_lastclose = xxx_lastclose,
   62: 	.d_discard = xxx_discard,
   63: 	.d_firstopen = xxx_firstopen
   64: };
   65: 
   66: static int      xxx_match(device_t, cfdata_t, void *);
   67: static void     xxx_attach(device_t, device_t, void *);
   68: static int      xxx_detach(device_t, int);
   69: 
   70: struct xxx_softc {
   71: 	struct dk_softc         sc_dksc; /* generic disk interface */
   72: 	// private data
   73: };
   74: 
   75: CFATTACH_DECL3_NEW(xxx, sizeof(struct xxx_softc),
   76:     xxx_match, xxx_attach, xxx_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
   77:     extern struct cfdriver xxx_cd;  
   78: extern struct   cfdriver xxx_cd;
   79: 
   80: #ifdef PSEUDODEVICE
   81: static void     xxxattach(int);
   82: static device_t xxx_create(int);
   83: static int      xxx_destroy(device_t);
   84: #endif
   85: 
   86: static int      xxx_init(device_t);
   87: static int      xxx_finish(device_t);
   88: 
   89: static int      xxxdone(struct buf *);
   90: 
   91: 
   92: #define DEVPROLOG \
   93: 	struct xxx_softc *sc; \
   94: 	struct dk_softc *dksc; \
   95: 	int unit; \
   96: \
   97: 	unit = DISKUNIT(dev); \
   98: 	if ((sc = device_lookup_private(&xxx_cd, unit)) == NULL) \
   99: 		return ENXIO; \
  100: 	dksc = &sc->sc_dksc
  101: </code></pre>
  102: 
  103: ----
  104: 
  105: ## Pseudo-Device Attachment and Standard driver interface
  106: 
  107: <pre><code>
  108: #ifdef PSEUDODEVICE
  109: void
  110: xxxattach(int num)
  111: {
  112: #ifndef _MODULE
  113: 	int error;
  114: 
  115: 	error = config_cfattach_attach(xxx_cd.cd_name, &xxx_ca);
  116: 	if (error) {
  117: 		aprint_error("%s: unable to register cfattach %d\n",
  118: 		    xxx_cd.cd_name, error);
  119: 		return;
  120: 	}
  121: 
  122: 	// some global initialization
  123: #endif
  124: }
  125: 
  126: static device_t
  127: xxx_create(int unit)
  128: {
  129: 	cfdata_t cf;
  130: 	device_t dv;
  131: 
  132: 	cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
  133: 	cf->cf_name = xxx_cd.cd_name;
  134: 	cf->cf_atname = xxx_cd.cd_name;
  135: 	cf->cf_unit = unit;
  136: 	cf->cf_fstate = FSTATE_STAR;
  137: 
  138: 	dv = config_attach_pseudo(cf);
  139: 	if (dv == NULL) {
  140: 		aprint_error("%s: failed to attach pseudo device\n",
  141: 		    xxx_cd.cd_name);
  142: 		free(cf, M_DEVBUF);
  143: 	}
  144: 
  145: 	return dv;
  146: }
  147: 
  148: static int
  149: xxx_destroy(device_t dv)
  150: {
  151: 	int error;
  152: 	cfdata_t cf;
  153: 
  154: 	cf = device_cfdata(dv);
  155: 	error = config_detach(dev, DETACH_QUIET);
  156: 	if (error)
  157: 		return error;
  158: 	free(cf, M_DEVBUF);
  159: 	return 0;
  160: }
  161: #endif
  162: 
  163: static int
  164: xxxopen(dev_t dev, int flags, int fmt, struct lwp *l)
  165: {
  166: 	DEVPROLOG;
  167: 
  168: 	return dk_open(dksc, dev, flags, fmt, l);
  169: }
  170: 
  171: static int
  172: xxxclose(dev_t dev, int flags, int fmt, struct lwp *l)
  173: {
  174: 	DEVPROLOG;
  175: 
  176: 	return dk_close(dksc, dev, flags, fmt, l);
  177: }
  178: 
  179: static int
  180: xxxread(dev_t dev, struct uio *uio, int ioflag)
  181: {
  182: 
  183: 	return physio(xxxstrategy, NULL, dev, B_READ, xxxminphys, uio);
  184: }
  185: 
  186: static int
  187: xxxwrite(dev_t dev, struct uio *uio, int ioflag)
  188: {
  189: 
  190: 	return physio(xxxstrategy, NULL, dev, B_WRITE, xxxminphys, uio);
  191: }
  192: 
  193: static int
  194: xxxioctl(dev_t dev, u_long cmd, void *addr, int32_t flag, struct lwp *l)
  195: {
  196: 	int error;
  197: 	DEVPROLOG;
  198: 
  199: 	error = dk_ioctl(dksc, dev, cmd, addr, flag, l);
  200: 	if (error != EPASSTHROUGH)
  201: 		return error;
  202: 
  203: 	error = 0;
  204: 
  205: 	switch (cmd) {
  206: 	// private IOCTLs
  207: 	default:
  208: 		error = ENOTTY;
  209: 	}
  210: 
  211: 	return error;
  212: }
  213: 
  214: static void
  215: xxxstrategy(struct buf *bp)
  216: {
  217: 	DEVPROLOG;
  218: 
  219: 	dk_strategy(dksc, bp);
  220: }
  221: 
  222: static int
  223: xxxdiscard(dev_t dev, off_t pos, off_t len)
  224: {
  225: 	DEVPROLOG;
  226: 
  227: 	return dk_discard(dksc, dev, pos, len);
  228: }
  229: 
  230: static int
  231: xxxsize(dev_t dev)
  232: {
  233: 	DEVPROLOG;
  234: 
  235: 	return dk_size(dksc, dev);
  236: }
  237: 
  238: static int
  239: xxxdump(dev_t dev, daddr_t blkno, void *va, size_t size)
  240: {
  241: 	DEVPROLOG;
  242: 
  243: 	return dk_dump(dksc, dev, blkno, va, size);
  244: }
  245: 
  246: static void
  247: xxxminphys(struct buf *bp)
  248: {
  249: 	struct xxx_softc *sc;
  250: 	int unit;
  251: 
  252: 	unit = DISKUNIT(bp->b_dev);
  253: 	if ((sc = device_lookup_private(&xxx_cd, unit)) == NULL)
  254: 		return;
  255: 
  256: 	xxx_iosize(sc->sc_dv, &bp->b_count);
  257: 	minphys(bp);
  258: }
  259: </code></pre>
  260: 
  261: ----
  262: 
  263: ## I/O callback
  264: 
  265: <pre><code>
  266: static void
  267: xxxdone(struct xxx_softc *sc, struct buf *bp)
  268: {
  269: 	struct dk_softc *dksc = &sc->sc_dksc;
  270: 
  271: 	dk_done(dksc, bp);
  272: 	dk_start(dksc, NULL);
  273: }
  274: </code></pre>
  275: 
  276: ----
  277: 
  278: ## Startup and Shutdown
  279: 
  280: <pre><code>
  281: static int
  282: xxx_init(device_t self)
  283: {
  284: 	struct xxx_softc *sc = device_private(self);
  285: 	struct dk_softc *dksc = &sc->sc_dk;
  286: 
  287: 	dk_init(dksc, self, DKTYPE_xxx);
  288: 	disk_init(&dksc->sc_dkdev, dksc->sc_xname, &xxdkdriver);
  289: 
  290: 	dk_attach(dksc);
  291: 	disk_attach(&dksc->sc_dkdev);
  292: 	// initialize dksc->sc_dkdev.dk_geom
  293: 
  294: 	bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
  295: 
  296: 	// possibly deferred with config_interrupts()
  297: 	dkwedge_discover(&dksc->sc_dkdev);
  298: 
  299: 	return 0;
  300: }
  301: 
  302: static int
  303: xxx_finish(device_t self)
  304: {
  305: 	struct xxx_softc *sc = device_private(self);
  306: 	struct dk_softc *dksc = &sc->sc_dksc;
  307: 
  308: 	dkwedge_delall(&dksc->sc_dkdev);
  309: 
  310: 	dk_drain(dksc);
  311: 	bufq_free(dksc->sc_bufq);
  312: 
  313: 	dk_detach(dksc);
  314: 	disk_detach(&dksc->sc_dkdev);
  315: 	disk_destroy(&dksc->sc_dkdev);
  316: 
  317: 	return 0;
  318: }
  319: </code></pre>
  320: 
  321: ----
  322: 
  323: ## Autoconf interface
  324: 
  325: <pre><code>
  326: static int
  327: xxx_match(device_t self, cfdata_t cfdata, void *aux)
  328: {
  329: 	return 1;
  330: }
  331: 
  332: static void
  333: xxx_attach(device_t parent, device_t self, void *aux)
  334: {
  335: #ifndef _MODULE
  336: 	xxx_init(self);
  337: #endif
  338: }
  339: 
  340: static void
  341: xxx_detach(device_t self, int flags)
  342: {
  343: #ifndef _MODULE
  344: 	xxx_finish(self);
  345: #endif
  346: }
  347: </code></pre>
  348: 
  349: ----
  350: 
  351: ## Kernel module interface
  352: 
  353: <pre><code>
  354: MODULE(MODULE_CLASS_DRIVER, xxx, "dk_subr");
  355: 
  356: static int
  357: xxx_modcmd(modcmd_t cmd, void *data)
  358: {
  359: 	int error;
  360: #ifdef _MODULE
  361: 	int bmajor, cmajor;
  362: #endif
  363: 
  364: 	error = 0;
  365: 	switch (cmd) {
  366: 	case MODULE_CMD_INIT:
  367: #ifdef _MODULE
  368: 		bmajor = cmajor = -1;
  369: 		error = devsw_attach("xxx", &xxx_bdevsw, &bmajor,
  370: 		    &xxx_cdevsw, &cmajor);
  371: 		if (error) {
  372: 			aprint_error("%s: devsw_attach failed %d\n",
  373: 			    xxx_cd.cd_name, error);
  374: 			break;
  375: 		}
  376: 		error = config_cfdriver_attach(&xxx_cd);
  377: 		if (error) {
  378: 			aprint_error("%s: config_cfdriver_attach failed %d\n",
  379: 			    xxx_cd.cd_name, error);
  380: 			devsw_detach(&xxx_bdevsw, &xxx_cdevsw);
  381: 			break;
  382: 		}
  383: 		error = config_cfattach_attach(&xxx_cd);
  384: 		if (error) {
  385: 			aprint_error("%s: config_cfattach_attach failed %d\n",
  386: 			    xxx_cd.cd_name, error);
  387: 			config_cfdriver_detach(&xxx_cd);
  388: 			devsw_detach(&xxx_bdevsw, &xxx_cdevsw);
  389: 			break;
  390: 		}
  391: 		// some global initialization
  392: 
  393: #ifdef PSEUDODEVICE
  394: 		xxxattach(0);
  395: #endif
  396: 		break;
  397: 	case MODULE_CMD_FINI:
  398: 		// outside of #ifdef _MODULE to allow removal of builtins
  399: 		// some global finalization
  400: #ifdef _MODULE
  401: 		error = config_cfattach_detach(&xxx_cd.cd_name, &xxx_ca);
  402: 		if (error)
  403: 			break;
  404: 		config_cfdriver_detach(&xxx_cd);
  405: 		devsw_detach(&xxx_bdevsw, &xxx_cdevsw);
  406: #endif
  407: 		break;
  408: 	case MODULE_CMD_STAT:
  409: 		error = ENOTTY;
  410: 		break;
  411: 	default:
  412: 		error = ENOTTY;
  413: 		break;
  414: 	}
  415: 
  416: 	return error;
  417: }
  418: </code></pre>
  419: 
  420: ----
  421: 
  422: ## DK driver interface
  423: 
  424: <pre><code>
  425: static int
  426: xxx_firstopen(device_t dv)
  427: {
  428: 	// private startup
  429: 
  430: 	return 0;
  431: }
  432: 
  433: static int
  434: xxx_lastclose(device_t dv)
  435: {
  436: 	// private cleanup
  437: 
  438: 	return 0;
  439: }
  440: 
  441: static int
  442: xxx_diskstart(device_t dv, struct buf *bp)
  443: {
  444: 	// issue I/O for bp
  445: 	// return EAGAIN if controller busy
  446: }
  447: 
  448: static int
  449: xxx_dumpblocks(device_t dv, void *va, daddr_t blkno, int nblk)
  450: {
  451: 	// issue polling I/O to dump a page
  452: }
  453: 
  454: static void
  455: xxx_iosize(device_t dv, int *countp)
  456: {
  457: 	// limit *countp as necessary
  458: }
  459: 
  460: static int
  461: xxx_discard(device_t dv, off_t pos, off_t len)
  462: {
  463: 	// issue request to discard bytes
  464: }
  465: </code></pre>
  466: 
  467: ----
  468: 
  469: ## Alternative when using a separate I/O thread
  470: 
  471: <pre><code>
  472: static void
  473: xxxstrategy(struct buf *bp)
  474: {
  475: 	DEVPROLOG;
  476: 
  477: 	if (dk_strategy_defer(dksc, bp))
  478: 		return;
  479: 
  480: 	// wake up I/O thread
  481: }
  482: 
  483: static int
  484: xxx_diskstart(device_t dv, struct buf *bp)
  485: {
  486: 	// issue I/O for bp
  487: }
  488: 
  489: static void
  490: xxxdone(struct xxx_softc *sc, struct buf *bp)
  491: {
  492: 	struct dk_softc *dksc = &sc->sc_dksc;
  493: 
  494: 	dk_done(dksc, bp);
  495: 	// wake up I/O thread
  496: }
  497: 
  498: static void
  499: xxx_IOTHREAD(struct dk_softc *dksc)
  500: {
  501: 	while (!shutting_down) {
  502: 		if (dk_strategy_pending(dksc))
  503: 			dk_start(dksc, NULL);
  504: 		// sleep
  505: 	}
  506: }
  507: </code></pre>
  508: 
  509: ----

CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb