[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>
This commit is contained in:
parent
46e5ba2b64
commit
859232113c
|
@ -351,6 +351,27 @@ static u8 dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
|
||||||
* (DCBs, SRBs, Queueing)
|
* (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)
|
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;
|
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
|
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;
|
u8 sstatus;
|
||||||
struct scatterlist *psgl;
|
u32 ResidCnt;
|
||||||
u32 ResidCnt, xferCnt;
|
|
||||||
u8 dstate = 0;
|
u8 dstate = 0;
|
||||||
|
|
||||||
sstatus = *psstatus;
|
sstatus = *psstatus;
|
||||||
|
@ -776,25 +796,20 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
|
||||||
if( pSRB->SGIndex < pSRB->SGcount )
|
if( pSRB->SGIndex < pSRB->SGcount )
|
||||||
{
|
{
|
||||||
pSRB->pSegmentList++;
|
pSRB->pSegmentList++;
|
||||||
psgl = pSRB->pSegmentList;
|
|
||||||
|
|
||||||
pSRB->SGBusAddr = sg_dma_address(psgl);
|
dc390_start_segment(pSRB);
|
||||||
pSRB->SGToBeXferLen = sg_dma_len(psgl);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pSRB->SGToBeXferLen = 0;
|
pSRB->SGToBeXferLen = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ResidCnt = (u32) DC390_read8 (Current_Fifo) & 0x1f;
|
ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
|
||||||
ResidCnt |= (u32) DC390_read8 (CtcReg_High) << 16;
|
(((u32) DC390_read8 (CtcReg_High) << 16) |
|
||||||
ResidCnt |= (u32) DC390_read8 (CtcReg_Mid) << 8;
|
((u32) DC390_read8 (CtcReg_Mid) << 8) |
|
||||||
ResidCnt += (u32) DC390_read8 (CtcReg_Low);
|
(u32) DC390_read8 (CtcReg_Low));
|
||||||
|
|
||||||
xferCnt = pSRB->SGToBeXferLen - ResidCnt;
|
dc390_advance_segment(pSRB, ResidCnt);
|
||||||
pSRB->SGBusAddr += xferCnt;
|
|
||||||
pSRB->TotalXferredLen += xferCnt;
|
|
||||||
pSRB->SGToBeXferLen = ResidCnt;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((*psstatus & 7) != SCSI_DATA_OUT)
|
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
|
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;
|
u8 sstatus, residual, bval;
|
||||||
struct scatterlist *psgl;
|
u32 ResidCnt, i;
|
||||||
u32 ResidCnt, i;
|
|
||||||
unsigned long xferCnt;
|
unsigned long xferCnt;
|
||||||
u8 *ptr;
|
|
||||||
|
|
||||||
sstatus = *psstatus;
|
sstatus = *psstatus;
|
||||||
|
|
||||||
|
@ -851,10 +864,8 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
|
||||||
if( pSRB->SGIndex < pSRB->SGcount )
|
if( pSRB->SGIndex < pSRB->SGcount )
|
||||||
{
|
{
|
||||||
pSRB->pSegmentList++;
|
pSRB->pSegmentList++;
|
||||||
psgl = pSRB->pSegmentList;
|
|
||||||
|
|
||||||
pSRB->SGBusAddr = sg_dma_address(psgl);
|
dc390_start_segment(pSRB);
|
||||||
pSRB->SGToBeXferLen = sg_dma_len(psgl);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pSRB->SGToBeXferLen = 0;
|
pSRB->SGToBeXferLen = 0;
|
||||||
|
@ -894,41 +905,38 @@ din_1:
|
||||||
/* It seems a DMA Blast abort isn't that bad ... */
|
/* It seems a DMA Blast abort isn't that bad ... */
|
||||||
if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
|
if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
|
||||||
//DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
|
//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));
|
DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
|
||||||
ResidCnt = (u32) DC390_read8 (CtcReg_High);
|
ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
|
||||||
ResidCnt <<= 8;
|
((u32) DC390_read8 (CtcReg_Mid) << 8)) |
|
||||||
ResidCnt |= (u32) DC390_read8 (CtcReg_Mid);
|
(u32) DC390_read8 (CtcReg_Low);
|
||||||
ResidCnt <<= 8;
|
|
||||||
ResidCnt |= (u32) DC390_read8 (CtcReg_Low);
|
|
||||||
|
|
||||||
xferCnt = pSRB->SGToBeXferLen - ResidCnt;
|
xferCnt = dc390_advance_segment(pSRB, ResidCnt);
|
||||||
pSRB->SGBusAddr += xferCnt;
|
|
||||||
pSRB->TotalXferredLen += xferCnt;
|
if (residual) {
|
||||||
pSRB->SGToBeXferLen = ResidCnt;
|
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 */
|
bval = DC390_read8 (ScsiFifo); /* get one residual byte */
|
||||||
|
|
||||||
if (!feedback_requested) {
|
local_irq_save(flags);
|
||||||
feedback_requested = 1;
|
ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
|
||||||
printk(KERN_WARNING "%s: Please, contact <linux-scsi@vger.kernel.org> "
|
if (likely(ptr)) {
|
||||||
"to help improve support for your system.\n", __FILE__);
|
*(ptr + offset) = bval;
|
||||||
|
scsi_kunmap_atomic_sg(ptr);
|
||||||
}
|
}
|
||||||
|
local_irq_restore(flags);
|
||||||
|
WARN_ON(!ptr);
|
||||||
|
|
||||||
ptr = (u8 *) bus_to_virt( pSRB->SGBusAddr );
|
/* 1 more byte read */
|
||||||
*ptr = bval;
|
xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
|
||||||
pSRB->SGBusAddr++;
|
|
||||||
xferCnt++;
|
|
||||||
pSRB->TotalXferredLen++;
|
|
||||||
pSRB->SGToBeXferLen--;
|
|
||||||
}
|
}
|
||||||
DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
|
DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
|
||||||
pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
|
pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if ((*psstatus & 7) != SCSI_DATA_IN)
|
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 */
|
/* 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
|
static void
|
||||||
dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
|
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->TotalXferredLen = 0;
|
||||||
pSRB->SGIndex = 0;
|
pSRB->SGIndex = 0;
|
||||||
if (pcmd->use_sg) {
|
if (pcmd->use_sg) {
|
||||||
|
size_t saved;
|
||||||
pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
|
pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
|
||||||
psgl = pSRB->pSegmentList;
|
psgl = pSRB->pSegmentList;
|
||||||
//dc390_pci_sync(pSRB);
|
//dc390_pci_sync(pSRB);
|
||||||
|
@ -1157,15 +1166,16 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
|
||||||
if( pSRB->SGIndex < pSRB->SGcount )
|
if( pSRB->SGIndex < pSRB->SGcount )
|
||||||
{
|
{
|
||||||
pSRB->pSegmentList++;
|
pSRB->pSegmentList++;
|
||||||
psgl = pSRB->pSegmentList;
|
|
||||||
pSRB->SGBusAddr = sg_dma_address(psgl);
|
dc390_start_segment(pSRB);
|
||||||
pSRB->SGToBeXferLen = sg_dma_len(psgl);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
pSRB->SGToBeXferLen = 0;
|
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",
|
printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
|
||||||
pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
|
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
|
static void
|
||||||
dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
|
dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
|
||||||
{
|
{
|
||||||
struct scatterlist *psgl;
|
|
||||||
unsigned long lval;
|
unsigned long lval;
|
||||||
struct dc390_dcb* pDCB = pACB->pActiveDCB;
|
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);
|
DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
|
||||||
if( !pSRB->SGToBeXferLen )
|
if( !pSRB->SGToBeXferLen )
|
||||||
{
|
{
|
||||||
psgl = pSRB->pSegmentList;
|
dc390_start_segment(pSRB);
|
||||||
pSRB->SGBusAddr = sg_dma_address(psgl);
|
|
||||||
pSRB->SGToBeXferLen = sg_dma_len(psgl);
|
|
||||||
DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
|
DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
|
||||||
}
|
}
|
||||||
lval = pSRB->SGToBeXferLen;
|
lval = pSRB->SGToBeXferLen;
|
||||||
|
|
Loading…
Reference in New Issue