diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2001-01-10 17:17:53 +0000 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2001-01-10 17:17:53 +0000 |
commit | b2ad5f821b1381492d792ca10b1eb7a107b48f14 (patch) | |
tree | 954a648692e7da983db1d2470953705f6a729264 /drivers/scsi/scsiiom.c | |
parent | c9c06167e7933d93a6e396174c68abf242294abb (diff) |
Merge with Linux 2.4.0-prerelease. Big Makefile rewrite, test your
Makefiles.
Diffstat (limited to 'drivers/scsi/scsiiom.c')
-rw-r--r-- | drivers/scsi/scsiiom.c | 2934 |
1 files changed, 1558 insertions, 1376 deletions
diff --git a/drivers/scsi/scsiiom.c b/drivers/scsi/scsiiom.c index 3923cb8e4..5d0520234 100644 --- a/drivers/scsi/scsiiom.c +++ b/drivers/scsi/scsiiom.c @@ -4,159 +4,146 @@ * Description: Device Driver for Tekram DC-390 (T) PCI SCSI * * Bus Master Host Adapter * ***********************************************************************/ -/* $Id: scsiiom.c,v 2.15 1998/12/25 17:33:27 garloff Exp $ */ +/* $Id: scsiiom.c,v 2.55.2.17 2000/12/20 00:39:37 garloff Exp $ */ + +static void __inline__ +dc390_freetag (PDCB pDCB, PSRB pSRB) +{ + if (pSRB->TagNumber < 255) { + pDCB->TagMask &= ~(1 << pSRB->TagNumber); /* free tag mask */ + pSRB->TagNumber = 255; + } +}; + UCHAR -dc390_StartSCSI(PACB pACB, PDCB pDCB, PSRB pSRB) +dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ) { - USHORT wlval; - UCHAR bval, bval1; - - pSRB->TagNumber = 31; - DC390_write8(Scsi_Dest_ID, pDCB->UnitSCSIID); - DC390_write8(Sync_Period, pDCB->SyncPeriod); - DC390_write8(Sync_Offset, pDCB->SyncOffset); - DC390_write8(CtrlReg1, pDCB->CtrlR1); - DC390_write8(CtrlReg3, pDCB->CtrlR3); - DC390_write8(CtrlReg4, pDCB->CtrlR4); - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); /* Flush FIFO */ - DEBUG1(printk(KERN_INFO "DC390: Start SCSI command: %02x (Sync:%02x)\n", \ - pSRB->CmdBlock[0], pDCB->SyncMode); - ) - pSRB->ScsiPhase = SCSI_NOP0; - //pSRB->MsgOutBuf[0] = MSG_NOP; - //pSRB->MsgCnt = 0; - bval = pDCB->IdentifyMsg; - if (!(pDCB->SyncMode & EN_ATN_STOP)) { /* Don't always try send Extended messages on arbitration */ - if ((pSRB->CmdBlock[0] == INQUIRY) || - (pSRB->CmdBlock[0] == REQUEST_SENSE) || - (pSRB->SRBFlag & AUTO_REQSENSE)) { - bval &= 0xBF; /* No DisConn */ - DC390_write8(ScsiFifo, bval); - bval1 = SEL_W_ATN; - pSRB->SRBState = SRB_START_; - DEBUG1(printk(KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1); - ) - if (pDCB->SyncMode & SYNC_ENABLE) { - if (!(pDCB->IdentifyMsg & 7) || /* LUN == 0 || Cmd != INQUIRY */ - (pSRB->CmdBlock[0] != INQUIRY)) { - bval1 = SEL_W_ATN_STOP; /* Try to establish SYNC nego */ - pSRB->SRBState = SRB_MSGOUT; - } - } - } else { /* TagQ ? */ - DC390_write8(ScsiFifo, bval); - if (pDCB->SyncMode & EN_TAG_QUEUEING) { - DC390_write8(ScsiFifo, MSG_SIMPLE_QTAG); - DEBUG1(printk(KERN_DEBUG "DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval & 0x40 ? "" : "No "), bval, SEL_W_ATN3, pDCB->TagMask); - ) - bval = 0; - wlval = 1; - while (wlval & pDCB->TagMask) { - bval++; - wlval <<= 1; - }; - pDCB->TagMask |= wlval; - DC390_write8(ScsiFifo, bval); - pSRB->TagNumber = bval; - DEBUG1(printk(KERN_DEBUG "DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval); - ) - bval1 = SEL_W_ATN3; - pSRB->SRBState = SRB_START_; - } else { /* No TagQ */ - bval1 = SEL_W_ATN; - DEBUG1(printk(KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval & 0x40 ? "" : "No "), bval, bval1, pDCB->TagMask); - ) - pSRB->SRBState = SRB_START_; - } - } + UCHAR cmd; UCHAR disc_allowed, try_sync_nego; - } else { /* ATN_STOP: Always try to establish Sync nego */ - if ((pSRB->CmdBlock[0] == INQUIRY) || - (pSRB->CmdBlock[0] == REQUEST_SENSE) || - (pSRB->SRBFlag & AUTO_REQSENSE)) { - bval &= 0xBF; /* No DisConn */ - DC390_write8(ScsiFifo, bval); - bval1 = SEL_W_ATN; - DEBUG1(printk(KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1); - ) - pSRB->SRBState = SRB_START_; - /* ??? */ - if (pDCB->SyncMode & SYNC_ENABLE) { - if (!(pDCB->IdentifyMsg & 7) || /* LUN == 0 || Cmd != INQUIRY */ - (pSRB->CmdBlock[0] != INQUIRY)) { - bval1 = SEL_W_ATN_STOP; /* Try to establish Sync nego */ - pSRB->SRBState = SRB_MSGOUT; - } - } - } else { /* TagQ ? */ - DC390_write8(ScsiFifo, bval); - if (pDCB->SyncMode & EN_TAG_QUEUEING) { - pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG; - DEBUG1(printk(KERN_DEBUG "DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval & 0x40 ? "" : "No "), bval, SEL_W_ATN_STOP, pDCB->TagMask); - ) - bval = 0; - wlval = 1; - while (wlval & pDCB->TagMask) { - bval++; - wlval <<= 1; - }; - pDCB->TagMask |= wlval; - pSRB->TagNumber = bval; - DEBUG1(printk(KERN_DEBUG "DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval); - ) - pSRB->MsgOutBuf[1] = bval; - pSRB->MsgCnt = 2; - bval1 = SEL_W_ATN_STOP; - pSRB->SRBState = SRB_START_; /* ?? */ - } else { /* No TagQ */ - pSRB->MsgOutBuf[0] = MSG_NOP; - pSRB->MsgCnt = 1; - pSRB->SRBState = SRB_START_; - bval1 = SEL_W_ATN_STOP; - DEBUG1(printk(KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval & 0x40 ? "" : "No "), bval, bval1, pDCB->TagMask); - ) - }; - } - } - if (bval1 != SEL_W_ATN_STOP) { /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */ - if (pSRB->SRBFlag & AUTO_REQSENSE) { - bval = 0; - DC390_write8(ScsiFifo, REQUEST_SENSE); - DC390_write8(ScsiFifo, pDCB->IdentifyMsg << 5); - DC390_write8(ScsiFifo, bval); - DC390_write8(ScsiFifo, bval); - DC390_write8(ScsiFifo, sizeof(pSRB->pcmd->sense_buffer)); - DC390_write8(ScsiFifo, bval); - DEBUG1(printk(KERN_DEBUG "DC390: AutoReqSense !\n"); - ) - } else { /* write cmnd to bus */ - PUCHAR ptr; - UCHAR i; - ptr = (PUCHAR) pSRB->CmdBlock; - for (i = 0; i < pSRB->ScsiCmdLen; i++) - DC390_write8(ScsiFifo, *(ptr++)); - }; - } - /* Check if we can't win arbitration */ - if (DC390_read8(Scsi_Status) & INTERRUPT) { - pSRB->SRBState = SRB_READY; - pDCB->TagMask &= ~(1 << pSRB->TagNumber); - DEBUG0(printk(KERN_WARNING "DC390: Interrupt during StartSCSI!\n"); - ) - return 1; - } else { - pSRB->ScsiPhase = SCSI_NOP1; - DEBUG0(if (pACB->pActiveDCB) \ - printk(KERN_WARNING "DC390: ActiveDCB != 0\n");) - DEBUG0(if (pDCB->pActiveSRB) \ - printk(KERN_WARNING "DC390: ActiveSRB != 0\n");) - pACB->pActiveDCB = pDCB; - pDCB->pActiveSRB = pSRB; - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); - DC390_write8(ScsiCmd, bval1); - return 0; - } + pSRB->ScsiPhase = SCSI_NOP0; + + if (pACB->Connected) + { + // Should not happen normally + printk (KERN_WARNING "DC390: Can't select when connected! (%08x,%02x)\n", + pSRB->SRBState, pSRB->SRBFlag); + pSRB->SRBState = SRB_READY; + pACB->SelConn++; + return 1; + } + if (time_before (jiffies, pACB->pScsiHost->last_reset)) + { + DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n");) + return 1; + } + DC390_write8 (Scsi_Dest_ID, pDCB->TargetID); + DC390_write8 (Sync_Period, pDCB->SyncPeriod); + DC390_write8 (Sync_Offset, pDCB->SyncOffset); + DC390_write8 (CtrlReg1, pDCB->CtrlR1); + DC390_write8 (CtrlReg3, pDCB->CtrlR3); + DC390_write8 (CtrlReg4, pDCB->CtrlR4); + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); /* Flush FIFO */ + DEBUG1(printk (KERN_INFO "DC390: Start SCSI command: %02x (Sync:%02x)\n",\ + pSRB->pcmd->cmnd[0], pDCB->SyncMode);) + disc_allowed = pDCB->DevMode & EN_DISCONNECT_; try_sync_nego = 0; + /* Don't disconnect on AUTO_REQSENSE, cause it might be an + * Contingent Allegiance Condition (6.6), where no tags should be used. + * All other have to be allowed to disconnect to prevent Incorrect + * Initiator Connection (6.8.2/6.5.2) */ + /* Changed KG, 99/06/06 */ + if( /*(((pSRB->pcmd->cmnd[0] == INQUIRY) || (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || + * (pSRB->pcmd->cmnd[0] == TEST_UNIT_READY)) && pACB->scan_devices) + ||*/ (pSRB->SRBFlag & AUTO_REQSENSE) ) + disc_allowed = 0; + if ( (pDCB->SyncMode & SYNC_ENABLE) && (pDCB->TargetLUN == 0) && (pDCB->Inquiry7 & 0x10) && + ( ( ( (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || (pSRB->SRBFlag & AUTO_REQSENSE) ) + && !(pDCB->SyncMode & SYNC_NEGO_DONE) ) || (pSRB->pcmd->cmnd[0] == INQUIRY) ) ) + try_sync_nego = 1; + + pSRB->MsgCnt = 0; cmd = SEL_W_ATN; + DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->TargetLUN)); + /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */ + if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed) + { + UCHAR tag_no = 0; + while ((1 << tag_no) & pDCB->TagMask) tag_no++; + if (tag_no >= sizeof (pDCB->TagMask)*8 || tag_no >= pDCB->MaxCommand) { + printk (KERN_WARNING "DC390: Out of tags for Dev. %02x %02x\n", pDCB->TargetID, pDCB->TargetLUN); + return 1; + //goto no_tag; + }; + DC390_write8 (ScsiFifo, SIMPLE_QUEUE_TAG); + pDCB->TagMask |= (1 << tag_no); pSRB->TagNumber = tag_no; + DC390_write8 (ScsiFifo, tag_no); + DEBUG1(printk (KERN_DEBUG "DC390: Select w/DisCn for Cmd %li (SRB %p), Using Tag %02x\n", pSRB->pcmd->pid, pSRB, tag_no);) + cmd = SEL_W_ATN3; + } + else /* No TagQ */ + { +// no_tag: + DEBUG1(printk (KERN_DEBUG "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", (disc_allowed?"":"o"), pSRB->pcmd->pid, pSRB);) + }; + + pSRB->SRBState = SRB_START_; + + if (try_sync_nego) + { + UCHAR Sync_Off = pDCB->SyncOffset; + DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);) + pSRB->MsgOutBuf[0] = EXTENDED_MESSAGE; + pSRB->MsgOutBuf[1] = 3; + pSRB->MsgOutBuf[2] = EXTENDED_SDTR; + pSRB->MsgOutBuf[3] = pDCB->NegoPeriod; + if (!(Sync_Off & 0x0f)) Sync_Off = SYNC_NEGO_OFFSET; + pSRB->MsgOutBuf[4] = Sync_Off; + pSRB->MsgCnt = 5; + //pSRB->SRBState = SRB_MSGOUT_; + pSRB->SRBState |= DO_SYNC_NEGO; + cmd = SEL_W_ATN_STOP; + }; + + /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */ + if (cmd != SEL_W_ATN_STOP) + { + if( pSRB->SRBFlag & AUTO_REQSENSE ) + { + DC390_write8 (ScsiFifo, REQUEST_SENSE); + DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5); + DC390_write8 (ScsiFifo, 0); + DC390_write8 (ScsiFifo, 0); + DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer)); + DC390_write8 (ScsiFifo, 0); + DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n");) + } + else /* write cmnd to bus */ + { + PUCHAR ptr; UCHAR i; + ptr = (PUCHAR) pSRB->pcmd->cmnd; + for (i=0; i<pSRB->pcmd->cmd_len; i++) + DC390_write8 (ScsiFifo, *(ptr++)); + }; + } + DEBUG0(if (pACB->pActiveDCB) \ + printk (KERN_WARNING "DC390: ActiveDCB != 0\n");) + DEBUG0(if (pDCB->pActiveSRB) \ + printk (KERN_WARNING "DC390: ActiveSRB != 0\n");) + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + if (DC390_read8 (Scsi_Status) & INTERRUPT) + { + dc390_freetag (pDCB, pSRB); + DEBUG0(printk ("DC390: Interrupt during Start SCSI (pid %li, target %02i-%02i)\n", + pSRB->pcmd->pid, pSRB->pcmd->target, pSRB->pcmd->lun);) + pSRB->SRBState = SRB_READY; + //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + pACB->SelLost++; + return 1; + }; + DC390_write8 (ScsiCmd, cmd); + pACB->pActiveDCB = pDCB; pDCB->pActiveSRB = pSRB; + pACB->Connected = 1; + pSRB->ScsiPhase = SCSI_NOP1; + return 0; } //#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/ @@ -164,400 +151,421 @@ dc390_StartSCSI(PACB pACB, PDCB pDCB, PSRB pSRB) #if DMA_INT /* This is similar to AM53C974.c ... */ -static UCHAR - dc390_dma_intr(PACB pACB) +static UCHAR +dc390_dma_intr (PACB pACB) { - PSRB pSRB; - UCHAR dstate; - DEBUG0(USHORT pstate; - PDEVDECL1; - ) - DEBUG0(PDEVSET1; - ) - DEBUG0(PCI_READ_CONFIG_WORD(PDEV, PCI_STATUS, &pstate); - ) - DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)) \ - { - printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \ - PCI_WRITE_CONFIG_WORD(PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)); - }; - ) - dstate = DC390_read8(DMA_Status); - - if (!pACB->pActiveDCB || !pACB->pActiveDCB->pActiveSRB) - return dstate; - else - pSRB = pACB->pActiveDCB->pActiveSRB; - - if (dstate & (DMA_XFER_ABORT | DMA_XFER_ERROR | POWER_DOWN | PCI_MS_ABORT)) { - printk(KERN_ERR "DC390: DMA error (%02x)!\n", dstate); - return dstate; - }; - if (dstate & DMA_XFER_DONE) { - ULONG residual, xferCnt; - int ctr = 5000000; - if (!(DC390_read8(DMA_Cmd) & READ_DIRECTION)) { - do { - DEBUG1(printk(KERN_DEBUG "DC390: read residual bytes ... \n"); - ) - dstate = DC390_read8(DMA_Status); - residual = DC390_read8(CtcReg_Low) | DC390_read8(CtcReg_Mid) << 8 | - DC390_read8(CtcReg_High) << 16; - residual += DC390_read8(Current_Fifo) & 0x1f; - } while (residual && !(dstate & SCSI_INTERRUPT) && --ctr); - if (!ctr) - printk(KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32(DMA_Wk_ByteCntr)); - /* residual = ... */ - } else - residual = 0; - - /* ??? */ - - xferCnt = pSRB->SGToBeXferLen - residual; - pSRB->SGBusAddr += xferCnt; - pSRB->TotalXferredLen += xferCnt; - pSRB->SGToBeXferLen = residual; -#ifdef DC390_DEBUG0 - printk(KERN_INFO "DC390: DMA: residual = %i, xfer = %i\n", - (unsigned int) residual, (unsigned int) xferCnt); -#endif - - DC390_write8(DMA_Cmd, DMA_IDLE_CMD); - } - dc390_laststatus &= ~0xff000000; - dc390_laststatus |= dstate << 24; + PSRB pSRB; + UCHAR dstate; + DEBUG0(USHORT pstate;PDEVDECL1;) + + DEBUG0(PDEVSET1;) + DEBUG0(PCI_READ_CONFIG_WORD (PDEV, PCI_STATUS, &pstate);) + DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\ + { printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \ + PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));};) + + dstate = DC390_read8 (DMA_Status); + + if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate; + else pSRB = pACB->pActiveDCB->pActiveSRB; + + if (dstate & (DMA_XFER_ABORT | DMA_XFER_ERROR | POWER_DOWN | PCI_MS_ABORT)) + { + printk (KERN_ERR "DC390: DMA error (%02x)!\n", dstate); return dstate; + }; + if (dstate & DMA_XFER_DONE) + { + UINT residual, xferCnt; int ctr = 6000000; + if (! (DC390_read8 (DMA_Cmd) & READ_DIRECTION)) + { + do + { + DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n");) + dstate = DC390_read8 (DMA_Status); + residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 | + DC390_read8 (CtcReg_High) << 16; + residual += DC390_read8 (Current_Fifo) & 0x1f; + } while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr); + if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr)); + /* residual = ... */ + } + else + residual = 0; + + /* ??? */ + + xferCnt = pSRB->SGToBeXferLen - residual; + pSRB->SGBusAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = residual; +# ifdef DC390_DEBUG0 + printk (KERN_INFO "DC390: DMA: residual = %i, xfer = %i\n", + (unsigned int)residual, (unsigned int)xferCnt); +# endif + + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + } + dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24; + return dstate; }; #endif void __inline__ - DC390_Interrupt(int irq, void *dev_id, struct pt_regs *regs) +DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs) { - PACB pACB; - PDCB pDCB; - PSRB pSRB; - UCHAR sstatus = 0; - UCHAR phase, i; - void (*stateV) (PACB, PSRB, PUCHAR); - UCHAR istate, istatus; + PACB pACB, pACB2; + PDCB pDCB; + PSRB pSRB; + UCHAR sstatus=0; + UCHAR phase; + void (*stateV)( PACB, PSRB, PUCHAR ); + UCHAR istate, istatus; #if DMA_INT - UCHAR dstatus; + UCHAR dstatus; #endif - DC390_AFLAGS DC390_IFLAGS DC390_DFLAGS + DC390_AFLAGS DC390_IFLAGS //DC390_DFLAGS - pACB = dc390_pACB_start; + pACB = (PACB)dev_id; + for (pACB2 = dc390_pACB_start; (pACB2 && pACB2 != pACB); pACB2 = pACB2->pNextACB); + if (!pACB2) + { + printk ("DC390: IRQ called with foreign dev_id %p!\n", pACB); + return; + } + + //DC390_LOCK_DRV; - if (pACB == 0) { - printk(KERN_WARNING "DC390: Interrupt on uninitialized adapter!\n"); - return; - } - DC390_LOCK_DRV; - - for (i = 0; i < dc390_adapterCnt; i++) { - if (pACB->IRQLevel == (UCHAR) irq) { - sstatus = DC390_read8(Scsi_Status); - if (sstatus & INTERRUPT) - break; - else - pACB = pACB->pNextACB; - } else { - pACB = pACB->pNextACB; - } - } + sstatus = DC390_read8 (Scsi_Status); + if( !(sstatus & INTERRUPT) ) + { /*DC390_UNLOCK_DRV;*/ return; }; - DEBUG1(printk(KERN_DEBUG "sstatus=%02x,", sstatus); - ) - if (!pACB) { - DC390_UNLOCK_DRV; - return; - }; + DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus);) #if DMA_INT - DC390_LOCK_IO; - DC390_LOCK_ACB; - dstatus = dc390_dma_intr(pACB); - DC390_UNLOCK_ACB; - DC390_UNLOCK_IO; - - DEBUG1(printk(KERN_DEBUG "dstatus=%02x,", dstatus); - ) - if (!(dstatus & SCSI_INTERRUPT)) { - DEBUG0(printk(KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n"); - ) - DC390_UNLOCK_DRV; - return; - }; + DC390_LOCK_IO; + DC390_LOCK_ACB; + dstatus = dc390_dma_intr (pACB); + DC390_UNLOCK_ACB; + DC390_UNLOCK_IO; + + DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus);) + if (! (dstatus & SCSI_INTERRUPT)) + { + DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n");) + //DC390_UNLOCK_DRV; + return; + }; #else - //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT); - //dstatus = DC390_read8 (DMA_Status); - //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); + //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT); + //dstatus = DC390_read8 (DMA_Status); + //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); #endif - DC390_LOCK_IO; - DC390_LOCK_ACB; - DC390_UNLOCK_DRV_NI; /* Allow _other_ CPUs to process IRQ (useful for shared IRQs) */ - - istate = DC390_read8(Intern_State); - istatus = DC390_read8(INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */ - - DEBUG1(printk(KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,", istatus); - ) - dc390_laststatus &= ~0x00ffffff; - dc390_laststatus |= /* dstatus<<24 | */ sstatus << 16 | istate << 8 | istatus; - - if (sstatus & ILLEGAL_OP_ERR) { - printk("DC390: Illegal Operation detected (%08lx)!\n", dc390_laststatus); - dc390_dumpinfo(pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB); - }; - - if (istatus & DISCONNECTED) { - dc390_Disconnect(pACB); - goto unlock; - } - if (istatus & RESELECTED) { - dc390_Reselect(pACB); - goto unlock; - } - if (istatus & (SUCCESSFUL_OP | SERVICE_REQUEST)) { - pDCB = pACB->pActiveDCB; - if (!pDCB) { - printk(KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n"); - goto unlock; - }; - pSRB = pDCB->pActiveSRB; - if (pDCB->DCBFlag & ABORT_DEV_) - dc390_EnableMsgOut_Abort(pACB, pSRB); - - phase = pSRB->ScsiPhase; - DEBUG1(printk(KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus); - ) - stateV = (void *) dc390_phase0[phase]; - (*stateV) (pACB, pSRB, &sstatus); - - pSRB->ScsiPhase = sstatus & 7; - phase = (UCHAR) sstatus & 7; - DEBUG1(printk(KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus); - ) - stateV = (void *) dc390_phase1[phase]; - (*stateV) (pACB, pSRB, &sstatus); - goto unlock; - } - if (istatus & INVALID_CMD) { - dc390_InvalidCmd(pACB); - goto unlock; - } - if (istatus & SCSI_RESET) { - dc390_ScsiRstDetect(pACB); + DC390_LOCK_IO; + DC390_LOCK_ACB; + //DC390_UNLOCK_DRV_NI; /* Allow _other_ CPUs to process IRQ (useful for shared IRQs) */ + + istate = DC390_read8 (Intern_State); + istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */ + + DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus);) + dc390_laststatus &= ~0x00ffffff; + dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus; + + if (sstatus & ILLEGAL_OP_ERR) + { + printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus); + dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB); + } + + else if (istatus & INVALID_CMD) + { + printk ("DC390: Invalid Command detected (%08x)!\n", dc390_laststatus); + dc390_InvalidCmd( pACB ); + goto unlock; + } + + if (istatus & SCSI_RESET) + { + dc390_ScsiRstDetect( pACB ); + goto unlock; + } + + if (istatus & DISCONNECTED) + { + dc390_Disconnect( pACB ); + goto unlock; + } + + if (istatus & RESELECTED) + { + dc390_Reselect( pACB ); + goto unlock; + } + + else if (istatus & (SELECTED | SEL_ATTENTION)) + { + printk (KERN_ERR "DC390: Target mode not supported!\n"); + goto unlock; + } + + if (istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) ) + { + pDCB = pACB->pActiveDCB; + if (!pDCB) + { + printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n"); goto unlock; - } - unlock: - DC390_LOCK_DRV_NI; - DC390_UNLOCK_ACB; - DC390_UNLOCK_IO; - DC390_UNLOCK_DRV; /* Restore initial flags */ + }; + pSRB = pDCB->pActiveSRB; + if( pDCB->DCBFlag & ABORT_DEV_ ) + dc390_EnableMsgOut_Abort (pACB, pSRB); + + phase = pSRB->ScsiPhase; + DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus);) + stateV = (void *) dc390_phase0[phase]; + ( *stateV )( pACB, pSRB, &sstatus ); + + pSRB->ScsiPhase = sstatus & 7; + phase = (UCHAR) sstatus & 7; + DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus);) + stateV = (void *) dc390_phase1[phase]; + ( *stateV )( pACB, pSRB, &sstatus ); + goto unlock; + } + + unlock: + //DC390_LOCK_DRV_NI; + DC390_UNLOCK_ACB; + DC390_UNLOCK_IO; + //DC390_UNLOCK_DRV; /* Restore initial flags */ } -void do_DC390_Interrupt(int irq, void *dev_id, struct pt_regs *regs) +void +do_DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs) { - DEBUG1(printk(KERN_INFO "DC390: Irq (%i) caught: ", irq); - ) - /* Locking is done in DC390_Interrupt */ - DC390_Interrupt(irq, dev_id, regs); - DEBUG1(printk(".. IRQ returned\n"); - ) + DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq);) + /* Locking is done in DC390_Interrupt */ + DC390_Interrupt(irq, dev_id, regs); + DEBUG1(printk (".. IRQ returned\n");) } -void dc390_DataOut_0(PACB pACB, PSRB pSRB, PUCHAR psstatus) +void +dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - UCHAR sstatus; - PSGL psgl; - ULONG ResidCnt, xferCnt; - UCHAR dstate = 0; - - sstatus = *psstatus; - - if (!(pSRB->SRBState & SRB_XFERPAD)) { - if (sstatus & (PARITY_ERR | ILLEGAL_OP_ERR)) - pSRB->SRBStatus |= PARITY_ERROR; - - if (sstatus & COUNT_2_ZERO) { - int ctr = 5000000; /* only try for about a tenth of a second */ - while (--ctr && !((dstate = DC390_read8(DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen); - if (!ctr) - printk(KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32(DMA_Wk_ByteCntr)); - dc390_laststatus &= ~0xff000000; - dc390_laststatus |= dstate << 24; - pSRB->TotalXferredLen += pSRB->SGToBeXferLen; - pSRB->SGIndex++; - if (pSRB->SGIndex < pSRB->SGcount) { - pSRB->pSegmentList++; - psgl = pSRB->pSegmentList; - - pSRB->SGBusAddr = virt_to_bus(psgl->address); - pSRB->SGToBeXferLen = (ULONG) psgl->length; - } else - pSRB->SGToBeXferLen = 0; - } else { - ResidCnt = (ULONG) DC390_read8(Current_Fifo) & 0x1f; - ResidCnt |= (ULONG) DC390_read8(CtcReg_High) << 16; - ResidCnt |= (ULONG) DC390_read8(CtcReg_Mid) << 8; - ResidCnt += (ULONG) DC390_read8(CtcReg_Low); - - xferCnt = pSRB->SGToBeXferLen - ResidCnt; - pSRB->SGBusAddr += xferCnt; - pSRB->TotalXferredLen += xferCnt; - pSRB->SGToBeXferLen = ResidCnt; - } + UCHAR sstatus; + PSGL psgl; + UINT ResidCnt, xferCnt; + UCHAR dstate = 0; + + sstatus = *psstatus; + + if( !(pSRB->SRBState & SRB_XFERPAD) ) + { + if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) ) + pSRB->SRBStatus |= PARITY_ERROR; + + if( sstatus & COUNT_2_ZERO ) + { + int ctr = 6000000; /* only try for about a second */ + while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen ); + if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr)); + dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24; + pSRB->TotalXferredLen += pSRB->SGToBeXferLen; + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + + pSRB->SGBusAddr = virt_to_bus( psgl->address ); + pSRB->SGToBeXferLen = (ULONG) psgl->length; + } + else + pSRB->SGToBeXferLen = 0; + } + else + { + ResidCnt = (UINT) DC390_read8 (Current_Fifo) & 0x1f; + ResidCnt |= (UINT) DC390_read8 (CtcReg_High) << 16; + ResidCnt |= (UINT) DC390_read8 (CtcReg_Mid) << 8; + ResidCnt += (UINT) DC390_read8 (CtcReg_Low); + + xferCnt = pSRB->SGToBeXferLen - ResidCnt; + pSRB->SGBusAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = ResidCnt; } - DC390_write8(DMA_Cmd, WRITE_DIRECTION + DMA_IDLE_CMD); /* | DMA_INT */ + } + if ((*psstatus & 7) != SCSI_DATA_OUT) + { + DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + } } -void dc390_DataIn_0(PACB pACB, PSRB pSRB, PUCHAR psstatus) +void +dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - UCHAR sstatus, residual, bval; - PSGL psgl; - ULONG ResidCnt, xferCnt, i; - PUCHAR ptr; - - sstatus = *psstatus; - - if (!(pSRB->SRBState & SRB_XFERPAD)) { - if (sstatus & (PARITY_ERR | ILLEGAL_OP_ERR)) - pSRB->SRBStatus |= PARITY_ERROR; - - if (sstatus & COUNT_2_ZERO) { - int ctr = 5000000; /* only try for about a tenth of a second */ - int dstate = 0; - while (--ctr && !((dstate = DC390_read8(DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen); - if (!ctr) - printk(KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32(DMA_Wk_ByteCntr)); - if (!ctr) - printk(KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate); - dc390_laststatus &= ~0xff000000; - dc390_laststatus |= dstate << 24; - DEBUG1(ResidCnt = ((ULONG) DC390_read8(CtcReg_High) << 16) \ - +((ULONG) DC390_read8(CtcReg_Mid) << 8) \ - +((ULONG) DC390_read8(CtcReg_Low)); - ) - DEBUG1(printk(KERN_DEBUG "Count_2_Zero (ResidCnt=%li,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen); - ) - DC390_write8(DMA_Cmd, READ_DIRECTION + DMA_IDLE_CMD); /* | DMA_INT */ - - pSRB->TotalXferredLen += pSRB->SGToBeXferLen; - pSRB->SGIndex++; - if (pSRB->SGIndex < pSRB->SGcount) { - pSRB->pSegmentList++; - psgl = pSRB->pSegmentList; - - pSRB->SGBusAddr = virt_to_bus(psgl->address); - pSRB->SGToBeXferLen = (ULONG) psgl->length; - } else - pSRB->SGToBeXferLen = 0; - } else { /* phase changed */ - residual = 0; - bval = DC390_read8(Current_Fifo); - while (bval & 0x1f) { - DEBUG1(printk(KERN_DEBUG "Check for residuals,"); - ) - if ((bval & 0x1f) == 1) { - for (i = 0; i < 0x100; i++) { - bval = DC390_read8(Current_Fifo); - if (!(bval & 0x1f)) - goto din_1; - else if (i == 0x0ff) { - residual = 1; /* ;1 residual byte */ - goto din_1; - } - } - } else - bval = DC390_read8(Current_Fifo); - } - din_1: - DC390_write8(DMA_Cmd, READ_DIRECTION + DMA_BLAST_CMD); - for (i = 0xa000; i; i--) { - bval = DC390_read8(DMA_Status); - if (bval & BLAST_COMPLETE) - break; - } - /* It seems a DMA Blast abort isn't that bad ... */ - if (!i) - printk(KERN_ERR "DC390: DMA Blast aborted unfinished!\n"); - //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ - dc390_laststatus &= ~0xff000000; - dc390_laststatus |= bval << 24; - - DEBUG1(printk(KERN_DEBUG "Blast: Read %li times DMA_Status %02x", 0xa000 - i, bval); - ) - ResidCnt = (ULONG) DC390_read8(CtcReg_High); - ResidCnt <<= 8; - ResidCnt |= (ULONG) DC390_read8(CtcReg_Mid); - ResidCnt <<= 8; - ResidCnt |= (ULONG) DC390_read8(CtcReg_Low); - - xferCnt = pSRB->SGToBeXferLen - ResidCnt; - pSRB->SGBusAddr += xferCnt; - pSRB->TotalXferredLen += xferCnt; - pSRB->SGToBeXferLen = ResidCnt; - - if (residual) { - bval = DC390_read8(ScsiFifo); /* get one residual byte */ - ptr = (PUCHAR) bus_to_virt(pSRB->SGBusAddr); - *ptr = bval; - pSRB->SGBusAddr++; - xferCnt++; - pSRB->TotalXferredLen++; - pSRB->SGToBeXferLen--; + UCHAR sstatus, residual, bval; + PSGL psgl; + UINT ResidCnt, i; + ULONG xferCnt; + PUCHAR ptr; + + sstatus = *psstatus; + + if( !(pSRB->SRBState & SRB_XFERPAD) ) + { + if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR)) + pSRB->SRBStatus |= PARITY_ERROR; + + if( sstatus & COUNT_2_ZERO ) + { + int ctr = 6000000; /* only try for about a second */ + int dstate = 0; + while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen ); + if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr)); + if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate); + dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24; + DEBUG1(ResidCnt = ((ULONG) DC390_read8 (CtcReg_High) << 16) \ + + ((ULONG) DC390_read8 (CtcReg_Mid) << 8) \ + + ((ULONG) DC390_read8 (CtcReg_Low));) + DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%i,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);) + + DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + + pSRB->TotalXferredLen += pSRB->SGToBeXferLen; + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + + pSRB->SGBusAddr = virt_to_bus( psgl->address ); + pSRB->SGToBeXferLen = (ULONG) psgl->length; + } + else + pSRB->SGToBeXferLen = 0; + } + else /* phase changed */ + { + residual = 0; + bval = DC390_read8 (Current_Fifo); + while( bval & 0x1f ) + { + DEBUG1(printk (KERN_DEBUG "Check for residuals,");) + if( (bval & 0x1f) == 1 ) + { + for(i=0; i < 0x100; i++) + { + bval = DC390_read8 (Current_Fifo); + if( !(bval & 0x1f) ) + goto din_1; + else if( i == 0x0ff ) + { + residual = 1; /* ;1 residual byte */ + goto din_1; } - DEBUG1(printk(KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt, \ - pSRB->TotalXferredLen, pSRB->SGToBeXferLen); - ) + } } + else + bval = DC390_read8 (Current_Fifo); + } +din_1: + DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD); + for (i = 0xa000; i; i--) + { + bval = DC390_read8 (DMA_Status); + if (bval & BLAST_COMPLETE) + break; + } + /* It seems a DMA Blast abort isn't that bad ... */ + if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n"); + //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24; + + DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval);) + ResidCnt = (UINT) DC390_read8 (CtcReg_High); + ResidCnt <<= 8; + ResidCnt |= (UINT) DC390_read8 (CtcReg_Mid); + ResidCnt <<= 8; + ResidCnt |= (UINT) DC390_read8 (CtcReg_Low); + + xferCnt = pSRB->SGToBeXferLen - ResidCnt; + pSRB->SGBusAddr += xferCnt; + pSRB->TotalXferredLen += xferCnt; + pSRB->SGToBeXferLen = ResidCnt; + + if( residual ) + { + bval = DC390_read8 (ScsiFifo); /* get one residual byte */ + ptr = (PUCHAR) bus_to_virt( pSRB->SGBusAddr ); + *ptr = bval; + pSRB->SGBusAddr++; xferCnt++; + pSRB->TotalXferredLen++; + pSRB->SGToBeXferLen--; + } + DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\ + pSRB->TotalXferredLen, pSRB->SGToBeXferLen);) + } + } + if ((*psstatus & 7) != SCSI_DATA_IN) + { + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + } } -static void dc390_Command_0(PACB pACB, PSRB pSRB, PUCHAR psstatus) +static void +dc390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) { } -static void dc390_Status_0(PACB pACB, PSRB pSRB, PUCHAR psstatus) +static void +dc390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - pSRB->TargetStatus = DC390_read8(ScsiFifo); - //udelay (1); - pSRB->EndMessage = DC390_read8(ScsiFifo); /* get message */ + pSRB->TargetStatus = DC390_read8 (ScsiFifo); + //udelay (1); + pSRB->EndMessage = DC390_read8 (ScsiFifo); /* get message */ - *psstatus = SCSI_NOP0; - pSRB->SRBState = SRB_COMPLETED; - DC390_write8(ScsiCmd, MSG_ACCEPTED_CMD); + *psstatus = SCSI_NOP0; + pSRB->SRBState = SRB_COMPLETED; + DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); } -static void dc390_MsgOut_0(PACB pACB, PSRB pSRB, PUCHAR psstatus) +static void +dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - if (pSRB->SRBState & (SRB_UNEXPECT_RESEL + SRB_ABORT_SENT)) - *psstatus = SCSI_NOP0; - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) ) + *psstatus = SCSI_NOP0; + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); } static void __inline__ - dc390_reprog(PACB pACB, PDCB pDCB) +dc390_reprog (PACB pACB, PDCB pDCB) { - DC390_write8(Sync_Period, pDCB->SyncPeriod); - DC390_write8(Sync_Offset, pDCB->SyncOffset); - DC390_write8(CtrlReg3, pDCB->CtrlR3); - DC390_write8(CtrlReg4, pDCB->CtrlR4); - dc390_SetXferRate(pACB, pDCB); + DC390_write8 (Sync_Period, pDCB->SyncPeriod); + DC390_write8 (Sync_Offset, pDCB->SyncOffset); + DC390_write8 (CtrlReg3, pDCB->CtrlR3); + DC390_write8 (CtrlReg4, pDCB->CtrlR4); + dc390_SetXferRate (pACB, pDCB); }; #ifdef DC390_DEBUG0 -static void dc390_printMsg(UCHAR * MsgBuf, UCHAR len) +static void +dc390_printMsg (UCHAR *MsgBuf, UCHAR len) { - int i; - printk(" %02x", MsgBuf[0]); - for (i = 1; i < len; i++) - printk(" %02x", MsgBuf[i]); - printk("\n"); + int i; + printk (" %02x", MsgBuf[0]); + for (i = 1; i < len; i++) + printk (" %02x", MsgBuf[i]); + printk ("\n"); }; #endif @@ -565,147 +573,201 @@ static void dc390_printMsg(UCHAR * MsgBuf, UCHAR len) /* reject_msg */ static void __inline__ - dc390_MsgIn_reject(PACB pACB, PSRB pSRB) +dc390_MsgIn_reject (PACB pACB, PSRB pSRB) { - pSRB->MsgOutBuf[0] = MSG_REJECT_; - pSRB->MsgCnt = 1; - DC390_ENABLE_MSGOUT; - DEBUG0(printk(KERN_INFO "DC390: Reject message\n"); - ) + pSRB->MsgOutBuf[0] = MESSAGE_REJECT; + pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; + DEBUG0 (printk (KERN_INFO "DC390: Reject message\n");) } /* abort command */ static void __inline__ - dc390_EnableMsgOut_Abort(PACB pACB, PSRB pSRB) +dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB ) { - pSRB->MsgOutBuf[0] = MSG_ABORT; - pSRB->MsgCnt = 1; - DC390_ENABLE_MSGOUT; - pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_; + pSRB->MsgOutBuf[0] = ABORT; + pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; + pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_; } static PSRB - dc390_MsgIn_QTag(PACB pACB, PDCB pDCB, UCHAR tag) +dc390_MsgIn_QTag (PACB pACB, PDCB pDCB, UCHAR tag) { - PSRB lastSRB = pDCB->pGoingLast; - PSRB pSRB = pDCB->pGoingSRB; - - if (pSRB) { - for (; pSRB;) { - if (pSRB->TagNumber == tag) - break; - if (pSRB == lastSRB) - goto mingx0; - pSRB = pSRB->pNextSRB; - } + PSRB lastSRB = pDCB->pGoingLast; + PSRB pSRB = pDCB->pGoingSRB; - if (pDCB->DCBFlag & ABORT_DEV_) { - pSRB->SRBState = SRB_ABORT_SENT; - dc390_EnableMsgOut_Abort(pACB, pSRB); - } - if (!(pSRB->SRBState & SRB_DISCONNECT)) - goto mingx0; + if (pSRB) + { + for( ;pSRB ; ) + { + if (pSRB->TagNumber == tag) break; + if (pSRB == lastSRB) goto mingx0; + pSRB = pSRB->pNextSRB; + } - pDCB->pActiveSRB = pSRB; - pSRB->SRBState = SRB_DATA_XFER; - } else { - mingx0: - pSRB = pACB->pTmpSRB; - pSRB->SRBState = SRB_UNEXPECT_RESEL; - pDCB->pActiveSRB = pSRB; - pSRB->MsgOutBuf[0] = MSG_ABORT_TAG; - pSRB->MsgCnt = 1; - DC390_ENABLE_MSGOUT; + if( pDCB->DCBFlag & ABORT_DEV_ ) + { + pSRB->SRBState = SRB_ABORT_SENT; + dc390_EnableMsgOut_Abort( pACB, pSRB ); } - return pSRB; + + if( !(pSRB->SRBState & SRB_DISCONNECT) ) + goto mingx0; + + pDCB->pActiveSRB = pSRB; + pSRB->SRBState = SRB_DATA_XFER; + } + else + { + mingx0: + pSRB = pACB->pTmpSRB; + pSRB->SRBState = SRB_UNEXPECT_RESEL; + pDCB->pActiveSRB = pSRB; + pSRB->MsgOutBuf[0] = ABORT_TAG; + pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; + } + return pSRB; } /* set async transfer mode */ -static void dc390_MsgIn_set_async(PACB pACB, PSRB pSRB) +static void +dc390_MsgIn_set_async (PACB pACB, PSRB pSRB) { - PDCB pDCB = pSRB->pSRBDCB; - if (!(pSRB->SRBState & DO_SYNC_NEGO)) - printk("DC390: Target %i initiates Non-Sync?\n", pDCB->UnitSCSIID); - pSRB->SRBState &= ~DO_SYNC_NEGO; - pDCB->SyncMode &= ~(SYNC_ENABLE + SYNC_NEGO_DONE); - pDCB->SyncPeriod = 0; - pDCB->SyncOffset = 0; - //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */ - pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */ - pDCB->CtrlR4 &= 0x3f; - pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */ - dc390_reprog(pACB, pDCB); + PDCB pDCB = pSRB->pSRBDCB; + if (!(pSRB->SRBState & DO_SYNC_NEGO)) + printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID); + pSRB->SRBState &= ~DO_SYNC_NEGO; + pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE); + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */ + pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */ + pDCB->CtrlR4 &= 0x3f; + pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */ + dc390_reprog (pACB, pDCB); } /* set sync transfer mode */ -static void dc390_MsgIn_set_sync(PACB pACB, PSRB pSRB) +static void +dc390_MsgIn_set_sync (PACB pACB, PSRB pSRB) { - UCHAR bval; - USHORT wval, wval1; - PDCB pDCB = pSRB->pSRBDCB; - UCHAR oldsyncperiod = pDCB->SyncPeriod; - UCHAR oldsyncoffset = pDCB->SyncOffset; - - if (!(pSRB->SRBState & DO_SYNC_NEGO)) { - printk("DC390: Target %i initiates Sync: %ins %i ... answer ...\n", - pDCB->UnitSCSIID, pSRB->MsgInBuf[3] << 2, pSRB->MsgInBuf[4]); - - /* reject */ - //dc390_MsgIn_reject (pACB, pSRB); - //return dc390_MsgIn_set_async (pACB, pSRB); - - /* Reply with corrected SDTR Message */ - if (pSRB->MsgInBuf[4] > 15) { - printk("DC390: Lower Sync Offset to 15\n"); - pSRB->MsgInBuf[4] = 15; - } - if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod) { - printk("DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2); - pSRB->MsgInBuf[3] = pDCB->NegoPeriod; - }; - memcpy(pSRB->MsgOutBuf, pSRB->MsgInBuf, 5); - pSRB->MsgCnt = 5; - DC390_ENABLE_MSGOUT; + UCHAR bval; + USHORT wval, wval1; + PDCB pDCB = pSRB->pSRBDCB; + UCHAR oldsyncperiod = pDCB->SyncPeriod; + UCHAR oldsyncoffset = pDCB->SyncOffset; + + if (!(pSRB->SRBState & DO_SYNC_NEGO)) + { + printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n", + pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]); + + /* reject */ + //dc390_MsgIn_reject (pACB, pSRB); + //return dc390_MsgIn_set_async (pACB, pSRB); + + /* Reply with corrected SDTR Message */ + if (pSRB->MsgInBuf[4] > 15) + { + printk (KERN_INFO "DC390: Lower Sync Offset to 15\n"); + pSRB->MsgInBuf[4] = 15; + } + if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod) + { + printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2); + pSRB->MsgInBuf[3] = pDCB->NegoPeriod; }; + memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5); + pSRB->MsgCnt = 5; + DC390_ENABLE_MSGOUT; + }; + + pSRB->SRBState &= ~DO_SYNC_NEGO; + pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE; + pDCB->SyncOffset &= 0x0f0; + pDCB->SyncOffset |= pSRB->MsgInBuf[4]; + pDCB->NegoPeriod = pSRB->MsgInBuf[3]; + + wval = (USHORT) pSRB->MsgInBuf[3]; + wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */ + if( (wval1 * 25) != wval) wval1++; + bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */ + + pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */ + if (pACB->glitch_cfg != NS_TO_GLITCH(0)) + pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1)); + else + pDCB->CtrlR4 |= NS_TO_GLITCH(0); + if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */ + + if (wval1 >= 8) + { + wval1--; /* Timing computation differs by 1 from FAST_SCSI */ + bval = FAST_CLK; /* fast clock / normal scsi */ + pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */ + } + + pDCB->CtrlR3 = bval; + pDCB->SyncPeriod = (UCHAR)wval1; + + if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0) + { + if (! (bval & FAST_SCSI)) wval1++; + printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID, + 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f); + } + + dc390_reprog (pACB, pDCB); +}; - pSRB->SRBState &= ~DO_SYNC_NEGO; - pDCB->SyncMode |= SYNC_ENABLE + SYNC_NEGO_DONE; - pDCB->SyncOffset &= 0x0f0; - pDCB->SyncOffset |= pSRB->MsgInBuf[4]; - pDCB->NegoPeriod = pSRB->MsgInBuf[3]; - - wval = (USHORT) pSRB->MsgInBuf[3]; - wval = wval << 2; - wval -= 3; - wval1 = wval / 25; /* compute speed */ - if ((wval1 * 25) != wval) - wval1++; - bval = FAST_CLK + FAST_SCSI; /* fast clock / fast scsi */ - - pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */ - if (pACB->glitch_cfg != NS_TO_GLITCH(0)) - pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1)); - else - pDCB->CtrlR4 |= NS_TO_GLITCH(0); - if (wval1 < 4) - pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */ - - if (wval1 >= 8) { - wval1--; /* Timing computation differs by 1 from FAST_SCSI */ - bval = FAST_CLK; /* fast clock / normal scsi */ - pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */ - } - pDCB->CtrlR3 = bval; - pDCB->SyncPeriod = (UCHAR) wval1; - - if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->UnitSCSILUN == 0) { - if (!(bval & FAST_SCSI)) - wval1++; - printk("DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->UnitSCSIID, - 40 / wval1, ((40 % wval1) * 10 + wval1 / 2) / wval1, pDCB->SyncOffset & 0x0f); + +/* handle RESTORE_PTR */ +static void +dc390_restore_ptr (PACB pACB, PSRB pSRB) +{ + PSGL psgl; + pSRB->TotalXferredLen = 0; + pSRB->SGIndex = 0; + if( pSRB->pcmd->use_sg ) + { + pSRB->SGcount = (UCHAR) pSRB->pcmd->use_sg; + pSRB->pSegmentList = (PSGL) pSRB->pcmd->request_buffer; + psgl = pSRB->pSegmentList; + while (pSRB->TotalXferredLen + (ULONG) psgl->length < pSRB->Saved_Ptr) + { + pSRB->TotalXferredLen += (ULONG) psgl->length; + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + + pSRB->SGBusAddr = virt_to_bus( psgl->address ); + pSRB->SGToBeXferLen = (ULONG) psgl->length; + } + else + pSRB->SGToBeXferLen = 0; } - dc390_reprog(pACB, pDCB); + pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen); + pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen); + printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n", pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr); + } + else if( pSRB->pcmd->request_buffer ) + { + pSRB->SGcount = 1; + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pSRB->pcmd->request_buffer + pSRB->Saved_Ptr; + pSRB->Segmentx.length = pSRB->pcmd->request_bufflen - pSRB->Saved_Ptr; + printk (KERN_INFO "DC390: Pointer restored. Total %li, Bus %p\n", + pSRB->Saved_Ptr, pSRB->Segmentx.address); + } + else + { + pSRB->SGcount = 0; + printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n"); + }; + + pSRB->TotalXferredLen = pSRB->Saved_Ptr; }; @@ -719,890 +781,1010 @@ static void dc390_MsgIn_set_sync(PACB pACB, PSRB pSRB) /* Check if the message is complete */ static UCHAR __inline__ - dc390_MsgIn_complete(UCHAR * msgbuf, ULONG len) -{ - if (*msgbuf == MSG_EXTENDED) { - if (len < 2) - return 0; - if (len < msgbuf[1] + 2) - return 0; - } else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages - - if (len < 2) - return 0; - return 1; +dc390_MsgIn_complete (UCHAR *msgbuf, UINT len) +{ + if (*msgbuf == EXTENDED_MESSAGE) + { + if (len < 2) return 0; + if (len < msgbuf[1] + 2) return 0; + } + else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages + if (len < 2) return 0; + return 1; } /* read and eval received messages */ -void dc390_MsgIn_0(PACB pACB, PSRB pSRB, PUCHAR psstatus) +void +dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - PDCB pDCB = pACB->pActiveDCB; - - /* Read the msg */ - - pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8(ScsiFifo); - //pSRB->SRBState = 0; - - /* Msg complete ? */ - if (dc390_MsgIn_complete(pSRB->MsgInBuf, pACB->MsgLen)) { - DEBUG0(printk(KERN_INFO "DC390: MsgIn:"); - dc390_printMsg(pSRB->MsgInBuf, pACB->MsgLen); - ) - /* Now eval the msg */ - switch (pSRB->MsgInBuf[0]) { - case MSG_DISCONNECT: - pSRB->SRBState = SRB_DISCONNECT; - break; - - case MSG_SIMPLE_QTAG: - case MSG_HEAD_QTAG: - case MSG_ORDER_QTAG: - pSRB = dc390_MsgIn_QTag(pACB, pDCB, pSRB->MsgInBuf[1]); - break; - - case MSG_REJECT_: - DC390_write8(ScsiCmd, RESET_ATN_CMD); - pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */ - if (pSRB->SRBState & DO_SYNC_NEGO) - dc390_MsgIn_set_async(pACB, pSRB); - break; - - case MSG_EXTENDED: - /* reject every extended msg but SDTR */ - if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR) - dc390_MsgIn_reject(pACB, pSRB); - else { - if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0) - dc390_MsgIn_set_async(pACB, pSRB); - else - dc390_MsgIn_set_sync(pACB, pSRB); - }; - - // nothing has to be done - case MSG_COMPLETE: - break; - - // SAVE POINTER my be ignored as we have the PSRB associated with the - // scsi command. Thanks, Gerard, for pointing it out. - case MSG_SAVE_PTR: - break; - // The device might want to restart transfer with a RESTORE - case MSG_RESTORE_PTR: - printk("DC390: RESTORE POINTER message received ... reject\n"); - // fall through - - // reject unknown messages - default: - dc390_MsgIn_reject(pACB, pSRB); - } - - /* Clear counter and MsgIn state */ - pSRB->SRBState &= ~SRB_MSGIN; - pACB->MsgLen = 0; - }; + PDCB pDCB = pACB->pActiveDCB; + + /* Read the msg */ + + pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo); + //pSRB->SRBState = 0; + + /* Msg complete ? */ + if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen)) + { + DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen);) + /* Now eval the msg */ + switch (pSRB->MsgInBuf[0]) + { + case DISCONNECT: + pSRB->SRBState = SRB_DISCONNECT; break; + + case SIMPLE_QUEUE_TAG: + case HEAD_OF_QUEUE_TAG: + case ORDERED_QUEUE_TAG: + pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]); + break; + + case MESSAGE_REJECT: + DC390_write8 (ScsiCmd, RESET_ATN_CMD); + pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */ + if( pSRB->SRBState & DO_SYNC_NEGO) + dc390_MsgIn_set_async (pACB, pSRB); + break; + + case EXTENDED_MESSAGE: + /* reject every extended msg but SDTR */ + if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR) + dc390_MsgIn_reject (pACB, pSRB); + else + { + if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0) + dc390_MsgIn_set_async (pACB, pSRB); + else + dc390_MsgIn_set_sync (pACB, pSRB); + }; + + // nothing has to be done + case COMMAND_COMPLETE: break; + + // SAVE POINTER may be ignored as we have the PSRB associated with the + // scsi command. Thanks, Gerard, for pointing it out. + case SAVE_POINTERS: + pSRB->Saved_Ptr = pSRB->TotalXferredLen; + break; + // The device might want to restart transfer with a RESTORE + case RESTORE_POINTERS: + DEBUG0(printk ("DC390: RESTORE POINTER message received ... try to handle\n");) + dc390_restore_ptr (pACB, pSRB); + break; + + // reject unknown messages + default: dc390_MsgIn_reject (pACB, pSRB); + } + + /* Clear counter and MsgIn state */ + pSRB->SRBState &= ~SRB_MSGIN; + pACB->MsgLen = 0; + }; - *psstatus = SCSI_NOP0; - DC390_write8(ScsiCmd, MSG_ACCEPTED_CMD); - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + *psstatus = SCSI_NOP0; + DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); } -void dc390_DataIO_Comm(PACB pACB, PSRB pSRB, UCHAR ioDir) +void +dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir) { - PSGL psgl; - ULONG lval; - - if (pSRB->SGIndex < pSRB->SGcount) { - DC390_write8(DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */ ); - if (!pSRB->SGToBeXferLen) { - psgl = pSRB->pSegmentList; - pSRB->SGBusAddr = virt_to_bus(psgl->address); - pSRB->SGToBeXferLen = (ULONG) psgl->length; - DEBUG1(printk(KERN_DEBUG " DC390: Next SG segment."); - ) - } - lval = pSRB->SGToBeXferLen; - DEBUG1(printk(KERN_DEBUG " DC390: Transfer %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr); - ) - DC390_write8(CtcReg_Low, (UCHAR) lval); - lval >>= 8; - DC390_write8(CtcReg_Mid, (UCHAR) lval); - lval >>= 8; - DC390_write8(CtcReg_High, (UCHAR) lval); - - DC390_write32(DMA_XferCnt, pSRB->SGToBeXferLen); - DC390_write32(DMA_XferAddr, pSRB->SGBusAddr); - - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */ - pSRB->SRBState = SRB_DATA_XFER; + PSGL psgl; + ULONG lval; + PDCB pDCB = pACB->pActiveDCB; + + if (pSRB == pACB->pTmpSRB) + { + if (pDCB) printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", + pDCB->TargetID, pDCB->TargetLUN); + else printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n"); + dc390_EnableMsgOut_Abort (pACB, pSRB); + if (pDCB) pDCB->DCBFlag |= ABORT_DEV; + return; + } - DC390_write8(ScsiCmd, DMA_COMMAND + INFO_XFER_CMD); - - DC390_write8(DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); - //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);) - //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));) - //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);) - } else { /* xfer pad */ - if (pSRB->SGcount) { - pSRB->AdaptStatus = H_OVER_UNDER_RUN; - pSRB->SRBStatus |= OVER_RUN; - DEBUG0(printk(KERN_WARNING " DC390: Overrun -"); - ) - } - DEBUG0(printk(KERN_WARNING " Clear transfer pad \n"); - ) - DC390_write8(CtcReg_Low, 0); - DC390_write8(CtcReg_Mid, 0); - DC390_write8(CtcReg_High, 0); - - pSRB->SRBState |= SRB_XFERPAD; - DC390_write8(ScsiCmd, DMA_COMMAND + XFER_PAD_BYTE); -/* - DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT; - DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); - */ + if( pSRB->SGIndex < pSRB->SGcount ) + { + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */); + if( !pSRB->SGToBeXferLen ) + { + psgl = pSRB->pSegmentList; + pSRB->SGBusAddr = virt_to_bus( psgl->address ); + pSRB->SGToBeXferLen = (ULONG) psgl->length; + DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.");) + } + lval = pSRB->SGToBeXferLen; + DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);) + DC390_write8 (CtcReg_Low, (UCHAR) lval); + lval >>= 8; + DC390_write8 (CtcReg_Mid, (UCHAR) lval); + lval >>= 8; + DC390_write8 (CtcReg_High, (UCHAR) lval); + + DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen); + DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr); + + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */ + pSRB->SRBState = SRB_DATA_XFER; + + DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD); + + DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); + //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);) + //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));) + //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);) + } + else /* xfer pad */ + { + if( pSRB->SGcount ) + { + pSRB->AdaptStatus = H_OVER_UNDER_RUN; + pSRB->SRBStatus |= OVER_RUN; + DEBUG0(printk (KERN_WARNING " DC390: Overrun -");) } + DEBUG0(printk (KERN_WARNING " Clear transfer pad \n");) + DC390_write8 (CtcReg_Low, 0); + DC390_write8 (CtcReg_Mid, 0); + DC390_write8 (CtcReg_High, 0); + + pSRB->SRBState |= SRB_XFERPAD; + DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE); +/* + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); // | DMA_INT; + DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); +*/ + } } -static void dc390_DataOutPhase(PACB pACB, PSRB pSRB, PUCHAR psstatus) +static void +dc390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - dc390_DataIO_Comm(pACB, pSRB, WRITE_DIRECTION); + dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION); } -static void dc390_DataInPhase(PACB pACB, PSRB pSRB, PUCHAR psstatus) +static void +dc390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - dc390_DataIO_Comm(pACB, pSRB, READ_DIRECTION); + dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION); } -void dc390_CommandPhase(PACB pACB, PSRB pSRB, PUCHAR psstatus) +void +dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - PDCB pDCB; - UCHAR i, cnt; - PUCHAR ptr; - - DC390_write8(ScsiCmd, RESET_ATN_CMD); - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); - if (!(pSRB->SRBFlag & AUTO_REQSENSE)) { - cnt = (UCHAR) pSRB->ScsiCmdLen; - ptr = (PUCHAR) pSRB->CmdBlock; - for (i = 0; i < cnt; i++) - DC390_write8(ScsiFifo, *(ptr++)); - } else { - UCHAR bval = 0; - DC390_write8(ScsiFifo, REQUEST_SENSE); - pDCB = pACB->pActiveDCB; - DC390_write8(ScsiFifo, pDCB->IdentifyMsg << 5); - DC390_write8(ScsiFifo, bval); - DC390_write8(ScsiFifo, bval); - DC390_write8(ScsiFifo, sizeof(pSRB->pcmd->sense_buffer)); - DC390_write8(ScsiFifo, bval); - } - pSRB->SRBState = SRB_COMMAND; - DC390_write8(ScsiCmd, INFO_XFER_CMD); + PDCB pDCB; + UCHAR i, cnt; + PUCHAR ptr; + + DC390_write8 (ScsiCmd, RESET_ATN_CMD); + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + if( !(pSRB->SRBFlag & AUTO_REQSENSE) ) + { + cnt = (UCHAR) pSRB->pcmd->cmd_len; + ptr = (PUCHAR) pSRB->pcmd->cmnd; + for(i=0; i < cnt; i++) + DC390_write8 (ScsiFifo, *(ptr++)); + } + else + { + UCHAR bval = 0; + DC390_write8 (ScsiFifo, REQUEST_SENSE); + pDCB = pACB->pActiveDCB; + DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5); + DC390_write8 (ScsiFifo, bval); + DC390_write8 (ScsiFifo, bval); + DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer)); + DC390_write8 (ScsiFifo, bval); + DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n");) + } + pSRB->SRBState = SRB_COMMAND; + DC390_write8 (ScsiCmd, INFO_XFER_CMD); } -static void dc390_StatusPhase(PACB pACB, PSRB pSRB, PUCHAR psstatus) +static void +dc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); - pSRB->SRBState = SRB_STATUS; - DC390_write8(ScsiCmd, INITIATOR_CMD_CMPLTE); - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + pSRB->SRBState = SRB_STATUS; + DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE); + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); } -void dc390_MsgOutPhase(PACB pACB, PSRB pSRB, PUCHAR psstatus) +void +dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - UCHAR bval, i, cnt; - PUCHAR ptr; - PDCB pDCB; - - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); - pDCB = pACB->pActiveDCB; - if (!(pSRB->SRBState & SRB_MSGOUT)) { - cnt = pSRB->MsgCnt; - if (cnt) { - ptr = (PUCHAR) pSRB->MsgOutBuf; - for (i = 0; i < cnt; i++) - DC390_write8(ScsiFifo, *(ptr++)); - pSRB->MsgCnt = 0; - if ((pDCB->DCBFlag & ABORT_DEV_) && - (pSRB->MsgOutBuf[0] == MSG_ABORT)) - pSRB->SRBState = SRB_ABORT_SENT; - } else { - bval = MSG_ABORT; /* ??? MSG_NOP */ - if ((pSRB->CmdBlock[0] == INQUIRY) || - (pSRB->CmdBlock[0] == REQUEST_SENSE) || - (pSRB->SRBFlag & AUTO_REQSENSE)) { - if (pDCB->SyncMode & SYNC_ENABLE) - goto mop1; - } - DC390_write8(ScsiFifo, bval); - } - DC390_write8(ScsiCmd, INFO_XFER_CMD); - } else { - mop1: - //printk ("DC390: Send SDTR message to %i %i ... \n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN); - DC390_write8(ScsiFifo, MSG_EXTENDED); - DC390_write8(ScsiFifo, 3); /* ;length of extended msg */ - DC390_write8(ScsiFifo, EXTENDED_SDTR); /* ; sync nego */ - DC390_write8(ScsiFifo, pDCB->NegoPeriod); - if (pDCB->SyncOffset & 0x0f) - DC390_write8(ScsiFifo, pDCB->SyncOffset); - else - DC390_write8(ScsiFifo, SYNC_NEGO_OFFSET); - pSRB->SRBState |= DO_SYNC_NEGO; - DC390_write8(ScsiCmd, INFO_XFER_CMD); + UCHAR bval, i, cnt; + PUCHAR ptr; + PDCB pDCB; + + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + pDCB = pACB->pActiveDCB; + if( !(pSRB->SRBState & SRB_MSGOUT) ) + { + cnt = pSRB->MsgCnt; + if( cnt ) + { + ptr = (PUCHAR) pSRB->MsgOutBuf; + for(i=0; i < cnt; i++) + DC390_write8 (ScsiFifo, *(ptr++)); + pSRB->MsgCnt = 0; + if( (pDCB->DCBFlag & ABORT_DEV_) && + (pSRB->MsgOutBuf[0] == ABORT) ) + pSRB->SRBState = SRB_ABORT_SENT; } + else + { + bval = ABORT; /* ??? MSG_NOP */ + if( (pSRB->pcmd->cmnd[0] == INQUIRY ) || + (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || + (pSRB->SRBFlag & AUTO_REQSENSE) ) + { + if( pDCB->SyncMode & SYNC_ENABLE ) + goto mop1; + } + DC390_write8 (ScsiFifo, bval); + } + DC390_write8 (ScsiCmd, INFO_XFER_CMD); + } + else + { +mop1: + printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN); + DC390_write8 (ScsiFifo, EXTENDED_MESSAGE); + DC390_write8 (ScsiFifo, 3); /* ;length of extended msg */ + DC390_write8 (ScsiFifo, EXTENDED_SDTR); /* ; sync nego */ + DC390_write8 (ScsiFifo, pDCB->NegoPeriod); + if (pDCB->SyncOffset & 0x0f) + DC390_write8 (ScsiFifo, pDCB->SyncOffset); + else + DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET); + pSRB->SRBState |= DO_SYNC_NEGO; + DC390_write8 (ScsiCmd, INFO_XFER_CMD); + } } -static void dc390_MsgInPhase(PACB pACB, PSRB pSRB, PUCHAR psstatus) +static void +dc390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus) { - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); - if (!(pSRB->SRBState & SRB_MSGIN)) { - pSRB->SRBState &= ~SRB_DISCONNECT; - pSRB->SRBState |= SRB_MSGIN; - } - DC390_write8(ScsiCmd, INFO_XFER_CMD); - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + if( !(pSRB->SRBState & SRB_MSGIN) ) + { + pSRB->SRBState &= ~SRB_DISCONNECT; + pSRB->SRBState |= SRB_MSGIN; + } + DC390_write8 (ScsiCmd, INFO_XFER_CMD); + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); } -static void dc390_Nop_0(PACB pACB, PSRB pSRB, PUCHAR psstatus) +static void +dc390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) { } -static void dc390_Nop_1(PACB pACB, PSRB pSRB, PUCHAR psstatus) +static void +dc390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus) { } -static void dc390_SetXferRate(PACB pACB, PDCB pDCB) +static void +dc390_SetXferRate( PACB pACB, PDCB pDCB ) { - UCHAR bval, i, cnt; - PDCB ptr; - - if (!(pDCB->IdentifyMsg & 0x07)) { - if (pACB->scan_devices) { - dc390_CurrSyncOffset = pDCB->SyncOffset; - } else { - ptr = pACB->pLinkDCB; - cnt = pACB->DCBCnt; - bval = pDCB->UnitSCSIID; - for (i = 0; i < cnt; i++) { - if (ptr->UnitSCSIID == bval) { - ptr->SyncPeriod = pDCB->SyncPeriod; - ptr->SyncOffset = pDCB->SyncOffset; - ptr->CtrlR3 = pDCB->CtrlR3; - ptr->CtrlR4 = pDCB->CtrlR4; - ptr->SyncMode = pDCB->SyncMode; - } - ptr = ptr->pNextDCB; - } + UCHAR bval, i, cnt; + PDCB ptr; + + if( !(pDCB->TargetLUN) ) + { + if( !pACB->scan_devices ) + { + ptr = pACB->pLinkDCB; + cnt = pACB->DCBCnt; + bval = pDCB->TargetID; + for(i=0; i<cnt; i++) + { + if( ptr->TargetID == bval ) + { + ptr->SyncPeriod = pDCB->SyncPeriod; + ptr->SyncOffset = pDCB->SyncOffset; + ptr->CtrlR3 = pDCB->CtrlR3; + ptr->CtrlR4 = pDCB->CtrlR4; + ptr->SyncMode = pDCB->SyncMode; } + ptr = ptr->pNextDCB; + } } - return; + } + return; } -void dc390_Disconnect(PACB pACB) +void +dc390_Disconnect( PACB pACB ) { - PDCB pDCB; - PSRB pSRB, psrb; - UCHAR i, cnt; - - DEBUG0(printk(KERN_INFO "DISC,"); - ) - pDCB = pACB->pActiveDCB; - if (!pDCB) { - int j = 400; - DEBUG0(printk(KERN_WARNING "ACB:%08lx->ActiveDCB:%08lx IOPort:%04x IRQ:%02x !\n", \ - (ULONG) pACB, (ULONG) pDCB, pACB->IOPortBase, pACB->IRQLevel); - ) - while (--j) - udelay(1000); - DC390_read8(INT_Status); /* Reset Pending INT */ - DC390_write8(ScsiCmd, EN_SEL_RESEL); - return; + PDCB pDCB; + PSRB pSRB, psrb; + UCHAR i, cnt; + + DEBUG0(printk(KERN_INFO "DISC,");) + + if (!pACB->Connected) printk(KERN_ERR "DC390: Disconnect not-connected bus?\n"); + pACB->Connected = 0; + pDCB = pACB->pActiveDCB; + if (!pDCB) + { + int j = 400; + DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\ + pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel);) + while (--j) udelay (1000); + DC390_read8 (INT_Status); /* Reset Pending INT */ + DC390_write8 (ScsiCmd, EN_SEL_RESEL); + return; + } + DC390_write8 (ScsiCmd, EN_SEL_RESEL); + pSRB = pDCB->pActiveSRB; + pACB->pActiveDCB = 0; + pSRB->ScsiPhase = SCSI_NOP0; + if( pSRB->SRBState & SRB_UNEXPECT_RESEL ) + { + pSRB->SRBState = 0; + dc390_Waiting_process ( pACB ); + } + else if( pSRB->SRBState & SRB_ABORT_SENT ) + { + pDCB->TagMask = 0; + pDCB->DCBFlag = 0; + cnt = pDCB->GoingSRBCnt; + pDCB->GoingSRBCnt = 0; + pSRB = pDCB->pGoingSRB; + for( i=0; i < cnt; i++) + { + psrb = pSRB->pNextSRB; + dc390_Free_insert (pACB, pSRB); + pSRB = psrb; } - pSRB = pDCB->pActiveSRB; - pACB->pActiveDCB = 0; - pSRB->ScsiPhase = SCSI_NOP0; - DC390_write8(ScsiCmd, EN_SEL_RESEL); - if (pSRB->SRBState & SRB_UNEXPECT_RESEL) { - pSRB->SRBState = 0; - dc390_DoWaitingSRB(pACB); - } else if (pSRB->SRBState & SRB_ABORT_SENT) { - pDCB->TagMask = 0; - pDCB->DCBFlag = 0; - cnt = pDCB->GoingSRBCnt; - pDCB->GoingSRBCnt = 0; - pSRB = pDCB->pGoingSRB; - for (i = 0; i < cnt; i++) { - psrb = pSRB->pNextSRB; - pSRB->pNextSRB = pACB->pFreeSRB; - pACB->pFreeSRB = pSRB; - pSRB = psrb; - } - pDCB->pGoingSRB = 0; - dc390_DoWaitingSRB(pACB); - } else { - if ((pSRB->SRBState & (SRB_START_ + SRB_MSGOUT)) || - !(pSRB->SRBState & (SRB_DISCONNECT + SRB_COMPLETED))) { /* Selection time out */ - if (!(pACB->scan_devices)) { - pSRB->SRBState = SRB_READY; - dc390_RewaitSRB(pDCB, pSRB); - } else { - pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT; - goto disc1; - } - } else if (pSRB->SRBState & SRB_DISCONNECT) { - dc390_DoWaitingSRB(pACB); - } else if (pSRB->SRBState & SRB_COMPLETED) { - disc1: - if (pDCB->MaxCommand > 1) { - pDCB->TagMask &= (~(1 << pSRB->TagNumber)); /* free tag mask */ - } - pDCB->pActiveSRB = 0; - pSRB->SRBState = SRB_FREE; - dc390_SRBdone(pACB, pDCB, pSRB); - } + pDCB->pGoingSRB = 0; + dc390_Query_to_Waiting (pACB); + dc390_Waiting_process (pACB); + } + else + { + if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) || + !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) ) + { /* Selection time out */ + if( !(1/*pACB->scan_devices*/) ) + { + pSRB->SRBState = SRB_READY; + dc390_freetag (pDCB, pSRB); + dc390_Going_to_Waiting (pDCB, pSRB); + dc390_waiting_timer (pACB, HZ/5); + } + else + { + pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT; + goto disc1; + } } - pACB->MsgLen = 0; + else if( pSRB->SRBState & SRB_DISCONNECT ) + { + dc390_Waiting_process ( pACB ); + } + else if( pSRB->SRBState & SRB_COMPLETED ) + { +disc1: + dc390_freetag (pDCB, pSRB); + pDCB->pActiveSRB = 0; + pSRB->SRBState = SRB_FREE; + dc390_SRBdone( pACB, pDCB, pSRB); + } + } + pACB->MsgLen = 0; } -void dc390_Reselect(PACB pACB) +void +dc390_Reselect( PACB pACB ) { - PDCB pDCB; - PSRB pSRB; - USHORT wval; - UCHAR bval; - - DEBUG0(printk(KERN_INFO "RSEL,"); - ) - pDCB = pACB->pActiveDCB; - if (pDCB) { /* Arbitration lost but Reselection won */ - DEBUG0(printk("(ActiveDCB != 0)"); - ) - pSRB = pDCB->pActiveSRB; - if (!(pACB->scan_devices)) { - pSRB->SRBState = SRB_READY; - dc390_RewaitSRB(pDCB, pSRB); - } + PDCB pDCB; + PSRB pSRB; + UCHAR id, lun; + + DEBUG0(printk(KERN_INFO "RSEL,");) + pACB->Connected = 1; + pDCB = pACB->pActiveDCB; + if( pDCB ) + { /* Arbitration lost but Reselection won */ + DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n");) + pSRB = pDCB->pActiveSRB; + if( !( pACB->scan_devices ) ) + { + pSRB->SRBState = SRB_READY; + dc390_freetag (pDCB, pSRB); + dc390_Going_to_Waiting ( pDCB, pSRB); + dc390_waiting_timer (pACB, HZ/5); } - bval = DC390_read8(ScsiFifo); /* get ID */ - DEBUG0(printk("Dev %02x,", bval); - ) - bval ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */ - wval = 0; - while (bval >>= 1) - wval++; - wval |= ((USHORT) DC390_read8(ScsiFifo) & 7) << 8; /* get LUN */ - DEBUG0(printk("(ID %02x, LUN %02x),", wval & 0xff, (wval & 0xff00) >> 8); - ) - pDCB = pACB->pLinkDCB; - while (wval != *((PUSHORT) & pDCB->UnitSCSIID)) { - pDCB = pDCB->pNextDCB; - if (pDCB == pACB->pLinkDCB) { - printk(KERN_ERR "DC390: Reselect from non existing device (ID %02x, LUN %02x)\n", - wval & 0xff, (wval & 0xff00) >> 8); - return; - } + } + /* Get ID */ + lun = DC390_read8 (ScsiFifo); + DEBUG0(printk ("Dev %02x,", lun);) + if (!(lun & (1 << pACB->pScsiHost->this_id))) + printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun); + else + lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */ + id = 0; while (lun >>= 1) id++; + /* Get LUN */ + lun = DC390_read8 (ScsiFifo); + if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n"); + lun &= 7; + DEBUG0(printk ("(%02i-%i),", id, lun);) + pDCB = dc390_findDCB (pACB, id, lun); + if (!pDCB) + { + printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n", + id, lun); + return; + } + pACB->pActiveDCB = pDCB; + /* TagQ: We expect a message soon, so never mind the exact SRB */ + if( pDCB->SyncMode & EN_TAG_QUEUEING ) + { + pSRB = pACB->pTmpSRB; + pDCB->pActiveSRB = pSRB; + } + else + { + pSRB = pDCB->pActiveSRB; + if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) ) + { + pSRB= pACB->pTmpSRB; + pSRB->SRBState = SRB_UNEXPECT_RESEL; + printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n", + id, lun); + pDCB->pActiveSRB = pSRB; + dc390_EnableMsgOut_Abort ( pACB, pSRB ); } - pACB->pActiveDCB = pDCB; - if (pDCB->SyncMode & EN_TAG_QUEUEING) { - pSRB = pACB->pTmpSRB; /* ?? */ - pDCB->pActiveSRB = pSRB; - } else { - pSRB = pDCB->pActiveSRB; - if (!pSRB || !(pSRB->SRBState & SRB_DISCONNECT)) { - pSRB = pACB->pTmpSRB; - pSRB->SRBState = SRB_UNEXPECT_RESEL; - printk(KERN_ERR "DC390: Reselect without outstanding cmnd (ID %02x, LUN %02x)\n", - wval & 0xff, (wval & 0xff00) >> 8); - pDCB->pActiveSRB = pSRB; - dc390_EnableMsgOut_Abort(pACB, pSRB); - } else { - if (pDCB->DCBFlag & ABORT_DEV_) { - pSRB->SRBState = SRB_ABORT_SENT; - printk(KERN_INFO "DC390: Reselect: Abort (ID %02x, LUN %02x)\n", - wval & 0xff, (wval & 0xff00) >> 8); - dc390_EnableMsgOut_Abort(pACB, pSRB); - } else - pSRB->SRBState = SRB_DATA_XFER; - } + else + { + if( pDCB->DCBFlag & ABORT_DEV_ ) + { + pSRB->SRBState = SRB_ABORT_SENT; + printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n", + id, lun); + dc390_EnableMsgOut_Abort( pACB, pSRB ); + } + else + pSRB->SRBState = SRB_DATA_XFER; } - - DEBUG1(printk(KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber); - ) - pSRB->ScsiPhase = SCSI_NOP0; - DC390_write8(Scsi_Dest_ID, pDCB->UnitSCSIID); - DC390_write8(Sync_Period, pDCB->SyncPeriod); - DC390_write8(Sync_Offset, pDCB->SyncOffset); - DC390_write8(CtrlReg1, pDCB->CtrlR1); - DC390_write8(CtrlReg3, pDCB->CtrlR3); - DC390_write8(CtrlReg4, pDCB->CtrlR4); /* ; Glitch eater */ - DC390_write8(ScsiCmd, MSG_ACCEPTED_CMD); /* ;to release the /ACK signal */ + } + + DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber);) + pSRB->ScsiPhase = SCSI_NOP0; + DC390_write8 (Scsi_Dest_ID, pDCB->TargetID); + DC390_write8 (Sync_Period, pDCB->SyncPeriod); + DC390_write8 (Sync_Offset, pDCB->SyncOffset); + DC390_write8 (CtrlReg1, pDCB->CtrlR1); + DC390_write8 (CtrlReg3, pDCB->CtrlR3); + DC390_write8 (CtrlReg4, pDCB->CtrlR4); /* ; Glitch eater */ + DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); /* ;to release the /ACK signal */ } -static void dc390_remove_dev(PACB pACB, PDCB pDCB) +static void +dc390_remove_dev (PACB pACB, PDCB pDCB) { - PDCB pPrevDCB = pACB->pLinkDCB; - - pACB->DCBmap[pDCB->UnitSCSIID] &= ~(1 << pDCB->UnitSCSILUN); - if (pDCB->GoingSRBCnt > 1) { - DCBDEBUG(printk(KERN_INFO "DC390: Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n", \ - pDCB->UnitSCSIID, pDCB->UnitSCSILUN, (int) pDCB, pDCB->GoingSRBCnt); - ) - return; - }; + PDCB pPrevDCB = pACB->pLinkDCB; - if (pDCB == pACB->pLinkDCB) { - if (pDCB->pNextDCB == pDCB) - pDCB->pNextDCB = 0; - pACB->pLinkDCB = pDCB->pNextDCB; - pACB->pLastDCB->pNextDCB = pDCB->pNextDCB; - } else { - while (pPrevDCB->pNextDCB != pDCB) - pPrevDCB = pPrevDCB->pNextDCB; - pPrevDCB->pNextDCB = pDCB->pNextDCB; - if (pDCB == pACB->pLastDCB) - pACB->pLastDCB = pPrevDCB; + if (pDCB->GoingSRBCnt > 1) + { + DCBDEBUG(printk (KERN_INFO "DC390: Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n",\ + pDCB->TargetID, pDCB->TargetLUN, (int)pDCB, pDCB->GoingSRBCnt);) + return; + }; + pACB->DCBmap[pDCB->TargetID] &= ~(1 << pDCB->TargetLUN); + + // The first one + if (pDCB == pACB->pLinkDCB) + { + // The last one + if (pACB->pLastDCB == pDCB) { + pDCB->pNextDCB = 0; pACB->pLastDCB = 0; } - - DCBDEBUG(printk(KERN_INFO "DC390: Driver about to free DCB (ID %i, LUN %i): 0x%08x\n", \ - pDCB->UnitSCSIID, pDCB->UnitSCSILUN, (int) pDCB); - ) - kfree(pDCB); - if (pDCB == pACB->pActiveDCB) - pACB->pActiveDCB = 0; - pACB->DCBCnt--; - /* pACB->DeviceCnt--; */ + pACB->pLinkDCB = pDCB->pNextDCB; + } + else + { + while (pPrevDCB->pNextDCB != pDCB) pPrevDCB = pPrevDCB->pNextDCB; + pPrevDCB->pNextDCB = pDCB->pNextDCB; + if (pDCB == pACB->pLastDCB) pACB->pLastDCB = pPrevDCB; + } + + DCBDEBUG(printk (KERN_INFO "DC390: Driver about to free DCB (ID %i, LUN %i): %p\n",\ + pDCB->TargetID, pDCB->TargetLUN, pDCB);) + if (pDCB == pACB->pActiveDCB) pACB->pActiveDCB = 0; + if (pDCB == pACB->pLinkDCB) pACB->pLinkDCB = pDCB->pNextDCB; + if (pDCB == pACB->pDCBRunRobin) pACB->pDCBRunRobin = pDCB->pNextDCB; + kfree (pDCB); + pACB->DCBCnt--; + /* pACB->DeviceCnt--; */ }; static UCHAR __inline__ - dc390_tagq_blacklist(char *name) +dc390_tagq_blacklist (char* name) { - UCHAR i; - for (i = 0; i < BADDEVCNT; i++) - if (memcmp(name, dc390_baddevname1[i], 28) == 0) - return 1; - return 0; + UCHAR i; + for(i=0; i<BADDEVCNT; i++) + if (memcmp (name, dc390_baddevname1[i], 28) == 0) + return 1; + return 0; }; + - -static void dc390_disc_tagq_set(PDCB pDCB, PSCSI_INQDATA ptr) +static void +dc390_disc_tagq_set (PDCB pDCB, PSCSI_INQDATA ptr) { - /* Check for SCSI format (ANSI and Response data format) */ - if ((ptr->Vers & 0x07) >= 2 || (ptr->RDF & 0x0F) == 2) { - if ((ptr->Flags & SCSI_INQ_CMDQUEUE) && - (pDCB->DevMode & TAG_QUEUEING_) && - /* ((pDCB->DevType == TYPE_DISK) - || (pDCB->DevType == TYPE_MOD)) && */ - !dc390_tagq_blacklist(((char *) ptr) + 8)) { - pDCB->MaxCommand = pDCB->pDCBACB->TagMaxNum; - pDCB->SyncMode |= EN_TAG_QUEUEING /* | EN_ATN_STOP */ ; - pDCB->TagMask = 0; - } else { - /* Do we really need to check for DevType here ? */ - if (0 /*(pDCB->DevMode & EN_DISCONNECT_) */ - /* && ((pDCB->DevType == TYPE_DISK) - || (pDCB->DevType == TYPE_MOD)) */ ) - pDCB->SyncMode |= EN_ATN_STOP; - else - //pDCB->SyncMode &= ~EN_ATN_STOP; - pDCB->SyncMode &= ~0; - } - } + /* Check for SCSI format (ANSI and Response data format) */ + if ( (ptr->Vers & 0x07) >= 2 || (ptr->RDF & 0x0F) == 2 ) + { + if ( (ptr->Flags & SCSI_INQ_CMDQUEUE) && + (pDCB->DevMode & TAG_QUEUEING_) && + /* ((pDCB->DevType == TYPE_DISK) + || (pDCB->DevType == TYPE_MOD)) &&*/ + !dc390_tagq_blacklist (((char*)ptr)+8) ) + { + if (pDCB->MaxCommand ==1) pDCB->MaxCommand = pDCB->pDCBACB->TagMaxNum; + pDCB->SyncMode |= EN_TAG_QUEUEING /* | EN_ATN_STOP */; + //pDCB->TagMask = 0; + } + else + pDCB->MaxCommand = 1; + } }; -static void dc390_add_dev(PACB pACB, PDCB pDCB, PSCSI_INQDATA ptr) +static void +dc390_add_dev (PACB pACB, PDCB pDCB, PSCSI_INQDATA ptr) { - UCHAR bval1 = ptr->DevType & SCSI_DEVTYPE; - pDCB->DevType = bval1; - /* if (bval1 == TYPE_DISK || bval1 == TYPE_MOD) */ - dc390_disc_tagq_set(pDCB, ptr); + UCHAR bval1 = ptr->DevType & SCSI_DEVTYPE; + pDCB->DevType = bval1; + /* if (bval1 == TYPE_DISK || bval1 == TYPE_MOD) */ + dc390_disc_tagq_set (pDCB, ptr); }; -void dc390_SRBdone(PACB pACB, PDCB pDCB, PSRB pSRB) +void +dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ) { - PSRB psrb; - UCHAR bval, status, i; - PSCSICMD pcmd; - PSCSI_INQDATA ptr; - PSGL ptr2; - ULONG swlval; - - pcmd = pSRB->pcmd; - status = pSRB->TargetStatus; - DEBUG0(printk(" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result, \ - pSRB, pcmd->pid); - ) - if (pSRB->SRBFlag & AUTO_REQSENSE) { /* Last command was a Request Sense */ - pSRB->SRBFlag &= ~AUTO_REQSENSE; - pSRB->AdaptStatus = 0; - pSRB->TargetStatus = SCSI_STAT_CHECKCOND; + UCHAR bval, status, i, DCB_removed; + PSCSICMD pcmd; + PSCSI_INQDATA ptr; + PSGL ptr2; + ULONG swlval; + + pcmd = pSRB->pcmd; DCB_removed = 0; + status = pSRB->TargetStatus; + ptr = (PSCSI_INQDATA) (pcmd->request_buffer); + if( pcmd->use_sg ) + ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address); + + DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\ + pSRB, pcmd->pid);) + if(pSRB->SRBFlag & AUTO_REQSENSE) + { /* Last command was a Request Sense */ + pSRB->SRBFlag &= ~AUTO_REQSENSE; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = CHECK_CONDITION << 1; #ifdef DC390_REMOVABLEDEBUG - switch (pcmd->sense_buffer[2] & 0x0f) { - case NOT_READY: - printk(KERN_INFO "DC390: ReqSense: NOT_READY (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n", - pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN, - status, pACB->scan_devices); - break; - case UNIT_ATTENTION: - printk(KERN_INFO "DC390: ReqSense: UNIT_ATTENTION (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n", - pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN, - status, pACB->scan_devices); - break; - case ILLEGAL_REQUEST: - printk(KERN_INFO "DC390: ReqSense: ILLEGAL_REQUEST (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n", - pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN, - status, pACB->scan_devices); - break; - case MEDIUM_ERROR: - printk(KERN_INFO "DC390: ReqSense: MEDIUM_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n", - pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN, - status, pACB->scan_devices); - break; - case HARDWARE_ERROR: - printk(KERN_INFO "DC390: ReqSense: HARDWARE_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n", - pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN, - status, pACB->scan_devices); - break; - } + switch (pcmd->sense_buffer[2] & 0x0f) + { + case NOT_READY: printk (KERN_INFO "DC390: ReqSense: NOT_READY (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n", + pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN, + status, pACB->scan_devices); break; + case UNIT_ATTENTION: printk (KERN_INFO "DC390: ReqSense: UNIT_ATTENTION (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n", + pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN, + status, pACB->scan_devices); break; + case ILLEGAL_REQUEST: printk (KERN_INFO "DC390: ReqSense: ILLEGAL_REQUEST (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n", + pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN, + status, pACB->scan_devices); break; + case MEDIUM_ERROR: printk (KERN_INFO "DC390: ReqSense: MEDIUM_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n", + pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN, + status, pACB->scan_devices); break; + case HARDWARE_ERROR: printk (KERN_INFO "DC390: ReqSense: HARDWARE_ERROR (Cmnd = 0x%02x, Dev = %i-%i, Stat = %i, Scan = %i)\n", + pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN, + status, pACB->scan_devices); break; + } #endif - //pcmd->result = DRIVER_SENSE << 24 | DID_OK << 16 | status; - if (status == SCSI_STAT_CHECKCOND) { - pcmd->result = DID_BAD_TARGET << 16; - goto ckc_e; - } - if (pSRB->RetryCnt == 0) { - (ULONG) (pSRB->CmdBlock[0]) = pSRB->Segment0[0]; - pSRB->TotalXferredLen = pSRB->Segment1[1]; - if ((pSRB->TotalXferredLen) && - (pSRB->TotalXferredLen >= pcmd->underflow)) - pcmd->result |= (DID_OK << 16); - else - pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) | - SCSI_STAT_CHECKCOND; - REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n", pSRB->CmdBlock[0], \ - (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen); - ) - goto ckc_e; - } else { /* Retry */ - pSRB->RetryCnt--; - pSRB->AdaptStatus = 0; - pSRB->TargetStatus = 0; - *((PULONG) & (pSRB->CmdBlock[0])) = pSRB->Segment0[0]; - *((PULONG) & (pSRB->CmdBlock[4])) = pSRB->Segment0[1]; - /* Don't retry on TEST_UNIT_READY */ - if (pSRB->CmdBlock[0] == TEST_UNIT_READY /* || pSRB->CmdBlock[0] == START_STOP */ ) { - pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) - | SCSI_STAT_CHECKCOND; - REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n", pSRB->CmdBlock[0], \ - (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen); - ) - goto ckc_e; - } - pcmd->result |= (DRIVER_SENSE << 24); - pSRB->SGcount = (UCHAR) pSRB->Segment1[0]; - pSRB->ScsiCmdLen = (UCHAR) (pSRB->Segment1[0] >> 8); - pSRB->SGIndex = 0; - pSRB->TotalXferredLen = 0; - pSRB->SGToBeXferLen = 0; - if (pcmd->use_sg) - pSRB->pSegmentList = (PSGL) pcmd->request_buffer; - else if (pcmd->request_buffer) { - pSRB->pSegmentList = (PSGL) & pSRB->Segmentx; - pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; - pSRB->Segmentx.length = pcmd->request_bufflen; - } - if (dc390_StartSCSI(pACB, pDCB, pSRB)) - dc390_RewaitSRB(pDCB, pSRB); - return; + //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status); + if (status == (CHECK_CONDITION << 1)) + { + pcmd->result = MK_RES_LNX(0,DID_BAD_TARGET,0,/*CHECK_CONDITION*/0); + goto ckc_e; + } + if(pSRB->RetryCnt == 0) + { + //(UINT)(pSRB->pcmd->cmnd[0]) = pSRB->Segment0[0]; + pSRB->TotalXferredLen = pSRB->SavedTotXLen; + if( (pSRB->TotalXferredLen) && + (pSRB->TotalXferredLen >= pcmd->underflow) ) + SET_RES_DID(pcmd->result,DID_OK) + else + pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION); + REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->pcmd->cmnd[0],\ + (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);) + goto ckc_e; + } + else /* Retry */ + { + pSRB->RetryCnt--; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + //*((PUINT) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; + //*((PUINT) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1]; + /* Don't retry on TEST_UNIT_READY */ + if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */) + { + pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION); + REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\ + (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);) + goto ckc_e; + } + SET_RES_DRV(pcmd->result,DRIVER_SENSE); + pSRB->SGcount = (UCHAR) pSRB->SavedSGCount; + //pSRB->ScsiCmdLen = (UCHAR) (pSRB->Segment1[0] >> 8); + DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->target, pcmd->lun);) + pSRB->SGIndex = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + if( pcmd->use_sg ) + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + else if( pcmd->request_buffer ) + { + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; + } + if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) { + dc390_Going_to_Waiting ( pDCB, pSRB ); + dc390_waiting_timer (pACB, HZ/5); + } + return; + } + } + if( status ) + { + if( status_byte(status) == CHECK_CONDITION ) + { + REMOVABLEDEBUG(printk (KERN_INFO "DC390: Check_Condition (Cmd %02x, Id %02x, LUN %02x)\n",\ + pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN);) + if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) ) + { + bval = pSRB->SGcount; + swlval = 0; + ptr2 = pSRB->pSegmentList; + for( i=pSRB->SGIndex; i < bval; i++) + { + swlval += ptr2->length; + ptr2++; } + REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n",\ + (UINT) pSRB->TotalXferredLen, (UINT) swlval);) + } + dc390_RequestSense( pACB, pDCB, pSRB ); + return; } - if (status) { - if (status == SCSI_STAT_CHECKCOND) { - REMOVABLEDEBUG(printk(KERN_INFO "DC390: Scsi_Stat_CheckCond (Cmd %02x, Id %02x, LUN %02x)\n", \ - pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN); - ) - if ((pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen)) { - bval = pSRB->SGcount; - swlval = 0; - ptr2 = pSRB->pSegmentList; - for (i = pSRB->SGIndex; i < bval; i++) { - swlval += ptr2->length; - ptr2++; - } - REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n", \ - (UINT) pSRB->TotalXferredLen, (UINT) swlval); - ) - } - dc390_RequestSense(pACB, pDCB, pSRB); - return; - } else if (status == SCSI_STAT_QUEUEFULL) { - bval = (UCHAR) pDCB->GoingSRBCnt; - bval--; - pDCB->MaxCommand = bval; - dc390_RewaitSRB(pDCB, pSRB); - pSRB->AdaptStatus = 0; - pSRB->TargetStatus = 0; - return; - } else if (status == SCSI_STAT_SEL_TIMEOUT) { - pSRB->AdaptStatus = H_SEL_TIMEOUT; - pSRB->TargetStatus = 0; - pcmd->result = DID_BAD_TARGET << 16; - /* Devices are removed below ... */ - } else if (status == SCSI_STAT_BUSY && - (pSRB->CmdBlock[0] == TEST_UNIT_READY || pSRB->CmdBlock[0] == INQUIRY) && - pACB->scan_devices) { - pSRB->AdaptStatus = 0; - pSRB->TargetStatus = status; - pcmd->result = (ULONG) (pSRB->EndMessage << 8) - /* | (ULONG) status */ ; - } else { /* Another error */ - pSRB->AdaptStatus = 0; - if (pSRB->RetryCnt) { /* Retry */ - pSRB->RetryCnt--; - pSRB->TargetStatus = 0; - pSRB->SGIndex = 0; - pSRB->TotalXferredLen = 0; - pSRB->SGToBeXferLen = 0; - if (pcmd->use_sg) - pSRB->pSegmentList = (PSGL) pcmd->request_buffer; - else if (pcmd->request_buffer) { - pSRB->pSegmentList = (PSGL) & pSRB->Segmentx; - pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; - pSRB->Segmentx.length = pcmd->request_bufflen; - } - if (dc390_StartSCSI(pACB, pDCB, pSRB)) - dc390_RewaitSRB(pDCB, pSRB); - return; - } else { /* Report error */ - pcmd->result |= (DID_ERROR << 16) | (ULONG) (pSRB->EndMessage << 8) | - (ULONG) status; - } + else if( status_byte(status) == QUEUE_FULL ) + { + bval = (UCHAR) pDCB->GoingSRBCnt; + bval--; + pDCB->MaxCommand = bval; + dc390_freetag (pDCB, pSRB); + dc390_Going_to_Waiting ( pDCB, pSRB ); + dc390_waiting_timer (pACB, HZ/5); + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + return; + } + else if(status == SCSI_STAT_SEL_TIMEOUT) + { + pSRB->AdaptStatus = H_SEL_TIMEOUT; + pSRB->TargetStatus = 0; + pcmd->result = MK_RES(0,DID_NO_CONNECT,0,0); + /* Devices are removed below ... */ + } + else if (status_byte(status) == BUSY && + (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) && + pACB->scan_devices) + { + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = status; + pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0); + } + else + { /* Another error */ + pSRB->AdaptStatus = 0; + if( pSRB->RetryCnt ) + { /* Retry */ + //printk ("DC390: retry\n"); + pSRB->RetryCnt--; + pSRB->TargetStatus = 0; + pSRB->SGIndex = 0; + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + if( pcmd->use_sg ) + pSRB->pSegmentList = (PSGL) pcmd->request_buffer; + else if( pcmd->request_buffer ) + { + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pcmd->request_buffer; + pSRB->Segmentx.length = pcmd->request_bufflen; } - } else { /* Target status == 0 */ - status = pSRB->AdaptStatus; - if (status & H_OVER_UNDER_RUN) { - pSRB->TargetStatus = 0; - pcmd->result |= (DID_OK << 16) | (pSRB->EndMessage << 8); - } else if (pSRB->SRBStatus & PARITY_ERROR) { - pcmd->result |= (DID_PARITY << 16) | (pSRB->EndMessage << 8); - } else { /* No error */ - pSRB->AdaptStatus = 0; - pSRB->TargetStatus = 0; - pcmd->result |= (DID_OK << 16); + if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) { + dc390_Going_to_Waiting ( pDCB, pSRB ); + dc390_waiting_timer (pACB, HZ/5); } + return; + } + else + { /* Report error */ + //pcmd->result = MK_RES(0, DID_ERROR, pSRB->EndMessage, status); + SET_RES_DID(pcmd->result,DID_ERROR); + SET_RES_MSG(pcmd->result,pSRB->EndMessage); + SET_RES_TARGET(pcmd->result,status); + } } - - ckc_e: - if (pACB->scan_devices) { - if (pSRB->CmdBlock[0] == TEST_UNIT_READY) { + } + else + { /* Target status == 0 */ + status = pSRB->AdaptStatus; + if(status & H_OVER_UNDER_RUN) + { + pSRB->TargetStatus = 0; + SET_RES_DID(pcmd->result,DID_OK); + SET_RES_MSG(pcmd->result,pSRB->EndMessage); + } + else if( pSRB->SRBStatus & PARITY_ERROR) + { + //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0); + SET_RES_DID(pcmd->result,DID_PARITY); + SET_RES_MSG(pcmd->result,pSRB->EndMessage); + } + else /* No error */ + { + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; + SET_RES_DID(pcmd->result,DID_OK); + } + } + if ((pcmd->result & RES_DID) == 0 && + pcmd->cmnd[0] == INQUIRY && + pcmd->cmnd[2] == 0 && + pcmd->request_bufflen >= 8 && + ptr && + (ptr->Vers & 0x07) >= 2) + pDCB->Inquiry7 = ptr->Flags; + +ckc_e: + if( pACB->scan_devices ) + { + if( pcmd->cmnd[0] == TEST_UNIT_READY || + pcmd->cmnd[0] == INQUIRY) + { #ifdef DC390_DEBUG0 - printk(KERN_INFO "DC390: Test_Unit_Ready: result: %08x", pcmd->result); - if (pcmd->result & DRIVER_SENSE << 24) - printk(" (sense: %02x %02x %02x %02x)\n", - pcmd->sense_buffer[0], pcmd->sense_buffer[1], - pcmd->sense_buffer[2], pcmd->sense_buffer[3]); - else - printk("\n"); + printk (KERN_INFO "DC390: %s: result: %08x", + (pcmd->cmnd[0] == INQUIRY? "INQUIRY": "TEST_UNIT_READY"), + pcmd->result); + if (pcmd->result & (DRIVER_SENSE << 24)) printk (" (sense: %02x %02x %02x %02x)\n", + pcmd->sense_buffer[0], pcmd->sense_buffer[1], + pcmd->sense_buffer[2], pcmd->sense_buffer[3]); + else printk ("\n"); #endif - if ((pcmd->result != (DID_OK << 16) && !(pcmd->result & SCSI_STAT_CHECKCOND) && !(pcmd->result & SCSI_STAT_BUSY)) || - ((pcmd->result & DRIVER_SENSE << 24) && (pcmd->sense_buffer[0] & 0x70) == 0x70 && - (pcmd->sense_buffer[2] & 0xf) == ILLEGAL_REQUEST) || pcmd->result & DID_ERROR << 16) { - /* device not present: remove */ - dc390_remove_dev(pACB, pDCB); - - if ((pcmd->target == pACB->pScsiHost->max_id - 1) && - ((pcmd->lun == 0) || (pcmd->lun == pACB->pScsiHost->max_lun - 1))) - pACB->scan_devices = 0; - } else { - /* device present: add */ - if ((pcmd->target == pACB->pScsiHost->max_id - 1) && - (pcmd->lun == pACB->pScsiHost->max_lun - 1)) - pACB->scan_devices = END_SCAN; - /* pACB->DeviceCnt++; *//* Dev is added on INQUIRY */ - } - } + if( (host_byte(pcmd->result) != DID_OK && !(status_byte(pcmd->result) & CHECK_CONDITION) && !(status_byte(pcmd->result) & BUSY)) || + ((driver_byte(pcmd->result) & DRIVER_SENSE) && (pcmd->sense_buffer[0] & 0x70) == 0x70 && + (pcmd->sense_buffer[2] & 0xf) == ILLEGAL_REQUEST) || host_byte(pcmd->result) & DID_ERROR ) + { + /* device not present: remove */ + //dc390_Going_remove (pDCB, pSRB); + dc390_remove_dev (pACB, pDCB); DCB_removed = 1; + + if( (pcmd->target == pACB->pScsiHost->max_id - 1) && + ((pcmd->lun == 0) || (pcmd->lun == pACB->pScsiHost->max_lun - 1)) ) + pACB->scan_devices = 0; + } + else + { + /* device present: add */ + if( (pcmd->target == pACB->pScsiHost->max_id - 1) && + (pcmd->lun == pACB->pScsiHost->max_lun - 1) ) + pACB->scan_devices = END_SCAN ; + /* pACB->DeviceCnt++; */ /* Dev is added on INQUIRY */ + } } - if (pSRB->CmdBlock[0] == INQUIRY && - (pcmd->result == DID_OK << 16 || pcmd->result & SCSI_STAT_CHECKCOND)) { - ptr = (PSCSI_INQDATA) (pcmd->request_buffer); - if (pcmd->use_sg) - ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address); - if ((ptr->DevType & SCSI_DEVTYPE) == TYPE_NODEV) { - /* device not present: remove */ - dc390_remove_dev(pACB, pDCB); - } else { - /* device found: add */ - dc390_add_dev(pACB, pDCB, ptr); - if (pACB->scan_devices) - pACB->DeviceCnt++; - } - if ((pcmd->target == pACB->pScsiHost->max_id - 1) && - (pcmd->lun == pACB->pScsiHost->max_lun - 1)) - pACB->scan_devices = 0; - }; -/* dc390_ReleaseSRB( pDCB, pSRB ); */ - - if (pSRB == pDCB->pGoingSRB) { - pDCB->pGoingSRB = pSRB->pNextSRB; - } else { - psrb = pDCB->pGoingSRB; - while (psrb->pNextSRB != pSRB) - psrb = psrb->pNextSRB; - psrb->pNextSRB = pSRB->pNextSRB; - if (pSRB == pDCB->pGoingLast) - pDCB->pGoingLast = psrb; - } - pSRB->pNextSRB = pACB->pFreeSRB; - pACB->pFreeSRB = pSRB; - pDCB->GoingSRBCnt--; + } + + //if( pSRB->pcmd->cmnd[0] == INQUIRY && + // (host_byte(pcmd->result) == DID_OK || status_byte(pcmd->result) & CHECK_CONDITION) ) + if( pcmd->cmnd[0] == INQUIRY && + (pcmd->result == (DID_OK << 16) || status_byte(pcmd->result) & CHECK_CONDITION) ) + { + if ((ptr->DevType & SCSI_DEVTYPE) == TYPE_NODEV && !DCB_removed) + { + //printk ("DC390: Type = nodev! (%02i-%i)\n", pcmd->target, pcmd->lun); + /* device not present: remove */ + //dc390_Going_remove (pDCB, pSRB); + dc390_remove_dev (pACB, pDCB); DCB_removed = 1; + } + else + { + /* device found: add */ + dc390_add_dev (pACB, pDCB, ptr); + if (pACB->scan_devices) pACB->DeviceCnt++; + } + if( (pcmd->target == pACB->pScsiHost->max_id - 1) && + (pcmd->lun == pACB->pScsiHost->max_lun - 1) ) + pACB->scan_devices = 0; + }; + +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,30) + pcmd->resid = pcmd->request_bufflen - pSRB->TotalXferredLen; +#endif - dc390_DoWaitingSRB(pACB); + if (!DCB_removed) dc390_Going_remove (pDCB, pSRB); + /* Add to free list */ + dc390_Free_insert (pACB, pSRB); - DC390_UNLOCK_ACB_NI; - pcmd->scsi_done(pcmd); - DC390_LOCK_ACB_NI; + DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid);) + DC390_UNLOCK_ACB_NI; + pcmd->scsi_done (pcmd); + DC390_LOCK_ACB_NI; - if (pDCB->QIORBCnt) - dc390_DoNextCmd(pACB, pDCB); - return; + dc390_Query_to_Waiting (pACB); + dc390_Waiting_process (pACB); + return; } -/* Remove all SRBs and tell midlevel code DID_RESET */ -void dc390_DoingSRB_Done(PACB pACB) +/* Remove all SRBs from Going list and inform midlevel */ +void +dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd ) { - PDCB pDCB, pdcb; - PSRB psrb, psrb2; - UCHAR i; - PSCSICMD pcmd; - - pDCB = pACB->pLinkDCB; - pdcb = pDCB; - if (!pdcb) - return; - do { - psrb = pdcb->pGoingSRB; - for (i = 0; i < pdcb->GoingSRBCnt; i++) { - psrb2 = psrb->pNextSRB; - pcmd = psrb->pcmd; - pcmd->result = DID_RESET << 16; - -/* ReleaseSRB( pDCB, pSRB ); */ - - psrb->pNextSRB = pACB->pFreeSRB; - pACB->pFreeSRB = psrb; - - DC390_UNLOCK_ACB_NI; - pcmd->scsi_done(pcmd); - DC390_LOCK_ACB_NI; - psrb = psrb2; - } - pdcb->GoingSRBCnt = 0;; - pdcb->pGoingSRB = NULL; - pdcb->TagMask = 0; - pdcb = pdcb->pNextDCB; - } while (pdcb != pDCB); + PDCB pDCB, pdcb; + PSRB psrb, psrb2; + UCHAR i; + PSCSICMD pcmd; + + pDCB = pACB->pLinkDCB; + pdcb = pDCB; + if (! pdcb) return; + do + { + psrb = pdcb->pGoingSRB; + for( i=0; i<pdcb->GoingSRBCnt; i++) + { + psrb2 = psrb->pNextSRB; + pcmd = psrb->pcmd; + dc390_Free_insert (pACB, psrb); +#ifndef USE_NEW_EH + /* New EH will crash on being given timed out cmnds */ + if (pcmd == cmd) + pcmd->result = MK_RES(0,DID_ABORT,0,0); + else + pcmd->result = MK_RES(0,DID_RESET,0,0); + +/* ReleaseSRB( pDCB, pSRB ); */ + + DEBUG0(printk (KERN_DEBUG "DC390: DoingSRB_Done: done pid %li\n", pcmd->pid);) + DC390_UNLOCK_ACB_NI; + pcmd->scsi_done( pcmd ); + DC390_LOCK_ACB_NI; +#endif + psrb = psrb2; + } + pdcb->GoingSRBCnt = 0;; + pdcb->pGoingSRB = NULL; + pdcb->TagMask = 0; + pdcb = pdcb->pNextDCB; + } while( pdcb != pDCB ); + dc390_Query_to_Waiting (pACB); } -static void dc390_ResetSCSIBus(PACB pACB) +static void +dc390_ResetSCSIBus( PACB pACB ) { - pACB->ACBFlag |= RESET_DEV; - - DC390_write8(ScsiCmd, RST_DEVICE_CMD); - udelay(250); - DC390_write8(ScsiCmd, NOP_CMD); + //DC390_write8 (ScsiCmd, RST_DEVICE_CMD); + //udelay (250); + //DC390_write8 (ScsiCmd, NOP_CMD); - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); - DC390_write8(DMA_Cmd, DMA_IDLE_CMD); - DC390_write8(ScsiCmd, RST_SCSI_BUS_CMD); + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD); + pACB->Connected = 0; - return; + return; } -static void dc390_ScsiRstDetect(PACB pACB) +static void +dc390_ScsiRstDetect( PACB pACB ) { - printk("DC390: Rst_Detect: laststat = %08lx\n", dc390_laststatus); - //DEBUG0(printk(KERN_INFO "RST_DETECT,");) - - DC390_write8(DMA_Cmd, DMA_IDLE_CMD); - /* Unlock before ? */ - /* delay a second */ - { - unsigned int msec = 1 * 1000; - while (--msec) - udelay(1000); - } - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); - - if (pACB->ACBFlag & RESET_DEV) - pACB->ACBFlag |= RESET_DONE; - else { - pACB->ACBFlag |= RESET_DETECT; - - dc390_ResetDevParam(pACB); -/* dc390_DoingSRB_Done( pACB ); ???? */ - dc390_RecoverSRB(pACB); - pACB->pActiveDCB = NULL; - pACB->ACBFlag = 0; - dc390_DoWaitingSRB(pACB); - } - return; + printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus); + //DEBUG0(printk(KERN_INFO "RST_DETECT,");) + + if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + /* Unlock before ? */ + /* delay half a second */ + udelay (1000); + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + pACB->pScsiHost->last_reset = jiffies + 5*HZ/2 + + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]; + pACB->Connected = 0; + + if( pACB->ACBFlag & RESET_DEV ) + pACB->ACBFlag |= RESET_DONE; + else + { /* Reset was issued by sb else */ + pACB->ACBFlag |= RESET_DETECT; + + dc390_ResetDevParam( pACB ); + dc390_DoingSRB_Done( pACB, 0 ); + //dc390_RecoverSRB( pACB ); + pACB->pActiveDCB = NULL; + pACB->ACBFlag = 0; + dc390_Waiting_process( pACB ); + } + return; } static void __inline__ - dc390_RequestSense(PACB pACB, PDCB pDCB, PSRB pSRB) +dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ) { - PSCSICMD pcmd; - - REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n", \ - pSRB->CmdBlock[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN); - ) - pSRB->SRBFlag |= AUTO_REQSENSE; - pSRB->Segment0[0] = (ULONG) pSRB->CmdBlock[0]; - pSRB->Segment0[1] = (ULONG) pSRB->CmdBlock[4]; - pSRB->Segment1[0] = (ULONG) ((pSRB->ScsiCmdLen << 8) + pSRB->SGcount); - pSRB->Segment1[1] = pSRB->TotalXferredLen; - pSRB->AdaptStatus = 0; - pSRB->TargetStatus = 0; /* SCSI_STAT_CHECKCOND; */ - - pcmd = pSRB->pcmd; - - pSRB->Segmentx.address = (PUCHAR) & (pcmd->sense_buffer); - pSRB->Segmentx.length = sizeof(pcmd->sense_buffer); - pSRB->pSegmentList = &pSRB->Segmentx; - pSRB->SGcount = 1; - pSRB->SGIndex = 0; - - pSRB->CmdBlock[0] = REQUEST_SENSE; - pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5; - (USHORT) pSRB->CmdBlock[2] = 0; - (USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer); - pSRB->ScsiCmdLen = 6; - - pSRB->TotalXferredLen = 0; - pSRB->SGToBeXferLen = 0; - if (dc390_StartSCSI(pACB, pDCB, pSRB)) - dc390_RewaitSRB(pDCB, pSRB); + PSCSICMD pcmd; + + REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\ + pSRB->pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN);) + + pSRB->SRBFlag |= AUTO_REQSENSE; + //pSRB->Segment0[0] = (UINT) pSRB->CmdBlock[0]; + //pSRB->Segment0[1] = (UINT) pSRB->CmdBlock[4]; + //pSRB->Segment1[0] = ((UINT)(pSRB->pcmd->cmd_len) << 8) + pSRB->SGcount; + //pSRB->Segment1[1] = pSRB->TotalXferredLen; + pSRB->SavedSGCount = pSRB->SGcount; + pSRB->SavedTotXLen = pSRB->TotalXferredLen; + pSRB->AdaptStatus = 0; + pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */ + + pcmd = pSRB->pcmd; + + pSRB->Segmentx.address = (PUCHAR) &(pcmd->sense_buffer); + pSRB->Segmentx.length = sizeof(pcmd->sense_buffer); + pSRB->pSegmentList = &pSRB->Segmentx; + pSRB->SGcount = 1; + pSRB->SGIndex = 0; + + //pSRB->CmdBlock[0] = REQUEST_SENSE; + //pSRB->CmdBlock[1] = pDCB->TargetLUN << 5; + //(USHORT) pSRB->CmdBlock[2] = 0; + //(USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer); + //pSRB->ScsiCmdLen = 6; + + pSRB->TotalXferredLen = 0; + pSRB->SGToBeXferLen = 0; + if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) { + dc390_Going_to_Waiting ( pDCB, pSRB ); + dc390_waiting_timer (pACB, HZ/5); + } } static void __inline__ - dc390_InvalidCmd(PACB pACB) +dc390_InvalidCmd( PACB pACB ) { - if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ + SRB_MSGOUT)) - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD); + if( pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_+SRB_MSGOUT) ) + DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); } + |