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

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

Diff for /src/sys/dev/scsipi/atapi_wdc.c between version 1.20 and 1.20.2.6

version 1.20, 1999/04/01 21:46:30 version 1.20.2.6, 2000/07/07 17:33:51
Line 234  wdc_atapi_start(chp, xfer)
Line 234  wdc_atapi_start(chp, xfer)
             sc_xfer->flags), DEBUG_XFERS);              sc_xfer->flags), DEBUG_XFERS);
         /* Adjust C_DMA, it may have changed if we are requesting sense */          /* Adjust C_DMA, it may have changed if we are requesting sense */
         if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&          if ((drvp->drive_flags & (DRIVE_DMA | DRIVE_UDMA)) &&
             (sc_xfer->datalen > 0 || (xfer->c_flags & C_SENSE)))              (sc_xfer->datalen > 0 || (xfer->c_flags & C_SENSE))) {
                   if (drvp->n_xfers <= NXFER)
                           drvp->n_xfers++;
                 xfer->c_flags |= C_DMA;                  xfer->c_flags |= C_DMA;
         else          } else {
                 xfer->c_flags &= ~C_DMA;                  xfer->c_flags &= ~C_DMA;
           }
           /* start timeout machinery */
           if ((sc_xfer->flags & SCSI_POLL) == 0)
                   timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);
         /* Do control operations specially. */          /* Do control operations specially. */
         if (drvp->state < READY) {          if (drvp->state < READY) {
                 if (drvp->state != PIOMODE) {                  if (drvp->state != RESET) {
                         printf("%s:%d:%d: bad state %d in wdc_atapi_start\n",                          printf("%s:%d:%d: bad state %d in wdc_atapi_start\n",
                             chp->wdc->sc_dev.dv_xname, chp->channel,                              chp->wdc->sc_dev.dv_xname, chp->channel,
                             xfer->drive, drvp->state);                              xfer->drive, drvp->state);
                         panic("wdc_atapi_start: bad state");                          panic("wdc_atapi_start: bad state");
                 }                  }
                   drvp->state = PIOMODE;
                 wdc_atapi_ctrl(chp, xfer, 0);                  wdc_atapi_ctrl(chp, xfer, 0);
                 return;                  return;
         }          }
Line 278  wdc_atapi_start(chp, xfer)
Line 285  wdc_atapi_start(chp, xfer)
          * the interrupt routine. If it is a polled command, call the interrupt           * the interrupt routine. If it is a polled command, call the interrupt
          * routine until command is done.           * routine until command is done.
          */           */
         if ((sc_xfer->sc_link->scsipi_atapi.cap  & 0x0300) != ACAP_DRQ_INTR ||          if ((sc_xfer->sc_link->scsipi_atapi.cap  & ATAPI_CFG_DRQ_MASK) !=
             sc_xfer->flags & SCSI_POLL) {              ATAPI_CFG_IRQ_DRQ || (sc_xfer->flags & SCSI_POLL)) {
                 /* Wait for at last 400ns for status bit to be valid */                  /* Wait for at last 400ns for status bit to be valid */
                 DELAY(1);                  DELAY(1);
                 wdc_atapi_intr(chp, xfer, 0);                  wdc_atapi_intr(chp, xfer, 0);
           } else {
                   chp->ch_flags |= WDCF_IRQ_WAIT;
         }          }
         if (sc_xfer->flags & SCSI_POLL) {          if (sc_xfer->flags & SCSI_POLL) {
                 while ((sc_xfer->flags & ITSDONE) == 0) {                  while ((sc_xfer->flags & ITSDONE) == 0) {
                         /* Wait for at last 400ns for status bit to be valid */                          /* Wait for at last 400ns for status bit to be valid */
                         DELAY(1);                          DELAY(1);
                           if (chp->ch_flags & WDCF_DMA_WAIT) {
                                   wdc_dmawait(chp, xfer, sc_xfer->timeout);
                                   chp->ch_flags &= ~WDCF_DMA_WAIT;
                           }
                         wdc_atapi_intr(chp, xfer, 0);                          wdc_atapi_intr(chp, xfer, 0);
                 }                  }
         }          }
Line 302  wdc_atapi_intr(chp, xfer, irq)
Line 315  wdc_atapi_intr(chp, xfer, irq)
         struct scsipi_xfer *sc_xfer = xfer->cmd;          struct scsipi_xfer *sc_xfer = xfer->cmd;
         struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];          struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];
         int len, phase, i, retries=0;          int len, phase, i, retries=0;
         int ire, dma_err = 0;          int ire;
         int dma_flags = 0;          int dma_flags = 0;
         struct scsipi_generic _cmd_reqsense;          struct scsipi_generic _cmd_reqsense;
         struct scsipi_sense *cmd_reqsense =          struct scsipi_sense *cmd_reqsense =
Line 319  wdc_atapi_intr(chp, xfer, irq)
Line 332  wdc_atapi_intr(chp, xfer, irq)
                     drvp->state);                      drvp->state);
                 panic("wdc_atapi_intr: bad state\n");                  panic("wdc_atapi_intr: bad state\n");
         }          }
           /*
            * If we missed an interrupt in a PIO transfer, reset and restart.
            * Don't try to continue transfer, we may have missed cycles.
            */
           if ((xfer->c_flags & (C_TIMEOU | C_DMA)) == C_TIMEOU) {
                   sc_xfer->error = XS_TIMEOUT;
                   wdc_atapi_reset(chp, xfer);
                   return 1;
           }
   
         /* Ack interrupt done in wait_for_unbusy */          /* Ack interrupt done in wait_for_unbusy */
         bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,          bus_space_write_1(chp->cmd_iot, chp->cmd_ioh, wd_sdh,
             WDSD_IBM | (xfer->drive << 4));              WDSD_IBM | (xfer->drive << 4));
Line 330  wdc_atapi_intr(chp, xfer, irq)
Line 353  wdc_atapi_intr(chp, xfer, irq)
                     chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,                      chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
                     xfer->c_bcount, xfer->c_skip);                      xfer->c_bcount, xfer->c_skip);
                 if (xfer->c_flags & C_DMA)                  if (xfer->c_flags & C_DMA)
                         drvp->n_dmaerrs++;                          ata_dmaerr(drvp);
                 sc_xfer->error = XS_TIMEOUT;                  sc_xfer->error = XS_TIMEOUT;
                 wdc_atapi_reset(chp, xfer);                  wdc_atapi_reset(chp, xfer);
                 return 1;                  return 1;
         }          }
           if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
                   chp->wdc->irqack(chp);
   
         /* If we missed an IRQ and were using DMA, flag it as a DMA error */          /* If we missed an IRQ and were using DMA, flag it as a DMA error */
         if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA))          if ((xfer->c_flags & C_TIMEOU) && (xfer->c_flags & C_DMA))
                 drvp->n_dmaerrs++;                  ata_dmaerr(drvp);
         /*          /*
          * if the request sense command was aborted, report the short sense           * if the request sense command was aborted, report the short sense
          * previously recorded, else continue normal processing           * previously recorded, else continue normal processing
Line 356  wdc_atapi_intr(chp, xfer, irq)
Line 382  wdc_atapi_intr(chp, xfer, irq)
         if (xfer->c_flags & C_DMA) {          if (xfer->c_flags & C_DMA) {
                 dma_flags = ((sc_xfer->flags & SCSI_DATA_IN) ||                  dma_flags = ((sc_xfer->flags & SCSI_DATA_IN) ||
                     (xfer->c_flags & C_SENSE)) ?  WDC_DMA_READ : 0;                      (xfer->c_flags & C_SENSE)) ?  WDC_DMA_READ : 0;
                 dma_flags |= sc_xfer->flags & SCSI_POLL ? WDC_DMA_POLL : 0;  
         }          }
 again:  again:
         len = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo) +          len = bus_space_read_1(chp->cmd_iot, chp->cmd_ioh, wd_cyl_lo) +
Line 417  again:
Line 442  again:
                 /* Start the DMA channel if necessary */                  /* Start the DMA channel if necessary */
                 if (xfer->c_flags & C_DMA) {                  if (xfer->c_flags & C_DMA) {
                         (*chp->wdc->dma_start)(chp->wdc->dma_arg,                          (*chp->wdc->dma_start)(chp->wdc->dma_arg,
                             chp->channel, xfer->drive, dma_flags);                              chp->channel, xfer->drive);
                            chp->ch_flags |= WDCF_DMA_WAIT;
                 }                  }
   
                 if ((sc_xfer->flags & SCSI_POLL) == 0) {                  if ((sc_xfer->flags & SCSI_POLL) == 0) {
                         chp->ch_flags |= WDCF_IRQ_WAIT;                          chp->ch_flags |= WDCF_IRQ_WAIT;
                         timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);  
                 }                  }
                 return 1;                  return 1;
   
Line 433  again:
Line 458  again:
                     (xfer->c_flags & C_DMA) != 0) {                      (xfer->c_flags & C_DMA) != 0) {
                         printf("wdc_atapi_intr: bad data phase DATAOUT\n");                          printf("wdc_atapi_intr: bad data phase DATAOUT\n");
                         if (xfer->c_flags & C_DMA) {                          if (xfer->c_flags & C_DMA) {
                                 (*chp->wdc->dma_finish)(chp->wdc->dma_arg,                                  ata_dmaerr(drvp);
                                     chp->channel, xfer->drive, dma_flags);  
                                 drvp->n_dmaerrs++;  
                         }                          }
                         sc_xfer->error = XS_TIMEOUT;                          sc_xfer->error = XS_TIMEOUT;
                         wdc_atapi_reset(chp, xfer);                          wdc_atapi_reset(chp, xfer);
Line 500  again:
Line 523  again:
                 }                  }
                 if ((sc_xfer->flags & SCSI_POLL) == 0) {                  if ((sc_xfer->flags & SCSI_POLL) == 0) {
                         chp->ch_flags |= WDCF_IRQ_WAIT;                          chp->ch_flags |= WDCF_IRQ_WAIT;
                         timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);  
                 }                  }
                 return 1;                  return 1;
   
Line 512  again:
Line 534  again:
                     (xfer->c_flags & C_DMA) != 0) {                      (xfer->c_flags & C_DMA) != 0) {
                         printf("wdc_atapi_intr: bad data phase DATAIN\n");                          printf("wdc_atapi_intr: bad data phase DATAIN\n");
                         if (xfer->c_flags & C_DMA) {                          if (xfer->c_flags & C_DMA) {
                                 (*chp->wdc->dma_finish)(chp->wdc->dma_arg,                                  ata_dmaerr(drvp);
                                     chp->channel, xfer->drive, dma_flags);  
                                 drvp->n_dmaerrs++;  
                         }                          }
                         sc_xfer->error = XS_TIMEOUT;                          sc_xfer->error = XS_TIMEOUT;
                         wdc_atapi_reset(chp, xfer);                          wdc_atapi_reset(chp, xfer);
Line 577  again:
Line 597  again:
                 }                  }
                 if ((sc_xfer->flags & SCSI_POLL) == 0) {                  if ((sc_xfer->flags & SCSI_POLL) == 0) {
                         chp->ch_flags |= WDCF_IRQ_WAIT;                          chp->ch_flags |= WDCF_IRQ_WAIT;
                         timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);  
                 }                  }
                 return 1;                  return 1;
   
Line 586  again:
Line 605  again:
                 WDCDEBUG_PRINT(("PHASE_COMPLETED\n"), DEBUG_INTR);                  WDCDEBUG_PRINT(("PHASE_COMPLETED\n"), DEBUG_INTR);
                 /* turn off DMA channel */                  /* turn off DMA channel */
                 if (xfer->c_flags & C_DMA) {                  if (xfer->c_flags & C_DMA) {
                         dma_err = (*chp->wdc->dma_finish)(chp->wdc->dma_arg,  
                             chp->channel, xfer->drive, dma_flags);  
                         if (xfer->c_flags & C_SENSE)                          if (xfer->c_flags & C_SENSE)
                                 xfer->c_bcount -=                                  xfer->c_bcount -=
                                     sizeof(sc_xfer->sense.scsi_sense);                                      sizeof(sc_xfer->sense.scsi_sense);
Line 595  again:
Line 612  again:
                                 xfer->c_bcount -= sc_xfer->datalen;                                  xfer->c_bcount -= sc_xfer->datalen;
                 }                  }
                 if (xfer->c_flags & C_SENSE) {                  if (xfer->c_flags & C_SENSE) {
                         if ((chp->ch_status & WDCS_ERR) || dma_err < 0) {                          if ((chp->ch_status & WDCS_ERR) ||
                               (chp->wdc->dma_status &
                                   (WDC_DMAST_NOIRQ | WDC_DMAST_ERR))) {
                                 /*                                  /*
                                  * request sense failed ! it's not suppossed                                   * request sense failed ! it's not suppossed
                                  * to be possible                                   * to be possible
                                  */                                   */
                                 if (dma_err < 0)                                  if (xfer->c_flags & C_DMA)
                                         drvp->n_dmaerrs++;                                          ata_dmaerr(drvp);
                                 sc_xfer->error = XS_RESET;                                  sc_xfer->error = XS_RESET;
                                 wdc_atapi_reset(chp, xfer);                                  wdc_atapi_reset(chp, xfer);
                                 return (1);                                  return (1);
Line 617  again:
Line 636  again:
                                 sc_xfer->error = XS_SHORTSENSE;                                  sc_xfer->error = XS_SHORTSENSE;
                         }                          }
                 } else {                  } else {
                           sc_xfer->resid = xfer->c_bcount;
                         if (chp->ch_status & WDCS_ERR) {                          if (chp->ch_status & WDCS_ERR) {
                                 /* save the short sense */                                  /* save the short sense */
                                 sc_xfer->error = XS_SHORTSENSE;                                  sc_xfer->error = XS_SHORTSENSE;
Line 630  again:
Line 650  again:
                                         xfer->databuf = &sc_xfer->sense;                                          xfer->databuf = &sc_xfer->sense;
                                         xfer->c_bcount =                                          xfer->c_bcount =
                                             sizeof(sc_xfer->sense.scsi_sense);                                              sizeof(sc_xfer->sense.scsi_sense);
                                           xfer->c_skip = 0;
                                         xfer->c_flags |= C_SENSE;                                          xfer->c_flags |= C_SENSE;
                                           untimeout(wdctimeout, chp);
                                         wdc_atapi_start(chp, xfer);                                          wdc_atapi_start(chp, xfer);
                                         return 1;                                          return 1;
                                 }                                  }
                         } else if (dma_err < 0) {                          } else if (chp->wdc->dma_status &
                                 drvp->n_dmaerrs++;                              (WDC_DMAST_NOIRQ | WDC_DMAST_ERR)) {
                                   ata_dmaerr(drvp);
                                 sc_xfer->error = XS_RESET;                                  sc_xfer->error = XS_RESET;
                                 wdc_atapi_reset(chp, xfer);                                  wdc_atapi_reset(chp, xfer);
                                 return (1);                                  return (1);
Line 667  again:
Line 690  again:
                         sc_xfer->error = XS_SHORTSENSE;                          sc_xfer->error = XS_SHORTSENSE;
                         sc_xfer->sense.atapi_sense = chp->ch_error;                          sc_xfer->sense.atapi_sense = chp->ch_error;
                 } else {                  } else {
                           if (xfer->c_flags & C_DMA)
                                   ata_dmaerr(drvp);
                         sc_xfer->error = XS_RESET;                          sc_xfer->error = XS_RESET;
                         wdc_atapi_reset(chp, xfer);                          wdc_atapi_reset(chp, xfer);
                         return (1);                          return (1);
Line 699  again:
Line 724  again:
             WDSD_IBM | (xfer->drive << 4));              WDSD_IBM | (xfer->drive << 4));
         switch (drvp->state) {          switch (drvp->state) {
         case PIOMODE:          case PIOMODE:
   piomode:
                 /* Don't try to set mode if controller can't be adjusted */                  /* Don't try to set mode if controller can't be adjusted */
                 if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)                  if ((chp->wdc->cap & WDC_CAPABILITY_MODE) == 0)
                         goto ready;                          goto ready;
Line 713  again:
Line 739  again:
                 errstring = "piomode";                  errstring = "piomode";
                 if (wait_for_unbusy(chp, delay))                  if (wait_for_unbusy(chp, delay))
                         goto timeout;                          goto timeout;
                 if (chp->ch_status & WDCS_ERR)                  if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
                         goto error;                          chp->wdc->irqack(chp);
                   if (chp->ch_status & WDCS_ERR) {
                           if (drvp->PIO_mode < 3) {
                                   drvp->PIO_mode = 3;
                                   goto piomode;
                           } else {
                                   goto error;
                           }
                   }
         /* fall through */          /* fall through */
   
         case DMAMODE:          case DMAMODE:
Line 733  again:
Line 767  again:
                 errstring = "dmamode";                  errstring = "dmamode";
                 if (wait_for_unbusy(chp, delay))                  if (wait_for_unbusy(chp, delay))
                         goto timeout;                          goto timeout;
                   if (chp->wdc->cap & WDC_CAPABILITY_IRQACK)
                           chp->wdc->irqack(chp);
                 if (chp->ch_status & WDCS_ERR)                  if (chp->ch_status & WDCS_ERR)
                         goto error;                          goto error;
         /* fall through */          /* fall through */
Line 741  again:
Line 777  again:
         ready:          ready:
                 drvp->state = READY;                  drvp->state = READY;
                 xfer->c_intr = wdc_atapi_intr;                  xfer->c_intr = wdc_atapi_intr;
                   untimeout(wdctimeout, chp);
                 wdc_atapi_start(chp, xfer);                  wdc_atapi_start(chp, xfer);
                 return 1;                  return 1;
         }          }
         if ((sc_xfer->flags & SCSI_POLL) == 0) {          if ((sc_xfer->flags & SCSI_POLL) == 0) {
                 chp->ch_flags |= WDCF_IRQ_WAIT;                  chp->ch_flags |= WDCF_IRQ_WAIT;
                 xfer->c_intr = wdc_atapi_ctrl;                  xfer->c_intr = wdc_atapi_ctrl;
                 timeout(wdctimeout, chp, sc_xfer->timeout * hz / 1000);  
         } else {          } else {
                 goto again;                  goto again;
         }          }
Line 779  wdc_atapi_done(chp, xfer)
Line 815  wdc_atapi_done(chp, xfer)
         struct wdc_xfer *xfer;          struct wdc_xfer *xfer;
 {  {
         struct scsipi_xfer *sc_xfer = xfer->cmd;          struct scsipi_xfer *sc_xfer = xfer->cmd;
         int need_done =  xfer->c_flags & C_NEEDDONE;  
         struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive];  
   
         WDCDEBUG_PRINT(("wdc_atapi_done %s:%d:%d: flags 0x%x\n",          WDCDEBUG_PRINT(("wdc_atapi_done %s:%d:%d: flags 0x%x\n",
             chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,              chp->wdc->sc_dev.dv_xname, chp->channel, xfer->drive,
             (u_int)xfer->c_flags), DEBUG_XFERS);              (u_int)xfer->c_flags), DEBUG_XFERS);
         sc_xfer->resid = xfer->c_bcount;          untimeout(wdctimeout, chp);
         /* remove this command from xfer queue */          /* remove this command from xfer queue */
         xfer->c_skip = 0;  
         wdc_free_xfer(chp, xfer);          wdc_free_xfer(chp, xfer);
         sc_xfer->flags |= ITSDONE;          sc_xfer->flags |= ITSDONE;
         if (drvp->n_dmaerrs ||  
           (sc_xfer->error != XS_NOERROR && sc_xfer->error != XS_SENSE &&  
           sc_xfer->error != XS_SHORTSENSE)) {  
                 drvp->n_dmaerrs = 0;  
                 wdc_downgrade_mode(drvp);  
         }  
   
         if (need_done) {          WDCDEBUG_PRINT(("wdc_atapi_done: scsipi_done\n"), DEBUG_XFERS);
                 WDCDEBUG_PRINT(("wdc_atapi_done: scsipi_done\n"), DEBUG_XFERS);          scsipi_done(sc_xfer);
                 scsipi_done(sc_xfer);  
         }  
         WDCDEBUG_PRINT(("wdcstart from wdc_atapi_done, flags 0x%x\n",          WDCDEBUG_PRINT(("wdcstart from wdc_atapi_done, flags 0x%x\n",
             chp->ch_flags), DEBUG_XFERS);              chp->ch_flags), DEBUG_XFERS);
         wdcstart(chp);          wdcstart(chp);

Legend:
Removed from v.1.20  
changed lines
  Added in v.1.20.2.6

CVSweb <webmaster@jp.NetBSD.org>