1
0
Fork 0

[SCSI] tmscsim: Remove the last bus_to_virt()

Dynamically map the buffer for PIO for the residue byte.

Signed-off-by: G. Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: James Bottomley <James.Bottomley@SteelEye.com>
hifive-unleashed-5.1
Guennadi Liakhovetski 2007-05-04 23:00:49 +02:00 committed by James Bottomley
parent 46e5ba2b64
commit 859232113c
1 changed files with 63 additions and 55 deletions

View File

@ -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;
@ -741,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;
@ -776,25 +796,20 @@ 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 = sg_dma_address(psgl);
pSRB->SGToBeXferLen = 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);
ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
(((u32) DC390_read8 (CtcReg_High) << 16) |
((u32) DC390_read8 (CtcReg_Mid) << 8) |
(u32) DC390_read8 (CtcReg_Low));
xferCnt = pSRB->SGToBeXferLen - ResidCnt;
pSRB->SGBusAddr += xferCnt;
pSRB->TotalXferredLen += xferCnt;
pSRB->SGToBeXferLen = ResidCnt;
dc390_advance_segment(pSRB, ResidCnt);
}
}
if ((*psstatus & 7) != SCSI_DATA_OUT)
@ -805,13 +820,11 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
}
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;
@ -851,10 +864,8 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
if( pSRB->SGIndex < pSRB->SGcount )
{
pSRB->pSegmentList++;
psgl = pSRB->pSegmentList;
pSRB->SGBusAddr = sg_dma_address(psgl);
pSRB->SGToBeXferLen = sg_dma_len(psgl);
dc390_start_segment(pSRB);
}
else
pSRB->SGToBeXferLen = 0;
@ -894,41 +905,38 @@ 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);
dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24;
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);
ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
((u32) DC390_read8 (CtcReg_Mid) << 8)) |
(u32) DC390_read8 (CtcReg_Low);
xferCnt = pSRB->SGToBeXferLen - ResidCnt;
pSRB->SGBusAddr += xferCnt;
pSRB->TotalXferredLen += xferCnt;
pSRB->SGToBeXferLen = ResidCnt;
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;
if( residual )
{
static int feedback_requested;
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: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
}
}
if ((*psstatus & 7) != SCSI_DATA_IN)
@ -1137,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)
{
@ -1146,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);
@ -1157,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 = sg_dma_address(psgl);
pSRB->SGToBeXferLen = 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);
@ -1286,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;
@ -1315,9 +1324,8 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
if( !pSRB->SGToBeXferLen )
{
psgl = pSRB->pSegmentList;
pSRB->SGBusAddr = sg_dma_address(psgl);
pSRB->SGToBeXferLen = sg_dma_len(psgl);
dc390_start_segment(pSRB);
DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
}
lval = pSRB->SGToBeXferLen;