Annotation of wikisrc/users/mlelstv/disk-driver-template.mdwn, revision 1.1
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>
! 10: const struct bdevsw xxx_bdevsww= {
! 11: .d_open = xxxopen,
! 12: .d_close = xxxclose,
! 13: .d_strategy = xxxstrategy,
! 14: .d_ioctl = xxxioctl,
! 15: .d_dump = xxxdump,
! 16: .d_psize = xxxsize,
! 17: .d_discard = xxxdiscard,
! 18: .d_flag = D_DISK
! 19: };
! 20:
! 21: const struct cdevsw xxx_cdevsw = {
! 22: .d_open = xxxopen,
! 23: .d_close = xxxclose,
! 24: .d_read = xxxread,
! 25: .d_write = xxxwrite,
! 26: .d_ioctl = xxxioctl,
! 27: .d_stop = nostop,
! 28: .d_tty = notty,
! 29: .d_poll = nopoll,
! 30: .d_mmap = nommap,
! 31: .d_kqfilter = nokqfilter,
! 32: .d_discard = xxxdiscard,
! 33: .d_flag = D_DISK
! 34: };
! 35:
! 36: static const struct dkdriver xxxdkdriver = {
! 37: .d_open = xxxopen,
! 38: .d_close = xxxclose,
! 39: .d_strategy = xxxstrategy,
! 40: .d_iosize = xxx_iosize,
! 41: .d_minphys = xxxminphys,
! 42: .d_diskstart = xxx_diskstart,
! 43: .d_dumpblocks = xxx_dumpblocks,
! 44: .d_lastclose = xxx_lastclose,
! 45: .d_discard = xxx_discard
! 46: };
! 47:
! 48: extern struct cfdriver xxx_cd;
! 49:
! 50: static dev_type_open(xxxopen);
! 51: static dev_type_close(xxxclose);
! 52: static dev_type_read(xxxread);
! 53: static dev_type_write(xxxwrite);
! 54: static dev_type_ioctl(xxxioctl);
! 55: static dev_type_strategy(xxxstrategy);
! 56: static dev_type_dump(xxxdump);
! 57: static dev_type_size(xxxsize);
! 58: static dev_type_discard(xxxdiscard);
! 59:
! 60: static void xxxminphys(struct buf *bp);
! 61: static int xxxdiskstart(device_t, struct buf *bp);
! 62: static void xxx_iosize(device_t, int *);
! 63: static int xxx_dumpblocks(device_t, void *, daddr_t, int);
! 64: static int xxx_lastclose(device_t);
! 65: static int xxx_discard(device_t, off_t, off_t);
! 66:
! 67:
! 68: #define DEVPROLOG \
! 69: struct xxx_softc *sc; \
! 70: struct dk_softc *dksc; \
! 71: int unit; \
! 72: \
! 73: unit = DISKUNIT(dev); \
! 74: if ((sc = device_lookup_private(&xxx_cd, unit)) == NULL) \
! 75: return ENXIO; \
! 76: dksc = &sc->sc_dksc
! 77: </code></pre>
! 78:
! 79: ----
! 80:
! 81: ## Attachment and Standard driver interface
! 82:
! 83: <pre><code>
! 84: void
! 85: xxxattach(struct xxx_softc *sc)
! 86: {
! 87: device_t self = sc->sc_dv;
! 88: struct dk_softc *dksc = &sc->sc_dk;
! 89:
! 90: dk_init(dksc, self, DKTYPE_xxx);
! 91: disk_init(&dksc->sc_dkdev, dksc->sc_xname, &xxdkdriver);
! 92:
! 93: dk_attach(dksc);
! 94: disk_attach(&dksc->sc_dkdev);
! 95: // initialize dksc->sc_dkdev.dk_geom
! 96:
! 97: bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
! 98:
! 99: // possibly deferred with config_interrupts()
! 100: dkwedge_discover(&dksc->sc_dkdev);
! 101: }
! 102:
! 103: static int
! 104: xxxopen(dev_t dev, int flags, int fmt, struct lwp *l)
! 105: {
! 106: DEVPROLOG;
! 107:
! 108: return dk_open(dksc, dev, flags, fmt, l);
! 109: }
! 110:
! 111: static int
! 112: xxxclose(dev_t dev, int flags, int fmt, struct lwp *l)
! 113: {
! 114: DEVPROLOG;
! 115:
! 116: return dk_close(dksc, dev, flags, fmt, l);
! 117: }
! 118:
! 119: static int
! 120: xxxread(dev_t dev, struct uio *uio, int ioflag)
! 121: {
! 122:
! 123: return physio(xxxstrategy, NULL, dev, B_READ, xxxminphys, uio);
! 124: }
! 125:
! 126: static int
! 127: xxxwrite(dev_t dev, struct uio *uio, int ioflag)
! 128: {
! 129:
! 130: return physio(xxxstrategy, NULL, dev, B_WRITE, xxxminphys, uio);
! 131: }
! 132:
! 133: static int
! 134: xxxioctl(dev_t dev, u_long cmd, void *addr, int32_t flag, struct lwp *l)
! 135: {
! 136: int error;
! 137: DEVPROLOG;
! 138:
! 139: error = dk_ioctl(dksc, dev, cmd, addr, flag, l);
! 140: if (error != EPASSTHROUGH)
! 141: return error;
! 142:
! 143: error = 0;
! 144:
! 145: switch (cmd) {
! 146: // private IOCTLs
! 147: default:
! 148: error = ENOTTY;
! 149: }
! 150:
! 151: return error;
! 152: }
! 153:
! 154: static void
! 155: xxxstrategy(struct buf *bp)
! 156: {
! 157: DEVPROLOG;
! 158:
! 159: dk_strategy(dksc, bp);
! 160: }
! 161:
! 162: static int
! 163: xxxdiscard(dev_t dev, off_t pos, off_t len)
! 164: {
! 165: DEVPROLOG;
! 166:
! 167: return dk_discard(dksc, dev, pos, len);
! 168: }
! 169:
! 170: static int
! 171: xxxsize(dev_t dev)
! 172: {
! 173: DEVPROLOG;
! 174:
! 175: return dk_size(dksc, dev);
! 176: }
! 177:
! 178: static int
! 179: xxxdump(dev_t dev, daddr_t blkno, void *va, size_t size)
! 180: {
! 181: DEVPROLOG;
! 182:
! 183: return dk_dump(dksc, dev, blkno, va, size);
! 184: }
! 185:
! 186: static void
! 187: xxxminphys(struct buf *bp)
! 188: {
! 189: struct xxx_softc *sc;
! 190: int unit;
! 191:
! 192: unit = DISKUNIT(bp->b_dev);
! 193: if ((sc = device_lookup_private(&xxx_cd, unit)) == NULL)
! 194: return;
! 195:
! 196: xxx_iosize(sc->sc_dv, &bp->b_count);
! 197: minphys(bp);
! 198: }
! 199: </code></pre>
! 200:
! 201: ----
! 202:
! 203: ## I/O callback
! 204:
! 205: <pre><code>
! 206: static void
! 207: xxxdone(struct xxx_softc *sc, struct buf *bp)
! 208: {
! 209: struct dk_softc *dksc = &sc->sc_dksc;
! 210:
! 211: dk_done(dksc, bp);
! 212: dk_start(dksc, NULL);
! 213: }
! 214:
! 215: ----
! 216:
! 217: ## DK driver interface
! 218:
! 219: static int
! 220: xxx_lastclose(device_t dv)
! 221: {
! 222: // private cleanup
! 223:
! 224: return 0;
! 225: }
! 226:
! 227: static int
! 228: xxx_diskstart(device_t dv, struct buf *bp)
! 229: {
! 230: // issue I/O for bp
! 231: // return EAGAIN if controller busy
! 232: }
! 233:
! 234: static int
! 235: xxx_dumpblocks(device_t dv, void *va, daddr_t blkno, int nblk)
! 236: {
! 237: // issue polling I/O to dump a page
! 238: }
! 239:
! 240: static void
! 241: xxx_iosize(device_t dv, int *countp)
! 242: {
! 243: // limit *countp as necessary
! 244: }
! 245:
! 246: static int
! 247: xxx_discard(device_t dv, off_t pos, off_t len)
! 248: {
! 249: // issue request to discard bytes
! 250: }
! 251:
! 252: ----
! 253:
! 254: ## Alternative when using a separate I/O thread
! 255:
! 256: static void
! 257: xxxstrategy(struct buf *bp)
! 258: {
! 259: DEVPROLOG;
! 260:
! 261: if (dk_strategy_defer(dksc, bp))
! 262: return;
! 263:
! 264: // wake up I/O thread
! 265: }
! 266:
! 267: static int
! 268: xxx_diskstart(device_t dv, struct buf *bp)
! 269: {
! 270: // issue I/O for bp
! 271: }
! 272:
! 273: static void
! 274: xxxdone(struct xxx_softc *sc, struct buf *bp)
! 275: {
! 276: struct dk_softc *dksc = &sc->sc_dksc;
! 277:
! 278: dk_done(dksc, bp);
! 279: // wake up I/O thread
! 280: }
! 281:
! 282: static void
! 283: xxx_IOTHREAD(struct dk_softc *dksc)
! 284: {
! 285: while (!shutting_down) {
! 286: if (dk_strategy_pending(dksc)
! 287: dk_start(dksc, NULL);
! 288: // sleep
! 289: }
! 290: }
! 291: </code></pre>
! 292:
! 293: ----
CVSweb for NetBSD wikisrc <wikimaster@NetBSD.org> software: FreeBSD-CVSweb