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

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

Diff for /src/sys/dev/ic/wdc.c between version 1.172.2.7 and 1.172.2.7.2.11

version 1.172.2.7, 2004/09/17 04:04:57 version 1.172.2.7.2.11, 2005/10/28 01:38:58
Line 125  __KERNEL_RCSID(0, "$NetBSD$");
Line 125  __KERNEL_RCSID(0, "$NetBSD$");
 /* timeout for the control commands */  /* timeout for the control commands */
 #define WDC_CTRL_DELAY 10000 /* 10s, for the recall command */  #define WDC_CTRL_DELAY 10000 /* 10s, for the recall command */
   
   /*
    * timeout when waiting for BSY to deassert when probing.
    * set to 5s. From the standards this could be up to 31, but we can't
    * wait that much at boot time, and 5s seems to be enouth.
    */
   #define WDC_PROBE_WAIT  5
   
 struct pool wdc_xfer_pool;  struct pool wdc_xfer_pool;
   
 #if NWD > 0  #if NWD > 0
Line 477  atabusconfig(struct atabus_softc *atabus
Line 484  atabusconfig(struct atabus_softc *atabus
 int  int
 wdcprobe(struct wdc_channel *chp)  wdcprobe(struct wdc_channel *chp)
 {  {
           struct wdc_softc *wdc = chp->ch_wdc;
           /* default reset method */
           if (wdc != NULL && wdc->reset == NULL)
                   wdc->reset = wdc_do_reset;
   
         return (wdcprobe1(chp, 1));          return (wdcprobe1(chp, 1));
 }  }
Line 485  static int
Line 496  static int
 wdcprobe1(struct wdc_channel *chp, int poll)  wdcprobe1(struct wdc_channel *chp, int poll)
 {  {
         struct wdc_softc *wdc = chp->ch_wdc;          struct wdc_softc *wdc = chp->ch_wdc;
         u_int8_t st0, st1, sc, sn, cl, ch;          u_int8_t st0 = 0, st1 = 0, sc, sn, cl, ch;
         u_int8_t ret_value = 0x03;          u_int8_t ret_value = 0x03;
         u_int8_t drive;          u_int8_t drive;
         int s;          int s;
           int wdc_probe_count =
               poll ? (WDC_PROBE_WAIT / WDCDELAY) : (WDC_PROBE_WAIT * hz);
   
         /*          /*
          * Sanity check to see if the wdc channel responds at all.           * Sanity check to see if the wdc channel responds at all.
Line 497  wdcprobe1(struct wdc_channel *chp, int p
Line 510  wdcprobe1(struct wdc_channel *chp, int p
         s = splbio();          s = splbio();
         if (wdc == NULL ||          if (wdc == NULL ||
             (wdc->cap & WDC_CAPABILITY_NO_EXTRA_RESETS) == 0) {              (wdc->cap & WDC_CAPABILITY_NO_EXTRA_RESETS) == 0) {
                   while (wdc_probe_count-- > 0) {
   
                 if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))                          if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
                         wdc->select(chp,0);                                  wdc->select(chp,0);
   
                 bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,                          bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
                     WDSD_IBM);                              0, WDSD_IBM);
                 delay(10);      /* 400ns delay */                          delay(10);      /* 400ns delay */
                 st0 = bus_space_read_1(chp->cmd_iot,                          st0 = bus_space_read_1(chp->cmd_iot,
                     chp->cmd_iohs[wd_status], 0);                              chp->cmd_iohs[wd_status], 0);
   
                 if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))                          if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))
                         wdc->select(chp,1);                                  wdc->select(chp,1);
   
                 bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,                          bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh],
                     WDSD_IBM | 0x10);                              0, WDSD_IBM | 0x10);
                 delay(10);      /* 400ns delay */                          delay(10);      /* 400ns delay */
                 st1 = bus_space_read_1(chp->cmd_iot,                          st1 = bus_space_read_1(chp->cmd_iot,
                     chp->cmd_iohs[wd_status], 0);                              chp->cmd_iohs[wd_status], 0);
                           if ((st0 & WDCS_BSY) == 0)
                                   break;
                   }
   
                 WDCDEBUG_PRINT(("%s:%d: before reset, st0=0x%x, st1=0x%x\n",                  WDCDEBUG_PRINT(("%s:%d: before reset, st0=0x%x, st1=0x%x\n",
                     wdc != NULL ? wdc->sc_dev.dv_xname : "wdcprobe",                      wdc != NULL ? wdc->sc_dev.dv_xname : "wdcprobe",
Line 697  wdcprobe1(struct wdc_channel *chp, int p
Line 714  wdcprobe1(struct wdc_channel *chp, int p
         delay(5000);          delay(5000);
 #endif  #endif
   
         if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_SELECT))          if (wdc != NULL)
                 wdc->select(chp,0);                  wdc->reset(chp, RESET_POLL);
         bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0, WDSD_IBM);          else
         delay(10);      /* 400ns delay */                  wdc_do_reset(chp, RESET_POLL);
         /* assert SRST, wait for reset to complete */  
         bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,  
             WDCTL_RST | WDCTL_IDS | WDCTL_4BIT);  
         DELAY(1000);  
         bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,  
             WDCTL_IDS | WDCTL_4BIT);  
         DELAY(2000);          DELAY(2000);
         (void) bus_space_read_1(chp->cmd_iot, chp->cmd_iohs[wd_error], 0);          (void) bus_space_read_1(chp->cmd_iot, chp->cmd_iohs[wd_error], 0);
         bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);          bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
         delay(10);      /* 400ns delay */  
         /* ACK interrupt in case there is one pending left (Promise ATA100) */  
         if (wdc != NULL && (wdc->cap & WDC_CAPABILITY_IRQACK))  
                 wdc->irqack(chp);  
         splx(s);          splx(s);
   
         ret_value = __wdcwait_reset(chp, ret_value, poll);          ret_value = __wdcwait_reset(chp, ret_value, poll);
Line 782  wdcattach(struct wdc_channel *chp)
Line 789  wdcattach(struct wdc_channel *chp)
         callout_init(&chp->ch_callout);          callout_init(&chp->ch_callout);
         if (wdc->drv_probe == NULL)          if (wdc->drv_probe == NULL)
                 wdc->drv_probe = wdc_drvprobe;                  wdc->drv_probe = wdc_drvprobe;
           if (wdc->reset == NULL)
                   wdc->reset = wdc_do_reset;
         if (inited == 0) {          if (inited == 0) {
                 /* Initialize the ata_xfer pool. */                  /* Initialize the ata_xfer pool. */
                 pool_init(&wdc_xfer_pool, sizeof(struct ata_xfer), 0,                  pool_init(&wdc_xfer_pool, sizeof(struct ata_xfer), 0,
Line 873  wdcstart(struct wdc_channel *chp)
Line 882  wdcstart(struct wdc_channel *chp)
         if (__predict_false(chp->ch_queue->queue_freeze > 0)) {          if (__predict_false(chp->ch_queue->queue_freeze > 0)) {
                 return; /* queue froozen */                  return; /* queue froozen */
         }          }
           /*
            * if someone is waiting for the command to be active, wake it up
            * and let it process the command
            */
           if (xfer->c_flags & C_WAITACT) {
                   WDCDEBUG_PRINT(("atastart: xfer %p channel %d drive %d "
                       "wait active\n", xfer, chp->ch_channel, xfer->c_drive),
                       DEBUG_XFERS);
                   wakeup(xfer);
                   return;
           }
 #ifdef DIAGNOSTIC  #ifdef DIAGNOSTIC
         if ((chp->ch_flags & WDCF_IRQ_WAIT) != 0)          if ((chp->ch_flags & WDCF_IRQ_WAIT) != 0)
                 panic("wdcstart: channel waiting for irq");                  panic("wdcstart: channel waiting for irq");
Line 1022  wdcreset(struct wdc_channel *chp, int po
Line 1042  wdcreset(struct wdc_channel *chp, int po
 {  {
         struct wdc_softc *wdc = chp->ch_wdc;          struct wdc_softc *wdc = chp->ch_wdc;
         int drv_mask1, drv_mask2;          int drv_mask1, drv_mask2;
   
           wdc->reset(chp, poll);
   
           drv_mask1 = (chp->ch_drive[0].drive_flags & DRIVE) ? 0x01:0x00;
           drv_mask1 |= (chp->ch_drive[1].drive_flags & DRIVE) ? 0x02:0x00;
           drv_mask2 = __wdcwait_reset(chp, drv_mask1,
               (poll == RESET_SLEEP) ? 0 : 1);
           if (drv_mask2 != drv_mask1) {
                   printf("%s channel %d: reset failed for",
                       wdc->sc_dev.dv_xname, chp->ch_channel);
                   if ((drv_mask1 & 0x01) != 0 && (drv_mask2 & 0x01) == 0)
                           printf(" drive 0");
                   if ((drv_mask1 & 0x02) != 0 && (drv_mask2 & 0x02) == 0)
                           printf(" drive 1");
                   printf("\n");
           }
           bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);
           return  (drv_mask1 != drv_mask2) ? 1 : 0;
   }
   
   void
   wdc_do_reset(struct wdc_channel *chp, int poll)
   {
           struct wdc_softc *wdc = chp->ch_wdc;
         int s = 0;          int s = 0;
   
         if (wdc->cap & WDC_CAPABILITY_SELECT)          if (wdc && wdc->cap & WDC_CAPABILITY_SELECT)
                 wdc->select(chp,0);                  wdc->select(chp,0);
         if (poll != RESET_SLEEP)          if (poll != RESET_SLEEP)
                 s = splbio();                  s = splbio();
Line 1032  wdcreset(struct wdc_channel *chp, int po
Line 1076  wdcreset(struct wdc_channel *chp, int po
         bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0, WDSD_IBM);          bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0, WDSD_IBM);
         delay(10);      /* 400ns delay */          delay(10);      /* 400ns delay */
         bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,          bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
               WDCTL_IDS | WDCTL_4BIT);
           delay(10);      /* 400ns delay */
           /* assert SRST, wait for reset to complete */
           bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr,
             WDCTL_RST | WDCTL_IDS | WDCTL_4BIT);              WDCTL_RST | WDCTL_IDS | WDCTL_4BIT);
         delay(2000);          delay(2000);
         (void) bus_space_read_1(chp->cmd_iot, chp->cmd_iohs[wd_error], 0);          (void) bus_space_read_1(chp->cmd_iot, chp->cmd_iohs[wd_error], 0);
Line 1039  wdcreset(struct wdc_channel *chp, int po
Line 1087  wdcreset(struct wdc_channel *chp, int po
             WDCTL_4BIT | WDCTL_IDS);              WDCTL_4BIT | WDCTL_IDS);
         delay(10);      /* 400ns delay */          delay(10);      /* 400ns delay */
         if (poll != RESET_SLEEP) {          if (poll != RESET_SLEEP) {
                 if (wdc->cap & WDC_CAPABILITY_IRQACK)                  if (wdc && wdc->cap & WDC_CAPABILITY_IRQACK)
                         wdc->irqack(chp);                          wdc->irqack(chp);
                 splx(s);                  splx(s);
         }          }
   
         drv_mask1 = (chp->ch_drive[0].drive_flags & DRIVE) ? 0x01:0x00;  
         drv_mask1 |= (chp->ch_drive[1].drive_flags & DRIVE) ? 0x02:0x00;  
         drv_mask2 = __wdcwait_reset(chp, drv_mask1,  
             (poll == RESET_SLEEP) ? 0 : 1);  
         if (drv_mask2 != drv_mask1) {  
                 printf("%s channel %d: reset failed for",  
                     wdc->sc_dev.dv_xname, chp->ch_channel);  
                 if ((drv_mask1 & 0x01) != 0 && (drv_mask2 & 0x01) == 0)  
                         printf(" drive 0");  
                 if ((drv_mask1 & 0x02) != 0 && (drv_mask2 & 0x02) == 0)  
                         printf(" drive 1");  
                 printf("\n");  
         }  
         bus_space_write_1(chp->ctl_iot, chp->ctl_ioh, wd_aux_ctlr, WDCTL_4BIT);  
         return  (drv_mask1 != drv_mask2) ? 1 : 0;  
 }  }
   
 static int  static int
Line 1573  wdc_downgrade_mode(struct ata_drive_data
Line 1605  wdc_downgrade_mode(struct ata_drive_data
                 return 0;                  return 0;
   
         /*          /*
          * If we were using Ultra-DMA mode > 2, downgrade to mode 2 first.           * If we were using Ultra-DMA mode, downgrade to the next lower mode.
          * Maybe we didn't properly notice the cable type  
          * If we were using Ultra-DMA mode 2, downgrade to mode 1 first.  
          * It helps in some cases.  
          */           */
         if ((drvp->drive_flags & DRIVE_UDMA) && drvp->UDMA_mode >= 2) {          if ((drvp->drive_flags & DRIVE_UDMA) && drvp->UDMA_mode >= 2) {
                 drvp->UDMA_mode = (drvp->UDMA_mode == 2) ? 1 : 2;                  drvp->UDMA_mode--;
                 printf("%s: transfer error, downgrading to Ultra-DMA mode %d\n",                  printf("%s: transfer error, downgrading to Ultra-DMA mode %d\n",
                     drv_dev->dv_xname, drvp->UDMA_mode);                      drv_dev->dv_xname, drvp->UDMA_mode);
         }          }
   
         /*          /*
          * If we were using ultra-DMA, don't downgrade to multiword DMA           * If we were using ultra-DMA, don't downgrade to multiword DMA.
          * if we noticed a CRC error. It has been noticed that CRC errors  
          * in ultra-DMA lead to silent data corruption in multiword DMA.  
          * Data corruption is less likely to occur in PIO mode.  
          */           */
         else if ((drvp->drive_flags & DRIVE_UDMA) &&          else if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) {
             (drvp->drive_flags & DRIVE_DMAERR) == 0) {  
                 drvp->drive_flags &= ~DRIVE_UDMA;  
                 drvp->drive_flags |= DRIVE_DMA;  
                 drvp->DMA_mode = drvp->DMA_cap;  
                 printf("%s: transfer error, downgrading to DMA mode %d\n",  
                     drv_dev->dv_xname, drvp->DMA_mode);  
         } else if (drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) {  
                 drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);                  drvp->drive_flags &= ~(DRIVE_DMA | DRIVE_UDMA);
                 drvp->PIO_mode = drvp->PIO_cap;                  drvp->PIO_mode = drvp->PIO_cap;
                 printf("%s: transfer error, downgrading to PIO mode %d\n",                  printf("%s: transfer error, downgrading to PIO mode %d\n",
Line 1635  wdc_exec_command(struct ata_drive_datas 
Line 1654  wdc_exec_command(struct ata_drive_datas 
                 wdc_c->flags |= AT_POLL;                  wdc_c->flags |= AT_POLL;
         if (wdc_c->flags & AT_POLL)          if (wdc_c->flags & AT_POLL)
                 xfer->c_flags |= C_POLL;                  xfer->c_flags |= C_POLL;
           if (wdc_c->flags & AT_WAIT)
                   xfer->c_flags |= C_WAIT;
         xfer->c_drive = drvp->drive;          xfer->c_drive = drvp->drive;
         xfer->c_databuf = wdc_c->data;          xfer->c_databuf = wdc_c->data;
         xfer->c_bcount = wdc_c->bcount;          xfer->c_bcount = wdc_c->bcount;
Line 1672  __wdccommand_start(struct wdc_channel *c
Line 1693  __wdccommand_start(struct wdc_channel *c
         struct wdc_softc *wdc = chp->ch_wdc;          struct wdc_softc *wdc = chp->ch_wdc;
         int drive = xfer->c_drive;          int drive = xfer->c_drive;
         struct wdc_command *wdc_c = xfer->c_cmd;          struct wdc_command *wdc_c = xfer->c_cmd;
           int wait_flags = (xfer->c_flags & C_POLL) ? AT_POLL : 0;
   
         WDCDEBUG_PRINT(("__wdccommand_start %s:%d:%d\n",          WDCDEBUG_PRINT(("__wdccommand_start %s:%d:%d\n",
             wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive),              wdc->sc_dev.dv_xname, chp->ch_channel, xfer->c_drive),
Line 1682  __wdccommand_start(struct wdc_channel *c
Line 1704  __wdccommand_start(struct wdc_channel *c
         bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,          bus_space_write_1(chp->cmd_iot, chp->cmd_iohs[wd_sdh], 0,
             WDSD_IBM | (drive << 4));              WDSD_IBM | (drive << 4));
         switch(wdcwait(chp, wdc_c->r_st_bmask | WDCS_DRQ,          switch(wdcwait(chp, wdc_c->r_st_bmask | WDCS_DRQ,
             wdc_c->r_st_bmask, wdc_c->timeout, wdc_c->flags)) {              wdc_c->r_st_bmask, wdc_c->timeout, wait_flags)) {
         case WDCWAIT_OK:          case WDCWAIT_OK:
                 break;                  break;
         case WDCWAIT_TOUT:          case WDCWAIT_TOUT:
Line 1722  __wdccommand_intr(struct wdc_channel *ch
Line 1744  __wdccommand_intr(struct wdc_channel *ch
         int bcount = wdc_c->bcount;          int bcount = wdc_c->bcount;
         char *data = wdc_c->data;          char *data = wdc_c->data;
         int wflags;          int wflags;
           int drive_flags = chp->ch_drive[xfer->c_drive].drive_flags;
           int wdc_cap;
   
           if (wdc_c->r_command == WDCC_IDENTIFY ||
               wdc_c->r_command == ATAPI_IDENTIFY_DEVICE) {
                   /*
                    * The IDENTIFY data has been designed as an array of
                    * u_int16_t, so we can byteswap it on the fly.
                    * Historically it's what we have always done so keeping it
                    * here ensure binary backward compatibility.
                    */
                    wdc_cap = WDC_CAPABILITY_ATA_NOSTREAM | wdc->cap;
           } else {
                   /*
                    * Other data structure are opaque and should be transfered
                    * as is.
                    */
                   wdc_cap = wdc->cap;
           }
   
         if ((wdc_c->flags & (AT_WAIT | AT_POLL)) == (AT_WAIT | AT_POLL)) {          if ((wdc_c->flags & (AT_WAIT | AT_POLL)) == (AT_WAIT | AT_POLL)) {
                 /* both wait and poll, we can tsleep here */                  /* both wait and poll, we can tsleep here */
Line 1763  __wdccommand_intr(struct wdc_channel *ch
Line 1804  __wdccommand_intr(struct wdc_channel *ch
                 wdc_c->flags |= AT_TIMEOU;                  wdc_c->flags |= AT_TIMEOU;
                 goto out;                  goto out;
         }          }
         if (wdc->cap & WDC_CAPABILITY_IRQACK)          if (wdc_cap & WDC_CAPABILITY_IRQACK)
                 wdc->irqack(chp);                  wdc->irqack(chp);
         if (wdc_c->flags & AT_READ) {          if (wdc_c->flags & AT_READ) {
                 if ((chp->ch_status & WDCS_DRQ) == 0) {                  if ((chp->ch_status & WDCS_DRQ) == 0) {
                         wdc_c->flags |= AT_TIMEOU;                          wdc_c->flags |= AT_TIMEOU;
                         goto out;                          goto out;
                 }                  }
                 if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_CAP32) {                  if (wdc_cap & WDC_CAPABILITY_ATA_NOSTREAM) {
                         bus_space_read_multi_4(chp->data32iot, chp->data32ioh,                          if (drive_flags & DRIVE_CAP32) {
                             0, (u_int32_t*)data, bcount >> 2);                                  bus_space_read_multi_4(chp->data32iot,
                         data += bcount & 0xfffffffc;                                      chp->data32ioh, 0, (u_int32_t*)data,
                         bcount = bcount & 0x03;                                      bcount >> 2);
                 }                                  data += bcount & 0xfffffffc;
                 if (bcount > 0)                                  bcount = bcount & 0x03;
                         bus_space_read_multi_2(chp->cmd_iot,                          }
                             chp->cmd_iohs[wd_data], 0,                          if (bcount > 0)
                             (u_int16_t *)data, bcount >> 1);                                  bus_space_read_multi_2(chp->cmd_iot,
                                       chp->cmd_iohs[wd_data], 0,
                                       (u_int16_t *)data, bcount >> 1);
                   } else {
                           if (drive_flags & DRIVE_CAP32) {
                                   bus_space_read_multi_stream_4(chp->data32iot,
                                       chp->data32ioh, 0, (u_int32_t*)data,
                                       bcount >> 2);
                                   data += bcount & 0xfffffffc;
                                   bcount = bcount & 0x03;
                           }
                           if (bcount > 0)
                                   bus_space_read_multi_stream_2(chp->cmd_iot,
                                       chp->cmd_iohs[wd_data], 0,
                                       (u_int16_t *)data, bcount >> 1);
                   }
                 /* at this point the drive should be in its initial state */                  /* at this point the drive should be in its initial state */
                 wdc_c->flags |= AT_XFDONE;                  wdc_c->flags |= AT_XFDONE;
                 /* XXX should read status register here ? */                  /* XXX should read status register here ? */
Line 1788  __wdccommand_intr(struct wdc_channel *ch
Line 1844  __wdccommand_intr(struct wdc_channel *ch
                         wdc_c->flags |= AT_TIMEOU;                          wdc_c->flags |= AT_TIMEOU;
                         goto out;                          goto out;
                 }                  }
                 if (chp->ch_drive[xfer->c_drive].drive_flags & DRIVE_CAP32) {                  if (wdc_cap & WDC_CAPABILITY_ATA_NOSTREAM) {
                         bus_space_write_multi_4(chp->data32iot, chp->data32ioh,                          if (drive_flags & DRIVE_CAP32) {
                             0, (u_int32_t*)data, bcount >> 2);                                  bus_space_write_multi_4(chp->data32iot,
                         data += bcount & 0xfffffffc;                                      chp->data32ioh, 0, (u_int32_t*)data,
                         bcount = bcount & 0x03;                                      bcount >> 2);
                 }                                  data += bcount & 0xfffffffc;
                 if (bcount > 0)                                  bcount = bcount & 0x03;
                         bus_space_write_multi_2(chp->cmd_iot,                          }
                             chp->cmd_iohs[wd_data], 0,                          if (bcount > 0)
                             (u_int16_t *)data, bcount >> 1);                                  bus_space_write_multi_2(chp->cmd_iot,
                                       chp->cmd_iohs[wd_data], 0,
                                       (u_int16_t *)data, bcount >> 1);
                   } else {
                           if (drive_flags & DRIVE_CAP32) {
                                   bus_space_write_multi_stream_4(chp->data32iot,
                                       chp->data32ioh, 0, (u_int32_t*)data,
                                       bcount >> 2);
                                   data += bcount & 0xfffffffc;
                                   bcount = bcount & 0x03;
                           }
                           if (bcount > 0)
                                   bus_space_write_multi_stream_2(chp->cmd_iot,
                                       chp->cmd_iohs[wd_data], 0,
                                       (u_int16_t *)data, bcount >> 1);
                   }
                 wdc_c->flags |= AT_XFDONE;                  wdc_c->flags |= AT_XFDONE;
                 if ((wdc_c->flags & AT_POLL) == 0) {                  if ((wdc_c->flags & AT_POLL) == 0) {
                         chp->ch_flags |= WDCF_IRQ_WAIT; /* wait for interrupt */                          chp->ch_flags |= WDCF_IRQ_WAIT; /* wait for interrupt */
Line 2016  wdc_exec_xfer(struct wdc_channel *chp, s
Line 2087  wdc_exec_xfer(struct wdc_channel *chp, s
         TAILQ_INSERT_TAIL(&chp->ch_queue->queue_xfer, xfer, c_xferchain);          TAILQ_INSERT_TAIL(&chp->ch_queue->queue_xfer, xfer, c_xferchain);
         WDCDEBUG_PRINT(("wdcstart from wdc_exec_xfer, flags 0x%x\n",          WDCDEBUG_PRINT(("wdcstart from wdc_exec_xfer, flags 0x%x\n",
             chp->ch_flags), DEBUG_XFERS);              chp->ch_flags), DEBUG_XFERS);
           /*
            * if polling and can sleep, wait for the xfer to be at head of queue
            */
           if ((xfer->c_flags & (C_POLL | C_WAIT)) ==  (C_POLL | C_WAIT)) {
                   while (TAILQ_FIRST(&chp->ch_queue->queue_xfer) != xfer) {
                           xfer->c_flags |= C_WAITACT;
                           tsleep(xfer, PRIBIO, "ataact", 0);
                           xfer->c_flags &= ~C_WAITACT;
                           if (xfer->c_flags & C_FREE) {
                                   wdc_free_xfer(chp, xfer);
                                   return;
                           }
                   }
           }
         wdcstart(chp);          wdcstart(chp);
 }  }
   
Line 2041  wdc_free_xfer(struct wdc_channel *chp, s
Line 2126  wdc_free_xfer(struct wdc_channel *chp, s
         struct wdc_softc *wdc = chp->ch_wdc;          struct wdc_softc *wdc = chp->ch_wdc;
         int s;          int s;
   
           if (xfer->c_flags & C_WAITACT) {
                   /* Someone is waiting for this xfer, so we can't free now */
                   xfer->c_flags |= C_FREE;
                   wakeup(xfer);
                   return;
           }
   
         if (wdc->cap & WDC_CAPABILITY_HWLOCK)          if (wdc->cap & WDC_CAPABILITY_HWLOCK)
                 (*wdc->free_hw)(chp);                  (*wdc->free_hw)(chp);
         s = splbio();          s = splbio();

Legend:
Removed from v.1.172.2.7  
changed lines
  Added in v.1.172.2.7.2.11

CVSweb <webmaster@jp.NetBSD.org>