BSD 4_4_Lite1 release
[unix-history] / usr / src / sys / pmax / dev / asc.c
index a59a5f9..4b36ea1 100644 (file)
@@ -1,13 +1,39 @@
 /*-
 /*-
- * Copyright (c) 1992 The Regents of the University of California.
- * All rights reserved.
+ * Copyright (c) 1992, 1993
+ *     The Regents of the University of California.  All rights reserved.
  *
  * This code is derived from software contributed to Berkeley by
  * Ralph Campbell and Rick Macklem.
  *
  *
  * This code is derived from software contributed to Berkeley by
  * Ralph Campbell and Rick Macklem.
  *
- * %sccs.include.redist.c%
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ *    must display the following acknowledgement:
+ *     This product includes software developed by the University of
+ *     California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
  *
  *
- *     @(#)asc.c       7.9 (Berkeley) %G%
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *     @(#)asc.c       8.2 (Berkeley) 1/4/94
  */
 
 /* 
  */
 
 /* 
@@ -163,12 +189,13 @@ int       asc_debug = 1;
 int    asc_debug_cmd;
 int    asc_debug_bn;
 int    asc_debug_sz;
 int    asc_debug_cmd;
 int    asc_debug_bn;
 int    asc_debug_sz;
-#define NLOG 16
+#define NLOG 32
 struct asc_log {
        u_int   status;
        u_char  state;
        u_char  msg;
        int     target;
 struct asc_log {
        u_int   status;
        u_char  state;
        u_char  msg;
        int     target;
+       int     resid;
 } asc_log[NLOG], *asc_logp = asc_log;
 #define PACK(unit, status, ss, ir) \
        ((unit << 24) | (status << 16) | (ss << 8) | ir)
 } asc_log[NLOG], *asc_logp = asc_log;
 #define PACK(unit, status, ss, ir) \
        ((unit << 24) | (status << 16) | (ss << 8) | ir)
@@ -195,7 +222,7 @@ typedef struct script {
 } script_t;
 
 /* Matching on the condition value */
 } script_t;
 
 /* Matching on the condition value */
-#define        SCRIPT_MATCH(ir, csr)           ((ir) | (ASC_PHASE(csr) << 8))
+#define        SCRIPT_MATCH(ir, csr)           ((ir) | (((csr) & 0x67) << 8))
 
 /* forward decls of script actions */
 static int script_nop();               /* when nothing needed */
 
 /* forward decls of script actions */
 static int script_nop();               /* when nothing needed */
@@ -244,7 +271,7 @@ script_t asc_scripts[] = {
                asc_last_dma_in, ASC_CMD_I_COMPLETE,
                &asc_scripts[SCRIPT_GET_STATUS]},
 
                asc_last_dma_in, ASC_CMD_I_COMPLETE,
                &asc_scripts[SCRIPT_GET_STATUS]},
 
-       /* continue data in after a chuck is finished */
+       /* continue data in after a chunk is finished */
        {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),                     /*  2 */
                asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
                &asc_scripts[SCRIPT_DATA_IN + 1]},
        {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAI),                     /*  2 */
                asc_dma_in, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
                &asc_scripts[SCRIPT_DATA_IN + 1]},
@@ -257,7 +284,7 @@ script_t asc_scripts[] = {
                asc_last_dma_out, ASC_CMD_I_COMPLETE,
                &asc_scripts[SCRIPT_GET_STATUS]},
 
                asc_last_dma_out, ASC_CMD_I_COMPLETE,
                &asc_scripts[SCRIPT_GET_STATUS]},
 
-       /* continue data out after a chuck is finished */
+       /* continue data out after a chunk is finished */
        {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),                     /*  5 */
                asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
                &asc_scripts[SCRIPT_DATA_OUT + 1]},
        {SCRIPT_MATCH(ASC_INT_BS, ASC_PHASE_DATAO),                     /*  5 */
                asc_dma_out, ASC_CMD_XFER_INFO | ASC_CMD_DMA,
                &asc_scripts[SCRIPT_DATA_OUT + 1]},
@@ -364,6 +391,7 @@ typedef struct scsi_state {
 #define DMA_OUT                0x10    /* true if writing to SCSI device */
 #define DID_SYNC       0x20    /* true if synchronous offset was negotiated */
 #define TRY_SYNC       0x40    /* true if try neg. synchronous offset */
 #define DMA_OUT                0x10    /* true if writing to SCSI device */
 #define DID_SYNC       0x20    /* true if synchronous offset was negotiated */
 #define TRY_SYNC       0x40    /* true if try neg. synchronous offset */
+#define PARITY_ERR     0x80    /* true if parity error seen */
 
 /*
  * State kept for each active SCSI host interface (53C94).
 
 /*
  * State kept for each active SCSI host interface (53C94).
@@ -628,19 +656,12 @@ asc_startcmd(asc, target)
        regs = asc->regs;
 
        /*
        regs = asc->regs;
 
        /*
-        * Check to see if a reselection is in progress and if so,
-        * try to cancel it or respond to the reselection if it won.
+        * If a reselection is in progress, it is Ok to ignore it since
+        * the ASC will automatically cancel the command and flush
+        * the FIFO if the ASC is reselected before the command starts.
+        * If we try to use ASC_CMD_DISABLE_SEL, we can hang the system if
+        * a reselect occurs before starting the command.
         */
         */
-       if (asc->state == ASC_STATE_RESEL) {
-               regs->asc_cmd = ASC_CMD_DISABLE_SEL;
-               readback(regs->asc_cmd);
-               while (!(regs->asc_status & ASC_CSR_INT))
-                       DELAY(1);
-               asc_intr(asc - asc_softc);
-               /* we will be busy if a reselecting device won */
-               if (asc->state == ASC_STATE_BUSY)
-                       return;
-       }
 
        asc->state = ASC_STATE_BUSY;
        asc->target = target;
 
        asc->state = ASC_STATE_BUSY;
        asc->target = target;
@@ -655,28 +676,11 @@ asc_startcmd(asc, target)
                        scsicmd->sd->sd_driver->d_name, target,
                        scsicmd->cmd[0], scsicmd->buflen);
        }
                        scsicmd->sd->sd_driver->d_name, target,
                        scsicmd->cmd[0], scsicmd->buflen);
        }
-       asc_debug_cmd = scsicmd->cmd[0];
-       if (scsicmd->cmd[0] == SCSI_READ_EXT) {
-               asc_debug_bn = (scsicmd->cmd[2] << 24) |
-                       (scsicmd->cmd[3] << 16) |
-                       (scsicmd->cmd[4] << 8) |
-                       scsicmd->cmd[5];
-               asc_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8];
-       }
-       asc_logp->status = PACK(asc - asc_softc, 0, 0, asc_debug_cmd);
-       asc_logp->target = asc->target;
-       asc_logp->state = 0;
-       asc_logp->msg = 0xff;
-       if (++asc_logp >= &asc_log[NLOG])
-               asc_logp = asc_log;
 #endif
 
        /*
         * Init the chip and target state.
         */
 #endif
 
        /*
         * Init the chip and target state.
         */
-       regs->asc_cmd = ASC_CMD_FLUSH;
-       readback(regs->asc_cmd);
-       DELAY(2);
        state->flags = state->flags & DID_SYNC;
        state->error = 0;
        state->script = (script_t *)0;
        state->flags = state->flags & DID_SYNC;
        state->error = 0;
        state->script = (script_t *)0;
@@ -709,11 +713,29 @@ asc_startcmd(asc, target)
                state->flags |= DMA_IN;
        }
 
                state->flags |= DMA_IN;
        }
 
+#ifdef DEBUG
+       asc_debug_cmd = scsicmd->cmd[0];
+       if (scsicmd->cmd[0] == SCSI_READ_EXT) {
+               asc_debug_bn = (scsicmd->cmd[2] << 24) |
+                       (scsicmd->cmd[3] << 16) |
+                       (scsicmd->cmd[4] << 8) |
+                       scsicmd->cmd[5];
+               asc_debug_sz = (scsicmd->cmd[7] << 8) | scsicmd->cmd[8];
+       }
+       asc_logp->status = PACK(asc - asc_softc, 0, 0, asc_debug_cmd);
+       asc_logp->target = asc->target;
+       asc_logp->state = asc->script - asc_scripts;
+       asc_logp->msg = SCSI_DIS_REC_IDENTIFY;
+       asc_logp->resid = scsicmd->buflen;
+       if (++asc_logp >= &asc_log[NLOG])
+               asc_logp = asc_log;
+#endif
+
        /* preload the FIFO with the message to be sent */
        regs->asc_fifo = SCSI_DIS_REC_IDENTIFY;
        MachEmptyWriteBuffer();
 
        /* preload the FIFO with the message to be sent */
        regs->asc_fifo = SCSI_DIS_REC_IDENTIFY;
        MachEmptyWriteBuffer();
 
-       /* start the asc */
+       /* initialize the DMA */
        (*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);
        ASC_TC_PUT(regs, len);
        readback(regs->asc_cmd);
        (*asc->dma_start)(asc, state, state->dmaBufAddr, ASCDMA_WRITE);
        ASC_TC_PUT(regs, len);
        readback(regs->asc_cmd);
@@ -762,6 +784,7 @@ again:
        asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1;
        asc_logp->state = scpt - asc_scripts;
        asc_logp->msg = -1;
        asc_logp->target = (asc->state == ASC_STATE_BUSY) ? asc->target : -1;
        asc_logp->state = scpt - asc_scripts;
        asc_logp->msg = -1;
+       asc_logp->resid = 0;
        if (++asc_logp >= &asc_log[NLOG])
                asc_logp = asc_log;
        if (asc_debug > 2)
        if (++asc_logp >= &asc_log[NLOG])
                asc_logp = asc_log;
        if (asc_debug > 2)
@@ -782,6 +805,27 @@ again:
                goto done;
        }
 
                goto done;
        }
 
+       /*
+        * Check for parity error.
+        * Hardware will automatically set ATN
+        * to request the device for a MSG_OUT phase.
+        */
+       if (status & ASC_CSR_PE) {
+               printf("asc%d: SCSI device %d: incomming parity error seen\n",
+                       asc - asc_softc, asc->target);
+               asc->st[asc->target].flags |= PARITY_ERR;
+       }
+
+       /*
+        * Check for gross error.
+        * Probably a bug in a device driver.
+        */
+       if (status & ASC_CSR_GE) {
+               printf("asc%d: SCSI device %d: gross error\n",
+                       asc - asc_softc, asc->target);
+               goto abort;
+       }
+
        /* check for message in or out */
        if ((ir & ~ASC_INT_FC) == ASC_INT_BS) {
                register int len, fifo;
        /* check for message in or out */
        if ((ir & ~ASC_INT_FC) == ASC_INT_BS) {
                register int len, fifo;
@@ -800,8 +844,19 @@ again:
                        break;
 
                case ASC_PHASE_MSG_OUT:
                        break;
 
                case ASC_PHASE_MSG_OUT:
+                       /*
+                        * Check for parity error.
+                        * Hardware will automatically set ATN
+                        * to request the device for a MSG_OUT phase.
+                        */
+                       if (state->flags & PARITY_ERR) {
+                               state->flags &= ~PARITY_ERR;
+                               state->msg_out = SCSI_MESSAGE_PARITY_ERROR;
+                               /* reset message in counter */
+                               state->msglen = 0;
+                       } else
+                               state->msg_out = SCSI_NO_OP;
                        regs->asc_fifo = state->msg_out;
                        regs->asc_fifo = state->msg_out;
-                       state->msg_out = SCSI_NO_OP;
                        regs->asc_cmd = ASC_CMD_XFER_INFO;
                        readback(regs->asc_cmd);
                        goto done;
                        regs->asc_cmd = ASC_CMD_XFER_INFO;
                        readback(regs->asc_cmd);
                        goto done;
@@ -841,63 +896,86 @@ again:
                                        state->dmalen, len, fifo); /* XXX */
                        regs->asc_cmd = ASC_CMD_FLUSH;
                        readback(regs->asc_cmd);
                                        state->dmalen, len, fifo); /* XXX */
                        regs->asc_cmd = ASC_CMD_FLUSH;
                        readback(regs->asc_cmd);
-                       MachEmptyWriteBuffer();
                        DELAY(2);
                }
                        DELAY(2);
                }
-               if (len) {
+               if (len && (state->flags & DMA_IN_PROGRESS)) {
                        /* save number of bytes still to be sent or received */
                        state->dmaresid = len;
                        /* save number of bytes still to be sent or received */
                        state->dmaresid = len;
+                       state->flags &= ~DMA_IN_PROGRESS;
+#ifdef DEBUG
+                       if (asc_logp == asc_log)
+                               asc_log[NLOG - 1].resid = len;
+                       else
+                               asc_logp[-1].resid = len;
+#endif
                        /* setup state to resume to */
                        /* setup state to resume to */
-                       if (state->flags & DMA_IN)
+                       if (state->flags & DMA_IN) {
+                               /*
+                                * Since the ASC_CNFG3_SRB bit of the
+                                * cnfg3 register bit is not set,
+                                * we just transferred an extra byte.
+                                * Since we can't resume on an odd byte
+                                * boundary, we copy the valid data out
+                                * and resume DMA at the start address.
+                                */
+                               if (len & 1) {
+                                       printf("asc_intr: msg in len %d (fifo %d)\n",
+                                               len, fifo); /* XXX */
+                                       len = state->dmalen - len;
+                                       goto do_in;
+                               }
                                state->script =
                                        &asc_scripts[SCRIPT_RESUME_DMA_IN];
                                state->script =
                                        &asc_scripts[SCRIPT_RESUME_DMA_IN];
-                       else if (state->flags & DMA_OUT)
+                       else if (state->flags & DMA_OUT)
                                state->script =
                                        &asc_scripts[SCRIPT_RESUME_DMA_OUT];
                        else
                                state->script = asc->script;
                                state->script =
                                        &asc_scripts[SCRIPT_RESUME_DMA_OUT];
                        else
                                state->script = asc->script;
-               } else {
+               } else if (state->flags & DMA_IN) {
+                       if (len)
+                               printf("asc_intr: 1: len %d (fifo %d)\n", len,
+                                       fifo); /* XXX */
                        /* setup state to resume to */
                        /* setup state to resume to */
-                       if (state->flags & DMA_IN) {
-                               if (state->flags & DMA_IN_PROGRESS) {
-                                       state->flags &= ~DMA_IN_PROGRESS;
-                                       (*asc->dma_end)(asc, state, ASCDMA_READ);
-                                       len = state->dmalen;
-                                       bcopy(state->dmaBufAddr, state->buf,
-                                               len);
-                                       state->buf += len;
-                                       state->buflen -= len;
-                               }
-                               if (state->buflen)
-                                       state->script =
-                                           &asc_scripts[SCRIPT_RESUME_IN];
-                               else
-                                       state->script =
-                                           &asc_scripts[SCRIPT_RESUME_NO_DATA];
-                       } else if (state->flags & DMA_OUT) {
-                               /*
-                                * If this is the last chunk, the next expected
-                                * state is to get status.
-                                */
-                               if (state->flags & DMA_IN_PROGRESS) {
-                                       state->flags &= ~DMA_IN_PROGRESS;
-                                       (*asc->dma_end)(asc, state, ASCDMA_WRITE);
-                                       len = state->dmalen;
-                                       state->buf += len;
-                                       state->buflen -= len;
-                               }
-                               if (state->buflen)
-                                       state->script =
-                                           &asc_scripts[SCRIPT_RESUME_OUT];
-                               else
-                                       state->script =
-                                           &asc_scripts[SCRIPT_RESUME_NO_DATA];
-                       } else if (asc->script == &asc_scripts[SCRIPT_SIMPLE])
+                       if (state->flags & DMA_IN_PROGRESS) {
+                               len = state->dmalen;
+                               state->flags &= ~DMA_IN_PROGRESS;
+                       do_in:
+                               (*asc->dma_end)(asc, state, ASCDMA_READ);
+                               bcopy(state->dmaBufAddr, state->buf, len);
+                               state->buf += len;
+                               state->buflen -= len;
+                       }
+                       if (state->buflen)
                                state->script =
                                state->script =
-                                           &asc_scripts[SCRIPT_RESUME_NO_DATA];
+                                   &asc_scripts[SCRIPT_RESUME_IN];
                        else
                        else
-                               state->script = asc->script;
-               }
+                               state->script =
+                                   &asc_scripts[SCRIPT_RESUME_NO_DATA];
+               } else if (state->flags & DMA_OUT) {
+                       if (len)
+                               printf("asc_intr: 2: len %d (fifo %d)\n", len,
+                                       fifo); /* XXX */
+                       /*
+                        * If this is the last chunk, the next expected
+                        * state is to get status.
+                        */
+                       if (state->flags & DMA_IN_PROGRESS) {
+                               state->flags &= ~DMA_IN_PROGRESS;
+                               (*asc->dma_end)(asc, state, ASCDMA_WRITE);
+                               len = state->dmalen;
+                               state->buf += len;
+                               state->buflen -= len;
+                       }
+                       if (state->buflen)
+                               state->script =
+                                   &asc_scripts[SCRIPT_RESUME_OUT];
+                       else
+                               state->script =
+                                   &asc_scripts[SCRIPT_RESUME_NO_DATA];
+               } else if (asc->script == &asc_scripts[SCRIPT_SIMPLE])
+                       state->script = &asc_scripts[SCRIPT_RESUME_NO_DATA];
+               else
+                       state->script = asc->script;
 
                /* setup to receive a message */
                asc->script = &asc_scripts[SCRIPT_MSG_IN];
 
                /* setup to receive a message */
                asc->script = &asc_scripts[SCRIPT_MSG_IN];
@@ -937,11 +1015,25 @@ again:
                state = &asc->st[asc->target];
                switch (ASC_SS(ss)) {
                case 0: /* device did not respond */
                state = &asc->st[asc->target];
                switch (ASC_SS(ss)) {
                case 0: /* device did not respond */
-                       state->error = ENXIO;
-                       asc_end(asc, status, ss, ir);
-                       return;
+                       /* check for one of the starting scripts */
+                       switch (asc->script - asc_scripts) {
+                       case SCRIPT_TRY_SYNC:
+                       case SCRIPT_SIMPLE:
+                       case SCRIPT_DATA_IN:
+                       case SCRIPT_DATA_OUT:
+                               if (regs->asc_flags & ASC_FLAGS_FIFO_CNT) {
+                                       regs->asc_cmd = ASC_CMD_FLUSH;
+                                       readback(regs->asc_cmd);
+                               }
+                               state->error = ENXIO;
+                               asc_end(asc, status, ss, ir);
+                               return;
+                       }
+                       /* FALLTHROUGH */
 
                default:
 
                default:
+                       printf("asc%d: SCSI device %d: unexpected disconnect\n",
+                               asc - asc_softc, asc->target);
                        /*
                         * On rare occasions my RZ24 does a disconnect during
                         * data in phase and the following seems to keep it
                        /*
                         * On rare occasions my RZ24 does a disconnect during
                         * data in phase and the following seems to keep it
@@ -976,8 +1068,6 @@ again:
                else
                        asc_logp[-1].msg = msg;
 #endif
                else
                        asc_logp[-1].msg = msg;
 #endif
-               if (asc->state != ASC_STATE_RESEL)
-                       goto abort;
                asc->state = ASC_STATE_BUSY;
                asc->target = id;
                state = &asc->st[id];
                asc->state = ASC_STATE_BUSY;
                asc->target = id;
                state = &asc->st[id];
@@ -997,7 +1087,11 @@ again:
        if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN))
                goto abort;
 
        if (ir & (ASC_INT_SEL | ASC_INT_SEL_ATN))
                goto abort;
 
-       /* must be just a ASC_INT_FC */
+       /*
+        * 'ir' must be just ASC_INT_FC.
+        * This is normal if canceling an ASC_ENABLE_SEL.
+        */
+
 done:
        MachEmptyWriteBuffer();
        /* watch out for HW race conditions and setup & hold time violations */
 done:
        MachEmptyWriteBuffer();
        /* watch out for HW race conditions and setup & hold time violations */
@@ -1047,6 +1141,7 @@ asc_get_status(asc, status, ss, ir)
         */
        if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) {
                printf("asc_get_status: fifo cnt %d\n", data); /* XXX */
         */
        if ((data = regs->asc_flags & ASC_FLAGS_FIFO_CNT) != 2) {
                printf("asc_get_status: fifo cnt %d\n", data); /* XXX */
+               asc_DumpLog("get_status"); /* XXX */
                if (data < 2) {
                        asc->regs->asc_cmd = ASC_CMD_MSG_ACPT;
                        readback(asc->regs->asc_cmd);
                if (data < 2) {
                        asc->regs->asc_cmd = ASC_CMD_MSG_ACPT;
                        readback(asc->regs->asc_cmd);
@@ -1118,7 +1213,11 @@ asc_end(asc, status, ss, ir)
                break;
        }
 
                break;
        }
 
-       /* look for another device that is ready */
+       /*
+        * Look for another device that is ready.
+        * May want to keep last one started and increment for fairness
+        * rather than always starting at zero.
+        */
        for (i = 0; i < ASC_NCMD; i++) {
                /* don't restart a disconnected command */
                if (!asc->cmd[i] || (asc->st[i].flags & DISCONN))
        for (i = 0; i < ASC_NCMD; i++) {
                /* don't restart a disconnected command */
                if (!asc->cmd[i] || (asc->st[i].flags & DISCONN))
@@ -1205,7 +1304,6 @@ asc_last_dma_in(asc, status, ss, ir)
                /* device must be trying to send more than we expect */
                regs->asc_cmd = ASC_CMD_FLUSH;
                readback(regs->asc_cmd);
                /* device must be trying to send more than we expect */
                regs->asc_cmd = ASC_CMD_FLUSH;
                readback(regs->asc_cmd);
-               MachEmptyWriteBuffer();
        }
        state->flags &= ~DMA_IN_PROGRESS;
        len = state->dmalen - len;
        }
        state->flags &= ~DMA_IN_PROGRESS;
        len = state->dmalen - len;
@@ -1309,7 +1407,7 @@ asc_dma_out(asc, status, ss, ir)
                state->buflen -= len;
        }
 
                state->buflen -= len;
        }
 
-       /* setup for this chunck */
+       /* setup for this chunk */
        len = state->buflen;
        if (len > state->dmaBufSize)
                len = state->dmaBufSize;
        len = state->buflen;
        if (len > state->dmaBufSize)
                len = state->dmaBufSize;
@@ -1354,7 +1452,8 @@ asc_last_dma_out(asc, status, ss, ir)
                len += fifo;
                regs->asc_cmd = ASC_CMD_FLUSH;
                readback(regs->asc_cmd);
                len += fifo;
                regs->asc_cmd = ASC_CMD_FLUSH;
                readback(regs->asc_cmd);
-               MachEmptyWriteBuffer();
+               printf("asc_last_dma_out: buflen %d dmalen %d tc %d fifo %d\n",
+                       state->buflen, state->dmalen, len, fifo);
        }
        state->flags &= ~DMA_IN_PROGRESS;
        len = state->dmalen - len;
        }
        state->flags &= ~DMA_IN_PROGRESS;
        len = state->dmalen - len;
@@ -1372,7 +1471,7 @@ asc_resume_out(asc, status, ss, ir)
        register State *state = &asc->st[asc->target];
        register int len;
 
        register State *state = &asc->st[asc->target];
        register int len;
 
-       /* setup for this chunck */
+       /* setup for this chunk */
        len = state->buflen;
        if (len > state->dmaBufSize)
                len = state->dmaBufSize;
        len = state->buflen;
        if (len > state->dmaBufSize)
                len = state->dmaBufSize;
@@ -1571,7 +1670,6 @@ asc_msg_in(asc, status, ss, ir)
                        if (!(state->flags & TRY_SYNC)) {
                                regs->asc_cmd = ASC_CMD_SET_ATN;
                                readback(regs->asc_cmd);
                        if (!(state->flags & TRY_SYNC)) {
                                regs->asc_cmd = ASC_CMD_SET_ATN;
                                readback(regs->asc_cmd);
-                               MachEmptyWriteBuffer();
 
                                if (state->sync_period < asc->min_period)
                                        state->sync_period =
 
                                if (state->sync_period < asc->min_period)
                                        state->sync_period =
@@ -1670,7 +1768,6 @@ asc_msg_in(asc, status, ss, ir)
                state->msg_out = SCSI_MESSAGE_REJECT;
                regs->asc_cmd = ASC_CMD_SET_ATN;
                readback(regs->asc_cmd);
                state->msg_out = SCSI_MESSAGE_REJECT;
                regs->asc_cmd = ASC_CMD_SET_ATN;
                readback(regs->asc_cmd);
-               MachEmptyWriteBuffer();
        }
 
 done:
        }
 
 done:
@@ -1697,14 +1794,20 @@ asc_disconnect(asc, status, ss, ir)
 {
        register State *state = &asc->st[asc->target];
 
 {
        register State *state = &asc->st[asc->target];
 
+#ifdef DIAGNOSTIC
+       if (!(state->flags & DISCONN)) {
+               printf("asc_disconnect: device %d: DISCONN not set!\n",
+                       asc->target);
+       }
+#endif
        asc->target = -1;
        asc->state = ASC_STATE_RESEL;
        return (1);
 }
 
 /*
        asc->target = -1;
        asc->state = ASC_STATE_RESEL;
        return (1);
 }
 
 /*
- * DMA handling routines. For a turbochannel device, just set the dmar
- * for the I/O ASIC, handle the actual DMA interface.
+ * DMA handling routines. For a turbochannel device, just set the dmar.
+ * For the I/O ASIC, handle the actual DMA interface.
  */
 static void
 tb_dma_start(asc, state, cp, flag)
  */
 static void
 tb_dma_start(asc, state, cp, flag)
@@ -1742,7 +1845,7 @@ asic_dma_start(asc, state, cp, flag)
 
        /* stop DMA engine first */
        *ssr &= ~ASIC_CSR_DMAEN_SCSI;
 
        /* stop DMA engine first */
        *ssr &= ~ASIC_CSR_DMAEN_SCSI;
-       * ((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0;
+       *((volatile int *)ASIC_REG_SCSI_SCR(asic_base)) = 0;
 
        phys = MACH_CACHED_TO_PHYS(cp);
        cp = (caddr_t)pmax_trunc_page(cp + NBPG);
 
        phys = MACH_CACHED_TO_PHYS(cp);
        cp = (caddr_t)pmax_trunc_page(cp + NBPG);
@@ -1770,10 +1873,15 @@ asic_dma_end(asc, state, flag)
 {
        register volatile u_int *ssr = (volatile u_int *)
                ASIC_REG_CSR(asic_base);
 {
        register volatile u_int *ssr = (volatile u_int *)
                ASIC_REG_CSR(asic_base);
+       register volatile u_int *dmap = (volatile u_int *)
+               ASIC_REG_SCSI_DMAPTR(asic_base);
+       register u_short *to;
+       register int w;
        int nb;
 
        *ssr &= ~ASIC_CSR_DMAEN_SCSI;
        int nb;
 
        *ssr &= ~ASIC_CSR_DMAEN_SCSI;
-       *((volatile int *)ASIC_REG_SCSI_DMAPTR(asic_base)) = -1;
+       to = (u_short *)MACH_PHYS_TO_CACHED(*dmap >> 3);
+       *dmap = -1;
        *((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1;
        MachEmptyWriteBuffer();
 
        *((volatile int *)ASIC_REG_SCSI_DMANPTR(asic_base)) = -1;
        MachEmptyWriteBuffer();
 
@@ -1782,11 +1890,8 @@ asic_dma_end(asc, state, flag)
                    MACH_UNCACHED_TO_PHYS(state->dmaBufAddr)), state->dmalen);
                if (nb = *((int *)ASIC_REG_SCSI_SCR(asic_base))) {
                        /* pick up last upto6 bytes, sigh. */
                    MACH_UNCACHED_TO_PHYS(state->dmaBufAddr)), state->dmalen);
                if (nb = *((int *)ASIC_REG_SCSI_SCR(asic_base))) {
                        /* pick up last upto6 bytes, sigh. */
-                       register u_short *to;
-                       register int w;
        
                        /* Last byte really xferred is.. */
        
                        /* Last byte really xferred is.. */
-                       to = (u_short *)(state->dmaBufAddr + state->dmalen - (nb << 1));
                        w = *(int *)ASIC_REG_SCSI_SDR0(asic_base);
                        *to++ = w;
                        if (--nb > 0) {
                        w = *(int *)ASIC_REG_SCSI_SDR0(asic_base);
                        *to++ = w;
                        if (--nb > 0) {
@@ -1835,12 +1940,10 @@ asc_DumpLog(str)
 
        printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,
                asc_debug_bn, asc_debug_sz);
 
        printf("asc: %s: cmd %x bn %d cnt %d\n", str, asc_debug_cmd,
                asc_debug_bn, asc_debug_sz);
-       lp = asc_logp + 1;
-       if (lp > &asc_log[NLOG])
-               lp = asc_log;
-       while (lp != asc_logp) {
+       lp = asc_logp;
+       do {
                status = lp->status;
                status = lp->status;
-               printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x\n",
+               printf("asc%d tgt %d status %x ss %x ir %x cond %d:%x msg %x resid %d\n",
                        status >> 24,
                        lp->target,
                        (status >> 16) & 0xFF,
                        status >> 24,
                        lp->target,
                        (status >> 16) & 0xFF,
@@ -1848,10 +1951,10 @@ asc_DumpLog(str)
                        status & 0XFF,
                        lp->state,
                        asc_scripts[lp->state].condition,
                        status & 0XFF,
                        lp->state,
                        asc_scripts[lp->state].condition,
-                       lp->msg);
+                       lp->msg, lp->resid);
                if (++lp >= &asc_log[NLOG])
                        lp = asc_log;
                if (++lp >= &asc_log[NLOG])
                        lp = asc_log;
-       }
+       } while (lp != asc_logp);
 }
 #endif
 
 }
 #endif