Diff for /wikisrc/users/mlelstv/disk-driver-template.mdwn between versions 1.2 and 1.12

version 1.2, 2015/12/21 10:07:51 version 1.12, 2016/12/08 11:39:34
Line 7 Line 7
 ## Declaration  ## Declaration
   
 <pre><code>  <pre><code>
   static dev_type_open(xxxopen);
   static dev_type_close(xxxclose);
   static dev_type_read(xxxread);
   static dev_type_write(xxxwrite);
   static dev_type_ioctl(xxxioctl);
   static dev_type_strategy(xxxstrategy);
   static dev_type_dump(xxxdump);
   static dev_type_size(xxxsize);
   static dev_type_discard(xxxdiscard);
   
 const struct bdevsw xxx_bdevsww= {  const struct bdevsw xxx_bdevsww= {
         .d_open = xxxopen,          .d_open = xxxopen,
         .d_close = xxxclose,          .d_close = xxxclose,
Line 15  const struct bdevsw xxx_bdevsww= { Line 25  const struct bdevsw xxx_bdevsww= {
         .d_dump = xxxdump,          .d_dump = xxxdump,
         .d_psize = xxxsize,          .d_psize = xxxsize,
         .d_discard = xxxdiscard,          .d_discard = xxxdiscard,
         .d_flag = D_DISK          .d_flag = D_DISK | D_MPSAFE
 };  };
   
 const struct cdevsw xxx_cdevsw = {  const struct cdevsw xxx_cdevsw = {
Line 30  const struct cdevsw xxx_cdevsw = { Line 40  const struct cdevsw xxx_cdevsw = {
         .d_mmap = nommap,          .d_mmap = nommap,
         .d_kqfilter = nokqfilter,          .d_kqfilter = nokqfilter,
         .d_discard = xxxdiscard,          .d_discard = xxxdiscard,
         .d_flag = D_DISK          .d_flag = D_DISK | D_MPSAFE
 };  };
   
   static void     xxxminphys(struct buf *bp);
   static int      xxxdiskstart(device_t, struct buf *bp);
   static void     xxx_iosize(device_t, int *);
   static int      xxx_dumpblocks(device_t, void *, daddr_t, int);
   static int      xxx_lastclose(device_t);
   static int      xxx_discard(device_t, off_t, off_t);
   
 static const struct dkdriver xxxdkdriver = {  static const struct dkdriver xxxdkdriver = {
         .d_open = xxxopen,          .d_open = xxxopen,
         .d_close = xxxclose,          .d_close = xxxclose,
         .d_strategy = xxxstrategy,          .d_strategy = xxxstrategy,
         .d_iosize = xxx_iosize,  
         .d_minphys  = xxxminphys,          .d_minphys  = xxxminphys,
         .d_diskstart = xxx_diskstart,          .d_diskstart = xxx_diskstart,
         .d_dumpblocks = xxx_dumpblocks,          .d_discard = xxx_discard,
         .d_lastclose = xxx_lastclose,          .d_dumpblocks = xxx_dumpblocks, /* optional */
         .d_discard = xxx_discard          .d_iosize = xxx_iosize,         /* optional */
           .d_lastclose = xxx_lastclose,   /* optional */
           .d_firstopen = xxx_firstopen,   /* optional */
           .d_label = xxx_label,           /* optional */
   };
   
   static int      xxx_match(device_t, cfdata_t, void *);
   static void     xxx_attach(device_t, device_t, void *);
   static int      xxx_detach(device_t, int);
   static int      xxx_activate(device_t, enum devact);
   
   struct xxx_softc {
           struct dk_softc         sc_dksc; /* generic disk interface */
           // private data
 };  };
   
   CFATTACH_DECL3_NEW(xxx, sizeof(struct xxx_softc),
       xxx_match, xxx_attach, xxx_detach, NULL, NULL, NULL, DVF_DETACH_SHUTDOWN);
       extern struct cfdriver xxx_cd;  
 extern struct   cfdriver xxx_cd;  extern struct   cfdriver xxx_cd;
   
 static dev_type_open(xxxopen);  #ifdef PSEUDODEVICE
 static dev_type_close(xxxclose);  static void     xxxattach(int);
 static dev_type_read(xxxread);  static device_t xxx_create(int);
 static dev_type_write(xxxwrite);  static int      xxx_destroy(device_t);
 static dev_type_ioctl(xxxioctl);  #endif
 static dev_type_strategy(xxxstrategy);  
 static dev_type_dump(xxxdump);  
 static dev_type_size(xxxsize);  
 static dev_type_discard(xxxdiscard);  
   
 static void     xxxminphys(struct buf *bp);  static int      xxx_init(device_t);
 static int      xxxdiskstart(device_t, struct buf *bp);  static int      xxx_finish(device_t);
 static void     xxx_iosize(device_t, int *);  
 static int      xxx_dumpblocks(device_t, void *, daddr_t, int);  static int      xxxdone(struct buf *);
 static int      xxx_lastclose(device_t);  
 static int      xxx_discard(device_t, off_t, off_t);  
   
   
 #define DEVPROLOG \  #define DEVPROLOG \
Line 78  static int      xxx_discard(device_t, of Line 104  static int      xxx_discard(device_t, of
   
 ----  ----
   
 ## Attachment and Standard driver interface  ## Pseudo-Device Attachment and Standard driver interface
   
 <pre><code>  <pre><code>
   #ifdef PSEUDODEVICE
 void  void
 xxxattach(struct xxx_softc *sc)  xxxattach(int num)
 {  {
         device_t self = sc->sc_dv;  #ifndef _MODULE
         struct dk_softc *dksc = &sc->sc_dk;          int error;
   
         dk_init(dksc, self, DKTYPE_xxx);          error = config_cfattach_attach(xxx_cd.cd_name, &xxx_ca);
         disk_init(&dksc->sc_dkdev, dksc->sc_xname, &xxdkdriver);          if (error) {
                   aprint_error("%s: unable to register cfattach %d\n",
                       xxx_cd.cd_name, error);
                   return;
           }
   
         dk_attach(dksc);          // some global initialization
         disk_attach(&dksc->sc_dkdev);  #endif
         // initialize dksc->sc_dkdev.dk_geom  }
   
         bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);  static device_t
   xxx_create(int unit)
   {
           cfdata_t cf;
           device_t dv;
   
           cf = malloc(sizeof(*cf), M_DEVBUF, M_WAITOK);
           cf->cf_name = xxx_cd.cd_name;
           cf->cf_atname = xxx_cd.cd_name;
           cf->cf_unit = unit;
           cf->cf_fstate = FSTATE_STAR;
   
           dv = config_attach_pseudo(cf);
           if (dv == NULL) {
                   aprint_error("%s: failed to attach pseudo device\n",
                       xxx_cd.cd_name);
                   free(cf, M_DEVBUF);
           }
   
         // possibly deferred with config_interrupts()          return dv;
         dkwedge_discover(&dksc->sc_dkdev);  }
   
   static int
   xxx_destroy(device_t dv)
   {
           int error;
           cfdata_t cf;
   
           cf = device_cfdata(dv);
           error = config_detach(dev, DETACH_QUIET);
           if (error)
                   return error;
           free(cf, M_DEVBUF);
           return 0;
 }  }
   #endif
   
 static int  static int
 xxxopen(dev_t dev, int flags, int fmt, struct lwp *l)  xxxopen(dev_t dev, int flags, int fmt, struct lwp *l)
Line 215  xxxdone(struct xxx_softc *sc, struct buf Line 277  xxxdone(struct xxx_softc *sc, struct buf
   
 ----  ----
   
 ##  DK driver interface  ## Startup and Shutdown
   
 <pre><code>  <pre><code>
 static int  static int
   xxx_init(device_t self)
   {
           struct xxx_softc *sc = device_private(self);
           struct dk_softc *dksc = &sc->sc_dk;
   
           dk_init(dksc, self, DKTYPE_xxx);
           disk_init(&dksc->sc_dkdev, dksc->sc_xname, &xxdkdriver);
   
           dk_attach(dksc);
           disk_attach(&dksc->sc_dkdev);
           // initialize dksc->sc_dkdev.dk_geom
   
           bufq_alloc(&dksc->sc_bufq, BUFQ_DISK_DEFAULT_STRAT, BUFQ_SORT_RAWBLOCK);
   
           // possibly deferred with config_interrupts()
           dkwedge_discover(&dksc->sc_dkdev);
   
           return 0;
   }
   
   static int
   xxx_finish(device_t self)
   {
           struct xxx_softc *sc = device_private(self);
           struct dk_softc *dksc = &sc->sc_dksc;
   
           dkwedge_delall(&dksc->sc_dkdev);
   
           dk_drain(dksc);
           bufq_free(dksc->sc_bufq);
   
           dk_detach(dksc);
           disk_detach(&dksc->sc_dkdev);
           disk_destroy(&dksc->sc_dkdev);
   
           return 0;
   }
   </code></pre>
   
   ----
   
   ## Autoconf interface
   
   <pre><code>
   static int
   xxx_match(device_t self, cfdata_t cfdata, void *aux)
   {
           return 1;
   }
   
   static void
   xxx_attach(device_t parent, device_t self, void *aux)
   {
   #ifndef _MODULE
           xxx_init(self);
   #endif
   }
   
   static void
   xxx_detach(device_t self, int flags)
   {
   #ifndef _MODULE
           xxx_finish(self);
   #endif
   }
   
   static int
   xxx_activate(device_t self, enum devact act)
   {
           // switch (act) {
           // case DVACT_ACTIVATE:
           //      return 0;
           // case DVACT_DEACTIVATE:
           //      return 0;
           // }
   
           return EOPNOTSUPP;
   }
   </code></pre>
   
   ----
   
   ## Kernel module interface
   
   <pre><code>
   MODULE(MODULE_CLASS_DRIVER, xxx, "dk_subr");
   
   static int
   xxx_modcmd(modcmd_t cmd, void *data)
   {
           int error;
   #ifdef _MODULE
           int bmajor, cmajor;
   #endif
   
           error = 0;
           switch (cmd) {
           case MODULE_CMD_INIT:
   #ifdef _MODULE
                   bmajor = cmajor = -1;
                   error = devsw_attach("xxx", &xxx_bdevsw, &bmajor,
                       &xxx_cdevsw, &cmajor);
                   if (error) {
                           aprint_error("%s: devsw_attach failed %d\n",
                               xxx_cd.cd_name, error);
                           break;
                   }
                   error = config_cfdriver_attach(&xxx_cd);
                   if (error) {
                           aprint_error("%s: config_cfdriver_attach failed %d\n",
                               xxx_cd.cd_name, error);
                           devsw_detach(&xxx_bdevsw, &xxx_cdevsw);
                           break;
                   }
                   error = config_cfattach_attach(&xxx_cd);
                   if (error) {
                           aprint_error("%s: config_cfattach_attach failed %d\n",
                               xxx_cd.cd_name, error);
                           config_cfdriver_detach(&xxx_cd);
                           devsw_detach(&xxx_bdevsw, &xxx_cdevsw);
                           break;
                   }
                   // some global initialization
   
   #ifdef PSEUDODEVICE
                   xxxattach(0);
   #endif
                   break;
           case MODULE_CMD_FINI:
                   // outside of #ifdef _MODULE to allow removal of builtins
                   // some global finalization
   #ifdef _MODULE
                   error = config_cfattach_detach(&xxx_cd.cd_name, &xxx_ca);
                   if (error)
                           break;
                   config_cfdriver_detach(&xxx_cd);
                   devsw_detach(&xxx_bdevsw, &xxx_cdevsw);
   #endif
                   break;
           case MODULE_CMD_STAT:
                   error = ENOTTY;
                   break;
           default:
                   error = ENOTTY;
                   break;
           }
   
           return error;
   }
   </code></pre>
   
   ----
   
   ## DK driver interface
   
   <pre><code>
   static int
   xxx_firstopen(device_t dv)
   {
           // private startup
   
           return 0;
   }
   
   static int
 xxx_lastclose(device_t dv)  xxx_lastclose(device_t dv)
 {  {
         // private cleanup          // private cleanup
Line 237  static int Line 464  static int
 xxx_dumpblocks(device_t dv, void *va, daddr_t blkno, int nblk)  xxx_dumpblocks(device_t dv, void *va, daddr_t blkno, int nblk)
 {  {
         // issue polling I/O to dump a page          // issue polling I/O to dump a page
           // return error
 }  }
   
 static void  static void
Line 249  static int Line 477  static int
 xxx_discard(device_t dv, off_t pos, off_t len)  xxx_discard(device_t dv, off_t pos, off_t len)
 {  {
         // issue request to discard bytes          // issue request to discard bytes
           // return error
   }
   
   static void
   xxx_label(device_t dv, struct disklabel *lp)
   {
           // lp is initialized for generic disk
           // augment with driver specific information
 }  }
   
 </code></pre>  </code></pre>
   
 ----  ----
Line 268  xxxstrategy(struct buf *bp) Line 505  xxxstrategy(struct buf *bp)
         // wake up I/O thread          // wake up I/O thread
 }  }
   
 static int  
 xxx_diskstart(device_t dv, struct buf *bp)  
 {  
         // issue I/O for bp  
 }  
   
 static void  static void
 xxxdone(struct xxx_softc *sc, struct buf *bp)  xxxdone(struct xxx_softc *sc, struct buf *bp)
 {  {
Line 284  xxxdone(struct xxx_softc *sc, struct buf Line 515  xxxdone(struct xxx_softc *sc, struct buf
 }  }
   
 static void  static void
 xxx_IOTHREAD(struct dk_softc *dksc)  xxx_iothread(struct dk_softc *dksc)
 {  {
         while (!shutting_down) {          while (!shutting_down) {
                 if (dk_strategy_pending(dksc)                  if (dk_strategy_pending(dksc))
                         dk_start(dksc, NULL);                          dk_start(dksc, NULL);
                 // sleep                  // sleep
         }          }

Removed from v.1.2  
changed lines
  Added in v.1.12


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