diff options
author | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 2000-08-09 07:43:15 +0000 |
---|---|---|
committer | Constantine Sapuntzakis <csapuntz@cvs.openbsd.org> | 2000-08-09 07:43:15 +0000 |
commit | a658de1be3bd4400df2c04c5fb4d0650235d7616 (patch) | |
tree | f304e1b9c21e375241046a897e722ce030344833 /sys | |
parent | 0584128e32cfdc5637a0fd8f73b21edd99c3b7fa (diff) |
Fixes for the BCD 48SB CD-ROM C2.4, which seems to like to drop
both DRQ and BSY.
The driver has been adjusted to ignore invalid/unexpected phases
while traversing the state machine.
This may break drives that do no set ireason correctly.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/atapiscsi/atapiscsi.c | 79 |
1 files changed, 57 insertions, 22 deletions
diff --git a/sys/dev/atapiscsi/atapiscsi.c b/sys/dev/atapiscsi/atapiscsi.c index 62edec6abe1..7ff1fbd557e 100644 --- a/sys/dev/atapiscsi/atapiscsi.c +++ b/sys/dev/atapiscsi/atapiscsi.c @@ -1,4 +1,4 @@ -/* $OpenBSD: atapiscsi.c,v 1.28 2000/07/20 07:40:33 csapuntz Exp $ */ +/* $OpenBSD: atapiscsi.c,v 1.29 2000/08/09 07:43:14 csapuntz Exp $ */ /* * This code is derived from code with the copyright below. @@ -66,7 +66,17 @@ #include <dev/ic/wdcreg.h> #include <dev/ic/wdcvar.h> -#include <dev/atapiscsi/atapiconf.h> +#include <scsi/scsiconf.h> + +/* drive states stored in ata_drive_datas */ +#define IDENTIFY 0 +#define IDENTIFY_WAIT 1 +#define PIOMODE 2 +#define PIOMODE_WAIT 3 +#define DMAMODE 4 +#define DMAMODE_WAIT 5 +#define READY 6 + #define WDCDEBUG @@ -930,11 +940,6 @@ wdc_atapi_intr_command(chp, xfer, timeout) wdc_output_bytes(drvp, cmd, cmdlen); - if (xfer->c_bcount == 0) - as->protocol_phase = as_completed; - else - as->protocol_phase = as_data; - /* Start the DMA channel if necessary */ if (xfer->c_flags & C_DMA) { (*chp->wdc->dma_start)(chp->wdc->dma_arg, @@ -942,6 +947,11 @@ wdc_atapi_intr_command(chp, xfer, timeout) dma_flags); } + if (xfer->c_bcount == 0) + as->protocol_phase = as_completed; + else + as->protocol_phase = as_data; + xfer->expect_irq = 1; /* If we read/write to a tape we will get into buffer @@ -1072,10 +1082,13 @@ wdc_atapi_intr_data(chp, xfer, timeout) xfer->c_skip += len; xfer->c_bcount -= len; } else { - /* Exceptional case */ + /* Exceptional case - drive want to transfer more + data than we have buffer for */ if (sc_xfer->flags & SCSI_DATA_OUT) { - printf("wdc_atapi_intr: warning: write only " - "%d of %d requested bytes\n", xfer->c_bcount, len); + /* Wouldn't it be better to just abort here rather + than to write random stuff to drive? */ + printf("wdc_atapi_intr: warning: device requesting " + "%d bytes, only %d left in buffer\n", len, xfer->c_bcount); wdc_output_bytes(drvp, (u_int8_t *)xfer->databuf + xfer->c_skip, xfer->c_bcount); @@ -1119,8 +1132,7 @@ wdc_atapi_intr_complete(chp, xfer, timeout) WDCDEBUG_PRINT(("PHASE_COMPLETED\n"), DEBUG_INTR); /* turn off DMA channel */ - if (as->protocol_phase == as_data && - 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); @@ -1223,9 +1235,10 @@ wdc_atapi_intr_for_us(chp, xfer, timeout) struct scsi_xfer *sc_xfer = xfer->cmd; struct ata_drive_datas *drvp = &chp->ch_drive[xfer->drive]; struct atapiscsi_softc *as = sc_xfer->sc_link->adapter_softc; - + u_int8_t ireason; +#if 0 WDCDEBUG_PRINT(("ATAPI_INTR\n"), DEBUG_INTR); - +#endif wdc_atapi_update_status(chp); if (timeout) { @@ -1249,27 +1262,49 @@ wdc_atapi_intr_for_us(chp, xfer, timeout) { CHP_WRITE_REG(chp, wdr_sdh, WDSD_IBM | (xfer->drive << 4)); delay (1); - + return (CONTINUE_POLL); } if (as->protocol_phase != as_cmdout && (xfer->c_flags & C_MEDIA_ACCESS) && - !(chp->ch_status & WDCS_DSC)) { + !(chp->ch_status & (WDCS_DSC | WDCS_DRQ))) { xfer->delay = 100; return (CONTINUE_POLL); } xfer->claim_irq = 1; - if (chp->ch_status & WDCS_DRQ) { - if (as->protocol_phase == as_cmdout) - return (wdc_atapi_intr_command(chp, xfer, timeout)); + ireason = CHP_READ_REG(chp, wdr_ireason); + WDCDEBUG_PRINT(("(%x, %x) ", chp->ch_status, ireason), DEBUG_INTR ); + + switch (as->protocol_phase) { + case as_cmdout: + if (!(chp->ch_status & WDCS_DRQ)) + return (CONTINUE_POLL); - return (wdc_atapi_intr_data(chp, xfer, timeout)); + return (wdc_atapi_intr_command(chp, xfer, timeout)); + + case as_data: + if ((chp->ch_status & WDCS_DRQ) || + (ireason & 3) != 3) + return (wdc_atapi_intr_data(chp, xfer, timeout)); + + case as_completed: + if ((chp->ch_status & WDCS_DRQ) || + (ireason & 3) != 3) { + xfer->delay = 100; + return (CONTINUE_POLL); + } + + return (wdc_atapi_intr_complete(chp, xfer, timeout)); + + default: + printf ("atapiscsi: Shouldn't get here\n"); + sc_xfer->error = XS_DRIVER_STUFFUP; + xfer->next = wdc_atapi_reset; + return (GOTO_NEXT); } - - return (wdc_atapi_intr_complete(chp, xfer, timeout)); } int |