aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/scsi/tmscsim.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/scsi/tmscsim.c')
-rw-r--r--drivers/scsi/tmscsim.c124
1 files changed, 66 insertions, 58 deletions
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
index 12d8fea3de93..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};
351 * (DCBs, SRBs, Queueing) 351 * (DCBs, SRBs, Queueing)
352 * 352 *
353 **********************************************************************/ 353 **********************************************************************/
354static void inline dc390_start_segment(struct dc390_srb* pSRB)
355{
356 struct scatterlist *psgl = pSRB->pSegmentList;
357
358 /* start new sg segment */
359 pSRB->SGBusAddr = sg_dma_address(psgl);
360 pSRB->SGToBeXferLen = sg_dma_len(psgl);
361}
362
363static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue)
364{
365 unsigned long xfer = pSRB->SGToBeXferLen - residue;
366
367 /* xfer more bytes transferred */
368 pSRB->SGBusAddr += xfer;
369 pSRB->TotalXferredLen += xfer;
370 pSRB->SGToBeXferLen = residue;
371
372 return xfer;
373}
374
354static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun) 375static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
355{ 376{
356 struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL; 377 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)
741} 762}
742 763
743static void 764static void
744dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) 765dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
745{ 766{
746 u8 sstatus; 767 u8 sstatus;
747 struct scatterlist *psgl; 768 u32 ResidCnt;
748 u32 ResidCnt, xferCnt;
749 u8 dstate = 0; 769 u8 dstate = 0;
750 770
751 sstatus = *psstatus; 771 sstatus = *psstatus;
@@ -776,25 +796,20 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
776 if( pSRB->SGIndex < pSRB->SGcount ) 796 if( pSRB->SGIndex < pSRB->SGcount )
777 { 797 {
778 pSRB->pSegmentList++; 798 pSRB->pSegmentList++;
779 psgl = pSRB->pSegmentList;
780 799
781 pSRB->SGBusAddr = sg_dma_address(psgl); 800 dc390_start_segment(pSRB);
782 pSRB->SGToBeXferLen = sg_dma_len(psgl);
783 } 801 }
784 else 802 else
785 pSRB->SGToBeXferLen = 0; 803 pSRB->SGToBeXferLen = 0;
786 } 804 }
787 else 805 else
788 { 806 {
789 ResidCnt = (u32) DC390_read8 (Current_Fifo) & 0x1f; 807 ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
790 ResidCnt |= (u32) DC390_read8 (CtcReg_High) << 16; 808 (((u32) DC390_read8 (CtcReg_High) << 16) |
791 ResidCnt |= (u32) DC390_read8 (CtcReg_Mid) << 8; 809 ((u32) DC390_read8 (CtcReg_Mid) << 8) |
792 ResidCnt += (u32) DC390_read8 (CtcReg_Low); 810 (u32) DC390_read8 (CtcReg_Low));
793 811
794 xferCnt = pSRB->SGToBeXferLen - ResidCnt; 812 dc390_advance_segment(pSRB, ResidCnt);
795 pSRB->SGBusAddr += xferCnt;
796 pSRB->TotalXferredLen += xferCnt;
797 pSRB->SGToBeXferLen = ResidCnt;
798 } 813 }
799 } 814 }
800 if ((*psstatus & 7) != SCSI_DATA_OUT) 815 if ((*psstatus & 7) != SCSI_DATA_OUT)
@@ -805,13 +820,11 @@ dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
805} 820}
806 821
807static void 822static void
808dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus) 823dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
809{ 824{
810 u8 sstatus, residual, bval; 825 u8 sstatus, residual, bval;
811 struct scatterlist *psgl; 826 u32 ResidCnt, i;
812 u32 ResidCnt, i;
813 unsigned long xferCnt; 827 unsigned long xferCnt;
814 u8 *ptr;
815 828
816 sstatus = *psstatus; 829 sstatus = *psstatus;
817 830
@@ -851,10 +864,8 @@ dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
851 if( pSRB->SGIndex < pSRB->SGcount ) 864 if( pSRB->SGIndex < pSRB->SGcount )
852 { 865 {
853 pSRB->pSegmentList++; 866 pSRB->pSegmentList++;
854 psgl = pSRB->pSegmentList;
855 867
856 pSRB->SGBusAddr = sg_dma_address(psgl); 868 dc390_start_segment(pSRB);
857 pSRB->SGToBeXferLen = sg_dma_len(psgl);
858 } 869 }
859 else 870 else
860 pSRB->SGToBeXferLen = 0; 871 pSRB->SGToBeXferLen = 0;
@@ -894,41 +905,38 @@ din_1:
894 /* It seems a DMA Blast abort isn't that bad ... */ 905 /* It seems a DMA Blast abort isn't that bad ... */
895 if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n"); 906 if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
896 //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); 907 //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
897 dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24; 908 dc390_laststatus &= ~0xff000000;
909 dc390_laststatus |= bval << 24;
898 910
899 DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval)); 911 DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
900 ResidCnt = (u32) DC390_read8 (CtcReg_High); 912 ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
901 ResidCnt <<= 8; 913 ((u32) DC390_read8 (CtcReg_Mid) << 8)) |
902 ResidCnt |= (u32) DC390_read8 (CtcReg_Mid); 914 (u32) DC390_read8 (CtcReg_Low);
903 ResidCnt <<= 8; 915
904 ResidCnt |= (u32) DC390_read8 (CtcReg_Low); 916 xferCnt = dc390_advance_segment(pSRB, ResidCnt);
905 917
906 xferCnt = pSRB->SGToBeXferLen - ResidCnt; 918 if (residual) {
907 pSRB->SGBusAddr += xferCnt; 919 size_t count = 1;
908 pSRB->TotalXferredLen += xferCnt; 920 size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList);
909 pSRB->SGToBeXferLen = ResidCnt; 921 unsigned long flags;
910 922 u8 *ptr;
911 if( residual ) 923
912 {
913 static int feedback_requested;
914 bval = DC390_read8 (ScsiFifo); /* get one residual byte */ 924 bval = DC390_read8 (ScsiFifo); /* get one residual byte */
915 925
916 if (!feedback_requested) { 926 local_irq_save(flags);
917 feedback_requested = 1; 927 ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
918 printk(KERN_WARNING "%s: Please, contact <linux-scsi@vger.kernel.org> " 928 if (likely(ptr)) {
919 "to help improve support for your system.\n", __FILE__); 929 *(ptr + offset) = bval;
930 scsi_kunmap_atomic_sg(ptr);
920 } 931 }
932 local_irq_restore(flags);
933 WARN_ON(!ptr);
921 934
922 ptr = (u8 *) bus_to_virt( pSRB->SGBusAddr ); 935 /* 1 more byte read */
923 *ptr = bval; 936 xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
924 pSRB->SGBusAddr++;
925 xferCnt++;
926 pSRB->TotalXferredLen++;
927 pSRB->SGToBeXferLen--;
928 } 937 }
929 DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\ 938 DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
930 pSRB->TotalXferredLen, pSRB->SGToBeXferLen)); 939 pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
931
932 } 940 }
933 } 941 }
934 if ((*psstatus & 7) != SCSI_DATA_IN) 942 if ((*psstatus & 7) != SCSI_DATA_IN)
@@ -1137,7 +1145,7 @@ dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
1137 1145
1138 1146
1139/* handle RESTORE_PTR */ 1147/* handle RESTORE_PTR */
1140/* I presume, this command is already mapped, so, have to remap. */ 1148/* This doesn't look very healthy... to-be-fixed */
1141static void 1149static void
1142dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB) 1150dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
1143{ 1151{
@@ -1146,6 +1154,7 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
1146 pSRB->TotalXferredLen = 0; 1154 pSRB->TotalXferredLen = 0;
1147 pSRB->SGIndex = 0; 1155 pSRB->SGIndex = 0;
1148 if (pcmd->use_sg) { 1156 if (pcmd->use_sg) {
1157 size_t saved;
1149 pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer; 1158 pSRB->pSegmentList = (struct scatterlist *)pcmd->request_buffer;
1150 psgl = pSRB->pSegmentList; 1159 psgl = pSRB->pSegmentList;
1151 //dc390_pci_sync(pSRB); 1160 //dc390_pci_sync(pSRB);
@@ -1157,15 +1166,16 @@ dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
1157 if( pSRB->SGIndex < pSRB->SGcount ) 1166 if( pSRB->SGIndex < pSRB->SGcount )
1158 { 1167 {
1159 pSRB->pSegmentList++; 1168 pSRB->pSegmentList++;
1160 psgl = pSRB->pSegmentList; 1169
1161 pSRB->SGBusAddr = sg_dma_address(psgl); 1170 dc390_start_segment(pSRB);
1162 pSRB->SGToBeXferLen = sg_dma_len(psgl);
1163 } 1171 }
1164 else 1172 else
1165 pSRB->SGToBeXferLen = 0; 1173 pSRB->SGToBeXferLen = 0;
1166 } 1174 }
1167 pSRB->SGToBeXferLen -= pSRB->Saved_Ptr - pSRB->TotalXferredLen; 1175
1168 pSRB->SGBusAddr += pSRB->Saved_Ptr - pSRB->TotalXferredLen; 1176 saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
1177 pSRB->SGToBeXferLen -= saved;
1178 pSRB->SGBusAddr += saved;
1169 printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n", 1179 printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
1170 pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr); 1180 pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
1171 1181
@@ -1286,7 +1296,6 @@ dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
1286static void 1296static void
1287dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir) 1297dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
1288{ 1298{
1289 struct scatterlist *psgl;
1290 unsigned long lval; 1299 unsigned long lval;
1291 struct dc390_dcb* pDCB = pACB->pActiveDCB; 1300 struct dc390_dcb* pDCB = pACB->pActiveDCB;
1292 1301
@@ -1315,9 +1324,8 @@ dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
1315 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir); 1324 DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
1316 if( !pSRB->SGToBeXferLen ) 1325 if( !pSRB->SGToBeXferLen )
1317 { 1326 {
1318 psgl = pSRB->pSegmentList; 1327 dc390_start_segment(pSRB);
1319 pSRB->SGBusAddr = sg_dma_address(psgl); 1328
1320 pSRB->SGToBeXferLen = sg_dma_len(psgl);
1321 DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.")); 1329 DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
1322 } 1330 }
1323 lval = pSRB->SGToBeXferLen; 1331 lval = pSRB->SGToBeXferLen;