[BACK]Return to seagate.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / dev / isa

Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.

Diff for /src/sys/dev/isa/seagate.c between version 1.39 and 1.39.2.3

version 1.39, 2000/12/17 19:35:23 version 1.39.2.3, 2001/11/14 19:14:54
Line 64 
Line 64 
  * disk has. Use these to disklabel your disk in an appropriate manner   * disk has. Use these to disklabel your disk in an appropriate manner
  */   */
   
   #include <sys/cdefs.h>
   __KERNEL_RCSID(0, "$NetBSD$");
   
 #include <sys/types.h>  #include <sys/types.h>
 #include <sys/param.h>  #include <sys/param.h>
 #include <sys/systm.h>  #include <sys/systm.h>
Line 196  struct sea_softc {
Line 199  struct sea_softc {
         caddr_t maddr_cr_sr;            /* Address of control and status reg */          caddr_t maddr_cr_sr;            /* Address of control and status reg */
         caddr_t maddr_dr;               /* Address of data register */          caddr_t maddr_dr;               /* Address of data register */
   
         struct scsipi_link sc_link;     /* prototype for subdevs */  
         struct scsipi_adapter sc_adapter;          struct scsipi_adapter sc_adapter;
           struct scsipi_channel sc_channel;
   
         TAILQ_HEAD(, sea_scb) free_list, ready_list, nexus_list;          TAILQ_HEAD(, sea_scb) free_list, ready_list, nexus_list;
         struct sea_scb *nexus;          /* currently connected command */          struct sea_scb *nexus;          /* currently connected command */
         int numscbs;                    /* number of scsi control blocks */          int numscbs;                    /* number of scsi control blocks */
Line 273  static const char *bases[] = {
Line 277  static const char *bases[] = {
 #endif  #endif
   
 int seaintr __P((void *));  int seaintr __P((void *));
 int sea_scsi_cmd __P((struct scsipi_xfer *));  void sea_scsipi_request __P((struct scsipi_channel *,
           scsipi_adapter_req_t, void *));
 void sea_timeout __P((void *));  void sea_timeout __P((void *));
 void sea_done __P((struct sea_softc *, struct sea_scb *));  void sea_done __P((struct sea_softc *, struct sea_scb *));
 struct sea_scb *sea_get_scb __P((struct sea_softc *, int));  struct sea_scb *sea_get_scb __P((struct sea_softc *, int));
Line 289  int sea_transfer_pio __P((struct sea_sof
Line 294  int sea_transfer_pio __P((struct sea_sof
     int *count, u_char **data));      int *count, u_char **data));
 int sea_abort __P((struct sea_softc *, struct sea_scb *scb));  int sea_abort __P((struct sea_softc *, struct sea_scb *scb));
   
 /* the below structure is so we have a default dev struct for our link struct */  void    sea_grow_scb __P((struct sea_softc *));
 struct scsipi_device sea_dev = {  
         NULL,           /* use default error handler */  
         NULL,           /* have a queue, served by this */  
         NULL,           /* have no async handler */  
         NULL,           /* Use default 'done' routine */  
 };  
   
 int     seaprobe __P((struct device *, struct cfdata *, void *));  int     seaprobe __P((struct device *, struct cfdata *, void *));
 void    seaattach __P((struct device *, struct device *, void *));  void    seaattach __P((struct device *, struct device *, void *));
Line 356  seaprobe(parent, match, aux)
Line 355  seaprobe(parent, match, aux)
   
         /* check board type */  /* No way to define this through config */          /* check board type */  /* No way to define this through config */
         for (i = 0; i < nsignatures; i++)          for (i = 0; i < nsignatures; i++)
                 if (!bcmp(maddr + signatures[i].offset,                  if (!memcmp(maddr + signatures[i].offset,
                     signatures[i].signature, signatures[i].length)) {                      signatures[i].signature, signatures[i].length)) {
                         type = signatures[i].type;                          type = signatures[i].type;
                         break;                          break;
Line 392  seaattach(parent, self, aux)
Line 391  seaattach(parent, self, aux)
 {  {
         struct isa_attach_args *ia = aux;          struct isa_attach_args *ia = aux;
         struct sea_softc *sea = (void *)self;          struct sea_softc *sea = (void *)self;
           struct scsipi_adapter *adapt = &sea->sc_adapter;
           struct scsipi_channel *chan = &sea->sc_channel;
         int i;          int i;
   
         sea->maddr = ISA_HOLE_VADDR(ia->ia_maddr);          sea->maddr = ISA_HOLE_VADDR(ia->ia_maddr);
   
         /* check board type */  /* No way to define this through config */          /* check board type */  /* No way to define this through config */
         for (i = 0; i < nsignatures; i++)          for (i = 0; i < nsignatures; i++)
                 if (!bcmp(sea->maddr + signatures[i].offset,                  if (!memcmp(sea->maddr + signatures[i].offset,
                     signatures[i].signature, signatures[i].length)) {                      signatures[i].signature, signatures[i].length)) {
                         sea->type = signatures[i].type;                          sea->type = signatures[i].type;
                         break;                          break;
Line 440  seaattach(parent, self, aux)
Line 441  seaattach(parent, self, aux)
         sea_init(sea);          sea_init(sea);
   
         /*          /*
          * Fill in the adapter.           * Fill in the scsipi_adapter.
          */           */
         sea->sc_adapter.scsipi_cmd = sea_scsi_cmd;          memset(adapt, 0, sizeof(*adapt));
         sea->sc_adapter.scsipi_minphys = minphys;          adapt->adapt_dev = &sea->sc_dev;
           adapt->adapt_nchannels = 1;
           adapt->adapt_openings = sea->numscbs;
           adapt->adapt_max_periph = 1;
           adapt->adapt_request = sea_scsipi_request;
           adapt->adapt_minphys = minphys;
   
         /*          /*
          * fill in the prototype scsipi_link.           * Fill in the scsipi_channel.
          */           */
         sea->sc_link.scsipi_scsi.channel = SCSI_CHANNEL_ONLY_ONE;          memset(chan, 0, sizeof(*chan));
         sea->sc_link.adapter_softc = sea;          chan->chan_adapter = adapt;
         sea->sc_link.scsipi_scsi.adapter_target = sea->our_id;          chan->chan_bustype = &scsi_bustype;
         sea->sc_link.adapter = &sea->sc_adapter;          chan->chan_channel = 0;
         sea->sc_link.device = &sea_dev;          chan->chan_ntargets = 8;
         sea->sc_link.openings = 1;          chan->chan_nluns = 8;
         sea->sc_link.scsipi_scsi.max_target = 7;          chan->chan_id = sea->our_id;
         sea->sc_link.scsipi_scsi.max_lun = 7;          chan->chan_flags = SCSIPI_CHAN_CANGROW;
         sea->sc_link.type = BUS_SCSI;  
   
         printf("\n");          printf("\n");
   
Line 466  seaattach(parent, self, aux)
Line 471  seaattach(parent, self, aux)
         /*          /*
          * ask the adapter what subunits are present           * ask the adapter what subunits are present
          */           */
         config_found(self, &sea->sc_link, scsiprint);          config_found(self, &sea->sc_channel, scsiprint);
 }  }
   
 /*  /*
Line 551  sea_init(sea)
Line 556  sea_init(sea)
  * start a scsi operation given the command and the data address. Also needs   * start a scsi operation given the command and the data address. Also needs
  * the unit, target and lu.   * the unit, target and lu.
  */   */
 int  void
 sea_scsi_cmd(xs)  sea_scsipi_request(chan, req, arg)
         struct scsipi_xfer *xs;          struct scsipi_channel *chan;
           scsipi_adapter_req_t req;
           void *arg;
 {  {
         struct scsipi_link *sc_link = xs->sc_link;          struct scsipi_xfer *xs;
         struct sea_softc *sea = sc_link->adapter_softc;          struct scsipi_periph *periph;
           struct sea_softc *sea = (void *)chan->chan_adapter->adapt_dev;
         struct sea_scb *scb;          struct sea_scb *scb;
         int flags;          int flags;
         int s;          int s;
   
         SC_DEBUG(sc_link, SDEV_DB2, ("sea_scsi_cmd\n"));          switch (req) {
           case ADAPTER_REQ_RUN_XFER:
         flags = xs->xs_control;                  xs = arg;
         if ((scb = sea_get_scb(sea, flags)) == NULL) {                  periph = xs->xs_periph;
                 xs->error = XS_DRIVER_STUFFUP;                  flags = xs->xs_control;
                 return TRY_AGAIN_LATER;  
         }                  SC_DEBUG(periph, SCSIPI_DB2, ("sea_scsipi_requeset\n"));
         scb->flags = SCB_ACTIVE;  
         scb->xs = xs;                  /* XXX Reset not implemented. */
                   if (flags & XS_CTL_RESET) {
                           printf("%s: resetting\n", sea->sc_dev.dv_xname);
                           xs->error = XS_DRIVER_STUFFUP;
                           scsipi_done(xs);
                           return;
                   }
   
         if (flags & XS_CTL_RESET) {                  /* Get an SCB to use. */
                   scb = sea_get_scb(sea, flags);
   #ifdef DIAGNOSTIC
                 /*                  /*
                  * Try to send a reset command to the card.                   * This should never happen as we track the resources
                  * XXX Not implemented.                   * in the mid-layer.
                  */                   */
                 printf("%s: resetting\n", sea->sc_dev.dv_xname);                  if (scb == NULL) {
                 xs->error = XS_DRIVER_STUFFUP;                          scsipi_printaddr(periph);
                 return COMPLETE;                          printf("unable to allocate scb\n");
         }                          panic("sea_scsipi_request");
                   }
   #endif
   
         /*                  scb->flags = SCB_ACTIVE;
          * Put all the arguments for the xfer in the scb                  scb->xs = xs;
          */  
         scb->datalen = xs->datalen;                  /*
         scb->data = xs->data;                   * Put all the arguments for the xfer in the scb
                    */
                   scb->datalen = xs->datalen;
                   scb->data = xs->data;
   
 #ifdef SEA_DEBUGQUEUE  #ifdef SEA_DEBUGQUEUE
         sea_queue_length(sea);                  sea_queue_length(sea);
 #endif  #endif
   
         s = splbio();                  s = splbio();
   
         sea_send_scb(sea, scb);                  sea_send_scb(sea, scb);
   
         /*                  if ((flags & XS_CTL_POLL) == 0) {
          * Usually return SUCCESSFULLY QUEUED                          callout_reset(&scb->xs->xs_callout,
          */                              (xs->timeout * hz) / 1000, sea_timeout, scb);
         if ((flags & XS_CTL_POLL) == 0) {                          splx(s);
                 callout_reset(&scb->xs->xs_callout, (xs->timeout * hz) / 1000,                          return;
                     sea_timeout, scb);                  }
                 splx(s);  
                 return SUCCESSFULLY_QUEUED;  
         }  
   
         splx(s);                  splx(s);
   
         /*                  /*
          * If we can't use interrupts, poll on completion                   * If we can't use interrupts, poll on completion
          */                   */
         if (sea_poll(sea, xs, xs->timeout)) {                  if (sea_poll(sea, xs, xs->timeout)) {
                 sea_timeout(scb);  
                 if (sea_poll(sea, xs, 2000))  
                         sea_timeout(scb);                          sea_timeout(scb);
                           if (sea_poll(sea, xs, 2000))
                                   sea_timeout(scb);
                   }
                   return;
   
           case ADAPTER_REQ_GROW_RESOURCES:
                   sea_grow_scb(sea);
                   return;
   
           case ADAPTER_REQ_SET_XFER_MODE:
               {
                   struct scsipi_xfer_mode *xm = arg;
   
                   /*
                    * We don't support sync or wide or tagged queueing,
                    * so announce that now.
                    */
                   xm->xm_mode = 0;
                   xm->xm_period = 0;
                   xm->xm_offset = 0;
                   scsipi_async_event(chan, ASYNC_EVENT_XFER_MODE, xm);
                   return;
               }
         }          }
         return COMPLETE;  
 }  }
   
 /*  /*
Line 631  sea_get_scb(sea, flags)
Line 669  sea_get_scb(sea, flags)
         struct sea_scb *scb;          struct sea_scb *scb;
   
         s = splbio();          s = splbio();
           if ((scb = TAILQ_FIRST(&sea->free_list)) != NULL)
         /*                  TAILQ_REMOVE(&sea->free_list, scb, chain);
          * If we can and have to, sleep waiting for one to come free  
          * but only if we can't allocate a new one.  
          */  
         for (;;) {  
                 scb = sea->free_list.tqh_first;  
                 if (scb) {  
                         TAILQ_REMOVE(&sea->free_list, scb, chain);  
                         break;  
                 }  
                 if (sea->numscbs < SEA_SCB_MAX) {  
                         scb = (struct sea_scb *) malloc(sizeof(struct sea_scb),  
                             M_TEMP, M_NOWAIT);  
                         if (scb) {  
                                 bzero(scb, sizeof(struct sea_scb));  
                                 sea->numscbs++;  
                         } else  
                                 printf("%s: can't malloc scb\n",  
                                     sea->sc_dev.dv_xname);  
                         break;  
                 }  
                 if ((flags & XS_CTL_NOSLEEP) != 0)  
                         break;  
                 tsleep(&sea->free_list, PRIBIO, "seascb", 0);  
         }  
   
         splx(s);          splx(s);
         return scb;  
           return (scb);
 }  }
   
 /*  /*
Line 687  sea_send_scb(sea, scb)
Line 701  sea_send_scb(sea, scb)
  * adapter in a system.  Both sea_scsi_cmd and sea_intr will try to start it in   * adapter in a system.  Both sea_scsi_cmd and sea_intr will try to start it in
  * case it is not running.   * case it is not running.
  */   */
   
 void  void
 sea_main()  sea_main()
 {  {
Line 716  loop:
Line 731  loop:
                          */                           */
                         for (scb = sea->ready_list.tqh_first; scb;                          for (scb = sea->ready_list.tqh_first; scb;
                             scb = scb->chain.tqe_next) {                              scb = scb->chain.tqe_next) {
                                 if (!(sea->busy[scb->xs->sc_link->scsipi_scsi.target] &                                  if (!(sea->busy[scb->xs->xs_periph->periph_target] &
                                     (1 << scb->xs->sc_link->scsipi_scsi.lun))) {                                      (1 << scb->xs->xs_periph->periph_lun))) {
                                         TAILQ_REMOVE(&sea->ready_list, scb,                                          TAILQ_REMOVE(&sea->ready_list, scb,
                                             chain);                                              chain);
   
Line 784  loop:
Line 799  loop:
         main_running = 0;          main_running = 0;
 }  }
   
   /*
    * Allocate an scb and add it to the free list.
    * We are called at splbio.
    */
   void
   sea_grow_scb(sea)
           struct sea_softc *sea;
   {
           struct sea_scb *scb;
   
           if (sea->numscbs == SEA_SCB_MAX) {
                   sea->sc_channel.chan_flags &= ~SCSIPI_CHAN_CANGROW;
                   return;
           }
   
           scb = malloc(sizeof(struct sea_scb), M_DEVBUF, M_NOWAIT);
           if (scb == NULL)
                   return;
   
           memset(scb, 0, sizeof(struct sea_scb));
   
           TAILQ_INSERT_TAIL(&sea->free_list, scb, chain);
           sea->numscbs++;
           sea->sc_adapter.adapt_openings++;
   }
 void  void
 sea_free_scb(sea, scb, flags)  sea_free_scb(sea, scb, flags)
         struct sea_softc *sea;          struct sea_softc *sea;
Line 793  sea_free_scb(sea, scb, flags)
Line 833  sea_free_scb(sea, scb, flags)
         int s;          int s;
   
         s = splbio();          s = splbio();
   
         scb->flags = SCB_FREE;          scb->flags = SCB_FREE;
         TAILQ_INSERT_HEAD(&sea->free_list, scb, chain);          TAILQ_INSERT_HEAD(&sea->free_list, scb, chain);
   
         /*  
          * If there were none, wake anybody waiting for one to come free,  
          * starting with queued entries.  
          */  
         if (!scb->chain.tqe_next)  
                 wakeup((caddr_t)&sea->free_list);  
   
         splx(s);          splx(s);
 }  }
   
Line 813  sea_timeout(arg)
Line 844  sea_timeout(arg)
 {  {
         struct sea_scb *scb = arg;          struct sea_scb *scb = arg;
         struct scsipi_xfer *xs = scb->xs;          struct scsipi_xfer *xs = scb->xs;
         struct scsipi_link *sc_link = xs->sc_link;          struct scsipi_periph *periph = xs->xs_periph;
         struct sea_softc *sea = sc_link->adapter_softc;          struct sea_softc *sea =
               (void *)periph->periph_channel->chan_adapter->adapt_dev;
         int s;          int s;
   
         scsi_print_addr(sc_link);          scsipi_printaddr(periph);
         printf("timed out");          printf("timed out");
   
         s = splbio();          s = splbio();
Line 830  sea_timeout(arg)
Line 862  sea_timeout(arg)
         if (scb->flags & SCB_ABORTED) {          if (scb->flags & SCB_ABORTED) {
                 /* abort timed out */                  /* abort timed out */
                 printf(" AGAIN\n");                  printf(" AGAIN\n");
                 scb->xs->retries = 0;                  scb->xs->xs_retries = 0;
                 scb->flags |= SCB_ABORTED;                  scb->flags |= SCB_ABORTED;
                 sea_done(sea, scb);                  sea_done(sea, scb);
         } else {          } else {
Line 911  sea_reselect(sea)
Line 943  sea_reselect(sea)
                  */                   */
                 for (scb = sea->nexus_list.tqh_first; scb;                  for (scb = sea->nexus_list.tqh_first; scb;
                     scb = scb->chain.tqe_next)                      scb = scb->chain.tqe_next)
                         if (target_mask == (1 << scb->xs->sc_link->scsipi_scsi.target) &&                          if (target_mask == (1 << scb->xs->xs_periph->periph_target) &&
                             lun == scb->xs->sc_link->scsipi_scsi.lun) {                              lun == scb->xs->xs_periph->periph_lun) {
                                 TAILQ_REMOVE(&sea->nexus_list, scb,                                  TAILQ_REMOVE(&sea->nexus_list, scb,
                                     chain);                                      chain);
                                 break;                                  break;
Line 1062  sea_select(sea, scb)
Line 1094  sea_select(sea, scb)
         }          }
   
         delay(2);          delay(2);
         DATA = (u_char)((1 << scb->xs->sc_link->scsipi_scsi.target) |          DATA = (u_char)((1 << scb->xs->xs_periph->periph_target) |
                 sea->our_id_mask);                  sea->our_id_mask);
         CONTROL =          CONTROL =
 #ifdef SEA_NOMSGS  #ifdef SEA_NOMSGS
Line 1105  sea_select(sea, scb)
Line 1137  sea_select(sea, scb)
                  * (THIS IS NOT AN ERROR!)                   * (THIS IS NOT AN ERROR!)
                  */                   */
         } else {          } else {
                 msg[0] = MSG_IDENTIFY(scb->xs->sc_link->scsipi_scsi.lun, 1);                  msg[0] = MSG_IDENTIFY(scb->xs->xs_periph->periph_lun, 1);
                 len = 1;                  len = 1;
                 data = msg;                  data = msg;
                 phase = PH_MSGOUT;                  phase = PH_MSGOUT;
Line 1117  sea_select(sea, scb)
Line 1149  sea_select(sea, scb)
                     sea->sc_dev.dv_xname);                      sea->sc_dev.dv_xname);
   
         sea->nexus = scb;          sea->nexus = scb;
         sea->busy[scb->xs->sc_link->scsipi_scsi.target] |=          sea->busy[scb->xs->xs_periph->periph_target] |=
                                                 1 << scb->xs->sc_link->scsipi_scsi.lun;              1 << scb->xs->xs_periph->periph_lun;
         /* This assignment should depend on possibility to send a message to target. */          /* This assignment should depend on possibility to send a message to target. */
         CONTROL = BASE_CMD | CMD_DRVR_ENABLE;          CONTROL = BASE_CMD | CMD_DRVR_ENABLE;
         /* XXX Reset pointer in command? */          /* XXX Reset pointer in command? */
Line 1209  sea_done(sea, scb)
Line 1241  sea_done(sea, scb)
                 if (scb->flags & SCB_ERROR)                  if (scb->flags & SCB_ERROR)
                         xs->error = XS_DRIVER_STUFFUP;                          xs->error = XS_DRIVER_STUFFUP;
         }          }
         xs->xs_status |= XS_STS_DONE;  
         sea_free_scb(sea, scb, xs->xs_control);          sea_free_scb(sea, scb, xs->xs_control);
         scsipi_done(xs);          scsipi_done(xs);
 }  }
Line 1379  sea_information_transfer(sea)
Line 1410  sea_information_transfer(sea)
                                 s = splbio();                                  s = splbio();
                                 sea->nexus = NULL;                                  sea->nexus = NULL;
                                 splx(s);                                  splx(s);
                                 sea->busy[scb->xs->sc_link->scsipi_scsi.target] &=                                  sea->busy[scb->xs->xs_periph->periph_target] &=
                                     ~(1 << scb->xs->sc_link->scsipi_scsi.lun);                                      ~(1 << scb->xs->xs_periph->periph_lun);
                                 CONTROL = BASE_CMD;                                  CONTROL = BASE_CMD;
                                 sea_done(sea, scb);                                  sea_done(sea, scb);
                                 return;                                  return;
                         case MSG_MESSAGE_REJECT:                          case MSG_MESSAGE_REJECT:
                                 printf("%s: message_reject recieved\n",                                  printf("%s: message_reject received\n",
                                     sea->sc_dev.dv_xname);                                      sea->sc_dev.dv_xname);
                                 break;                                  break;
                         case MSG_DISCONNECT:                          case MSG_DISCONNECT:
Line 1421  sea_information_transfer(sea)
Line 1452  sea_information_transfer(sea)
                                 printf("%s: sent message abort to target\n",                                  printf("%s: sent message abort to target\n",
                                     sea->sc_dev.dv_xname);                                      sea->sc_dev.dv_xname);
                                 s = splbio();                                  s = splbio();
                                 sea->busy[scb->xs->sc_link->scsipi_scsi.target] &=                                  sea->busy[scb->xs->xs_periph->periph_target] &=
                                     ~(1 << scb->xs->sc_link->scsipi_scsi.lun);                                      ~(1 << scb->xs->xs_periph->periph_lun);
                                 sea->nexus = NULL;                                  sea->nexus = NULL;
                                 scb->flags = SCB_ABORTED;                                  scb->flags = SCB_ABORTED;
                                 splx(s);                                  splx(s);

Legend:
Removed from v.1.39  
changed lines
  Added in v.1.39.2.3

CVSweb <webmaster@jp.NetBSD.org>