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