Index: README.dc395x =================================================================== RCS file: /home/cvsroot/dc395/README.dc395x,v retrieving revision 1.6 retrieving revision 1.7 diff -u -r1.6 -r1.7 --- README.dc395x 2000/02/14 11:08:31 1.6 +++ README.dc395x 2000/02/19 15:27:19 1.7 @@ -2,7 +2,7 @@ ========================================== Preliminary. 2000-02-14 Kurt Garloff -$Id: README.dc395x,v 1.6 2000/02/14 11:08:31 garloff Exp $ +$Id: README.dc395x,v 1.7 2000/02/19 15:27:19 garloff Exp $ This driver is similar to the DC390/AM53c974 driver (tmscsim), so you might want to have a look into the README.tmscsim. @@ -88,6 +88,20 @@ (Bits: 0: Always 1, 1: Active Negation, 2: Fast Filter enable, 3: Data Filter disable, 4: Active Negation enhance) +Status (4) +---------- +Part of the above said has to be taken back. The driver did still have one +serious bug which -- for timing reasons -- only showed on fast transfers and +a busy SCSI bus. A FIFO was cleared at the wrong place. +Now, the driver seems to work with 20MHz on my system reliably. +The hardware is not quite well supporting more than one initiator controller +on the bus: If the bus is busy and the TRM_S1040 tries to arbitrate and +select a device, it does not always generate an interrupt (which would +indicate Disconnection, Selection Timeout, Reselection or -- in the best +case -- a phase change). The driver takes this into account now and does not +even try. Instead the waiting queue will be woken up by a timer a 50 ms +later to try again. + Exception handling and automatic downgrading -------------------------------------------- For the positive side: @@ -112,12 +126,16 @@ OK, you want to use it anyway? Start with read-only access of your data. catting od dding it to /dev/null is a good start. Proceed with read-only filesystem checks (e2fsck -nfF). -Produce concurrent load on your SCSI bus. Still no trouble? +Produce concurrent load on your SCSI bus. Still no trouble? What does the +badblocks program say? (Take care: With -w it will overwrite your data!) Go on, mount rw an unused partition and run bonnie a couple of times. Run it twice concurrently. If you have not seen any problems by now, you might want to take the risk and use it on your normal filesystems. If you find any trouble, you can reduce the Sync Speed and try again. That way, you may find the best safe settings for your bus. + +Please note that the driver spits out some debug messages from time to time. +Those start with "DC395x: Debug:" and are certainly no reason to worry. If you find trouble, you can contact me, of course. Please, don't bother sending useless bug reports saying: It does not work. You should at least be Index: dc395x_trm.c =================================================================== RCS file: /home/cvsroot/dc395/dc395x_trm.c,v retrieving revision 1.36 retrieving revision 1.42 diff -u -r1.36 -r1.42 --- dc395x_trm.c 2000/02/14 11:08:32 1.36 +++ dc395x_trm.c 2000/02/19 17:57:22 1.42 @@ -12,7 +12,7 @@ //* Kurt Garloff //* (C) 1999-2000 Kurt Garloff //* License: GNU GPL -//* $Id: dc395x_trm.c,v 1.36 2000/02/14 11:08:32 garloff Exp $ +//* $Id: dc395x_trm.c,v 1.42 2000/02/19 17:57:22 garloff Exp $ //*********************************************************************** //* Tekram PCI SCSI adapter (DC395/U/UW/F or DC315/U) revision history //* @@ -62,6 +62,10 @@ //* Fix bug wrt to lowering of sync speed //* Boot params for BIOS-less adapters //* Respect reset cfg but not on shutdown +//* 1.25 00/02/16 KG There was one CLRFIFO too much ... +//* The TRM_S1040 does not reliably send an IRQ +//* in caise of a failed selection/arbitration +//* DEBUGTRACE now safe. New DEBUGFIFO option //*********************************************************************** /* ************************************************************************* @@ -101,6 +105,7 @@ //#define DC395x_DEBUGTRACEALL //#define DC395x_DEBUGPARSE //#define DC395x_SGPARANOIA +//#define DC395x_DEBUGFIFO /* DISable features */ //#define DC395x_NO_DISCONNECT @@ -142,10 +147,13 @@ #endif #ifdef DC395x_DEBUGTRACE # define DEBUGTRACEBUFSZ 704 +static char DC395x_tracebuf[64]; # define TRACEPRINTF(x...) \ -do { pSRB->debugpos += sprintf (pSRB->debugtrace+pSRB->debugpos, ## x) - 1; \ - if (pSRB->debugpos >= DEBUGTRACEBUFSZ-16) \ - { pSRB->debugtrace[pSRB->debugpos] = 0; pSRB->debugpos = DEBUGTRACEBUFSZ/5; pSRB->debugtrace[pSRB->debugpos++] = '-'; }; \ +do { int ln = sprintf (DC395x_tracebuf, ## x); \ + if (pSRB->debugpos + ln >= DEBUGTRACEBUFSZ) \ + { pSRB->debugtrace[pSRB->debugpos] = 0; pSRB->debugpos = DEBUGTRACEBUFSZ/5; pSRB->debugtrace[pSRB->debugpos++] = '>'; }; \ + sprintf (pSRB->debugtrace + pSRB->debugpos, "%s", DC395x_tracebuf); \ + pSRB->debugpos += ln - 1; \ } while (0) # define TRACEOUT(x...) printk (## x) #else @@ -284,7 +292,7 @@ #define IRQ_NONE 255 #define TAG_NONE 255 -typedef unsigned char BYTE; /* 8 bits */ +typedef unsigned char BYTE; /* 8 bits */ typedef unsigned short WORD; /* 16 bits */ typedef unsigned int DWORD; /* 32 bits */ typedef unsigned int UINT; /* 32 bits */ @@ -297,14 +305,15 @@ typedef Scsi_Cmnd *PSCSICMD; typedef void *PVOID; typedef struct scatterlist *PSGL, SGL; + /* -**struct scatterlist -**{ -** char * address; // Location data is to be transferred to -** char * alt_address; // Location of actual if address is a dma indirect buffer. NULL otherwise -** unsigned int length; -**}; -*/ + **struct scatterlist + **{ + ** char * address; // Location data is to be transferred to + ** char * alt_address; // Location of actual if address is a dma indirect buffer. NULL otherwise + ** unsigned int length; + **}; + */ /*-----------------------------------------------------------------------*/ typedef struct _SyncMsg { @@ -1232,9 +1241,9 @@ static void TRM_S1040_write_all(PNVRAMTYPE pEEpromBuf,WORD scsiIOPort); static void TRM_S1040_set_data(WORD scsiIOPort, BYTE bAddr, BYTE bData); static void TRM_S1040_write_cmd(WORD scsiIOPort, BYTE bCmd, BYTE bAddr); - void TRM_S1040_wait_30us(WORD scsiIOPort); +static void TRM_S1040_wait_30us(WORD scsiIOPort); -static void DC395x_DataOutPhase0( PACB pACB, PSRB pSRB, PWORD pscsi_status); + void DC395x_DataOutPhase0( PACB pACB, PSRB pSRB, PWORD pscsi_status); void DC395x_DataInPhase0( PACB pACB, PSRB pSRB, PWORD pscsi_status); static void DC395x_CommandPhase0( PACB pACB, PSRB pSRB, PWORD pscsi_status); static void DC395x_StatusPhase0( PACB pACB, PSRB pSRB, PWORD pscsi_status); @@ -1257,7 +1266,7 @@ void DC395x_Reselect( PACB pACB ); WORD DC395x_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); static void DC395x_BuildSRB(Scsi_Cmnd* pcmd, PDCB pDCB, PSRB pSRB); -static void DC395x_DoingSRB_Done( PACB pACB, BYTE did_code); + void DC395x_DoingSRB_Done( PACB pACB, BYTE did_code); static void DC395x_ScsiRstDetect( PACB pACB ); //static void DC395x_printMsg (BYTE *MsgBuf, DWORD len); static inline void DC395x_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB ); @@ -1336,9 +1345,9 @@ ** 110 175ns, 5.7 MHz ** 111 200ns, 5.0 MHz */ -//BYTE dc395x_clock_period[] = {12,19,25,31,37,44,50,62}; +//static BYTE dc395x_clock_period[] = {12,19,25,31,37,44,50,62}; /* real period:48ns,76ns,100ns,124ns,148ns,176ns,200ns,248ns */ -BYTE dc395x_clock_period[] = {12,18,25,31,37,43,50,62}; +static BYTE dc395x_clock_period[] = {12,18,25,31,37,43,50,62}; /* real period:48ns,72ns,100ns,124ns,148ns,172ns,200ns,248ns */ /* Startup values, to be overriden on the commandline */ @@ -1461,151 +1470,192 @@ } }; -#if 0 -/* Look for a SCSI cmd in a SRB queue */ -static PSRB DC395x_find_cmd_in_SRBq (PSCSICMD cmd, PSRB queue) +/* Find cmd in SRB list */ +inline static PSRB DC395x_find_cmd (PSCSICMD pcmd, PSRB start) { - PSRB q = queue; - while (q) - { - if (q->pcmd == cmd) return q; - q = q->pNextSRB; - if (q == queue) return 0; - } - return q; -}; -#endif - + PSRB psrb = start; + if (!start) return 0; + do + { + if (psrb->pcmd == pcmd) return psrb; + psrb = psrb->pNextSRB; + } while (psrb && psrb != start); + return 0; +} /* Append to Query List */ static void DC395x_Query_append( PSCSICMD cmd, PACB pACB ) { - DEBUG0(printk ("DC395x: Append cmd %li to Query\n", cmd->pid);) - if( !pACB->QueryCnt ) - pACB->pQueryHead = cmd; - else - pACB->pQueryTail->next = cmd; + DEBUG0(printk ("DC395x: Append cmd %li to Query\n", cmd->pid);) + if( !pACB->QueryCnt ) + pACB->pQueryHead = cmd; + else + pACB->pQueryTail->next = cmd; - pACB->pQueryTail = cmd; - pACB->QueryCnt++; - pACB->CmdOutOfSRB++; - cmd->next = NULL; + pACB->pQueryTail = cmd; + pACB->QueryCnt++; + pACB->CmdOutOfSRB++; + cmd->next = NULL; } /* Return next cmd from Query list */ static PSCSICMD DC395x_Query_get ( PACB pACB ) { - PSCSICMD pcmd; + PSCSICMD pcmd; - pcmd = pACB->pQueryHead; - if (!pcmd) return pcmd; - DEBUG0(printk ("DC395x: Get cmd %li from Query\n", pcmd->pid);) - pACB->pQueryHead = pcmd->next; - pcmd->next = NULL; - if (!pACB->pQueryHead) pACB->pQueryTail = NULL; - pACB->QueryCnt--; - return( pcmd ); + pcmd = pACB->pQueryHead; + if (!pcmd) return pcmd; + DEBUG0(printk ("DC395x: Get cmd %li from Query\n", pcmd->pid);) + pACB->pQueryHead = pcmd->next; + pcmd->next = NULL; + if (!pACB->pQueryHead) pACB->pQueryTail = NULL; + pACB->QueryCnt--; + return( pcmd ); } /* Return next free SRB */ static __inline__ PSRB DC395x_Free_get ( PACB pACB ) { - PSRB pSRB; + PSRB pSRB; - pSRB = pACB->pFreeSRB; - DEBUG0(printk ("DC395x: Get Free SRB %p\n", pSRB);) - if( pSRB ) - { - pACB->pFreeSRB = pSRB->pNextSRB; - pSRB->pNextSRB = NULL; - } + //DC395x_Free_integrity (pACB); + pSRB = pACB->pFreeSRB; + if (!pSRB) printk ("DC395x: Out of Free SRBs :-(\n"); + if (pSRB) + { + pACB->pFreeSRB = pSRB->pNextSRB; + pSRB->pNextSRB = NULL; + } - return( pSRB ); + return pSRB; } /* Insert SRB oin top of free list */ static __inline__ void DC395x_Free_insert (PACB pACB, PSRB pSRB) { - DEBUG0(printk ("DC395x: Free SRB %p\n", pSRB);) - pSRB->pNextSRB = pACB->pFreeSRB; - pACB->pFreeSRB = pSRB; + DEBUG0(printk ("DC395x: Free SRB %p\n", pSRB);) + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; } /* Inserts a SRB to the top of the Waiting list */ static __inline__ void DC395x_Waiting_insert ( PDCB pDCB, PSRB pSRB ) { - DEBUG0(printk ("DC395x: Insert pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);) - pSRB->pNextSRB = pDCB->pWaitingSRB; - if (!pDCB->pWaitingSRB) - pDCB->pWaitLast = pSRB; - pDCB->pWaitingSRB = pSRB; - pDCB->WaitSRBCnt++; + DEBUG0(printk ("DC395x: Insert pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);) + pSRB->pNextSRB = pDCB->pWaitingSRB; + if (!pDCB->pWaitingSRB) + pDCB->pWaitLast = pSRB; + pDCB->pWaitingSRB = pSRB; + pDCB->WaitSRBCnt++; } /* Queue SRB to waiting list */ static __inline__ void DC395x_Waiting_append ( PDCB pDCB, PSRB pSRB) { - DEBUG0(printk ("DC395x: Append pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);) - if( pDCB->pWaitingSRB ) - pDCB->pWaitLast->pNextSRB = pSRB; - else - pDCB->pWaitingSRB = pSRB; - - pDCB->pWaitLast = pSRB; - pSRB->pNextSRB = NULL; - pDCB->WaitSRBCnt++; - //pDCB->pDCBACB->CmdInQ++; + DEBUG0(printk ("DC395x: Append pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);) + if( pDCB->pWaitingSRB ) + pDCB->pWaitLast->pNextSRB = pSRB; + else + pDCB->pWaitingSRB = pSRB; + + pDCB->pWaitLast = pSRB; + /* No next one in waiting list */ + pSRB->pNextSRB = NULL; + pDCB->WaitSRBCnt++; + //pDCB->pDCBACB->CmdInQ++; } static __inline__ void DC395x_Going_append (PDCB pDCB, PSRB pSRB) { - pDCB->GoingSRBCnt++; - DEBUG0(printk("DC395x: Append SRB %p to Going\n", pSRB);) - /* Append to the list of Going commands */ - if( pDCB->pGoingSRB ) - pDCB->pGoingLast->pNextSRB = pSRB; - else - pDCB->pGoingSRB = pSRB; - - pDCB->pGoingLast = pSRB; - /* No next one in sent list */ - pSRB->pNextSRB = NULL; + DEBUG0(printk("DC395x: Append SRB %p to Going\n", pSRB);) + /* Append to the list of Going commands */ + if( pDCB->pGoingSRB ) + pDCB->pGoingLast->pNextSRB = pSRB; + else + pDCB->pGoingSRB = pSRB; + + pDCB->pGoingLast = pSRB; + /* No next one in sent list */ + pSRB->pNextSRB = NULL; + pDCB->GoingSRBCnt++; }; -static __inline__ void DC395x_Going_remove (PDCB pDCB, PSRB pSRB) +/* Find predecessor SRB */ +inline static PSRB DC395x_find_SRBpre (PSRB pSRB, PSRB start) { - DEBUG0(printk("DC395x: Remove SRB %p from Going\n", pSRB);) - if (!pSRB) printk ("DC395x: Going_remove %p!\n", pSRB); - if (pSRB == pDCB->pGoingSRB) - pDCB->pGoingSRB = pSRB->pNextSRB; - else - { - PSRB psrb = pDCB->pGoingSRB; - while (psrb && psrb->pNextSRB != pSRB) - psrb = psrb->pNextSRB; - if (!psrb) - { printk (KERN_ERR "DC395x: Remove non-ex. SRB %p from Going!\n", pSRB); return; } - psrb->pNextSRB = pSRB->pNextSRB; + PSRB srb = start; + if (!start) return 0; + do + { + if (srb->pNextSRB == pSRB) return srb; + srb = srb->pNextSRB; + } while (srb && srb != start); + return 0; +} + +/* Remove SRB from SRB queue */ +inline static PSRB DC395x_rmv_SRB (PSRB pSRB, PSRB pre) +{ + if (pre->pNextSRB != pSRB) + pre = DC395x_find_SRBpre (pSRB, pre); + if (!pre) + { + printk ("DC395x: Internal ERROR: SRB to rmv not found in Q!\n"); + return 0; + } + pre->pNextSRB = pSRB->pNextSRB; + //pSRB->pNextSRB = 0; + return pre; +} + +/* Remove SRB from Going queue */ +static void DC395x_Going_remove (PDCB pDCB, PSRB pSRB, PSRB hint) +{ + PSRB pre = 0; + DEBUG0(printk("DC395x: Remove SRB %p from Going\n", pSRB);) + if (!pSRB) printk ("DC395x: Going_remove %p!\n", pSRB); + if (pSRB == pDCB->pGoingSRB) + pDCB->pGoingSRB = pSRB->pNextSRB; + else if (hint && hint->pNextSRB == pSRB) + pre = DC395x_rmv_SRB (pSRB, hint); + else + pre = DC395x_rmv_SRB (pSRB, pDCB->pGoingSRB); if (pSRB == pDCB->pGoingLast) - pDCB->pGoingLast = psrb; - } - pDCB->GoingSRBCnt--; -}; + pDCB->pGoingLast = pre; + pDCB->GoingSRBCnt--; +} +/* Remove SRB from Waiting queue */ +static void DC395x_Waiting_remove (PDCB pDCB, PSRB pSRB, PSRB hint) +{ + PSRB pre = 0; + DEBUG0(printk("DC395x: Remove SRB %p from Waiting\n", pSRB);) + if (!pSRB) printk ("DC395x: Waiting_remove %p!\n", pSRB); + if (pSRB == pDCB->pWaitingSRB) + pDCB->pWaitingSRB = pSRB->pNextSRB; + else if (hint && hint->pNextSRB == pSRB) + pre = DC395x_rmv_SRB (pSRB, hint); + else + pre = DC395x_rmv_SRB (pSRB, pDCB->pWaitingSRB); + if (pSRB == pDCB->pWaitLast) + pDCB->pWaitLast = pre; + pDCB->WaitSRBCnt--; +} + /* Moves SRB from Going list to the top of Waiting list */ static void DC395x_Going_to_Waiting ( PDCB pDCB, PSRB pSRB ) { - DEBUG0(printk(KERN_INFO "DC395x: Going_to_Waiting (SRB %p) pid = %li\n", pSRB, pSRB->pcmd->pid);) - /* Remove SRB from Going */ - DC395x_Going_remove (pDCB, pSRB); - TRACEPRINTF("GtW *"); - /* Insert on top of Waiting */ - DC395x_Waiting_insert (pDCB, pSRB); - /* Tag Mask must be freed elsewhere ! (KG, 99/06/18) */ + DEBUG0(printk(KERN_INFO "DC395x: Going_to_Waiting (SRB %p) pid = %li\n", pSRB, pSRB->pcmd->pid);) + /* Remove SRB from Going */ + DC395x_Going_remove (pDCB, pSRB, 0); + TRACEPRINTF("GtW *"); + /* Insert on top of Waiting */ + DC395x_Waiting_insert (pDCB, pSRB); + /* Tag Mask must be freed elsewhere ! (KG, 99/06/18) */ } /* Moves first SRB from Waiting list to Going list */ @@ -1613,10 +1663,8 @@ { /* Remove from waiting list */ DEBUG0(printk("DC395x: Remove SRB %p from head of Waiting\n", pSRB);) - pDCB->pWaitingSRB = pSRB->pNextSRB; - pDCB->WaitSRBCnt--; + DC395x_Waiting_remove (pDCB, pSRB, 0); TRACEPRINTF("WtG *"); - if( !pDCB->pWaitingSRB ) pDCB->pWaitLast = NULL; DC395x_Going_append (pDCB, pSRB); } @@ -1638,44 +1686,46 @@ /* Send the next command from the waiting list to the bus */ void DC395x_Waiting_process ( PACB pACB ) { - PDCB ptr, ptr1; - PSRB pSRB; - - if( (pACB->pActiveDCB) || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) + PDCB ptr, ptr1; + PSRB pSRB; + + if( (pACB->pActiveDCB) || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) + return; + if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); + ptr = pACB->pDCBRunRobin; + if( !ptr ) + { + printk ("DC395x: ERROR! pDCBRunRobin == 0!\n"); + ptr = pACB->pLinkDCB; + pACB->pDCBRunRobin = ptr; + } + ptr1 = ptr; + if (!ptr1) return; + do + { + /* Make sure, the next another device gets scheduled ... */ + pACB->pDCBRunRobin = ptr1->pNextDCB; + if( !( pSRB = ptr1->pWaitingSRB ) || + ( ptr1->MaxCommand <= ptr1->GoingSRBCnt )) + ptr1 = ptr1->pNextDCB; + else + { + /* Try to send to the bus */ + if( !DC395x_StartSCSI(pACB, ptr1, pSRB) ) + DC395x_Waiting_to_Going (ptr1, pSRB); + else + DC395x_waiting_timer (pACB, HZ/20); + break; + } + } while (ptr1 != ptr); return; - if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); - ptr = pACB->pDCBRunRobin; - if( !ptr ) - { - ptr = pACB->pLinkDCB; - pACB->pDCBRunRobin = ptr; - } - ptr1 = ptr; - if (!ptr1) return; - do - { - pACB->pDCBRunRobin = ptr1->pNextDCB; - if( !( pSRB = ptr1->pWaitingSRB ) || - ( ptr1->MaxCommand <= ptr1->GoingSRBCnt )) - ptr1 = ptr1->pNextDCB; - else - { - /* Try to send to the bus */ - if( !DC395x_StartSCSI(pACB, ptr1, pSRB) ) - DC395x_Waiting_to_Going (ptr1, pSRB); - else - DC395x_waiting_timer (pACB, HZ/5); - break; - } - } while (ptr1 != ptr); - return; } /* Wake up waiting queue */ void DC395x_waiting_timed_out (unsigned long ptr) { unsigned int flags; - printk ("DC395x: Debug: Waiting queue woken up by timer!\n"); + printk ("DC395x: Debug: Waiting queue woken up by timer.\n"); DC395x_LOCK_IO; DC395x_Waiting_process ((PACB)ptr); DC395x_UNLOCK_IO; @@ -1737,7 +1787,7 @@ else { DC395x_Waiting_insert (pDCB, pSRB); - DC395x_waiting_timer (pACB, HZ/5); + DC395x_waiting_timer (pACB, HZ/20); } } @@ -1977,7 +2027,7 @@ } else { - pSRB = DC395x_Free_get ( pACB ); + pSRB = DC395x_Free_get ( pACB ); DEBUG0(if (!pSRB) printk ("DC395x: No free SRB w/o Waiting\n"); else printk ("DC395x: Free SRB w/o Waiting\n");) if (!pSRB) { @@ -2154,21 +2204,22 @@ static int DC395x_recover (PACB pACB, PDCB pDCB, PSRB pSRB) { int ctr = 4097; - unsigned char lines = DC395x_read8 (TRM_S1040_SCSI_SIGNAL); + //unsigned char lines = DC395x_read8 (TRM_S1040_SCSI_SIGNAL); DC395x_EnableMsgOut_Abort (pACB, pSRB); DC395x_cleanup_after_transfer (pACB, pSRB); - if (lines & 1) + if (/*lines & */1) { /* read */ - DC395x_write8 (TRM_S1040_SCSI_CONTROL, DO_HWRESELECT | DO_DATALATCH); + //DC395x_write8 (TRM_S1040_SCSI_CONTROL, DO_HWRESELECT | DO_DATALATCH); while (--ctr && !(DC395x_read16 (TRM_S1040_SCSI_STATUS) & SCSIINTERRUPT)) { - int ctr2 = 16; - DC395x_write32 (TRM_S1040_SCSI_COUNTER, ctr2); - DC395x_write8 (TRM_S1040_SCSI_COMMAND, SCMD_FIFO_IN); - while (ctr2--) DC395x_read8 (TRM_S1040_SCSI_FIFO); + DC395x_write8(TRM_S1040_SCSI_SIGNAL, 0x48); + udelay (1); + DC395x_write8(TRM_S1040_SCSI_SIGNAL, 0x08); + udelay (1); } return ctr; + DC395x_write8 (TRM_S1040_SCSI_CONTROL, DO_HWRESELECT | DO_DATALATCH); } else { @@ -2183,7 +2234,18 @@ return ctr; } } - + +static inline void DC395x_clrfifo (PACB pACB, char *txt) +{ +#ifdef DC395x_DEBUGFIFO + BYTE lines = DC395x_read8(TRM_S1040_SCSI_SIGNAL); + BYTE fifocnt = DC395x_read8 (TRM_S1040_SCSI_FIFOCNT); + if (!(fifocnt & 0x40)) + printk ("DC395x: Clr FIFO (%i bytes) on phase %02x in %s\n", + fifocnt & 0x3f, lines, txt); +#endif + DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); +} /* ********************************************************************** @@ -2198,12 +2260,13 @@ { PACB pACB; PDCB pDCB; - PSRB pSRB = 0, psrb; + PSRB pSRB = 0; + //PSRB psrb; WORD count, i; PSCSICMD pcmd; int status; //DWORD acb_flags=0; - BYTE lines; + //BYTE lines; pACB = (PACB) cmd->host->hostdata; printk(KERN_INFO "DC395x_abort: pid=%li, target=%02i-%i\n", @@ -2248,13 +2311,14 @@ pDCB = DC395x_findDCB (pACB, cmd->target, cmd->lun); if( !pDCB ) goto NOT_RUN; +#if 0 lines = DC395x_read8 (TRM_S1040_SCSI_SIGNAL); if (lines & 0x20 && !pACB->pActiveDCB) { /* We are not connected, but the device is ? */ pSRB = pACB->pTmpSRB; printk ("DC395x: Device is busy, but we are not connected!\n"); - DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "abort"); //DC395x_EnableMsgOut_Abort (pACB, pSRB); pDCB->DCBFlag |= ABORT_DEV_; pDCB->pActiveSRB = pSRB; @@ -2262,54 +2326,24 @@ status = SCSI_ABORT_SNOOZE; goto ABO_X; } - - //pSRB = pDCB->pActiveSRB; - - pSRB = pDCB->pWaitingSRB; - if( !pSRB ) - goto ON_GOING; - - /* Now scan Waiting queue */ - if( pSRB->pcmd == cmd ) - { - pDCB->pWaitingSRB = pSRB->pNextSRB; - goto IN_WAIT; - } - else +#endif + /* Handle waiting queue */ + pSRB = DC395x_find_cmd (cmd, pDCB->pWaitingSRB); + if (pSRB) { - psrb = pSRB; - if( !(psrb->pNextSRB) ) - goto ON_GOING; - while( psrb->pNextSRB->pcmd != cmd ) - { - psrb = psrb->pNextSRB; - if( !(psrb->pNextSRB) || psrb == pSRB) - goto ON_GOING; - } - pSRB = psrb->pNextSRB; - psrb->pNextSRB = pSRB->pNextSRB; - if( pSRB == pDCB->pWaitLast ) - pDCB->pWaitLast = psrb; -IN_WAIT: + DC395x_Waiting_remove (pDCB, pSRB, 0); TRACEPRINTF("abort (SU)!*"); - pDCB->WaitSRBCnt--; DC395x_freetag (pDCB, pSRB); DC395x_Free_insert (pACB, pSRB); - cmd->next = NULL; + //cmd->next = NULL; status = SCSI_ABORT_SUCCESS; goto ABO_X; } - /* SRB has already been sent ? */ -ON_GOING: - pSRB = pDCB->pGoingSRB; - /* Now for the hard part: The command is currently processed */ - for( count = pDCB->GoingSRBCnt, i=0; ipGoingSRB); + if (pSRB) { - if( pSRB->pcmd != cmd ) - pSRB = pSRB->pNextSRB; - else - { PNVRAMTYPE pEEpromBuf = &dc395x_trm_eepromBuf[pACB->AdapterIndex]; /* The command has already been sent: Send MSG_ABORT on the next occasion ! * This will abort all cmnds for this initiator on the device @@ -2373,10 +2407,12 @@ TRACEPRINTF("abort (SN)!*"); goto ABO_X; } - } } -NOT_RUN: +NOT_RUN: + /* If we get here, the cmnd is not in our queues! */ + printk ("DC395x: Abort non-ex. command pid %li (%02i-%i)?", + cmd->pid, cmd->target, cmd->lun); status = SCSI_ABORT_NOT_RUNNING; ABO_X: @@ -2526,7 +2562,7 @@ */ /* Clear SCSI FIFO */ DC395x_write8(TRM_S1040_DMA_CONTROL, CLRXFIFO); - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "reset"); /* Delete pending IRQ */ DC395x_read8 (TRM_S1040_SCSI_INTSTATUS); DC395x_basic_config (pACB); @@ -2603,7 +2639,7 @@ WORD DC395x_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ) { WORD s_stat2, return_code; - BYTE s_stat, scsicommand, i, command, identify_message; + BYTE s_stat, scsicommand, i, identify_message; PBYTE ptr; #ifdef DC395x_DEBUG0 @@ -2614,12 +2650,19 @@ s_stat = DC395x_read8 (TRM_S1040_SCSI_SIGNAL); s_stat2 = 0; s_stat2 = DC395x_read16 (TRM_S1040_SCSI_STATUS); TRACEPRINTF("Start %02x *", s_stat); -#if 0 +#if 1 if (s_stat & 0x20/* s_stat2 & 0x02000 */) { - printk ("DC395x: Debug: StartSCSI: pid %li(%02i-%i): BUSY %02x %04x\n", - pSRB->pcmd->pid, pDCB->TargetID, pDCB->TargetLUN, s_stat, s_stat2); - /* Try anyway! */ + DEBUG0(printk ("DC395x: Debug: StartSCSI: pid %li(%02i-%i): BUSY %02x %04x\n", + pSRB->pcmd->pid, pDCB->TargetID, pDCB->TargetLUN, s_stat, s_stat2);) + /* Try anyway? */ + /* We could, BUT: Sometimes the TRM_S1040 misses to produce a Selection + * Timeout, a Disconnect or a Reselction IRQ, so we would be screwed! + * (This is likely to be a bug in the hardware. Obviously, most people + * only have one initiator per SCSI bus.) + * Instead let this fail and have the timer make sure the command is tried + * again after a short time */ + TRACEPRINTF ("^*"); return 1; }; #endif @@ -2637,6 +2680,7 @@ { DEBUG0(printk ("DC395x: Debug: StartSCSI failed (busy) for pid %li(%02i-%i)\n", pSRB->pcmd->pid, pDCB->TargetID, pDCB->TargetLUN);) + TRACEPRINTF ("°*"); return 1; } /* Allow starting of SCSI commands half a second before we allow the mid-level @@ -2648,7 +2692,7 @@ } /* Flush FIFO */ - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "Start"); DC395x_write8(TRM_S1040_SCSI_HOSTID,pACB->pScsiHost->this_id); DC395x_write8(TRM_S1040_SCSI_TARGETID,pDCB->TargetID); DC395x_write8(TRM_S1040_SCSI_SYNC,pDCB->SyncPeriod); @@ -2747,10 +2791,7 @@ { ptr = (PBYTE) pSRB->pcmd->cmnd; for(i=0; i < pSRB->pcmd->cmd_len; i++) - { - command = *ptr++; - DC395x_write8(TRM_S1040_SCSI_FIFO,command); - } + DC395x_write8(TRM_S1040_SCSI_FIFO, *ptr++); } no_cmd: DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_HWRESELECT | DO_DATALATCH); @@ -2758,11 +2799,12 @@ { /* ** If DC395x_StartSCSI return 1: - ** we caught an interrupt: Let's process it first! + ** we caught an interrupt (must be reset or reselection ... ) + ** : Let's process it first! */ DEBUG0(printk ("DC395x: Debug: StartSCSI failed (busy) for pid %li(%02i-%i)!\n", pSRB->pcmd->pid, pDCB->TargetID, pDCB->TargetLUN);) - //DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + //DC395x_clrfifo (pACB, "Start2"); //DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_HWRESELECT | DO_DATALATCH); pSRB->SRBState = SRB_READY; DC395x_freetag (pDCB, pSRB); @@ -2847,6 +2889,14 @@ if (dma_status) { printk ("DC395x: Interrupt from DMA engine: %02x!\n", dma_status); + printk ("DC395x: This means DMA error! Try to handle ...\n"); + if (pACB->pActiveDCB) + { + pACB->pActiveDCB->DCBFlag |= ABORT_DEV_; + if (pACB->pActiveDCB->pActiveSRB) + DC395x_EnableMsgOut_Abort (pACB, pACB->pActiveDCB->pActiveSRB); + } + DC395x_write16 (TRM_S1040_DMA_CONTROL, ABORTXFER | CLRXFIFO); break; } else @@ -3032,7 +3082,7 @@ #endif TRACEPRINTF ("MOP1*"); pDCB = pACB->pActiveDCB; - DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "MOP1"); if( !(pSRB->SRBState & SRB_MSGOUT) ) { pSRB->SRBState |= SRB_MSGOUT; @@ -3064,6 +3114,8 @@ if( /*(pDCB->DCBFlag & ABORT_DEV_) && */ (pSRB->MsgOutBuf[0] == MSG_ABORT) ) pSRB->SRBState = SRB_ABORT_SENT; + //1.25 + //DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_DATALATCH);/* it's important for atn stop*/ /* ** SCSI command */ @@ -3083,7 +3135,8 @@ static void DC395x_CommandPhase0( PACB pACB, PSRB pSRB, PWORD pscsi_status) { TRACEPRINTF("COP0 *"); - DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + //1.25 + //DC395x_clrfifo (pACB, COP0); DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_DATALATCH); } /* @@ -3106,7 +3159,8 @@ printk(KERN_INFO "DC395x_CommandPhase1..............\n "); #endif TRACEPRINTF("COP1*"); - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRATN | DO_CLRFIFO ); + DC395x_clrfifo (pACB, "COP1"); + DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRATN); if( !(pSRB->SRBFlag & AUTO_REQSENSE) ) { ptr = (PBYTE) pSRB->pcmd->cmnd; @@ -3172,7 +3226,7 @@ /* Compute the next Scatter Gather list index and adjust its length * and address if necessary */ -static void DC395x_update_SGlist (PSRB pSRB, DWORD Left) +void DC395x_update_SGlist (PSRB pSRB, DWORD Left) { PSGE0 psge; DWORD Xferred; @@ -3224,23 +3278,24 @@ TRACEPRINTF (" Cln*"); //DC395x_write8 (TRM_S1040_DMA_STATUS, FORCEDMACOMP); if (DC395x_read16(TRM_S1040_DMA_COMMAND) & 0x0001) - { + { /* read */ if (!(DC395x_read8(TRM_S1040_SCSI_FIFOCNT) & 0x40)) - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "ClnIn"); if (!(DC395x_read16(TRM_S1040_DMA_FIFOCNT) & 0x8000)) DC395x_write8(TRM_S1040_DMA_CONTROL, CLRXFIFO); } else - { + { /* write */ if (!(DC395x_read16(TRM_S1040_DMA_FIFOCNT) & 0x8000)) DC395x_write8(TRM_S1040_DMA_CONTROL, CLRXFIFO); if (!(DC395x_read8(TRM_S1040_SCSI_FIFOCNT) & 0x40)) - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "ClnOut"); } - //DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_DATALATCH); + //1.25 + DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_DATALATCH); } @@ -3269,12 +3324,22 @@ //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 + */ + DC395x_write16 (TRM_S1040_DMA_CONTROL, STOPDMAXFER | CLRXFIFO); if( !(pSRB->SRBState & SRB_XFERPAD) ) { if( scsi_status & PARITYERROR ) pSRB->SRBStatus |= PARITY_ERROR; + /* 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 ...) */ if (!(scsi_status & SCSIXFERDONE)) { /* @@ -3284,13 +3349,24 @@ dLeftCounter = (DWORD) (DC395x_read8(TRM_S1040_SCSI_FIFOCNT) & 0x1F); if (pDCB->SyncPeriod & WIDE_SYNC) dLeftCounter <<= 1; +#ifdef DC395x_DEBUG0 + printk ("DC395x: Debug: SCSI FIFO contains %i %s in DOP0\n", + DC395x_read8(TRM_S1040_SCSI_FIFOCNT), + (pDCB->SyncPeriod & WIDE_SYNC)? "words": "bytes"); + printk ("DC395x: SCSI FIFOCNT %02x, SCSI CTR %08x\n", + DC395x_read8 (TRM_S1040_SCSI_FIFOCNT), + DC395x_read32 (TRM_S1040_SCSI_COUNTER)); + printk ("DC395x: DMA FIFOCNT %04x, DMA CTR %08x\n", + DC395x_read16 (TRM_S1040_DMA_FIFOCNT), + DC395x_read32 (TRM_S1040_DMA_CXCNT)); +#endif /* ** if WIDE scsi SCSI FIFOCNT unit is word !!! ** so need to *= 2 */ } /* - ** caculate all the residue data that not yet tranfered + ** calculate all the residue data that not yet tranfered ** SCSI transfer counter + left in SCSI FIFO data ** ** .....TRM_S1040_SCSI_COUNTER (24bits) @@ -3299,11 +3375,15 @@ ** 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 ( dLeftCounter == 1 ) { dLeftCounter = 0; - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + printk ("DC395x: DOP0: Discard 1 byte.\n"); } + /* 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; @@ -3312,6 +3392,7 @@ TempDMAstatus = DC395x_read8(TRM_S1040_DMA_STATUS); } 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; } @@ -3330,13 +3411,14 @@ printk ("DC395x: DOP0(%li): %i bytes in SCSI FIFO! (Clear!)\n", pSRB->pcmd->pid, DC395x_read8 (TRM_S1040_SCSI_FIFOCNT) & 0x1f); #endif - //DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + //DC395x_clrfifo (pACB, "DOP0"); //DC395x_write8 (TRM_S1040_DMA_CONTROL, CLRXFIFO | ABORTXFER); - +#if 0 if ((*pscsi_status & PHASEMASK) != PH_DATA_OUT) { //printk ("DC395x: Debug: Clean up after Data Out ...\n"); DC395x_cleanup_after_transfer (pACB, pSRB); } +#endif TRACEPRINTF(".*"); } /* @@ -3355,8 +3437,9 @@ #ifdef DC395x_DEBUG0 printk(KERN_INFO "DC395x_DataOutPhase1..... "); #endif - //DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + //1.25 TRACEPRINTF("DOP1*"); + DC395x_clrfifo (pACB, "DOP1"); /* ** do prepare befor transfer when data out phase */ @@ -3389,6 +3472,16 @@ TRACEPRINTF("DIP0*"); //if (timer_pending (&pACB->Data_Timer)) del_timer (&pACB->Data_Timer); scsi_status = *pscsi_status; + + /* KG: DataIn is much more tricky than DataOut. When the device is finished + * and switches to another phase, the SCSI engine should be finished too. + * But: There might still be bytes left in its FIFO to be fetched by the DMA + * engine and transferred to memory. + * We should wait for the FIFOs to be emptied by that (is there any way to + * enforce this?) and then stop the DMA engine, because it might think, that + * there are more bytes to follow. Yes, the device might disconnect prior to + * having all bytes transferred! */ + if( !(pSRB->SRBState & SRB_XFERPAD) ) { if( scsi_status & PARITYERROR ) @@ -3398,7 +3491,7 @@ pSRB->SRBStatus |= PARITY_ERROR; } #if 0 - // KG: Is this needed also for DataIn? + // KG: This was in DATAOUT. If anywhere, it belongs here. if (!(scsi_status & SCSIXFERDONE)) { /* @@ -3415,9 +3508,22 @@ */ } #endif - // KG: This is always in bytes? - dLeftCounter += DC395x_read32(TRM_S1040_SCSI_COUNTER); + dLeftCounter += DC395x_read32(TRM_S1040_SCSI_COUNTER); + + // 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"); + while (!(DC395x_read16 (TRM_S1040_DMA_FIFOCNT) & 0x8000) && --ctr); + if (ctr < 6000000-1) printk ("DC395x: Debug: Had to wait for DMA ...\n"); + if (!ctr) printk (KERN_ERR "DC395x: Deadlock in DIP0 waiting for DMA FIFO empty!!\n"); + } + // KG: This should not be needed any more! if((dLeftCounter == 0) || (scsi_status & SCSIXFERCNT_2_ZERO) ) { int ctr = 6000000; @@ -3458,13 +3564,13 @@ pSRB->pcmd->pid, bval & 0x1f, scsi_status, dLeftCounter); if((dLeftCounter == 0) || (scsi_status & SCSIXFERCNT_2_ZERO) ) { printk ("DC395x: Clear FIFO!\n"); - DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "DIP0"); } } #endif //DC395x_write8 (TRM_S1040_DMA_CONTROL, CLRXFIFO | ABORTXFER); - //DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + //DC395x_clrfifo (pACB, "DIP0"); //DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_DATALATCH); TRACEPRINTF(".*"); } @@ -3484,7 +3590,7 @@ printk(KERN_INFO "DC395x_DataInPhase1..... "); #endif /* FIFO should be cleared, if previous phase was not DataPhase */ - //DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + //DC395x_clrfifo (pACB, "DIP1"); /* Allow data in! */ //DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_DATALATCH); TRACEPRINTF("DIP1:*"); @@ -3612,6 +3718,10 @@ TRACEPRINTF("%05x(%i/%i)*", pSRB->SRBTotalXferLength, pSRB->SRBSGIndex, pSRB->SRBSGCount); pDCB = pSRB->pSRBDCB; + if (pSRB == pACB->pTmpSRB) + { + printk ("DC395x: ERROR! Using TmpSRB in DataPhase!\n"); + } if( pSRB->SRBSGIndex < pSRB->SRBSGCount ) { if( pSRB->SRBTotalXferLength != 0 ) @@ -3624,7 +3734,7 @@ DC395x_dumpinfo (pACB, pDCB, pSRB); DC395x_write8 (TRM_S1040_DMA_CONTROL, CLRXFIFO); } - //DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + //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 @@ -3708,7 +3818,8 @@ pSRB->EndMessage = DC395x_read8(TRM_S1040_SCSI_FIFO); /* get message */ pSRB->SRBState = SRB_COMPLETED; *pscsi_status = PH_BUS_FREE; /*.. initial phase*/ - DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + //1.25 + //DC395x_clrfifo (pACB, "STP0"); DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_DATALATCH);/* it's important for atn stop*/ /* ** SCSI command @@ -3875,7 +3986,7 @@ DC395x_MsgIn_set_async (PACB pACB, PSRB pSRB) { PDCB pDCB = pSRB->pSRBDCB; - printk ("DC395x: SDTR got rejected from target %02i\n", + printk ("DC395x: Target %02i: No sync transfers\n", pDCB->TargetID); pDCB->SyncMode &= ~(SYNC_NEGO_ENABLE); pDCB->SyncMode |= SYNC_NEGO_DONE; //pDCB->SyncPeriod &= 0; @@ -3901,7 +4012,7 @@ //BYTE oldsyncoffset = pDCB->SyncOffset; #ifdef DC395x_DEBUG1 - printk (KERN_INFO "DC395x: Target %i: Sync: %ins (%02i.%01i MHz) Offset %i\n", + printk (KERN_INFO "DC395x: Target %02i: Sync: %ins (%02i.%01i MHz) Offset %i\n", pDCB->TargetID, pSRB->MsgInBuf[3]<<2, (250/pSRB->MsgInBuf[3]), ((250%pSRB->MsgInBuf[3])*10)/pSRB->MsgInBuf[3], pSRB->MsgInBuf[4]); @@ -4207,8 +4318,9 @@ pACB->MsgLen = 0; }; + //1.25 if ((*pscsi_status & PHASEMASK) != PH_MSG_IN) - DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "MIP0"); *pscsi_status = PH_BUS_FREE; DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_DATALATCH); /* it's important ... you know! */ DC395x_write8 (TRM_S1040_SCSI_COMMAND, SCMD_MSGACCEPT); @@ -4230,7 +4342,7 @@ printk(KERN_INFO "DC395x_MsgInPhase1..............\n "); #endif TRACEPRINTF("MIP1 *"); - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "MIP1"); DC395x_write32(TRM_S1040_SCSI_COUNTER, 1); if( !(pSRB->SRBState & SRB_MSGIN) ) { @@ -4340,15 +4452,17 @@ // Suspend queue for a while pACB->pScsiHost->last_reset = jiffies + HZ/2 + HZ * dc395x_trm_eepromBuf[pACB->AdapterIndex].NvramDelayTime; - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO | DO_HWRESELECT); + DC395x_clrfifo (pACB, "DiscEx"); + DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_HWRESELECT); return; } pSRB = pDCB->pActiveSRB; - TRACEPRINTF("DISC *"); pACB->pActiveDCB = 0; + TRACEPRINTF("DISC *"); pSRB->ScsiPhase = PH_BUS_FREE;/* initial phase */ - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO | DO_HWRESELECT); + DC395x_clrfifo (pACB, "Disc"); + DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_HWRESELECT); if( pSRB->SRBState & SRB_UNEXPECT_RESEL ) { printk(KERN_ERR "DC395x: Disc: Unexpected Reselection (%i-%i)\n", pDCB->TargetID, pDCB->TargetLUN); @@ -4387,7 +4501,8 @@ { /* Normal selection timeout */ TRACEPRINTF("SlTO *"); - //printk ("DC395x: Disc: Move SRB (pid=%li) to Waiting\n", pSRB->pcmd->pid); + DEBUG0(printk ("DC395x: Disc: SelTO (pid=%li) for dev %02i-%i\n", pSRB->pcmd->pid, + pDCB->TargetID, pDCB->TargetLUN);) if (pSRB->RetryCnt++ > DC395x_MAX_RETRIES || pACB->scan_devices) { pSRB->TargetStatus = SCSI_STAT_SEL_TIMEOUT; @@ -4395,7 +4510,7 @@ } DC395x_freetag (pDCB, pSRB); DC395x_Going_to_Waiting (pDCB, pSRB); - DC395x_waiting_timer (pACB, HZ/5); + DC395x_waiting_timer (pACB, HZ/20); } } else if( pSRB->SRBState & SRB_DISCONNECT ) @@ -4408,12 +4523,12 @@ TRACEPRINTF("+*"); if (bval & 0x40) { - printk ("DC395x: Debug: DISC: SCSI bus stat %02x: ACK set! SYNC trouble?\n", - bval); + DEBUG0(printk ("DC395x: Debug: DISC: SCSI bus stat %02x: ACK set! Other controllers?\n", + bval);) // It could come from another initiator, therefore don't do much ! - TRACEPRINTF("ACK(%02x)!*", bval); + TRACEPRINTF("ACK(%02x) *", bval); //DC395x_dumpinfo (pACB, pDCB, pSRB); - TRACEOUT (" %s\n", pSRB->debugtrace); + //TRACEOUT (" %s\n", pSRB->debugtrace); //pDCB->DCBFlag |= ABORT_DEV_; //DC395x_EnableMsgOut_Abort (pACB, pSRB); //DC395x_write16 (TRM_S1040_SCSI_CONTROL, DO_CLRFIFO | DO_CLRATN | DO_HWRESELECT); @@ -4456,7 +4571,7 @@ printk(KERN_INFO "DC395x_Reselect..............\n "); #endif - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "Resel"); //DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_HWRESELECT | DO_DATALATCH); /* Read Reselected Target ID and LUN */ RselTarLunId = DC395x_read16(TRM_S1040_SCSI_TARGETID); @@ -4483,7 +4598,7 @@ pSRB->SRBState = SRB_READY; DC395x_freetag (pDCB, pSRB); DC395x_Going_to_Waiting (pDCB, pSRB); - DC395x_waiting_timer (pACB, HZ/5); + DC395x_waiting_timer (pACB, HZ/20); // return; } @@ -4597,8 +4712,10 @@ if (pDCB == pACB->pLastDCB) pACB->pLastDCB = pPrevDCB; } - DCBDEBUG(printk (KERN_INFO "DC395x: Driver about to free DCB (ID %i, LUN %i): %p\n",\ - pDCB->TargetID, pDCB->TargetLUN, pDCB);) + DCBDEBUG(\ + printk (KERN_INFO "DC395x: Driver about to free DCB (ID %i, LUN %i): %p\n",\ + pDCB->TargetID, pDCB->TargetLUN, pDCB);\ + ) if (pDCB == pACB->pActiveDCB) pACB->pActiveDCB = 0; if (pDCB == pACB->pLinkDCB) pACB->pLinkDCB = pDCB->pNextDCB; if (pDCB == pACB->pDCBRunRobin) pACB->pDCBRunRobin = pDCB->pNextDCB; @@ -4746,11 +4863,13 @@ else if( status_byte(status) == QUEUE_FULL ) { tempcnt = (BYTE) pDCB->GoingSRBCnt; - tempcnt--; + printk ("DC395x: QUEUE_FULL for dev %02i-%i with %i cmnds\n", + pDCB->TargetID, pDCB->TargetLUN, tempcnt); + if (tempcnt > 1) tempcnt--; pDCB->MaxCommand = tempcnt; DC395x_freetag (pDCB, pSRB); DC395x_Going_to_Waiting ( pDCB, pSRB ); - DC395x_waiting_timer (pACB, HZ/5); + DC395x_waiting_timer (pACB, HZ/20); pSRB->AdaptStatus = 0; pSRB->TargetStatus = 0; return; @@ -4845,13 +4964,22 @@ if( pSRB->pcmd->cmnd[0] == INQUIRY && (pcmd->result == (DID_OK << 16) || status_byte(pcmd->result) & CHECK_CONDITION) ) { + DEBUG0(int i;) ptr = (PSCSI_INQDATA) (pcmd->request_buffer); if( pcmd->use_sg ) ptr = (PSCSI_INQDATA) (((PSGL) ptr)->address); +#ifdef DC395x_DEBUG0 + printk ("DC395x: Inquiry result:"); + for (i = 0; i < 8; i++) printk (" %02x", ((PBYTE)ptr)[i]); + ((PBYTE)ptr)[96] = 0; + printk ("\nDC395x: %s\n", (char*)ptr + 8); +#endif if ((ptr->DevType & SCSI_DEVTYPE) == TYPE_NODEV) { + printk ("DC395x: Device %02i-%i: TYPE_NODEV?\n", + pDCB->TargetID, pDCB->TargetLUN); /* device not present: remove */ - DC395x_remove_dev (pACB, pDCB); DCB_removed = 1; + //DC395x_remove_dev (pACB, pDCB); DCB_removed = 1; } else { @@ -4864,9 +4992,12 @@ pACB->scan_devices = 0; }; - if (!DCB_removed) DC395x_Going_remove (pDCB, pSRB); + if (!DCB_removed) DC395x_Going_remove (pDCB, pSRB, 0); /* Add to free list */ - DC395x_Free_insert (pACB, pSRB); + if (pSRB == pACB->pTmpSRB) + printk ("DC395x: ERROR! Completed Cmnd with TmpSRB!\n"); + else + DC395x_Free_insert (pACB, pSRB); DEBUG0(printk (KERN_DEBUG "DC395x: SRBdone: done pid %li\n", pcmd->pid);) #ifdef DC395x_DEBUG_KG @@ -4890,7 +5021,7 @@ ** abort all cmds in our queues ********************************************************************* */ -static void DC395x_DoingSRB_Done( PACB pACB, BYTE did_flag ) +void DC395x_DoingSRB_Done( PACB pACB, BYTE did_flag ) { PDCB pDCB; PSRB pSRB, pSRBTemp; @@ -4924,8 +5055,8 @@ TRACEOUT ("%s\n", pSRB->debugtrace); pDCB->pGoingSRB = pSRBTemp; pDCB->GoingSRBCnt--; if (!pSRBTemp) pDCB->pGoingLast = NULL; - DC395x_Free_insert (pACB, pSRB); DC395x_freetag (pDCB, pSRB); + DC395x_Free_insert (pACB, pSRB); #ifndef USE_NEW_EH /* For new EH, don't give commands back */ pcmd->result = result; @@ -5065,8 +5196,10 @@ pACB->pScsiHost->last_reset = jiffies + 5*HZ/2 + HZ * dc395x_trm_eepromBuf[pACB->AdapterIndex].NvramDelayTime; - DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_CLRFIFO); + DC395x_clrfifo (pACB, "RstDet"); DC395x_basic_config (pACB); + //1.25 + //DC395x_write16(TRM_S1040_SCSI_CONTROL, DO_HWRESELECT); if( pACB->ACBFlag & RESET_DEV ) /* RESET_DETECT, RESET_DONE, RESET_DEV */ { @@ -5124,6 +5257,8 @@ printk ("DC395x: Request Sense failed for pid %li (%02i-%i)!\n", pSRB->pcmd->pid, pDCB->TargetID, pDCB->TargetLUN); TRACEPRINTF ("?*"); + DC395x_Going_to_Waiting (pDCB, pSRB); + DC395x_waiting_timer (pACB, HZ/50); } TRACEPRINTF (".*"); } @@ -5267,22 +5402,6 @@ /* -********************************************************************** -** DC395x_linkSRB -** DC395x_initACB -** -** Function : static void DC395x_initSRB -** Purpose : initialize the internal structures for a given SRB -** Inputs : pSRBTemp - pointer to this scsi request block structure -** -********************************************************************** -*/ -static inline void DC395x_initSRB( PSRB pSRB ) -{ - //pSRB->PhysSRB = virt_to_bus ((DWORD) pSRB); -} - -/* ********************************************************************* ** scsiio ** DC395x_initACB @@ -5291,31 +5410,12 @@ */ void __init DC395x_linkSRB( PACB pACB ) { - WORD count, i; + int i; - count = pACB->SRBCount; - - for( i=0; i< count; i++) - { - if( i != count - 1) - { - /* - ** link all SRB - */ - pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; - } - else - { - /* - ** load NULL to NextSRB of the last SRB - */ - pACB->SRB_array[i].pNextSRB = NULL; - } - /* - ** convert and save physical address of SRB to pSRB->PhysSRB - */ - DC395x_initSRB( (PSRB) &pACB->SRB_array[i] ); - } + for( i=0; i < pACB->SRBCount - 1; i++) + pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; + pACB->SRB_array[i].pNextSRB = NULL; + //DC395x_Free_integrity (pACB); } @@ -5367,7 +5467,6 @@ pACB->pLinkDCB = NULL; pACB->pDCBRunRobin = NULL; pACB->pActiveDCB = NULL; - pACB->pFreeSRB = pACB->SRB_array; pACB->SRBCount = DC395x_MAX_SRB_CNT; pACB->AdapterIndex = index; pACB->status = 0; @@ -5383,23 +5482,17 @@ pACB->Gmode2 = pEEpromBuf->NvramChannelCfg; if( pEEpromBuf->NvramChannelCfg & NAC_SCANLUN ) pACB->LUNchk = 1; - /* - ******************************** - */ - //pACB->pDCB_free = &pACB->DCB_array[0]; /* ** link all device's SRB Q of this adapter */ DC395x_linkSRB( pACB ); + pACB->pFreeSRB = pACB->SRB_array; /* ** temp SRB for Q tag used or abort command used */ pACB->pTmpSRB = &pACB->TmpSRB; pACB->TmpSRB.pSRBDCB = 0; - /* - ** convert and save physical address of SRB to pSRB->PhysSRB - */ - DC395x_initSRB( pACB->pTmpSRB ); + pACB->TmpSRB.pNextSRB = 0; init_timer (&pACB->Waiting_Timer); for (i = 0; i < DC395x_MAX_SCSI_ID; i++) @@ -5685,7 +5778,7 @@ ** Output : none ************************************************************************ */ -void TRM_S1040_wait_30us(WORD scsiIOPort) +static __init void TRM_S1040_wait_30us(WORD scsiIOPort) { /* ScsiPortStallExecution(30); wait 30 us */ outb( 5 , scsiIOPort+TRM_S1040_GEN_TIMER); @@ -6174,10 +6267,18 @@ DC395x_updateDCB (pACB, pDCB); }; }; - if (!(pDCB->SyncMode & SYNC_NEGO_DONE)) - { pDCB->SyncOffset = 0; /*pDCB->SyncMode &= ~SYNC_NEGO_ENABLE;*/ }; - if (!(pDCB->SyncMode & WIDE_NEGO_DONE)) - { pDCB->SyncPeriod &= ~WIDE_SYNC; pDCB->SyncMode &= ~WIDE_NEGO_ENABLE; }; + if (pDCB) + { + if (!(pDCB->SyncMode & SYNC_NEGO_DONE)) + { pDCB->SyncOffset = 0; /*pDCB->SyncMode &= ~SYNC_NEGO_ENABLE;*/ }; + if (!(pDCB->SyncMode & WIDE_NEGO_DONE)) + { pDCB->SyncPeriod &= ~WIDE_SYNC; pDCB->SyncMode &= ~WIDE_NEGO_ENABLE; }; + } + else + { + printk ("DC395x: ERROR! No DCB existent for %02i-%i ?\n", + cmd->target, cmd->lun); + } kfree (cmd); }; @@ -6670,7 +6771,7 @@ pACB->DCBmap[8], pACB->DCBmap[9], pACB->DCBmap[10], pACB->DCBmap[11], pACB->DCBmap[12], pACB->DCBmap[13], pACB->DCBmap[14], pACB->DCBmap[15]); - SPRINTF("Un ID LUN Prty Sync Wide DsCn SndS TagQ NegoPeriod SyncFreq SyncOffs\n"); + SPRINTF("Un ID LUN Prty Sync Wide DsCn SndS TagQ NegoPeriod SyncFreq SyncOffs MaxCmd\n"); pDCB = pACB->pLinkDCB; for (dev = 0; dev < pACB->DCBCnt; dev++) @@ -6694,12 +6795,13 @@ spd = 1000/(NegoPeriod); spd1 = 1000%(NegoPeriod); spd1 = (spd1 * 10 + NegoPeriod/2)/(NegoPeriod); - SPRINTF(" %2i.%1i M %02i\n", spd, spd1, (pDCB->SyncOffset & 0x0f)); + SPRINTF(" %2i.%1i M %02i ", spd, spd1, (pDCB->SyncOffset & 0x0f)); } else - SPRINTF("\n"); + SPRINTF(" "); /* Add more info ...*/ + SPRINTF (" %02i\n", pDCB->MaxCommand); pDCB = pDCB->pNextDCB; } @@ -6780,7 +6882,8 @@ if (1 || pACB->Config & HCC_SCSI_RESET) DC395x_ResetSCSIBus( pACB ); - + + DC395x_read8 (TRM_S1040_SCSI_INTSTATUS); return( 0 ); } @@ -6829,23 +6932,19 @@ for (irq_count = 0, pACB = DC395x_pACB_start; pACB != (PACB)-1; pACB = pACB->pNextACB) { - if ( pACB->IRQLevel == host->irq ) - ++irq_count; + if ( pACB->IRQLevel == host->irq ) + ++irq_count; } if (irq_count == 1) - free_irq(host->irq, NULL); + free_irq(host->irq, NULL); } release_region(host->io_port,host->n_io_port); - printk ("."); - DC395x_freeDCBs (host); - + DC395x_UNLOCK_IO; //DC395x_DRV_UNLOCK(drv_flags); - printk ("\n"); return( 1 ); } Scsi_Host_Template driver_template = DC395x_TRMS1040; #include "scsi_module.c" #endif /* def MODULE */ - Index: dc395x_trm.h =================================================================== RCS file: /home/cvsroot/dc395/dc395x_trm.h,v retrieving revision 1.21 retrieving revision 1.23 diff -u -r1.21 -r1.23 --- dc395x_trm.h 2000/02/14 19:58:10 1.21 +++ dc395x_trm.h 2000/02/19 15:27:20 1.23 @@ -8,7 +8,7 @@ ** ********************************************************************** */ -/* $Id: dc395x_trm.h,v 1.21 2000/02/14 19:58:10 garloff Exp $ */ +/* $Id: dc395x_trm.h,v 1.23 2000/02/19 15:27:20 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.24, 2000-02-14" +#define DC395x_VERSION "1.25, 2000-02-19" /* Kernel version autodetection */ #include