File:  [NetBSD Developer Wiki] / wikisrc / users / mlelstv / disk-driver-template.mdwn
Revision 1.13: download - view: text, annotated - select for diffs
Sun May 2 13:33:00 2021 UTC (4 months, 3 weeks ago) by mlelstv
Branches: MAIN
CVS tags: HEAD
Missing #endif

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

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