summaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>2000-08-09 07:43:15 +0000
committerConstantine Sapuntzakis <csapuntz@cvs.openbsd.org>2000-08-09 07:43:15 +0000
commita658de1be3bd4400df2c04c5fb4d0650235d7616 (patch)
treef304e1b9c21e375241046a897e722ce030344833 /sys
parent0584128e32cfdc5637a0fd8f73b21edd99c3b7fa (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.c79
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