diff options
Diffstat (limited to 'drivers/scsi/tmscsim.c')
-rw-r--r-- | drivers/scsi/tmscsim.c | 225 |
1 files changed, 77 insertions, 148 deletions
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index 3158949ffa62..e7b85e832eb5 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -351,6 +351,27 @@ static u8 dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20}; * (DCBs, SRBs, Queueing) * **********************************************************************/ +static void inline dc390_start_segment(struct dc390_srb* pSRB) +{ + struct scatterlist *psgl = pSRB->pSegmentList; + + /* start new sg segment */ + pSRB->SGBusAddr = sg_dma_address(psgl); + pSRB->SGToBeXferLen = sg_dma_len(psgl); +} + +static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue) +{ + unsigned long xfer = pSRB->SGToBeXferLen - residue; + + /* xfer more bytes transferred */ + pSRB->SGBusAddr += xfer; + pSRB->TotalXferredLen += xfer; + pSRB->SGToBeXferLen = residue; + + return xfer; +} + static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun) { struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL; @@ -625,70 +646,6 @@ dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_sr return 0; } -//#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/ -#define DMA_INT 0 - -#if DMA_INT -/* This is similar to AM53C974.c ... */ -static u8 -dc390_dma_intr (struct dc390_acb* pACB) -{ - struct dc390_srb* pSRB; - u8 dstate; - DEBUG0(u16 pstate; struct pci_dev *pdev = pACB->pdev); - - 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) - { - u32 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 - static void __inline__ dc390_InvalidCmd(struct dc390_acb* pACB) @@ -708,9 +665,6 @@ DC390_Interrupt(void *dev_id) u8 phase; void (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *); u8 istate, istatus; -#if DMA_INT - u8 dstatus; -#endif sstatus = DC390_read8 (Scsi_Status); if( !(sstatus & INTERRUPT) ) @@ -718,22 +672,9 @@ DC390_Interrupt(void *dev_id) DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus)); -#if DMA_INT - spin_lock_irq(pACB->pScsiHost->host_lock); - dstatus = dc390_dma_intr (pACB); - spin_unlock_irq(pACB->pScsiHost->host_lock); - - DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus)); - if (! (dstatus & SCSI_INTERRUPT)) - { - DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n")); - return IRQ_NONE; - } -#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); -#endif spin_lock_irq(pACB->pScsiHost->host_lock); @@ -821,11 +762,10 @@ static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id) } static void -dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) { u8 sstatus; - struct scatterlist *psgl; - u32 ResidCnt, xferCnt; + u32 ResidCnt; u8 dstate = 0; sstatus = *psstatus; @@ -856,42 +796,35 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) if( pSRB->SGIndex < pSRB->SGcount ) { pSRB->pSegmentList++; - psgl = pSRB->pSegmentList; - pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); - pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); + dc390_start_segment(pSRB); } else pSRB->SGToBeXferLen = 0; } else { - ResidCnt = (u32) DC390_read8 (Current_Fifo) & 0x1f; - ResidCnt |= (u32) DC390_read8 (CtcReg_High) << 16; - ResidCnt |= (u32) DC390_read8 (CtcReg_Mid) << 8; - ResidCnt += (u32) DC390_read8 (CtcReg_Low); - - xferCnt = pSRB->SGToBeXferLen - ResidCnt; - pSRB->SGBusAddr += xferCnt; - pSRB->TotalXferredLen += xferCnt; - pSRB->SGToBeXferLen = ResidCnt; + ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) + + (((u32) DC390_read8 (CtcReg_High) << 16) | + ((u32) DC390_read8 (CtcReg_Mid) << 8) | + (u32) DC390_read8 (CtcReg_Low)); + + dc390_advance_segment(pSRB, ResidCnt); } } if ((*psstatus & 7) != SCSI_DATA_OUT) { - DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD); DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); } } static void -dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) +dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) { u8 sstatus, residual, bval; - struct scatterlist *psgl; - u32 ResidCnt, i; + u32 ResidCnt, i; unsigned long xferCnt; - u8 *ptr; sstatus = *psstatus; @@ -922,19 +855,17 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16) \ + ((unsigned long) DC390_read8 (CtcReg_Mid) << 8) \ + ((unsigned long) DC390_read8 (CtcReg_Low))); - DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%i,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen)); + DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%u,ToBeXfer=%lu),", ResidCnt, pSRB->SGToBeXferLen)); - DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); pSRB->TotalXferredLen += pSRB->SGToBeXferLen; pSRB->SGIndex++; if( pSRB->SGIndex < pSRB->SGcount ) { pSRB->pSegmentList++; - psgl = pSRB->pSegmentList; - pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); - pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); + dc390_start_segment(pSRB); } else pSRB->SGToBeXferLen = 0; @@ -973,47 +904,45 @@ din_1: } /* 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; + //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); + dc390_laststatus &= ~0xff000000; + dc390_laststatus |= bval << 24; DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval)); - ResidCnt = (u32) DC390_read8 (CtcReg_High); - ResidCnt <<= 8; - ResidCnt |= (u32) DC390_read8 (CtcReg_Mid); - ResidCnt <<= 8; - ResidCnt |= (u32) DC390_read8 (CtcReg_Low); - - xferCnt = pSRB->SGToBeXferLen - ResidCnt; - pSRB->SGBusAddr += xferCnt; - pSRB->TotalXferredLen += xferCnt; - pSRB->SGToBeXferLen = ResidCnt; - - if( residual ) - { - static int feedback_requested; + ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) | + ((u32) DC390_read8 (CtcReg_Mid) << 8)) | + (u32) DC390_read8 (CtcReg_Low); + + xferCnt = dc390_advance_segment(pSRB, ResidCnt); + + if (residual) { + size_t count = 1; + size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList); + unsigned long flags; + u8 *ptr; + bval = DC390_read8 (ScsiFifo); /* get one residual byte */ - if (!feedback_requested) { - feedback_requested = 1; - printk(KERN_WARNING "%s: Please, contact <linux-scsi@vger.kernel.org> " - "to help improve support for your system.\n", __FILE__); + local_irq_save(flags); + ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count); + if (likely(ptr)) { + *(ptr + offset) = bval; + scsi_kunmap_atomic_sg(ptr); } + local_irq_restore(flags); + WARN_ON(!ptr); - ptr = (u8 *) bus_to_virt( pSRB->SGBusAddr ); - *ptr = bval; - pSRB->SGBusAddr++; xferCnt++; - pSRB->TotalXferredLen++; - pSRB->SGToBeXferLen--; + /* 1 more byte read */ + xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1); } - DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\ + DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\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 */ + DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); } } @@ -1216,7 +1145,7 @@ dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB) /* handle RESTORE_PTR */ -/* I presume, this command is already mapped, so, have to remap. */ +/* This doesn't look very healthy... to-be-fixed */ static void dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) { @@ -1225,6 +1154,7 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) pSRB->TotalXferredLen = 0; pSRB->SGIndex = 0; if (pcmd->use_sg) { + size_t saved; pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer; psgl = pSRB->pSegmentList; //dc390_pci_sync(pSRB); @@ -1236,15 +1166,16 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) if( pSRB->SGIndex < pSRB->SGcount ) { pSRB->pSegmentList++; - psgl = pSRB->pSegmentList; - pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); - pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); + + dc390_start_segment(pSRB); } else pSRB->SGToBeXferLen = 0; } - pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen); - pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen); + + saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen; + pSRB->SGToBeXferLen -= saved; + pSRB->SGBusAddr += saved; printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n", pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr); @@ -1365,7 +1296,6 @@ dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) static void dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) { - struct scatterlist *psgl; unsigned long lval; struct dc390_dcb* pDCB = pACB->pActiveDCB; @@ -1391,12 +1321,11 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) if( pSRB->SGIndex < pSRB->SGcount ) { - DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */); + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); if( !pSRB->SGToBeXferLen ) { - psgl = pSRB->pSegmentList; - pSRB->SGBusAddr = cpu_to_le32(pci_dma_lo32(sg_dma_address(psgl))); - pSRB->SGToBeXferLen = cpu_to_le32(sg_dma_len(psgl)); + dc390_start_segment(pSRB); + DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.")); } lval = pSRB->SGToBeXferLen; @@ -1410,12 +1339,12 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen); DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr); - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); /* | DMA_INT; */ + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); pSRB->SRBState = SRB_DATA_XFER; DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD); - DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); + DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir); //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)); @@ -1436,8 +1365,8 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) 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); + DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); + DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir); */ } } |