diff options
Diffstat (limited to 'drivers/scsi/tmscsim.c')
| -rw-r--r-- | drivers/scsi/tmscsim.c | 227 | 
1 files changed, 78 insertions, 149 deletions
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index a583e89238f..e7b85e832eb 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);  */      }  } @@ -2680,7 +2609,7 @@ static int __init dc390_module_init(void)  		printk (KERN_INFO "DC390: Using safe settings.\n");  	} -	return pci_module_init(&dc390_driver); +	return pci_register_driver(&dc390_driver);  }  static void __exit dc390_module_exit(void)  | 
