Index: dc395x_trm.c =================================================================== RCS file: /home/cvsroot/dc395/dc395x_trm.c,v retrieving revision 1.42 retrieving revision 1.55 diff -u -r1.42 -r1.55 --- dc395x_trm.c 2000/02/19 17:57:22 1.42 +++ dc395x_trm.c 2000/02/25 18:34:14 1.55 @@ -12,7 +12,7 @@ //* Kurt Garloff //* (C) 1999-2000 Kurt Garloff //* License: GNU GPL -//* $Id: dc395x_trm.c,v 1.42 2000/02/19 17:57:22 garloff Exp $ +//* $Id: dc395x_trm.c,v 1.55 2000/02/25 18:34:14 garloff Exp $ //*********************************************************************** //* Tekram PCI SCSI adapter (DC395/U/UW/F or DC315/U) revision history //* @@ -66,6 +66,11 @@ //* The TRM_S1040 does not reliably send an IRQ //* in caise of a failed selection/arbitration //* DEBUGTRACE now safe. New DEBUGFIFO option +//* 1.26 00/02/25 KG __init cleanup. IRQ sharing. dev_id for +//* irq_req. 2.0 compatibility (timer) +//* Avoid DMA for up to 4 bytes (=:PIO) +//* DOP1: Don't rely on CTR being zero, as +//* FIFO may be non-empty. //*********************************************************************** /* ************************************************************************* @@ -106,6 +111,8 @@ //#define DC395x_DEBUGPARSE //#define DC395x_SGPARANOIA //#define DC395x_DEBUGFIFO +//#define DC395x_DEBUGRECURSION +//#define DC395x_DEBUGPIO /* DISable features */ //#define DC395x_NO_DISCONNECT @@ -137,6 +144,19 @@ # define PARSEDEBUG(x) #endif +#ifdef DC395x_DEBUGRECURSION +# define DEBUGRECURSION(x) x +#else +# define DEBUGRECURSION(x) +#endif + +#ifdef DC395x_DEBUGPIO +# define DEBUGPIO(x) x +#else +# define DEBUGPIO(x) +#endif + +/* Here comes the joker of all debugging facilities! */ #ifdef DC395x_DEBUGTRACEALL # ifndef DC395x_DEBUGTRACE # define DC395x_DEBUGTRACE @@ -147,7 +167,7 @@ #endif #ifdef DC395x_DEBUGTRACE # define DEBUGTRACEBUFSZ 704 -static char DC395x_tracebuf[64]; +char DC395x_tracebuf[64]; # define TRACEPRINTF(x...) \ do { int ln = sprintf (DC395x_tracebuf, ## x); \ if (pSRB->debugpos + ln >= DEBUGTRACEBUFSZ) \ @@ -943,6 +963,7 @@ **************************************** */ #define TRM_S1040_SCSI_CONFIG2 0x8F /* SCSI Configuration 2 (R/W) */ +#define CFG2_WIDEFIFO 0x02 /* **************************************** */ @@ -1264,7 +1285,7 @@ void DC395x_DataIO_transfer( PACB pACB, PSRB pSRB, WORD ioDir); void DC395x_Disconnect( PACB pACB ); void DC395x_Reselect( PACB pACB ); - WORD DC395x_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); + BYTE DC395x_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); static void DC395x_BuildSRB(Scsi_Cmnd* pcmd, PDCB pDCB, PSRB pSRB); void DC395x_DoingSRB_Done( PACB pACB, BYTE did_code); static void DC395x_ScsiRstDetect( PACB pACB ); @@ -1287,7 +1308,7 @@ static WORD DC395x_adapterCnt = 0; static WORD DC395x_CurrSyncOffset = 0; -static char in_driver = 0; +DEBUGRECURSION(static char in_driver = 0;) static char DC395x_monitor_next_IRQ = 0; /* @@ -1373,13 +1394,13 @@ #endif /* Delaying after a reset */ -static __initdata char DC395x_interpd [] = {1,3,5,10,16,30,60,120}; -static __init void DC395x_interpret_delay (PNVRAMTYPE pEEpromBuf) +static char __initdata DC395x_interpd [] = {1,3,5,10,16,30,60,120}; +static void __init DC395x_interpret_delay (PNVRAMTYPE pEEpromBuf) { //printk ("DC395x: Debug: Delay: %i\n", pEEpromBuf->NvramDelayTime); pEEpromBuf->NvramDelayTime = DC395x_interpd[pEEpromBuf->NvramDelayTime]; }; -static __init int DC395x_uninterpret_delay (int delay) +static int __init DC395x_uninterpret_delay (int delay) { BYTE idx = 0; while (idx < 7 && DC395x_interpd[idx] < delay) idx++; @@ -1668,6 +1689,16 @@ DC395x_Going_append (pDCB, pSRB); } +/* 2.0 timer compatibility */ +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,1,30) + static inline int timer_pending(struct timer_list * timer) + { + return timer->prev != NULL; + } + #define time_after(a,b) ((long)(b) - (long)(a) < 0) + #define time_before(a,b) time_after(b,a) +#endif + void DC395x_waiting_timed_out (unsigned long ptr); /* Sets the timer to wake us up */ static void DC395x_waiting_timer (PACB pACB, unsigned long to) @@ -1694,8 +1725,7 @@ if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); ptr = pACB->pDCBRunRobin; if( !ptr ) - { - printk ("DC395x: ERROR! pDCBRunRobin == 0!\n"); + { /* This can happen! */ ptr = pACB->pLinkDCB; pACB->pDCBRunRobin = ptr; } @@ -1725,7 +1755,7 @@ void DC395x_waiting_timed_out (unsigned long ptr) { unsigned int flags; - printk ("DC395x: Debug: Waiting queue woken up by timer.\n"); + DEBUG0(printk ("DC395x: Debug: Waiting queue woken up by timer.\n");) DC395x_LOCK_IO; DC395x_Waiting_process ((PACB)ptr); DC395x_UNLOCK_IO; @@ -1832,15 +1862,25 @@ sgp->length = (DWORD) sl[i].length; len += (DWORD) sl[i].length; } + /* WIDE padding */ + if (pDCB->SyncPeriod & WIDE_SYNC && len%2) + { + len++; + sgp->length++; + } pSRB->SRBTotalXferLength = len; } else if( pcmd->request_buffer ) { + DWORD len = pcmd->request_bufflen; /* Actual request size */ pSRB->SRBSGCount = 1; pSRB->SRBSGListPointer = (PSGE0) &pSRB->SegmentX[0];/* a one entry of S/G list table */ pSRB->SegmentX[0].address = (DWORD) virt_to_bus( pcmd->request_buffer );/* Actual requested buffer */ - pSRB->SegmentX[0].length = (DWORD) pcmd->request_bufflen;/* Actual request size */ - pSRB->SRBTotalXferLength = (DWORD) pcmd->request_bufflen; + /* WIDE padding */ + if (pDCB->SyncPeriod & WIDE_SYNC && len%2) + len++; + pSRB->SegmentX[0].length = len; + pSRB->SRBTotalXferLength = len; } else { @@ -1858,8 +1898,8 @@ pSRB->RetryCnt = 0; pSRB->debugpos = 0; - TRACEPRINTF ("pid %li(%li):%02x(%i-%i) *", pcmd->pid, jiffies, - pcmd->cmnd[0], pcmd->target, pcmd->lun); + TRACEPRINTF ("pid %li(%li):%02x %02x..(%i-%i) *", pcmd->pid, jiffies, + pcmd->cmnd[0], pcmd->cmnd[1], pcmd->target, pcmd->lun); pSRB->TagNumber = TAG_NONE; pSRB->ScsiPhase = PH_BUS_FREE; /* initial phase */ @@ -1927,8 +1967,8 @@ printk(KERN_INFO "DC395x: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li)\n",\ cmd->cmnd[0],cmd->target,cmd->lun,cmd->pid);) - if (in_driver++ > NORM_REC_LVL) printk ("DC395x: %i queue_command () recursion? (pid=%li)\n", - in_driver, cmd->pid); + DEBUGRECURSION(if (in_driver++ > NORM_REC_LVL) printk ("DC395x: %i queue_command () recursion? (pid=%li)\n", + in_driver, cmd->pid);) /* Assume BAD_TARGET; will be cleared later */ cmd->result = DID_BAD_TARGET << 16; @@ -1948,7 +1988,7 @@ { /* printk ("DC390: Ignore target %d lun %d\n", cmd->target, cmd->lun); */ - in_driver--; + DEBUGRECURSION(in_driver--;) //return (1); done (cmd); return (0); @@ -1964,7 +2004,7 @@ printk (KERN_ERR "DC395x: kmalloc for DCB failed, target %02x lun %02x\n", cmd->target, cmd->lun); printk ("DC395x: No DCB in queuecommand!\n"); - in_driver--; + DEBUGRECURSION(in_driver--;) #ifdef USE_NEW_EH return (1); #else @@ -1979,7 +2019,7 @@ printk(KERN_INFO "DC395x: Ignore target %02x lun %02x\n", cmd->target, cmd->lun); //return (1); - in_driver--; + DEBUGRECURSION(in_driver--;) done (cmd); return (0); } @@ -1991,7 +2031,7 @@ printk (KERN_ERR "DC395x: no DCB failed, target %02x lun %02x\n", cmd->target, cmd->lun); printk ("DC395x: No DCB in queuecommand (2)!\n"); - in_driver--; + DEBUGRECURSION(in_driver--;) #ifdef USE_NEW_EH return (1); #else @@ -2043,7 +2083,7 @@ //DC395x_ACB_LOCK(pACB,acb_flags); DEBUG1(printk (KERN_DEBUG " ... command (pid %li) queued successfully.\n", cmd->pid);) - in_driver--; + DEBUGRECURSION(in_driver--;) return(0); } @@ -2153,7 +2193,7 @@ #else BYTE pbus = pACB->pbus; BYTE pdevfn = pACB->pdevfn; - pcibios_read_config_word (pbus, pdevfn, PCISTATUS, &pstat); + pcibios_read_config_word (pbus, pdevfn, PCI_STATUS, &pstat); #endif if (!pDCB) pDCB = pACB->pActiveDCB; if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB; @@ -2175,21 +2215,22 @@ TRACEOUT (" %s\n", pSRB->debugtrace); } printk ("DC395x: dump: SCSI block\n"); - printk (" Status %04x FIFOCnt %02x Signal %02x IRQStat %02x\n", + printk (" Status %04x FIFOCnt %02x Signals %02x IRQStat %02x\n", DC395x_read16 (TRM_S1040_SCSI_STATUS), DC395x_read8 (TRM_S1040_SCSI_FIFOCNT), DC395x_read8 (TRM_S1040_SCSI_SIGNAL), DC395x_read8 (TRM_S1040_SCSI_INTSTATUS)); printk (" Sync %02x Target %02x RSelID %02x SCSICtr %08x\n", DC395x_read8 (TRM_S1040_SCSI_SYNC), DC395x_read8 (TRM_S1040_SCSI_TARGETID), DC395x_read8 (TRM_S1040_SCSI_IDMSG), DC395x_read32 (TRM_S1040_SCSI_COUNTER)); - printk (" IRQEn %02x Config %04x Cmd %02x SelTO %02x\n", + printk (" IRQEn %02x Config %04x Cfg2 %02x Cmd %02x SelTO %02x\n", DC395x_read8 (TRM_S1040_SCSI_INTEN), DC395x_read16 (TRM_S1040_SCSI_CONFIG0), + DC395x_read8 (TRM_S1040_SCSI_CONFIG2), DC395x_read8 (TRM_S1040_SCSI_COMMAND), DC395x_read8 (TRM_S1040_SCSI_TIMEOUT)); printk ("DC395x: dump: DMA block\n"); - printk (" Cmd %02x FIFOCnt %02x IRQStat %02x IRQEn %02x Cfg %04x\n", - DC395x_read8 (TRM_S1040_DMA_COMMAND), DC395x_read16 (TRM_S1040_DMA_FIFOCNT), + printk (" Cmd %04x FIFOCnt %04x IRQStat %02x IRQEn %02x Cfg %04x\n", + DC395x_read16 (TRM_S1040_DMA_COMMAND), DC395x_read16 (TRM_S1040_DMA_FIFOCNT), DC395x_read8 (TRM_S1040_DMA_STATUS), DC395x_read8 (TRM_S1040_DMA_INTEN), DC395x_read16 (TRM_S1040_DMA_CONFIG)); - printk (" TCtr %08x CCtr %08x Addr %08x%08x\n", + printk (" TCtr %08x CTCtr %08x Addr %08x%08x\n", DC395x_read32 (TRM_S1040_DMA_XCNT), DC395x_read32 (TRM_S1040_DMA_CXCNT), DC395x_read32 (TRM_S1040_DMA_XHIGHADDR), DC395x_read32 (TRM_S1040_DMA_XLOWADDR)); printk ("DC395x: dump: Misc: GCtrl %02x GStat %02x GTmr %02x\n", @@ -2271,8 +2312,8 @@ pACB = (PACB) cmd->host->hostdata; printk(KERN_INFO "DC395x_abort: pid=%li, target=%02i-%i\n", cmd->pid, cmd->target, cmd->lun); - if (in_driver++ > NORM_REC_LVL) printk ("DC395x: %i abort() recursion? (pid=%li)\n", - in_driver, cmd->pid); + DEBUGRECURSION(if (in_driver++ > NORM_REC_LVL) printk ("DC395x: %i abort() recursion? (pid=%li)\n", + in_driver, cmd->pid);) //DC395x_ACB_LOCK(pACB,acb_flags); @@ -2423,7 +2464,7 @@ #ifndef USE_NEW_EH if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd); #endif - in_driver--; + DEBUGRECURSION(in_driver--;) return( status ); } @@ -2538,8 +2579,8 @@ pACB = (PACB ) cmd->host->hostdata; printk(KERN_INFO "DC395x: reset requested!\n"); pACB = (PACB) cmd->host->hostdata; - if (in_driver++ > NORM_REC_LVL) printk ("DC395x: %i reset recursion? (pid=%li)\n", - in_driver, cmd->pid); + DEBUGRECURSION(if (in_driver++ > NORM_REC_LVL) printk ("DC395x: %i reset recursion? (pid=%li)\n", + in_driver, cmd->pid);) //DC395x_ACB_LOCK(pACB,acb_flags); if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); @@ -2575,7 +2616,7 @@ DC395x_Waiting_process( pACB ); //DC395x_ACB_LOCK(pACB,acb_flags); - in_driver--; + DEBUGRECURSION(in_driver--;) return( SCSI_RESET_SUCCESS ); } @@ -2636,7 +2677,7 @@ ** ********************************************************************* */ -WORD DC395x_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ) +BYTE DC395x_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ) { WORD s_stat2, return_code; BYTE s_stat, scsicommand, i, identify_message; @@ -2869,7 +2910,7 @@ DC395x_LOCK_IO; - if (in_driver++ > NORM_REC_LVL) printk ("DC395x: %i interrupt recursion?\n", in_driver); + DEBUGRECURSION(if (in_driver++ > NORM_REC_LVL) printk ("DC395x: %i interrupt recursion?\n", in_driver);) //DC395x_DRV_LOCK(drv_flags); @@ -2886,7 +2927,7 @@ dma_status = DC395x_read8 (TRM_S1040_DMA_STATUS); if( scsi_status & SCSIINTERRUPT ) break; - if (dma_status) + if (dma_status & 0x20) { printk ("DC395x: Interrupt from DMA engine: %02x!\n", dma_status); printk ("DC395x: This means DMA error! Try to handle ...\n"); @@ -3014,7 +3055,7 @@ DC395x_stateV( pACB, pSRB, &scsi_status ); } out_unlock: - in_driver--; + DEBUGRECURSION(in_driver--;) DC395x_UNLOCK_IO; //printk ("... done\n"); //DC395x_ACB_UNLOCK(pACB,acb_flags); @@ -3298,8 +3339,10 @@ DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_DATALATCH); } - +/* Those no of bytes will be transfered w/ PIO through the SCSI FIFO * + * Seems to be needed for unknown reasons; could be a hardware bug :-( */ +#define DC395x_LASTPIO 4 /* ********************************************************************* ** scsiio @@ -3312,7 +3355,6 @@ */ void DC395x_DataOutPhase0( PACB pACB, PSRB pSRB, PWORD pscsi_status) { - BYTE TempDMAstatus; WORD scsi_status; DWORD dLeftCounter = 0; PDCB pDCB = pSRB->pSRBDCB; @@ -3324,11 +3366,18 @@ //if (timer_pending (&pACB->Data_Timer)) del_timer (&pACB->Data_Timer); pDCB = pSRB->pSRBDCB; scsi_status = *pscsi_status; - + /* * KG: Stop DMA engine pushing more data into the SCSI FIFO * If we need more data, the DMA SG list will be freshly set up, anyway */ +#ifdef DC395x_DEBUGPIO + printk ("DC395x: DOP1: DMA_CNT: %04x, SCSI_FCNT: %02x, CTR %06x, stat %04x, Tot: %06x\n", + DC395x_read16 (TRM_S1040_DMA_FIFOCNT), + DC395x_read8 (TRM_S1040_SCSI_FIFOCNT), + DC395x_read32 (TRM_S1040_SCSI_COUNTER), + *pscsi_status, pSRB->SRBTotalXferLength); +#endif DC395x_write16 (TRM_S1040_DMA_CONTROL, STOPDMAXFER | CLRXFIFO); if( !(pSRB->SRBState & SRB_XFERPAD) ) @@ -3339,7 +3388,7 @@ /* KG: Right, we can't just rely on the SCSI_COUNTER, because this * is the no of bytes it got from the DMA engine not the no it * transferred successfully to the device. (And the difference could - * be as much as the Sync Offset, I guess ...) */ + * be as much as the FIFO size, I guess ...) */ if (!(scsi_status & SCSIXFERDONE)) { /* @@ -3374,26 +3423,35 @@ ** .....TRM_S1040_SCSI_FIFOCNT ( 5bits) ** The counter is SCSI FIFO offset counter (in units of bytes or words) */ - dLeftCounter += DC395x_read32(TRM_S1040_SCSI_COUNTER); - DC395x_clrfifo (pACB, "DOP0"); - /* KG: What is this supposed to be useful for? */ + if (pSRB->SRBTotalXferLength > DC395x_LASTPIO) + dLeftCounter += DC395x_read32(TRM_S1040_SCSI_COUNTER); + TRACEPRINTF ("%05x *", dLeftCounter); + + /* Is this a good idea? */ + //DC395x_clrfifo (pACB, "DOP0"); + /* KG: What is this supposed to be useful for? WIDE padding stuff? */ if ( dLeftCounter == 1 ) { dLeftCounter = 0; printk ("DC395x: DOP0: Discard 1 byte.\n"); } + /* KG: Oops again. Same thinko as above: The SCSI might have been + * faster than the DMA engine, so that it ran out of data. + * In that case, we have to do just nothing! + * But: Why the interrupt: No phase change. No XFERCNT_2_ZERO. Or? */ + /* KG: This is nonsense: We have been WRITING data to the bus * If the SCSI engine has no bytes left, how should the DMA engine? */ - if((dLeftCounter == 0) || (scsi_status & SCSIXFERCNT_2_ZERO) ) - { - int ctr = 6000000; + if ((dLeftCounter == 0) /*|| (scsi_status & SCSIXFERCNT_2_ZERO) )*/) + { /* + int ctr = 6000000; BYTE TempDMAstatus; do { TempDMAstatus = DC395x_read8(TRM_S1040_DMA_STATUS); - } - while( !(TempDMAstatus & DMAXFERCOMP) && --ctr); + } while( !(TempDMAstatus & DMAXFERCOMP) && --ctr); if (ctr < 6000000-1) printk ("DC395x: DMA should be complete ... in DOP1\n"); if (!ctr) printk (KERN_ERR "DC395x: Deadlock in DataOutPhase0 !!\n"); + */ pSRB->SRBTotalXferLength = 0; } else /* Update SG list */ @@ -3413,7 +3471,7 @@ #endif //DC395x_clrfifo (pACB, "DOP0"); //DC395x_write8 (TRM_S1040_DMA_CONTROL, CLRXFIFO | ABORTXFER); -#if 0 +#if 1 if ((*pscsi_status & PHASEMASK) != PH_DATA_OUT) { //printk ("DC395x: Debug: Clean up after Data Out ...\n"); DC395x_cleanup_after_transfer (pACB, pSRB); @@ -3490,8 +3548,49 @@ pSRB->pcmd->pid, pSRB->pcmd->target, pSRB->pcmd->lun); pSRB->SRBStatus |= PARITY_ERROR; } +#if DC395x_LASTPIO + /* KG: Less than or equal to 4 bytes can not be transfered via DMA, it seems. */ + if (pSRB->SRBTotalXferLength <= DC395x_LASTPIO) + { + //DWORD addr = (pSRB->SRBSGListPointer[pSRB->SRBSGIndex].address); + char *ptr = bus_to_virt(pSRB->SRBSGListPointer[pSRB->SRBSGIndex].address); + DEBUGPIO( + printk ("DC395x: DIP0: Try to do PIO (%i %s) for remaining %i bytes:", + DC395x_read8(TRM_S1040_SCSI_FIFOCNT) & 0x1f, + (pSRB->pSRBDCB->SyncPeriod & WIDE_SYNC)? "words": "bytes", + pSRB->SRBTotalXferLength); + ) + + if (pSRB->pSRBDCB->SyncPeriod & WIDE_SYNC) + DC395x_write8 (TRM_S1040_SCSI_CONFIG2, CFG2_WIDEFIFO); + + while (DC395x_read8(TRM_S1040_SCSI_FIFOCNT) != 0x40) + { + BYTE byte = DC395x_read8 (TRM_S1040_SCSI_FIFO); + *ptr++ = byte; DEBUGPIO(printk (" %02x", byte);) + pSRB->SRBTotalXferLength--; + } + if (pSRB->pSRBDCB->SyncPeriod & WIDE_SYNC) + { +#if 1 /* Read the last byte ... */ + if (pSRB->SRBTotalXferLength > 0) + { + BYTE byte = DC395x_read8 (TRM_S1040_SCSI_FIFO); + *ptr++ = byte; pSRB->SRBTotalXferLength--; + DEBUGPIO(printk (" %02x", byte);) + } +#endif + DC395x_write8 (TRM_S1040_SCSI_CONFIG2, 0); + } + //printk (" %08x", *(DWORD*)(bus_to_virt (addr))); + //pSRB->SRBTotalXferLength = 0; + DEBUGPIO(printk ("\n");) + } +#endif /* DC395x_LASTPIO */ + #if 0 - // KG: This was in DATAOUT. If anywhere, it belongs here. + // KG: This was in DATAOUT. Does it also belong here? + // Nobody seems to know what counter and fifo_cnt count exactly ... if (!(scsi_status & SCSIXFERDONE)) { /* @@ -3510,18 +3609,31 @@ #endif dLeftCounter += DC395x_read32(TRM_S1040_SCSI_COUNTER); - +#if 0 + printk ("DC395x: DIP0: ctr=%08x, DMA_FIFO=%04x, SCSI_FIFO=%02x\n", + dLeftCounter, DC395x_read16 (TRM_S1040_DMA_FIFOCNT), + DC395x_read8 (TRM_S1040_SCSI_FIFOCNT)); + printk ("DC395x: DIP0: DMAStat %02x\n", + DC395x_read8 (TRM_S1040_DMA_STATUS)); +#endif + // KG: We should wait for the DMA FIFO to be empty ... // but: it would be better to wait first for the SCSI FIFO and then the // the DMA FIFO to become empty? How do we know, that the device not already // sent data to the FIFO in a MsgIn phase, eg.? if (!(DC395x_read16 (TRM_S1040_DMA_FIFOCNT) & 0x8000)) { - int ctr = 6000000; - printk ("DC395x: Wait for DMA FIFO to flush ...\n"); + //int ctr = 6000000; + DEBUG0(printk ("DC395x: DIP0: Wait for DMA FIFO to flush ...\n");) +#if 0 + //DC395x_write16 (TRM_S1040_DMA_CONTROL, STOPDMAXFER); + DC395x_write32 (TRM_S1040_SCSI_COUNTER, 7); + DC395x_write8 (TRM_S1040_SCSI_COMMAND, SCMD_DMA_IN); while (!(DC395x_read16 (TRM_S1040_DMA_FIFOCNT) & 0x8000) && --ctr); - if (ctr < 6000000-1) printk ("DC395x: Debug: Had to wait for DMA ...\n"); + if (ctr < 6000000-1) printk ("DC395x: Debug: DIP0: Had to wait for DMA ...\n"); if (!ctr) printk (KERN_ERR "DC395x: Deadlock in DIP0 waiting for DMA FIFO empty!!\n"); + DC395x_write32 (TRM_S1040_SCSI_COUNTER, 0); +#endif } // KG: This should not be needed any more! if((dLeftCounter == 0) || (scsi_status & SCSIXFERCNT_2_ZERO) ) @@ -3724,7 +3836,7 @@ } if( pSRB->SRBSGIndex < pSRB->SRBSGCount ) { - if( pSRB->SRBTotalXferLength != 0 ) + if( pSRB->SRBTotalXferLength > DC395x_LASTPIO ) { BYTE dma_status = DC395x_read8 (TRM_S1040_DMA_STATUS); /* KG: What should we do: Use SCSI Cmd 0x90/0x92? */ @@ -3757,35 +3869,91 @@ DC395x_write8 (TRM_S1040_SCSI_COMMAND, SCMD_DMA_IN); DC395x_write16(TRM_S1040_DMA_COMMAND, ioDir); } -#if 0 - /* SCSI command */ - bval = (ioDir == XFERDATAOUT) ? SCMD_DMA_OUT : SCMD_DMA_IN; - /* Start DMA transfer */ - DC395x_write16(TRM_S1040_DMA_COMMAND, ioDir); - /* Start SCSI transfer */ - DC395x_write8(TRM_S1040_SCSI_COMMAND, bval); - //DC395x_data1_timer (pSRB, HZ*2); -#endif } +#if DC395x_LASTPIO + else if (pSRB->SRBTotalXferLength > 0) + { /* The last four bytes: Do PIO */ + //DC395x_clrfifo (pACB, "IO"); + pSRB->SRBSGBusAddr = virt_to_bus (pSRB->SRBSGListPointer + pSRB->SRBSGIndex); + /* + ** load what physical address of Scatter/Gather list table want to be + ** transfer + */ + pSRB->SRBState |= SRB_DATA_XFER; + /* load total transfer length (24bits) max value 16Mbyte */ + DC395x_write32(TRM_S1040_SCSI_COUNTER, pSRB->SRBTotalXferLength); + DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_DATALATCH);/* it's important for atn stop*/ + if (ioDir == XFERDATAOUT) { + char *ptr = bus_to_virt (pSRB->SRBSGListPointer[pSRB->SRBSGIndex].address); + int ln = pSRB->SRBTotalXferLength; + if (pSRB->pSRBDCB->SyncPeriod & WIDE_SYNC) + DC395x_write8 (TRM_S1040_SCSI_CONFIG2, CFG2_WIDEFIFO); + DEBUGPIO(printk ("DC395x: DOP1: PIO %i bytes:", pSRB->SRBTotalXferLength);) + while (pSRB->SRBTotalXferLength) + { + DEBUGPIO(printk (" %02x", (unsigned char)*ptr);) + DC395x_write8 (TRM_S1040_SCSI_FIFO, *ptr++); + pSRB->SRBTotalXferLength--; + } + if (pSRB->pSRBDCB->SyncPeriod & WIDE_SYNC) { + if (ln % 2) { + DC395x_write8 (TRM_S1040_SCSI_FIFO, 0); + DEBUGPIO(printk (" |00");) + } + DC395x_write8 (TRM_S1040_SCSI_CONFIG2, 0); + } + //DC395x_write32(TRM_S1040_SCSI_COUNTER, ln); + DEBUGPIO(printk ("\n");) + DC395x_write8 (TRM_S1040_SCSI_COMMAND, SCMD_FIFO_OUT); + } + else + { + DC395x_write8 (TRM_S1040_SCSI_COMMAND, SCMD_FIFO_IN); + } + } +#endif /* DC395x_LASTPIO */ else /* xfer pad */ { + BYTE data = 0, data2 = 0; if( pSRB->SRBSGCount ) { pSRB->AdaptStatus = H_OVER_UNDER_RUN; pSRB->SRBStatus |= OVER_RUN; } + // KG: despite the fact that we are using 16 bits I/O ops + // the SCSI FIFO is only 8 bits according to the docs + // (we can set bit 1 in 0x8f to serialize FIFO access ...) if (pDCB->SyncPeriod & WIDE_SYNC) + { DC395x_write32(TRM_S1040_SCSI_COUNTER, 2); + DC395x_write8 (TRM_S1040_SCSI_CONFIG2, CFG2_WIDEFIFO); + /* Danger, Robinson: If you find KGs scattered over the wide + * disk, the driver or chip is to blame :-( */ + if (ioDir == XFERDATAOUT) { + DC395x_write8 (TRM_S1040_SCSI_FIFO, 'K'); + DC395x_write8 (TRM_S1040_SCSI_FIFO, 'G'); + } + else + { + data = DC395x_read8(TRM_S1040_SCSI_FIFO); + data2 = DC395x_read8(TRM_S1040_SCSI_FIFO); + //printk ("DC395x: DataIO: Xfer pad: %02x %02x\n", data, data2); + } + DC395x_write8 (TRM_S1040_SCSI_CONFIG2, 0); + } else + { DC395x_write32(TRM_S1040_SCSI_COUNTER, 1); - - // KG: despite the fact that we are using 16 bits I/O ops - // the SCSI FIFO is only 8 bits according to the docs (which are probably wrong) - if(ioDir == XFERDATAOUT) - DC395x_write16(TRM_S1040_SCSI_FIFO, 0); - else - DC395x_read16(TRM_S1040_SCSI_FIFO); - + /* Danger, Robinson: If you find a collection of Ks on your disk + * something broke :-( */ + if (ioDir == XFERDATAOUT) + DC395x_write8(TRM_S1040_SCSI_FIFO, 'K'); + else + { + data = DC395x_read8(TRM_S1040_SCSI_FIFO); + //printk ("DC395x: DataIO: Xfer pad: %02x\n", data); + } + } pSRB->SRBState |= SRB_XFERPAD; DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_DATALATCH);/* it's important for atn stop*/ /* @@ -4044,7 +4212,7 @@ if (pDCB->SyncPeriod & WIDE_SYNC) fact = 500; else fact = 250; - printk (KERN_INFO "DC395x: Target %i: %s Sync: %ins Offset %i (%02i.%01i MB/s)\n", + printk (KERN_INFO "DC395x: Target %02i: %s Sync: %ins Offset %i (%02i.%01i MB/s)\n", pDCB->TargetID, (fact == 500)? "Wide16" :"", pDCB->MinNegoPeriod<<2, pDCB->SyncOffset, (fact/pDCB->MinNegoPeriod), ((fact%pDCB->MinNegoPeriod)*10+pDCB->MinNegoPeriod/2)/pDCB->MinNegoPeriod); @@ -4106,7 +4274,7 @@ /* Completed */ if (!(pSRB->SRBState & SRB_DO_WIDE_NEGO)) { - printk ("DC395x: Target %i initiates Wide Nego ...\n", pDCB->TargetID); + printk ("DC395x: Target %02i initiates Wide Nego ...\n", pDCB->TargetID); memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 4); pSRB->MsgCnt = 4; pSRB->SRBState |= SRB_DO_WIDE_NEGO; DC395x_ENABLE_MSGOUT; @@ -4118,7 +4286,7 @@ pSRB->SRBState &= ~SRB_DO_WIDE_NEGO; //pDCB->SyncMode &= ~(WIDE_NEGO_ENABLE+WIDE_NEGO_DONE); #ifdef DC395x_DEBUG_KG - printk ("DC395x: Wide transfers (%i bit) negotiated with target %i\n", + printk ("DC395x: Wide transfers (%i bit) negotiated with target %02i\n", (8 << pSRB->MsgInBuf[3]), pDCB->TargetID); #endif DC395x_reprog (pACB, pDCB); @@ -4270,9 +4438,9 @@ // Discard wide residual case MSG_IGNOREWIDE: - printk ("DC395x: Ignore Wide Residual!\n"); - DC395x_write32 (TRM_S1040_SCSI_COUNTER, 1); - DC395x_read8 (TRM_S1040_SCSI_FIFO); + DEBUG0(printk ("DC395x: Ignore Wide Residual!\n");) + //DC395x_write32 (TRM_S1040_SCSI_COUNTER, 1); + //DC395x_read8 (TRM_S1040_SCSI_FIFO); break; // nothing has to be done @@ -4719,8 +4887,8 @@ if (pDCB == pACB->pActiveDCB) pACB->pActiveDCB = 0; if (pDCB == pACB->pLinkDCB) pACB->pLinkDCB = pDCB->pNextDCB; if (pDCB == pACB->pDCBRunRobin) pACB->pDCBRunRobin = pDCB->pNextDCB; - kfree (pDCB); pACB->DCBCnt--; + kfree (pDCB); /* pACB->DeviceCnt--; */ }; @@ -4791,7 +4959,7 @@ pcmd = pSRB->pcmd; #ifdef DC395x_DEBUG_KG - printk(KERN_INFO "DC395x: SRBdone (pid %li, target %i-%i): ", + printk(KERN_INFO "DC395x: SRBdone (pid %li, target %02i-%i): ", pSRB->pcmd->pid, pSRB->pcmd->target, pSRB->pcmd->lun); #endif TRACEPRINTF("DONE *"); @@ -4992,6 +5160,18 @@ pACB->scan_devices = 0; }; + /* Here is the info for Doug Gilbert's sg3 ... */ +#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,30) + pcmd->SCp.resid = pSRB->SRBTotalXferLength; +#endif + /* This may be interpreted by sb. or not ... */ + pcmd->SCp.this_residual = pSRB->SRBTotalXferLength; + pcmd->SCp.buffers_residual = 0; +#if 0 + if (pSRB->SRBTotalXferLength && !DCB_removed) + printk ("DC395x: pid %li: %02x (%02i-%i): Missed %i bytes\n", + pcmd->pid, pcmd->cmnd[0], pcmd->target, pcmd->lun, pSRB->SRBTotalXferLength); +#endif if (!DCB_removed) DC395x_Going_remove (pDCB, pSRB, 0); /* Add to free list */ if (pSRB == pACB->pTmpSRB) @@ -5232,7 +5412,7 @@ pcmd = pSRB->pcmd; #ifdef DC395x_DEBUG_KG - printk(KERN_INFO "DC395x_RequestSense for pid %li, target %i-%i\n", + printk(KERN_INFO "DC395x_RequestSense for pid %li, target %02i-%i\n", pcmd->pid, pcmd->target, pcmd->lun); #endif TRACEPRINTF ("RqSn*"); @@ -5560,7 +5740,7 @@ ** before the driver interrupt function is called. */ - if( request_irq(Irq, DC395x_Interrupt, SA_SHIRQ, "DC395x_TRM", NULL) ) + if( request_irq(Irq, DC395x_Interrupt, SA_SHIRQ, "DC395x_TRM", (void*)psh->hostdata) ) { printk(KERN_INFO "DC395x: register IRQ error!\n"); return( -1 ); @@ -5606,7 +5786,7 @@ ** Output : none ************************************************************************ */ -static __init void TRM_S1040_write_all(PNVRAMTYPE pEEpromBuf,WORD scsiIOPort) +static void __init TRM_S1040_write_all(PNVRAMTYPE pEEpromBuf,WORD scsiIOPort) { BYTE *bpEeprom = (BYTE *) pEEpromBuf; BYTE bAddr; @@ -5646,7 +5826,7 @@ ** Output : none *********************************************************************** */ -static __init void TRM_S1040_set_data(WORD scsiIOPort, BYTE bAddr, BYTE bData) +static void __init TRM_S1040_set_data(WORD scsiIOPort, BYTE bAddr, BYTE bData) { int i; BYTE bSendData; @@ -5706,7 +5886,7 @@ ** Output : none ************************************************************************ */ -static __init void TRM_S1040_read_all(PNVRAMTYPE pEEpromBuf, WORD scsiIOPort) +static void __init TRM_S1040_read_all(PNVRAMTYPE pEEpromBuf, WORD scsiIOPort) { BYTE *bpEeprom = (BYTE *) pEEpromBuf; BYTE bAddr; @@ -5737,7 +5917,7 @@ ** Output : bData - data of SEEPROM ************************************************************************ */ -static __init BYTE TRM_S1040_get_data(WORD scsiIOPort, BYTE bAddr) +static BYTE __init TRM_S1040_get_data(WORD scsiIOPort, BYTE bAddr) { int i; BYTE bReadData, bData = 0; @@ -5778,7 +5958,7 @@ ** Output : none ************************************************************************ */ -static __init void TRM_S1040_wait_30us(WORD scsiIOPort) +static void __init TRM_S1040_wait_30us(WORD scsiIOPort) { /* ScsiPortStallExecution(30); wait 30 us */ outb( 5 , scsiIOPort+TRM_S1040_GEN_TIMER); @@ -5798,7 +5978,7 @@ ** Output : none ************************************************************************ */ -static __init void TRM_S1040_write_cmd(WORD scsiIOPort, BYTE bCmd, BYTE bAddr) +static void __init TRM_S1040_write_cmd(WORD scsiIOPort, BYTE bCmd, BYTE bAddr) { int i; BYTE bSendData; @@ -5847,7 +6027,7 @@ ** Output : none ************************************************************************ */ -static __init void DC395x_check_eeprom(PNVRAMTYPE pEEpromBuf, WORD scsiIOPort) +static void __init DC395x_check_eeprom(PNVRAMTYPE pEEpromBuf, WORD scsiIOPort) { WORD *wpEeprom = (WORD *) pEEpromBuf; WORD wAddr, wCheckSum; @@ -5900,7 +6080,7 @@ } /* Print connector and termination config */ -static __init void DC395x_print_config (PACB pACB) +static void __init DC395x_print_config (PACB pACB) { BYTE bval; @@ -5948,7 +6128,7 @@ ** field of the pACB structure MUST have been set. ********************************************************************** */ -static __init PSH DC395x_init(PSHT psht, DWORD io_port, BYTE Irq, WORD index) +static PSH __init DC395x_init(PSHT psht, DWORD io_port, BYTE Irq, WORD index) { PSH psh; PACB pACB; @@ -6011,7 +6191,7 @@ ********************************************************************** */ #ifndef NEW_PCI -static __init void DC395x_set_master(BYTE pci_bus,BYTE pci_device_fn) +static void __init DC395x_set_master(BYTE pci_bus,BYTE pci_device_fn) { WORD cmd; BYTE latency_timer; @@ -6045,7 +6225,7 @@ ********************************************************************** */ #ifdef NEW_PCI -static __init void DC395x_set_pci_cfg( struct pci_dev *pPCI_DEVICE ) +static void __init DC395x_set_pci_cfg( struct pci_dev *pPCI_DEVICE ) { WORD cmd, stat; @@ -6063,7 +6243,7 @@ printk ("->%04x\n", stat); } #else -static __init void DC395x_set_pci_cfg(BYTE pci_bus,BYTE pci_device_fn) +static void __init DC395x_set_pci_cfg(BYTE pci_bus,BYTE pci_device_fn) { WORD cmd; @@ -6936,7 +7116,7 @@ ++irq_count; } if (irq_count == 1) - free_irq(host->irq, NULL); + free_irq(host->irq, DC395x_pACB_start); } release_region(host->io_port,host->n_io_port); Index: dc395x_trm.h =================================================================== RCS file: /home/cvsroot/dc395/dc395x_trm.h,v retrieving revision 1.23 retrieving revision 1.25 diff -u -r1.23 -r1.25 --- dc395x_trm.h 2000/02/19 15:27:20 1.23 +++ dc395x_trm.h 2000/02/25 09:21:11 1.25 @@ -8,7 +8,7 @@ ** ********************************************************************** */ -/* $Id: dc395x_trm.h,v 1.23 2000/02/19 15:27:20 garloff Exp $ */ +/* $Id: dc395x_trm.h,v 1.25 2000/02/25 09:21:11 garloff Exp $ */ /* ***************************************************** ** Tekram TRM_S1040 for DC395x driver, header file @@ -18,7 +18,7 @@ #define DC395x_trm_H #define DC395x_BANNER "Tekram DC395U/UW/F DC315/U" -#define DC395x_VERSION "1.25, 2000-02-19" +#define DC395x_VERSION "1.26, 2000-02-25" /* Kernel version autodetection */ #include