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