--- linux/MAINTAINERS.orig Mon Nov 23 23:14:52 1998 +++ linux/MAINTAINERS Fri Dec 25 19:06:26 1998 @@ -202,8 +202,8 @@ DC390/AM53C974 SCSI driver P: Kurt Garloff -M: K.Garloff@ping.de -W: ftp://student.physik.uni-dortmund.de/pub/linux/kernel/dc390/ +M: kurt@garloff.de +W: http://www.garloff.de/kurt/linux/dc390/ S: Maintained DECnet NETWORK LAYER --- linux/drivers/scsi/README.tmscsim.orig Tue Oct 27 19:10:08 1998 +++ linux/drivers/scsi/README.tmscsim Fri Dec 25 19:04:20 1998 @@ -17,6 +17,7 @@ chip. AM53C974 based SCSI adapters include: Tekram DC390, DC390T Dawicontrol 2974 + QLogic Fast! PCI Basic some on-board adapters (This is most probably not a complete list) @@ -44,7 +45,8 @@ 1.12, then 1.20a to 1.20t. Finally I decided to use the ncr53c8xx scheme. So the next revisions will be 2.0a to 2.0X (stable), 2.1a to 2.1X (experimental), 2.2a to 2.2X (stable, again) etc. (X = anything between a and z.) If I send -fixes to people for testing, those will have a digit appended, e.g. 2.0a1. +fixes to people for testing, I create intermediate versions with a digit +appended, e.g. 2.0c3. 2. Installation @@ -55,32 +57,36 @@ support into your kernel or as module when configuring your kernel for compiling. -If you got an older kernel with an old version of this driver included, you -should copy the files (dc390.h, tmscsim.h, tmscsim.c, scsiiom.c and -README.tmscsim) from this directory to linux/drivers/scsi. You have to -recompile your kernel/module of course. - -You should apply the three patches included in dc390-20-kernel.diff -(Applying them: cd /usr/src; patch -p0 <~/dc390-20-kernel.diff) -The patches are against 2.1.103, so you might have to manually resolve -rejections when applying to another kernel version. - -The patches will update the kernel startup code to allow boot parameters to -be passed to the driver, update the Documentation and finally offer you the -possibility to omit the non-DC390 parts of the driver. -(By selecting "Omit support for non DC390" you basically disable the -emulation of a DC390 EEPROM for non DC390 adapters. This saves a few bytes -of memory.) + If you got an old kernel (pre 2.1.127, pre 2.0.37p1) with an old version of + this driver: Get dc390-21125-20b.diff.gz or dc390-2036p21-20b1.diff.gz from + my website and apply the patch. + + If you want to do it manually, you should copy the files (dc390.h, + tmscsim.h, tmscsim.c, scsiiom.c and README.tmscsim) from this directory to + linux/drivers/scsi. You have to recompile your kernel/module of course. + + You should apply the three patches included in dc390-120-kernel.diff + (Applying them: cd /usr/src; patch -p0 <~/dc390-120-kernel.diff) + The patches are against 2.1.125, so you might have to manually resolve + rejections when applying to another kernel version. + + The patches will update the kernel startup code to allow boot parameters to + be passed to the driver, update the Documentation and finally offer you the + possibility to omit the non-DC390 parts of the driver. + (By selecting "Omit support for non DC390" you basically disable the + emulation of a DC390 EEPROM for non DC390 adapters. This saves a few bytes + of memory.) If you got a very old kernel without the tmscsim driver (pre 2.0.31) I recommend upgrading your kernel. However, if you don't want to, please contact me to get the appropriate patches. -Testing a SCSI driver is always a delicate thing to do. The 2.0 driver has + +Upgrading a SCSI driver is always a delicate thing to do. The 2.0 driver has proven stable on many systems, but it's still a good idea to take some precautions. In an ideal world you would have a full backup of your disks. The world isn't ideal and most people don't have full backups (me neither). -So take at least the following two measures: +So take at least the following measures: * make your kernel remount the FS read-only on detecting an error: tune2fs -e remount-ro /dev/sd?? * have copies of your SCSI disk's partition tables on some safe location: @@ -103,18 +109,19 @@ 3.Features ---------- - SCSI - * Tagged queueing + * Tagged command queueing * Sync speed up to 10 MHz * Disconnection * Multiple LUNs - General / Linux interface - * Support for up to 4 adapters. + * Support for up to 4 AM53C974 adapters. * DC390 EEPROM usage or boot/module params * Information via cat /proc/scsi/tmscsim/? * Dynamically configurable by writing to /proc/scsi/tmscsim/? * Dynamic allocation of resources - * SMP support: Adapter specific locks (Linux 2.1.x) + * SMP support: Locking on io_request lock (Linux 2.1/2.2) or adapter + specific locks (Linux 2.3) * Uniform source code for Linux-2.x.y * Support for dyn. addition/removal of devices via add/remove-single-device (Try: echo "scsi add-single-device H C I L" >/proc/scsi/scsi @@ -336,9 +343,7 @@ Further investigation on these problems: -* TagQ and Disconnection (Resel: SRB Tag Seleection) -* Problems with IRQ sharing (IO-APIC on SMP Systems) (??) -* Driver crashes with readcdda (xcdroast) +* Driver hangs with sync readcdda (xcdroast) (most probably VIA PCI error) Known problems: @@ -362,12 +367,9 @@ Richard Waltham or Doug Ledford , if you want to help further debugging it. * 2.0.35: CD changers (e.g. NAKAMICHI MBR-7.{0,2}) have problems because - the mid-level code doesn't handle BLIST_SINGLELUN correctly. Apply - the patch 2035-scsi-singlelun.diff. Thanks to Chiaki Ishikawa. - I was told that this fix will be in 2.0.36, so you don't need it for - 2.0.36. -[The patch file is contained in the dc390-XXX.tar.gz files which can be found -on the ftp server. See below.] + the mid-level code doesn't handle BLIST_SINGLELUN correctly. There used + to be a patch included here to fix this, but I was told that it is fixed + in 2.0.36. 7. Bug reports, debugging and updates @@ -379,7 +381,7 @@ Please append the output of /proc/scsi/scsi, /proc/scsi/tmscsim/? and maybe the DC390 log messages to the report. -Bug reports should be send to me (Kurt Garloff ) as well +Bug reports should be send to me (Kurt Garloff ) as well as to the linux-scsi list (), as sometimes bugs are caused by the SCSI mid-level code. @@ -391,7 +393,10 @@ having your box spending most of its time doing the logging. The latest version of the driver can be found at: -ftp://student.physik.uni-dortmund.de/pub/linux/kernel/dc390/ + http://www.garloff.de/kurt/linux/dc390/ +and + ftp://student.physik.uni-dortmund.de/pub/linux/kernel/dc390/ +(The latter might shut down some day.) 8. Acknowledgements @@ -408,6 +413,6 @@ ------------------------------------------------------------------------- -Written by Kurt Garloff 1998/06/11 -Last updated 1998/10/15, driver revision 2.0b -$Id: README.tmscsim,v 2.4 1998/10/24 08:45:02 garloff Exp $ +Written by Kurt Garloff 1998/06/11 +Last updated 1998/12/25, driver revision 2.0d +$Id: README.tmscsim,v 2.9 1998/12/25 18:04:20 garloff Exp $ --- linux/drivers/scsi/tmscsim.c.orig Tue Oct 27 19:10:08 1998 +++ linux/drivers/scsi/tmscsim.c Fri Dec 25 18:54:44 1998 @@ -5,9 +5,11 @@ * Bus Master Host Adapter * * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. * ***********************************************************************/ -/* $Id: tmscsim.c,v 2.4 1998/10/24 08:50:47 garloff Exp $ */ +/* (C) Copyright: put under GNU GPL in 10/96 * +*************************************************************************/ +/* $Id: tmscsim.c,v 2.16 1998/12/25 17:54:44 garloff Exp $ */ /* Enhancements and bugfixes by * - * Kurt Garloff * + * Kurt Garloff * ***********************************************************************/ /* HISTORY: * * * @@ -90,6 +92,11 @@ * bios_param() now respects part. table. * * 2.0b 98/10/24 KG Docu fixes. Timeout Msg in DMA Blast. * * Disallow illegal idx in INQUIRY/REMOVE * + * 2.0c 98/11/19 KG Cleaned up detect/init for SMP boxes, * + * Write Erase DMA (1.20t) caused problems * + * 2.0d 98/12/25 KG Christmas release ;-) Message handling * + * competely reworked. Handle target ini- * + * tiated SDTR correctly. * ***********************************************************************/ /* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */ @@ -206,9 +213,9 @@ # if USE_SPINLOCKS == 3 /* both */ # if defined (__SMP__) || DEBUG_SPINLOCKS > 0 -# define DC390_LOCK_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; }; +# define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; }; # else -# define DC390_LOCK_INIT +# define DC390_LOCKA_INIT # endif spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED; @@ -228,16 +235,16 @@ # define DC390_UNLOCK_ACB spin_unlock_irqrestore (&(pACB->lock), aflags) # define DC390_LOCK_ACB_NI spin_lock (&(pACB->lock)) # define DC390_UNLOCK_ACB_NI spin_unlock (&(pACB->lock)) -//# define DC390_LOCK_INIT spin_lock_init (&(pACB->lock)) +//# define DC390_LOCKA_INIT spin_lock_init (&(pACB->lock)) # else # if USE_SPINLOCKS == 2 /* adapter specific locks */ # if defined (__SMP__) || DEBUG_SPINLOCKS > 0 -# define DC390_LOCK_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; }; +# define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; }; # else -# define DC390_LOCK_INIT +# define DC390_LOCKA_INIT # endif spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED; # define DC390_AFLAGS unsigned long aflags; @@ -253,7 +260,7 @@ # define DC390_UNLOCK_ACB spin_unlock_irqrestore (&(pACB->lock), aflags) # define DC390_LOCK_ACB_NI spin_lock (&(pACB->lock)) # define DC390_UNLOCK_ACB_NI spin_unlock (&(pACB->lock)) -//# define DC390_LOCK_INIT spin_lock_init (&(pACB->lock)) +//# define DC390_LOCKA_INIT spin_lock_init (&(pACB->lock)) # else /* USE_SPINLOCKS == 1: global lock io_request_lock */ @@ -271,7 +278,7 @@ # define DC390_UNLOCK_ACB /* DC390_UNLOCK_IO */ # define DC390_LOCK_ACB_NI /* spin_lock (&(pACB->lock)) */ # define DC390_UNLOCK_ACB_NI /* spin_unlock (&(pACB->lock)) */ -# define DC390_LOCK_INIT /* DC390_LOCK_INIT */ +# define DC390_LOCKA_INIT /* DC390_LOCKA_INIT */ # endif /* 2 */ # endif /* 3 */ @@ -291,7 +298,7 @@ # define DC390_UNLOCK_ACB restore_flags (aflags) # define DC390_LOCK_ACB_NI # define DC390_UNLOCK_ACB_NI -# define DC390_LOCK_INIT +# define DC390_LOCKA_INIT #endif /* def */ @@ -365,9 +372,8 @@ static void dc390_ScsiRstDetect( PACB pACB ); static void dc390_ResetSCSIBus( PACB pACB ); static void __inline__ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ); -static void __inline__ dc390_EnableMsgOut2( PACB pACB, PSRB pSRB ); -static void __inline__ dc390_EnableMsgOut( PACB pACB, PSRB pSRB ); static void __inline__ dc390_InvalidCmd( PACB pACB ); +static void __inline__ dc390_EnableMsgOut_Abort (PACB, PSRB); static void dc390_remove_dev (PACB pACB, PDCB pDCB); void do_DC390_Interrupt( int, void *, struct pt_regs *); @@ -481,9 +487,190 @@ S_IFDIR | S_IRUGO | S_IXUGO, 2 }; + /*********************************************************************** + * Functions for access to DC390 EEPROM + * and some to emulate it * - * + **********************************************************************/ + + +static void __init dc390_EnDisableCE( UCHAR mode, PDEVDECL, PUCHAR regval ) +{ + UCHAR bval; + + bval = 0; + if(mode == ENABLE_CE) + *regval = 0xc0; + else + *regval = 0x80; + PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); + if(mode == DISABLE_CE) + PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); + udelay(160); +} + +#ifndef CONFIG_SCSI_DC390T_NOGENSUPP +static void __init dc390_EEpromDefaults (UCHAR index) +{ + PUCHAR ptr; + UCHAR id; + ptr = (PUCHAR) dc390_eepromBuf[index]; + + /* Adapter Settings */ + ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0]; /* Adapter ID */ + ptr[EE_MODE2] = (UCHAR)tmscsim[3]; + ptr[EE_DELAY] = 0; /* ?? */ + ptr[EE_TAG_CMD_NUM] = (UCHAR)tmscsim[4]; /* Tagged Comds */ + + /* Device Settings */ + for (id = 0; id < MAX_SCSI_ID; id++) + { + ptr[id<<2] = (UCHAR)tmscsim[2]; /* EE_MODE1 */ + ptr[(id<<2) + 1] = (UCHAR)tmscsim[1]; /* EE_Speed */ + }; + dc390_adapname = "AM53C974"; +} + +static void __init dc390_checkparams (void) +{ + PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x\n", tmscsim[0],\ + tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4]);) + if (tmscsim[0] < 0 || tmscsim[0] > 7) /* modules-2.0.0 passes -1 as string */ + { + tmscsim[0] = 7; tmscsim[1] = 4; + tmscsim[2] = 9; tmscsim[3] = 15; + tmscsim[4] = 2; + printk (KERN_INFO "DC390: Using safe settings.\n"); + } + else + { + /* if (tmscsim[0] < 0 || tmscsim[0] > 7) tmscsim[0] = 7; */ + if (tmscsim[1] < 0 || tmscsim[1] > 7) tmscsim[1] = 4; + if (tmscsim[4] < 0 || tmscsim[4] > 5) tmscsim[4] = 4; + }; +}; +/* Override defaults on cmdline: + * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped) + */ +void __init dc390_setup (char *str, int *ints) +{ + int i; + for (i = 0; i < ints[0]; i++) + tmscsim[i] = ints[i+1]; + if (ints[0] > 5) + printk (KERN_NOTICE "DC390: ignore extra params!\n"); + /* dc390_checkparams (); */ +}; +#endif /* CONFIG_SCSI_DC390T_NOGENSUPP */ + + +static void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry ) +{ + UCHAR bval; + + bval = 0; + if(Carry) + { + bval = 0x40; + *regval = 0x80; + PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); + } + udelay(160); + bval |= 0x80; + PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); + udelay(160); + bval = 0; + PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); + udelay(160); +} + + +static UCHAR __init dc390_EEpromInDO( PDEVDECL ) +{ + UCHAR bval; + + PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x80); + udelay(160); + PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x40); + udelay(160); + PCI_READ_CONFIG_BYTE(PDEV, 0x00, &bval); + if(bval == 0x22) + return(1); + else + return(0); +} + + +static USHORT __init dc390_EEpromGetData1( PDEVDECL ) +{ + UCHAR i; + UCHAR carryFlag; + USHORT wval; + + wval = 0; + for(i=0; i<16; i++) + { + wval <<= 1; + carryFlag = dc390_EEpromInDO(PDEV); + wval |= carryFlag; + } + return(wval); +} + + +static void __init dc390_Prepare( PDEVDECL, PUCHAR regval, UCHAR EEpromCmd ) +{ + UCHAR i,j; + UCHAR carryFlag; + + carryFlag = 1; + j = 0x80; + for(i=0; i<9; i++) + { + dc390_EEpromOutDI(PDEV,regval,carryFlag); + carryFlag = (EEpromCmd & j) ? 1 : 0; + j >>= 1; + } +} + + +static void __init dc390_ReadEEprom( PDEVDECL, PUSHORT ptr) +{ + UCHAR regval,cmd; + UCHAR i; + + cmd = EEPROM_READ; + for(i=0; i<0x40; i++) + { + dc390_EnDisableCE(ENABLE_CE, PDEV, ®val); + dc390_Prepare(PDEV, ®val, cmd++); + *ptr++ = dc390_EEpromGetData1(PDEV); + dc390_EnDisableCE(DISABLE_CE, PDEV, ®val); + } +} + + +static UCHAR __init dc390_CheckEEpromCheckSum( PDEVDECL, UCHAR index ) +{ + UCHAR i; + char EEbuf[128]; + USHORT wval, *ptr = (PUSHORT)EEbuf; + + dc390_ReadEEprom( PDEV, ptr ); + memcpy (dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID); + memcpy (&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID], + &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID); + wval = 0; + for(i=0; i<0x40; i++, ptr++) + wval += *ptr; + return (wval == 0x1234 ? 0 : 1); +} + + +/*********************************************************************** + * Functions for the management of the internal structures + * (DCBs, SRBs, Queueing) * **********************************************************************/ static PDCB __inline__ dc390_findDCB ( PACB pACB, Scsi_Cmnd *cmd) @@ -494,7 +681,7 @@ pDCB = pDCB->pNextDCB; if (pDCB == pACB->pLinkDCB) { - printk (KERN_ERR "DC390: DCB not found (DCB=%08x, DCBmap[%2x]=%2x)\n", + printk (KERN_WARNING "DC390: DCB not found (DCB=%08x, DCBmap[%2x]=%2x)\n", (int)pDCB, cmd->target, pACB->DCBmap[cmd->target]); return 0; } @@ -578,7 +765,7 @@ UCHAR bval; pDCB->GoingSRBCnt--; pDCB->pDCBACB->SelLost++; - DEBUG0(printk("DC390: RewaitSRB (%p, %p) pid = %li\n", pDCB, pSRB, pSRB->pcmd->pid);) + DEBUG0(printk(KERN_INFO "DC390: RewaitSRB (%p, %p) pid = %li\n", pDCB, pSRB, pSRB->pcmd->pid);) psrb1 = pDCB->pGoingSRB; if( pSRB == psrb1 ) { @@ -678,6 +865,13 @@ } +/*********************************************************************** + * Function: static void dc390_SendSRB (PACB pACB, PSRB pSRB) + * + * Purpose: Send SCSI Request Block (pSRB) to adapter (pACB) + * + ***********************************************************************/ + static void dc390_SendSRB( PACB pACB, PSRB pSRB ) { PDCB pDCB; @@ -720,6 +914,14 @@ return; } +/*********************************************************************** + * Function: static void dc390_BuildSRB (Scsi_Cmd *pcmd, PDCB pDCB, + * PSRB pSRB) + * + * Purpose: Prepare SRB for being sent to Device DCB w/ command *pcmd + * + ***********************************************************************/ + static void dc390_BuildSRB (Scsi_Cmnd* pcmd, PDCB pDCB, PSRB pSRB) { pSRB->pSRBDCB = pDCB; @@ -790,7 +992,7 @@ DEBUG0(/* if(pACB->scan_devices) */ \ - printk(KERN_DEBUG "DC390: Queue Cmd=%02x,ID=%d,LUN=%d (pid=%li)\n",\ + printk(KERN_INFO "DC390: Queue Cmd=%02x,ID=%d,LUN=%d (pid=%li)\n",\ cmd->cmnd[0],cmd->target,cmd->lun,cmd->pid);) DC390_LOCK_ACB; @@ -1056,15 +1258,17 @@ printk (" %02x %02x %02x %02x %02x %02x\n", DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1), DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4)); + DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT); printk ("DC390: Register dump: DMA engine:\n"); printk ("DC390: Cmd STrCnt SBusA WrkBC WrkAC Stat SBusCtrl\n"); printk ("DC390: %02x %08x %08x %08x %08x %02x %08x\n", DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr), DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr), DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl)); + DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); PDEVSET1; PCI_READ_CONFIG_WORD(PDEV, PCI_STATUS, &pstat); printk ("DC390: Register dump: PCI Status: %04x\n", pstat); - printk ("DC390: Please report driver trouble to K.Garloff@ping.de\n"); + printk ("DC390: In case of driver trouble read linux/drivers/scsi/README.tmscsim\n"); }; @@ -1076,6 +1280,8 @@ * Inputs : cmd - command to abort * * Returns : 0 on success, -1 on failure. + * + * Status: Buggy ! ***********************************************************************/ int DC390_abort (Scsi_Cmnd *cmd) @@ -1347,13 +1553,13 @@ /*********************************************************************** - * Function : static void dc390_initDCB + * Function : static void dc390_initDCB() * * Purpose : initialize the internal structures for a given DCB * * Inputs : cmd - pointer to this scsi cmd request block structure - * ***********************************************************************/ + void dc390_initDCB( PACB pACB, PDCB *ppDCB, PSCSICMD cmd ) { PEEprom prom; @@ -1412,11 +1618,11 @@ } /*********************************************************************** - * Function : static void dc390_updateDCB + * Function : static void dc390_updateDCB() * * Purpose : Set the configuration dependent DCB parameters - * ***********************************************************************/ + void dc390_updateDCB (PACB pACB, PDCB pDCB) { pDCB->IdentifyMsg = IDENTIFY (pDCB->DevMode & EN_DISCONNECT_, pDCB->UnitSCSILUN); @@ -1441,11 +1647,11 @@ /*********************************************************************** - * Function : static void dc390_updateDCBs + * Function : static void dc390_updateDCBs () * * Purpose : Set the configuration dependent DCB params for all DCBs - * ***********************************************************************/ + static void dc390_updateDCBs (PACB pACB) { int i; @@ -1459,13 +1665,13 @@ /*********************************************************************** - * Function : static void dc390_initSRB + * Function : static void dc390_initSRB() * * Purpose : initialize the internal structures for a given SRB * * Inputs : psrb - pointer to this scsi request block structure - * ***********************************************************************/ + static void __inline__ dc390_initSRB( PSRB psrb ) { /* psrb->PhysSRB = virt_to_phys( psrb ); */ @@ -1489,13 +1695,14 @@ /*********************************************************************** - * Function : static void dc390_initACB + * Function : static void dc390_initACB () * * Purpose : initialize the internal structures for a given SCSI host * * Inputs : psh - pointer to this host adapter's structure - * + * io_port, Irq, index: Resources and adapter index ***********************************************************************/ + void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index) { PACB pACB; @@ -1510,14 +1717,14 @@ psh->irq = Irq; pACB = (PACB) psh->hostdata; - DC390_LOCK_INIT; + DC390_LOCKA_INIT; DC390_LOCK_ACB; pACB->pScsiHost = psh; pACB->IOPortBase = (USHORT) io_port; pACB->IRQLevel = Irq; - DEBUG0(printk (KERN_DEBUG "DC390: Adapter index %i, ID %i, IO 0x%08x, IRQ 0x%02x\n", \ + DEBUG0(printk (KERN_INFO "DC390: Adapter index %i, ID %i, IO 0x%08x, IRQ 0x%02x\n", \ index, psh->this_id, (int)io_port, Irq);) psh->max_id = 8; @@ -1541,6 +1748,8 @@ pACB->TagMaxNum = 2 << dc390_eepromBuf[index][EE_TAG_CMD_NUM]; pACB->ACBFlag = 0; pACB->scan_devices = 1; + pACB->MsgLen = 0; + pACB->Ignore_IRQ = 0; pACB->Gmode2 = dc390_eepromBuf[index][EE_MODE2]; dc390_linkSRB( pACB ); pACB->pTmpSRB = &pACB->TmpSRB; @@ -1554,33 +1763,44 @@ /*********************************************************************** - * Function : static int dc390_initAdapter + * Function : static int dc390_initAdapter () * * Purpose : initialize the SCSI chip ctrl registers * * Inputs : psh - pointer to this host adapter's structure + * io_port, Irq, index: Resources * + * Outputs: 0 on success, -1 on error ***********************************************************************/ + int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index) { - PACB pACB, pacb; + PACB pACB, pACB2; UCHAR used_irq = 0, dstate; int i; + + pACB = (PACB) psh->hostdata; + + for ( pACB2 = dc390_pACB_start; pACB2 ; ) + { + if( pACB2->IRQLevel == Irq ) + { + used_irq = 1; + break; + } + else + pACB2 = pACB2->pNextACB; + } - pacb = dc390_pACB_start; - if( pacb != NULL ) - { - for ( ; (pacb != (PACB) -1) ; ) + if (check_region (io_port, psh->n_io_port)) { - if( pacb->IRQLevel == Irq ) - { - used_irq = 1; - break; - } - else - pacb = pacb->pNextACB; + printk(KERN_ERR "DC390: register IO ports error!\n"); + return( -1 ); } - } + else + request_region (io_port, psh->n_io_port, "tmscsim"); + + DC390_read8_ (INT_Status, io_port); /* Reset Pending INT */ if( !used_irq ) { @@ -1591,18 +1811,22 @@ } } - if (check_region (io_port, psh->n_io_port)) - { - printk(KERN_ERR "DC390: register IO ports error!\n"); - return( -1 ); - } + if( !dc390_pACB_start ) + { + pACB2 = NULL; + dc390_pACB_start = pACB; + dc390_pACB_current = pACB; + pACB->pNextACB = NULL; + } else - request_region (io_port, psh->n_io_port, "tmscsim"); - - pACB = (PACB) psh->hostdata; - /* pACB->IOPortBase = (USHORT) io_port; */ + { + pACB2 = dc390_pACB_current; + dc390_pACB_current->pNextACB = pACB; + dc390_pACB_current = pACB; + pACB->pNextACB = NULL; + }; - DC390_write8_ (CtrlReg1, DIS_INT_ON_SCSI_RST | psh->this_id, io_port); /* Disable SCSI bus reset interrupt */ + DC390_write8 (CtrlReg1, DIS_INT_ON_SCSI_RST | psh->this_id); /* Disable SCSI bus reset interrupt */ if (pACB->Gmode2 & RST_SCSI_BUS) { @@ -1612,6 +1836,7 @@ udelay(1000); }; pACB->ACBFlag = 0; + DC390_read8 (INT_Status); /* Reset Pending INT */ DC390_write8 (Scsi_TimeOut, SEL_TIMEOUT); /* 250ms selection timeout */ DC390_write8 (Clk_Factor, CLK_FREQ_40MHZ); /* Conversion factor = 0 , 40MHz clock */ @@ -1622,7 +1847,7 @@ (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ? NEGATE_REQACKDATA : 0); /* Negation */ DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); - DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT); + DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); dstate = DC390_read8 (DMA_Status); DC390_write8 (DMA_Status, dstate); /* clear */ @@ -1630,194 +1855,24 @@ } -static void __init dc390_EnDisableCE( UCHAR mode, PDEVDECL, PUCHAR regval ) -{ - UCHAR bval; - - bval = 0; - if(mode == ENABLE_CE) - *regval = 0xc0; - else - *regval = 0x80; - PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); - if(mode == DISABLE_CE) - PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); - udelay(160); -} - -#ifndef CONFIG_SCSI_DC390T_NOGENSUPP -static void __init dc390_EEpromDefaults (UCHAR index) -{ - PUCHAR ptr; - UCHAR id; - ptr = (PUCHAR) dc390_eepromBuf[index]; - - /* Adapter Settings */ - ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0]; /* Adapter ID */ - ptr[EE_MODE2] = (UCHAR)tmscsim[3]; - ptr[EE_DELAY] = 0; /* ?? */ - ptr[EE_TAG_CMD_NUM] = (UCHAR)tmscsim[4]; /* Tagged Comds */ - - /* Device Settings */ - for (id = 0; id < MAX_SCSI_ID; id++) - { - ptr[id<<2] = (UCHAR)tmscsim[2]; /* EE_MODE1 */ - ptr[(id<<2) + 1] = (UCHAR)tmscsim[1]; /* EE_Speed */ - }; - dc390_adapname = "AM53C974"; -} - -static void __init dc390_checkparams (void) -{ - PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x\n", tmscsim[0],\ - tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4]);) - if (tmscsim[0] < 0 || tmscsim[0] > 7) /* modules-2.0.0 passes -1 as string */ - { - tmscsim[0] = 7; tmscsim[1] = 4; - tmscsim[2] = 9; tmscsim[3] = 15; - tmscsim[4] = 2; - printk (KERN_INFO "DC390: Using safe settings.\n"); - } - else - { - /* if (tmscsim[0] < 0 || tmscsim[0] > 7) tmscsim[0] = 7; */ - if (tmscsim[1] < 0 || tmscsim[1] > 7) tmscsim[1] = 4; - if (tmscsim[4] < 0 || tmscsim[4] > 5) tmscsim[4] = 4; - }; -}; -/* Override defaults on cmdline: - * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped) - */ -void __init dc390_setup (char *str, int *ints) -{ - int i; - for (i = 0; i < ints[0]; i++) - tmscsim[i] = ints[i+1]; - if (ints[0] > 5) - printk (KERN_NOTICE "DC390: ignore extra params!\n"); - /* dc390_checkparams (); */ -}; -#endif /* CONFIG_SCSI_DC390T_NOGENSUPP */ - - -static void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry ) -{ - UCHAR bval; - - bval = 0; - if(Carry) - { - bval = 0x40; - *regval = 0x80; - PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); - } - udelay(160); - bval |= 0x80; - PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); - udelay(160); - bval = 0; - PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); - udelay(160); -} - - -static UCHAR __init dc390_EEpromInDO( PDEVDECL ) -{ - UCHAR bval; - - PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x80); - udelay(160); - PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x40); - udelay(160); - PCI_READ_CONFIG_BYTE(PDEV, 0x00, &bval); - if(bval == 0x22) - return(1); - else - return(0); -} - - -static USHORT __init dc390_EEpromGetData1( PDEVDECL ) -{ - UCHAR i; - UCHAR carryFlag; - USHORT wval; - - wval = 0; - for(i=0; i<16; i++) - { - wval <<= 1; - carryFlag = dc390_EEpromInDO(PDEV); - wval |= carryFlag; - } - return(wval); -} - - -static void __init dc390_Prepare( PDEVDECL, PUCHAR regval, UCHAR EEpromCmd ) -{ - UCHAR i,j; - UCHAR carryFlag; - - carryFlag = 1; - j = 0x80; - for(i=0; i<9; i++) - { - dc390_EEpromOutDI(PDEV,regval,carryFlag); - carryFlag = (EEpromCmd & j) ? 1 : 0; - j >>= 1; - } -} - - -static void __init dc390_ReadEEprom( PDEVDECL, PUSHORT ptr) -{ - UCHAR regval,cmd; - UCHAR i; - - cmd = EEPROM_READ; - for(i=0; i<0x40; i++) - { - dc390_EnDisableCE(ENABLE_CE, PDEV, ®val); - dc390_Prepare(PDEV, ®val, cmd++); - *ptr++ = dc390_EEpromGetData1(PDEV); - dc390_EnDisableCE(DISABLE_CE, PDEV, ®val); - } -} - - -static UCHAR __init dc390_CheckEEpromCheckSum( PDEVDECL, UCHAR index ) -{ - UCHAR i; - char EEbuf[128]; - USHORT wval, *ptr = (PUSHORT)EEbuf; - - dc390_ReadEEprom( PDEV, ptr ); - memcpy (dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID); - memcpy (&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID], - &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID); - wval = 0; - for(i=0; i<0x40; i++, ptr++) - wval += *ptr; - return (wval == 0x1234 ? 0 : 1); -} - - /*********************************************************************** - * Function : static int DC390_init (struct Scsi_Host *host) + * Function : static int DC390_init (struct Scsi_Host *host, ...) * * Purpose : initialize the internal structures for a given SCSI host * - * Inputs : host - pointer to this host adapter's structure/ + * Inputs : host - pointer to this host adapter's structure + * io_port - IO ports mapped to this adapter + * Irq - IRQ assigned to this adpater + * PDEVDECL - PCI access handle + * index - Adapter index * - * Preconditions : when this function is called, the chip_type - * field of the pACB structure MUST have been set. + * Outputs: 0 on success, -1 on error * * Note: written in capitals, because the locking is only done here, * not in DC390_detect, called from outside ***********************************************************************/ -static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, PDEVDECL, int index) +static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, PDEVDECL, UCHAR index) { PSH psh; PACB pACB; @@ -1846,7 +1901,7 @@ if( !psh ) return( -1 ); pACB = (PACB) psh->hostdata; - DC390_LOCK_INIT; + DC390_LOCKA_INIT; DC390_LOCK_ACB; #if 0 @@ -1862,37 +1917,21 @@ } #endif - DEBUG0(printk("DC390: pSH = %8x,", (UINT) psh);) - DEBUG0(printk("DC390: Index %02i,", index);) + DEBUG0(printk(KERN_INFO "DC390: pSH = %8x,", (UINT) psh);) + DEBUG0(printk(" Index %02i,", index);) dc390_initACB( psh, io_port, Irq, index ); + pACB = (PACB) psh->hostdata; + PDEVSET; - DC390_read8_ (INT_Status, io_port); /* Reset Pending INT */ - if( !dc390_initAdapter( psh, io_port, Irq, index ) ) { - pACB = (PACB) psh->hostdata; - if( !dc390_pACB_start ) - { - dc390_pACB_start = pACB; - dc390_pACB_current = pACB; - pACB->pNextACB = (PACB) -1; - } - else - { - dc390_pACB_current->pNextACB = pACB; - dc390_pACB_current = pACB; - pACB->pNextACB = (PACB) -1; - } - - DEBUG0(printk("DC390: pACB = %8x, pDCBmap = %8x, pSRB_array = %8x\n",\ + DEBUG0(printk("\nDC390: pACB = %8x, pDCBmap = %8x, pSRB_array = %8x\n",\ (UINT) pACB, (UINT) pACB->DCBmap, (UINT) pACB->SRB_array);) DEBUG0(printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",\ sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) );) - DC390_read8_ (INT_Status, io_port); /* Reset Pending INT */ - DC390_UNLOCK_ACB; return (0); } @@ -1960,7 +1999,6 @@ PDEVDECL0; UCHAR irq; UINT io_port; - UCHAR adaptCnt = 0; /* Number of boards detected */ DC390_IFLAGS DC390_DFLAGS DC390_LOCK_DRV; @@ -1972,29 +2010,36 @@ { DC390_LOCK_IO; /* Remove this when going to new eh */ PCI_GET_IO_AND_IRQ; - DEBUG0(printk(KERN_DEBUG "DC390(%i): IO_PORT=%04x,IRQ=%x\n", adaptCnt, (UINT) io_port, irq);) + DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq);) - if( !DC390_init(psht, io_port, irq, PDEV, adaptCnt)) + if( !DC390_init(psht, io_port, irq, PDEV, dc390_adapterCnt)) { PCI_SET_MASTER; dc390_set_pci_cfg (PDEV); - adaptCnt++; + dc390_adapterCnt++; }; DC390_UNLOCK_IO; /* Remove when going to new eh */ } else printk (KERN_ERR "DC390: No PCI BIOS found!\n"); - if (adaptCnt) + if (dc390_adapterCnt) psht->proc_dir = &DC390_proc_scsi_tmscsim; - printk(KERN_INFO "DC390: %i adapters found\n", adaptCnt); - dc390_adapterCnt = adaptCnt; + printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt); DC390_UNLOCK_DRV; - return( adaptCnt ); + return( dc390_adapterCnt ); } +/*********************************************************************** + * Functions: dc390_inquiry(), dc390_inquiry_done() + * + * Purpose: When changing speed etc., we have to issue an INQUIRY + * command to make sure, we agree upon the nego parameters + * with the device + ***********************************************************************/ + static void dc390_inquiry_done (Scsi_Cmnd* cmd) { printk (KERN_INFO "DC390: INQUIRY (ID %02x LUN %02x) returned %08x\n", @@ -2211,7 +2256,7 @@ /* NegoPeriod */ if (*pos != '-') { - SCANF (pos, p0, dum, 76, 800); + SCANF (pos, p0, dum, 72, 800); pDCB->NegoPeriod = dum >> 2; if (pDCB->NegoPeriod != olddevmode) needs_inquiry++; if (!pos) goto ok; @@ -2367,8 +2412,6 @@ * ********************************************************************/ -/* KG: proc_info taken from driver aha152x.c */ - #undef SPRINTF #define SPRINTF(args...) pos += sprintf(pos, ## args) @@ -2529,14 +2572,14 @@ if (host->irq != IRQ_NONE) { for (irq_count = 0, pACB = dc390_pACB_start; - pACB && pACB != (PACB)-1; pACB = pACB->pNextACB) + pACB; pACB = pACB->pNextACB) { if ( pACB->IRQLevel == host->irq ) ++irq_count; } if (irq_count == 1) { - DEBUG0(printk(KERN_DEBUG "DC390: Free IRQ %i\n",host->irq);) + DEBUG0(printk(KERN_INFO "DC390: Free IRQ %i\n",host->irq);) free_irq(host->irq,NULL); } } --- linux/drivers/scsi/tmscsim.h.orig Tue Oct 27 19:10:08 1998 +++ linux/drivers/scsi/tmscsim.h Fri Dec 25 18:33:27 1998 @@ -3,7 +3,7 @@ ;* TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter * ;* Device Driver * ;***********************************************************************/ -/* $Id: tmscsim.h,v 2.1 1998/10/14 10:31:48 garloff Exp $ */ +/* $Id: tmscsim.h,v 2.4 1998/12/25 17:33:27 garloff Exp $ */ #ifndef _TMSCSIM_H #define _TMSCSIM_H @@ -95,15 +95,13 @@ /* 0x48: */ SGL Segmentx; /* make a one entry of S/G list table */ -PUCHAR pMsgPtr; - UCHAR ScsiCmdLen; UCHAR ScsiPhase; UCHAR AdaptStatus; UCHAR TargetStatus; -/* 0x5c: */ +/* 0x58: */ UCHAR MsgCnt; UCHAR EndMessage; UCHAR RetryCnt; @@ -115,7 +113,7 @@ UCHAR SRBStatus; //UCHAR IORBFlag; /*;81h-Reset, 2-retry */ -/* 0x64: */ +/* 0x60: */ }; @@ -218,14 +216,16 @@ UCHAR sel_timeout; UCHAR glitch_cfg; -UCHAR reserved[2]; /* alignment */ +UCHAR MsgLen; +UCHAR Ignore_IRQ; /* Not used */ PDEVDECL1; /* Pointer to PCI cfg. space */ -/* 0x44/0x40: */ +/* 0x40/0x3c: */ ULONG Cmds; ULONG CmdInQ; ULONG CmdOutOfSRB; ULONG SelLost; + /* 0x50/0x4c: */ DC390_SRB TmpSRB; --- linux/drivers/scsi/dc390.h.orig Wed Nov 25 19:14:25 1998 +++ linux/drivers/scsi/dc390.h Fri Dec 25 18:33:27 1998 @@ -4,7 +4,7 @@ * Description: Device Driver for Tekram DC-390(T) PCI SCSI * * Bus Master Host Adapter * ***********************************************************************/ -/* $Id: dc390.h,v 2.3 1998/10/24 08:45:02 garloff Exp $ */ +/* $Id: dc390.h,v 2.12 1998/12/25 17:33:27 garloff Exp $ */ #include @@ -16,7 +16,7 @@ #define DC390_H #define DC390_BANNER "Tekram DC390/AM53C974" -#define DC390_VERSION "2.0b 1998/10/24" +#define DC390_VERSION "2.0d 1998/12/25" #if defined(HOSTS_C) || defined(MODULE) --- linux/drivers/scsi/scsiiom.c.orig Tue Oct 27 19:10:08 1998 +++ linux/drivers/scsi/scsiiom.c Fri Dec 25 18:33:27 1998 @@ -4,7 +4,7 @@ * Description: Device Driver for Tekram DC-390 (T) PCI SCSI * * Bus Master Host Adapter * ***********************************************************************/ -/* $Id: scsiiom.c,v 2.3 1998/10/24 09:10:28 garloff Exp $ */ +/* $Id: scsiiom.c,v 2.15 1998/12/25 17:33:27 garloff Exp $ */ UCHAR dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ) @@ -36,7 +36,7 @@ DC390_write8 (ScsiFifo, bval); bval1 = SEL_W_ATN; pSRB->SRBState = SRB_START_; - DEBUG1(printk ("DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);) + DEBUG1(printk (KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);) if( pDCB->SyncMode & SYNC_ENABLE ) { if( !(pDCB->IdentifyMsg & 7) || /* LUN == 0 || Cmd != INQUIRY */ @@ -53,21 +53,21 @@ if(pDCB->SyncMode & EN_TAG_QUEUEING) { DC390_write8 (ScsiFifo, MSG_SIMPLE_QTAG); - DEBUG1(printk ("DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN3, pDCB->TagMask);) + DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN3, pDCB->TagMask);) bval = 0; wlval = 1; while (wlval & pDCB->TagMask) { bval++; wlval <<= 1; }; pDCB->TagMask |= wlval; DC390_write8 (ScsiFifo, bval); pSRB->TagNumber = bval; - DEBUG1(printk ("DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);) + DEBUG1(printk (KERN_DEBUG "DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);) bval1 = SEL_W_ATN3; pSRB->SRBState = SRB_START_; } else /* No TagQ */ { bval1 = SEL_W_ATN; - DEBUG1(printk ("DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);) + DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);) pSRB->SRBState = SRB_START_; } } @@ -82,7 +82,7 @@ bval &= 0xBF; /* No DisConn */ DC390_write8 (ScsiFifo, bval); bval1 = SEL_W_ATN; - DEBUG1(printk ("DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);) + DEBUG1(printk (KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);) pSRB->SRBState = SRB_START_; /* ??? */ if( pDCB->SyncMode & SYNC_ENABLE ) @@ -101,13 +101,13 @@ if(pDCB->SyncMode & EN_TAG_QUEUEING) { pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG; - DEBUG1(printk ("DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN_STOP, pDCB->TagMask);) + DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, SEL_W_ATN_STOP, pDCB->TagMask);) bval = 0; wlval = 1; while (wlval & pDCB->TagMask) { bval++; wlval <<= 1; }; pDCB->TagMask |= wlval; pSRB->TagNumber = bval; - DEBUG1(printk ("DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);) + DEBUG1(printk (KERN_DEBUG "DC390: SRB %p (Cmd %li), Tag %02x queued\n", pSRB, pSRB->pcmd->pid, bval);) pSRB->MsgOutBuf[1] = bval; pSRB->MsgCnt = 2; bval1 = SEL_W_ATN_STOP; @@ -119,7 +119,7 @@ pSRB->MsgCnt = 1; pSRB->SRBState = SRB_START_; bval1 = SEL_W_ATN_STOP; - DEBUG1(printk ("DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);) + DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);) }; } } @@ -134,7 +134,7 @@ DC390_write8 (ScsiFifo, bval); DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer)); DC390_write8 (ScsiFifo, bval); - DEBUG1(printk ("DC390: AutoReqSense !\n");) + DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n");) } else /* write cmnd to bus */ { @@ -150,16 +150,16 @@ { pSRB->SRBState = SRB_READY; pDCB->TagMask &= ~( 1 << pSRB->TagNumber ); - DEBUG0(printk ("DC390: Interrupt during StartSCSI!\n");) + DEBUG0(printk (KERN_WARNING "DC390: Interrupt during StartSCSI!\n");) return 1; } else { pSRB->ScsiPhase = SCSI_NOP1; DEBUG0(if (pACB->pActiveDCB) \ - printk ("DC390: ActiveDCB != 0\n");) + printk (KERN_WARNING "DC390: ActiveDCB != 0\n");) DEBUG0(if (pDCB->pActiveSRB) \ - printk ("DC390: ActiveSRB != 0\n");) + printk (KERN_WARNING "DC390: ActiveSRB != 0\n");) pACB->pActiveDCB = pDCB; pDCB->pActiveSRB = pSRB; //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); @@ -183,12 +183,10 @@ DEBUG0(PDEVSET1;) DEBUG0(PCI_READ_CONFIG_WORD (PDEV, PCI_STATUS, &pstate);) DEBUG0(if (pstate & (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY))\ - { printk("DC390: PCI state = %04x!\n", pstate); \ + { printk(KERN_WARNING "DC390: PCI state = %04x!\n", pstate); \ PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY));};) - dstate = DC390_read8 (DMA_Status); - DC390_write8 (DMA_Status, dstate); /* clear */ - //DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */ + dstate = DC390_read8 (DMA_Status); if (! pACB->pActiveDCB || ! pACB->pActiveDCB->pActiveSRB) return dstate; else pSRB = pACB->pActiveDCB->pActiveSRB; @@ -207,12 +205,11 @@ { DEBUG1(printk (KERN_DEBUG "DC390: read residual bytes ... \n");) dstate = DC390_read8 (DMA_Status); - DC390_write8 (DMA_Status, dstate); /* clear */ residual = DC390_read8 (CtcReg_Low) | DC390_read8 (CtcReg_Mid) << 8 | DC390_read8 (CtcReg_High) << 16; residual += DC390_read8 (Current_Fifo) & 0x1f; } while (residual && ! (dstate & SCSI_INTERRUPT) && --ctr); - if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!\n", DC390_read32 (DMA_Wk_ByteCntr)); + if (!ctr) printk (KERN_CRIT "DC390: dma_intr: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr)); /* residual = ... */ } else @@ -231,6 +228,7 @@ DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); } + dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24; return dstate; }; #endif @@ -245,14 +243,16 @@ UCHAR phase, i; void (*stateV)( PACB, PSRB, PUCHAR ); UCHAR istate, istatus; +#if DMA_INT UCHAR dstatus; +#endif DC390_AFLAGS DC390_IFLAGS DC390_DFLAGS pACB = dc390_pACB_start; if (pACB == 0) { - printk(KERN_ERR "DC390: Interrupt on uninitialized adapter!\n"); + printk(KERN_WARNING "DC390: Interrupt on uninitialized adapter!\n"); return; } DC390_LOCK_DRV; @@ -275,8 +275,8 @@ DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus);) - if( pACB == (PACB )-1) { DC390_UNLOCK_DRV; return; }; - + if( !pACB ) { DC390_UNLOCK_DRV; return; }; + #if DMA_INT DC390_LOCK_IO; DC390_LOCK_ACB; @@ -284,15 +284,17 @@ DC390_UNLOCK_ACB; DC390_UNLOCK_IO; - DEBUG1(printk ("dstatus=%02x,", dstatus);) + DEBUG1(printk (KERN_DEBUG "dstatus=%02x,", dstatus);) if (! (dstatus & SCSI_INTERRUPT)) { - DEBUG0(printk ("DC390 Int w/o SCSI actions (only DMA?)\n");) + DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n");) DC390_UNLOCK_DRV; return; }; #else - dstatus = DC390_read8 (DMA_Status); + //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT); + //dstatus = DC390_read8 (DMA_Status); + //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); #endif DC390_LOCK_IO; @@ -302,14 +304,15 @@ istate = DC390_read8 (Intern_State); istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */ - DEBUG1(printk ("Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus);) - dc390_laststatus = dstatus<<24 | sstatus<<16 | istate<<8 | istatus; + DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus);) + dc390_laststatus &= ~0x00ffffff; + dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus; if (sstatus & ILLEGAL_OP_ERR) - { - printk ("DC390: Illegal Operation detected (%08lx)!\n", dc390_laststatus); - dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB); - }; + { + printk ("DC390: Illegal Operation detected (%08lx)!\n", dc390_laststatus); + dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB); + }; if(istatus & DISCONNECTED) { @@ -323,18 +326,6 @@ goto unlock; } - if(istatus & INVALID_CMD) - { - dc390_InvalidCmd( pACB ); - goto unlock; - } - - if(istatus & SCSI_RESET) - { - dc390_ScsiRstDetect( pACB ); - goto unlock; - } - if( istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) ) { pDCB = pACB->pActiveDCB; @@ -345,7 +336,7 @@ }; pSRB = pDCB->pActiveSRB; if( pDCB->DCBFlag & ABORT_DEV_ ) - dc390_EnableMsgOut( pACB, pSRB ); + dc390_EnableMsgOut_Abort (pACB, pSRB); phase = pSRB->ScsiPhase; DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus);) @@ -357,7 +348,21 @@ DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus);) stateV = (void *) dc390_phase1[phase]; ( *stateV )( pACB, pSRB, &sstatus ); + goto unlock; } + + if(istatus & INVALID_CMD) + { + dc390_InvalidCmd( pACB ); + goto unlock; + } + + if(istatus & SCSI_RESET) + { + dc390_ScsiRstDetect( pACB ); + goto unlock; + } + unlock: DC390_LOCK_DRV_NI; DC390_UNLOCK_ACB; @@ -380,6 +385,7 @@ UCHAR sstatus; PSGL psgl; ULONG ResidCnt, xferCnt; + UCHAR dstate = 0; sstatus = *psstatus; @@ -391,10 +397,9 @@ if( sstatus & COUNT_2_ZERO ) { int ctr = 5000000; /* only try for about a tenth of a second */ - while( --ctr && !(DC390_read8 (DMA_Status) & DMA_XFER_DONE) && pSRB->SGToBeXferLen ) - DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */ - if (!ctr) printk (KERN_CRIT "DC390: DataOut_0: DMA aborted unfinished: %06x bytes remain!\n", DC390_read32 (DMA_Wk_ByteCntr)); - DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */ + while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen ); + if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr)); + dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24; pSRB->TotalXferredLen += pSRB->SGToBeXferLen; pSRB->SGIndex++; if( pSRB->SGIndex < pSRB->SGcount ) @@ -443,15 +448,14 @@ { int ctr = 5000000; /* only try for about a tenth of a second */ int dstate = 0; - while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen ) - DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */ - if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA aborted unfinished: %06x bytes remain!\n", DC390_read32 (DMA_Wk_ByteCntr)); + while( --ctr && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE) && pSRB->SGToBeXferLen ); + if (!ctr) printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n", DC390_read32 (DMA_Wk_ByteCntr)); if (!ctr) printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate); + dc390_laststatus &= ~0xff000000; dc390_laststatus |= dstate << 24; DEBUG1(ResidCnt = ((ULONG) DC390_read8 (CtcReg_High) << 16) \ + ((ULONG) DC390_read8 (CtcReg_Mid) << 8) \ + ((ULONG) DC390_read8 (CtcReg_Low));) - DEBUG1(printk ("Count_2_Zero (ResidCnt=%li,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);) - DC390_write8 (DMA_Status, DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */ + DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%li,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);) DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ @@ -474,7 +478,7 @@ bval = DC390_read8 (Current_Fifo); while( bval & 0x1f ) { - DEBUG1(printk ("Check for residuals,");) + DEBUG1(printk (KERN_DEBUG "Check for residuals,");) if( (bval & 0x1f) == 1 ) { for(i=0; i < 0x100; i++) @@ -494,17 +498,18 @@ } din_1: DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD); - for (i=0; i<0x8000; i++) + for (i = 0xa000; i; i--) { bval = DC390_read8 (DMA_Status); - DC390_write8 (DMA_Status, BLAST_COMPLETE | DMA_XFER_DONE | DMA_XFER_ABORT | DMA_XFER_ERROR | PCI_MS_ABORT); /* clear */ if (bval & BLAST_COMPLETE) break; } - if (i == 0x8000) printk (KERN_CRIT "DC390: DMA Blast aborted unfinished!!\n"); + /* It seems a DMA Blast abort isn't that bad ... */ + if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n"); //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ + dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24; - DEBUG1(printk ("Blast: Read %i times DMA_Status %02x", i, bval);) + DEBUG1(printk (KERN_DEBUG "Blast: Read %li times DMA_Status %02x", 0xa000-i, bval);) ResidCnt = (ULONG) DC390_read8 (CtcReg_High); ResidCnt <<= 8; ResidCnt |= (ULONG) DC390_read8 (CtcReg_Mid); @@ -525,7 +530,7 @@ pSRB->TotalXferredLen++; pSRB->SGToBeXferLen--; } - DEBUG1(printk ("Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\ + DEBUG1(printk (KERN_DEBUG "Xfered: %li, Total: %li, Remaining: %li\n", xferCnt,\ pSRB->TotalXferredLen, pSRB->SGToBeXferLen);) } @@ -558,164 +563,278 @@ //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); } -void -dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) + +static void __inline__ +dc390_reprog (PACB pACB, PDCB pDCB) { - UCHAR bval; - USHORT wval, wval1; - PDCB pDCB; - PSRB psrb; + DC390_write8 (Sync_Period, pDCB->SyncPeriod); + DC390_write8 (Sync_Offset, pDCB->SyncOffset); + DC390_write8 (CtrlReg3, pDCB->CtrlR3); + DC390_write8 (CtrlReg4, pDCB->CtrlR4); + dc390_SetXferRate (pACB, pDCB); +}; - pDCB = pACB->pActiveDCB; - bval = DC390_read8 (ScsiFifo); - if( !(pSRB->SRBState & SRB_MSGIN_MULTI) ) +#ifdef DC390_DEBUG0 +static void +dc390_printMsg (UCHAR *MsgBuf, UCHAR len) +{ + int i; + printk (" %02x", MsgBuf[0]); + for (i = 1; i < len; i++) + printk (" %02x", MsgBuf[i]); + printk ("\n"); +}; +#endif + +#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD) + +/* reject_msg */ +static void __inline__ +dc390_MsgIn_reject (PACB pACB, PSRB pSRB) +{ + pSRB->MsgOutBuf[0] = MSG_REJECT_; + pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; + DEBUG0 (printk (KERN_INFO "DC390: Reject message\n");) +} + +/* abort command */ +static void __inline__ +dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB ) +{ + pSRB->MsgOutBuf[0] = MSG_ABORT; + pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; + pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_; +} + +static PSRB +dc390_MsgIn_QTag (PACB pACB, PDCB pDCB, UCHAR tag) +{ + PSRB lastSRB = pDCB->pGoingLast; + PSRB pSRB = pDCB->pGoingSRB; + + if (pSRB) { - if(bval == MSG_DISCONNECT) - { - pSRB->SRBState = SRB_DISCONNECT; - } - else if( bval == MSG_SAVE_PTR ) - goto min6; - else if( (bval == MSG_EXTENDED) || ((bval >= MSG_SIMPLE_QTAG) && - (bval <= MSG_ORDER_QTAG)) ) + for( ;pSRB ; ) { - pSRB->SRBState |= SRB_MSGIN_MULTI; - pSRB->MsgInBuf[0] = bval; - pSRB->MsgCnt = 1; - pSRB->pMsgPtr = &(pSRB->MsgInBuf[1]); + if (pSRB->TagNumber == tag) break; + if (pSRB == lastSRB) goto mingx0; + pSRB = pSRB->pNextSRB; } - else if(bval == MSG_REJECT_) + + if( pDCB->DCBFlag & ABORT_DEV_ ) { - DC390_write8 (ScsiCmd, RESET_ATN_CMD); - pDCB->NegoPeriod = 50; - if( pSRB->SRBState & DO_SYNC_NEGO) - goto set_async; + pSRB->SRBState = SRB_ABORT_SENT; + dc390_EnableMsgOut_Abort( pACB, pSRB ); } - else if( bval == MSG_RESTORE_PTR) - goto min6; - else - goto min6; + + if( !(pSRB->SRBState & SRB_DISCONNECT) ) + goto mingx0; + + pDCB->pActiveSRB = pSRB; + pSRB->SRBState = SRB_DATA_XFER; } - else - { /* minx: */ + else + { + mingx0: + pSRB = pACB->pTmpSRB; + pSRB->SRBState = SRB_UNEXPECT_RESEL; + pDCB->pActiveSRB = pSRB; + pSRB->MsgOutBuf[0] = MSG_ABORT_TAG; + pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; + } + return pSRB; +} - *pSRB->pMsgPtr = bval; - pSRB->MsgCnt++; - pSRB->pMsgPtr++; - if( (pSRB->MsgInBuf[0] >= MSG_SIMPLE_QTAG) && - (pSRB->MsgInBuf[0] <= MSG_ORDER_QTAG) ) - { - if( pSRB->MsgCnt == 2) - { - pSRB->SRBState = 0; - bval = pSRB->MsgInBuf[1]; - pSRB = pDCB->pGoingSRB; - psrb = pDCB->pGoingLast; - if( pSRB ) - { - for( ;pSRB ; ) - { - if(pSRB->TagNumber != bval) - { - if( pSRB == psrb ) - goto mingx0; - pSRB = pSRB->pNextSRB; - } - else - break; - } - if( pDCB->DCBFlag & ABORT_DEV_ ) - { - pSRB->SRBState = SRB_ABORT_SENT; - dc390_EnableMsgOut( pACB, pSRB ); - } - if( !(pSRB->SRBState & SRB_DISCONNECT) ) - goto mingx0; - pDCB->pActiveSRB = pSRB; - pSRB->SRBState = SRB_DATA_XFER; - } - else - { -mingx0: - pSRB = pACB->pTmpSRB; - pSRB->SRBState = SRB_UNEXPECT_RESEL; - pDCB->pActiveSRB = pSRB; - pSRB->MsgOutBuf[0] = MSG_ABORT_TAG; - dc390_EnableMsgOut2( pACB, pSRB ); - } - } - } - else if( (pSRB->MsgInBuf[0] == MSG_EXTENDED) && (pSRB->MsgCnt == 5) ) - { /* Note: This will fail for target initiated SDTR ? */ - pSRB->SRBState &= ~(SRB_MSGIN_MULTI); - if( (pSRB->MsgInBuf[1] != 3) || (pSRB->MsgInBuf[2] != EXTENDED_SDTR) ) - { /* reject_msg: */ - pSRB->MsgCnt = 1; - pSRB->MsgInBuf[0] = MSG_REJECT_; - DC390_write8 (ScsiCmd, SET_ATN_CMD); - } - else if( !(pSRB->MsgInBuf[3]) || !(pSRB->MsgInBuf[4]) ) - { -set_async: - pDCB = pSRB->pSRBDCB; - if (!(pSRB->SRBState & DO_SYNC_NEGO)) - printk ("DC390: Target (%i,%i) initiates Non-Sync?\n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN); - pSRB->SRBState &= ~DO_SYNC_NEGO; - pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE); - pDCB->SyncPeriod = 0; - pDCB->SyncOffset = 0; - pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */ - pDCB->CtrlR4 &= 0x3f; - pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */ - goto re_prog; - } - else - { /* set_sync: */ - pDCB = pSRB->pSRBDCB; - if (!(pSRB->SRBState & DO_SYNC_NEGO)) - printk ("DC390: Target (%i,%i) initiates Sync: %ins %i ?\n", - pDCB->UnitSCSIID, pDCB->UnitSCSILUN, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]); - pSRB->SRBState &= ~DO_SYNC_NEGO; - pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE; - pDCB->SyncOffset &= 0x0f0; - pDCB->SyncOffset |= pSRB->MsgInBuf[4]; - pDCB->NegoPeriod = pSRB->MsgInBuf[3]; - wval = (USHORT) pSRB->MsgInBuf[3]; - wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */ - if( (wval1 * 25) != wval) - wval1++; - bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */ - pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */ - if (pACB->glitch_cfg != NS_TO_GLITCH(0)) - pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1)); - else - pDCB->CtrlR4 |= NS_TO_GLITCH(0); - if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */ - if (wval1 >= 8) - { - wval1--; /* Timing computation differs by 1 from FAST_SCSI */ - bval = FAST_CLK; /* fast clock / normal scsi */ - pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */ - } - pDCB->CtrlR3 = bval; - pDCB->SyncPeriod = (UCHAR)wval1; -re_prog: - DC390_write8 (Sync_Period, pDCB->SyncPeriod); - DC390_write8 (Sync_Offset, pDCB->SyncOffset); - DC390_write8 (CtrlReg3, pDCB->CtrlR3); - DC390_write8 (CtrlReg4, pDCB->CtrlR4); - dc390_SetXferRate (pACB, pDCB); - } +/* set async transfer mode */ +static void +dc390_MsgIn_set_async (PACB pACB, PSRB pSRB) +{ + PDCB pDCB = pSRB->pSRBDCB; + if (!(pSRB->SRBState & DO_SYNC_NEGO)) + printk ("DC390: Target %i initiates Non-Sync?\n", pDCB->UnitSCSIID); + pSRB->SRBState &= ~DO_SYNC_NEGO; + pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE); + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */ + pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */ + pDCB->CtrlR4 &= 0x3f; + pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */ + dc390_reprog (pACB, pDCB); +} + +/* set sync transfer mode */ +static void +dc390_MsgIn_set_sync (PACB pACB, PSRB pSRB) +{ + UCHAR bval; + USHORT wval, wval1; + PDCB pDCB = pSRB->pSRBDCB; + UCHAR oldsyncperiod = pDCB->SyncPeriod; + UCHAR oldsyncoffset = pDCB->SyncOffset; + + if (!(pSRB->SRBState & DO_SYNC_NEGO)) + { + printk ("DC390: Target %i initiates Sync: %ins %i ... answer ...\n", + pDCB->UnitSCSIID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]); + + /* reject */ + //dc390_MsgIn_reject (pACB, pSRB); + //return dc390_MsgIn_set_async (pACB, pSRB); + + /* Reply with corrected SDTR Message */ + if (pSRB->MsgInBuf[4] > 15) + { + printk ("DC390: Lower Sync Offset to 15\n"); + pSRB->MsgInBuf[4] = 15; } + if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod) + { + printk ("DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2); + pSRB->MsgInBuf[3] = pDCB->NegoPeriod; + }; + memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5); + pSRB->MsgCnt = 5; + DC390_ENABLE_MSGOUT; + }; + + pSRB->SRBState &= ~DO_SYNC_NEGO; + pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE; + pDCB->SyncOffset &= 0x0f0; + pDCB->SyncOffset |= pSRB->MsgInBuf[4]; + pDCB->NegoPeriod = pSRB->MsgInBuf[3]; + + wval = (USHORT) pSRB->MsgInBuf[3]; + wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */ + if( (wval1 * 25) != wval) wval1++; + bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */ + + pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */ + if (pACB->glitch_cfg != NS_TO_GLITCH(0)) + pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1)); + else + pDCB->CtrlR4 |= NS_TO_GLITCH(0); + if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */ + + if (wval1 >= 8) + { + wval1--; /* Timing computation differs by 1 from FAST_SCSI */ + bval = FAST_CLK; /* fast clock / normal scsi */ + pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */ } -min6: + + pDCB->CtrlR3 = bval; + pDCB->SyncPeriod = (UCHAR)wval1; + + if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->UnitSCSILUN == 0) + { + if (! (bval & FAST_SCSI)) wval1++; + printk ("DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->UnitSCSIID, + 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f); + } + + dc390_reprog (pACB, pDCB); +}; + + +/* According to the docs, the AM53C974 reads the message and + * generates a Succesful Operation IRQ before asserting ACK for + * the last byte (how does it know whether it's the last ?) */ +/* The old code handled it in another way, indicating, that on + * every message byte an IRQ is generated and every byte has to + * be manually ACKed. Hmmm ? (KG, 98/11/28) */ +/* The old implementation was correct. Sigh! */ + +/* Check if the message is complete */ +static UCHAR __inline__ +dc390_MsgIn_complete (UCHAR *msgbuf, ULONG len) +{ + if (*msgbuf == MSG_EXTENDED) + { + if (len < 2) return 0; + if (len < msgbuf[1] + 2) return 0; + } + else if (*msgbuf >= 0x20 && *msgbuf <= 0x2f) // two byte messages + if (len < 2) return 0; + return 1; +} + + + +/* read and eval received messages */ +void +dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus) +{ + PDCB pDCB = pACB->pActiveDCB; + + /* Read the msg */ + + pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo); + //pSRB->SRBState = 0; + + /* Msg complete ? */ + if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen)) + { + DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen);) + /* Now eval the msg */ + switch (pSRB->MsgInBuf[0]) + { + case MSG_DISCONNECT: + pSRB->SRBState = SRB_DISCONNECT; break; + + case MSG_SIMPLE_QTAG: + case MSG_HEAD_QTAG: + case MSG_ORDER_QTAG: + pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]); + break; + + case MSG_REJECT_: + DC390_write8 (ScsiCmd, RESET_ATN_CMD); + pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */ + if( pSRB->SRBState & DO_SYNC_NEGO) + dc390_MsgIn_set_async (pACB, pSRB); + break; + + case MSG_EXTENDED: + /* reject every extended msg but SDTR */ + if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR) + dc390_MsgIn_reject (pACB, pSRB); + else + { + if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0) + dc390_MsgIn_set_async (pACB, pSRB); + else + dc390_MsgIn_set_sync (pACB, pSRB); + }; + + // nothing has to be done + case MSG_COMPLETE: break; + + // SAVE POINTER my be ignored as we have the PSRB associated with the + // scsi command. Thanks, Gerard, for pointing it out. + case MSG_SAVE_PTR: break; + // The device might want to restart transfer with a RESTORE + case MSG_RESTORE_PTR: + printk ("DC390: RESTORE POINTER message received ... reject\n"); + // fall through + + // reject unknown messages + default: dc390_MsgIn_reject (pACB, pSRB); + } + + /* Clear counter and MsgIn state */ + pSRB->SRBState &= ~SRB_MSGIN; + pACB->MsgLen = 0; + }; + *psstatus = SCSI_NOP0; DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); } + void dc390_DataIO_Comm( PACB pACB, PSRB pSRB, UCHAR ioDir) { @@ -730,10 +849,10 @@ psgl = pSRB->pSegmentList; pSRB->SGBusAddr = virt_to_bus( psgl->address ); pSRB->SGToBeXferLen = (ULONG) psgl->length; - DEBUG1(printk (" DC390: Next SG segment.");) + DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.");) } lval = pSRB->SGToBeXferLen; - DEBUG1(printk (" DC390: Transfer %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);) + DEBUG1(printk (KERN_DEBUG " DC390: Transfer %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);) DC390_write8 (CtcReg_Low, (UCHAR) lval); lval >>= 8; DC390_write8 (CtcReg_Mid, (UCHAR) lval); @@ -749,21 +868,22 @@ DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD); DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir | DMA_INT); - //DEBUG1(printk ("DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));) + //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);) + //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status));) + //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);) } else /* xfer pad */ { - UCHAR bval = 0; if( pSRB->SGcount ) { pSRB->AdaptStatus = H_OVER_UNDER_RUN; pSRB->SRBStatus |= OVER_RUN; - DEBUG0(printk (" DC390: Overrun -");) + DEBUG0(printk (KERN_WARNING " DC390: Overrun -");) } - DEBUG0(printk (" Clear transfer pad \n");) - DC390_write8 (CtcReg_Low, bval); - DC390_write8 (CtcReg_Mid, bval); - DC390_write8 (CtcReg_High, bval); + DEBUG0(printk (KERN_WARNING " Clear transfer pad \n");) + DC390_write8 (CtcReg_Low, 0); + DC390_write8 (CtcReg_Mid, 0); + DC390_write8 (CtcReg_High, 0); pSRB->SRBState |= SRB_XFERPAD; DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE); @@ -1017,7 +1137,7 @@ dc390_SRBdone( pACB, pDCB, pSRB); } } - return; + pACB->MsgLen = 0; } @@ -1032,7 +1152,7 @@ DEBUG0(printk(KERN_INFO "RSEL,");) pDCB = pACB->pActiveDCB; if( pDCB ) - { /* Arbitration lost but Reselection win */ + { /* Arbitration lost but Reselection won */ DEBUG0(printk ("(ActiveDCB != 0)");) pSRB = pDCB->pActiveSRB; if( !( pACB->scan_devices ) ) @@ -1075,23 +1195,23 @@ printk (KERN_ERR "DC390: Reselect without outstanding cmnd (ID %02x, LUN %02x)\n", wval & 0xff, (wval & 0xff00) >> 8); pDCB->pActiveSRB = pSRB; - dc390_EnableMsgOut( pACB, pSRB ); + dc390_EnableMsgOut_Abort ( pACB, pSRB ); } else { if( pDCB->DCBFlag & ABORT_DEV_ ) { pSRB->SRBState = SRB_ABORT_SENT; - printk (KERN_NOTICE "DC390: Reselect: Abort (ID %02x, LUN %02x)\n", + printk (KERN_INFO "DC390: Reselect: Abort (ID %02x, LUN %02x)\n", wval & 0xff, (wval & 0xff00) >> 8); - dc390_EnableMsgOut( pACB, pSRB ); + dc390_EnableMsgOut_Abort( pACB, pSRB ); } else pSRB->SRBState = SRB_DATA_XFER; } } - DEBUG1(printk ("Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber);) + DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber);) pSRB->ScsiPhase = SCSI_NOP0; DC390_write8 (Scsi_Dest_ID, pDCB->UnitSCSIID); DC390_write8 (Sync_Period, pDCB->SyncPeriod); @@ -1244,7 +1364,7 @@ else pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) | SCSI_STAT_CHECKCOND; - REMOVABLEDEBUG(printk("Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->CmdBlock[0],\ + REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->CmdBlock[0],\ (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);) goto ckc_e; } @@ -1260,7 +1380,7 @@ { pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) | SCSI_STAT_CHECKCOND; - REMOVABLEDEBUG(printk("Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->CmdBlock[0],\ + REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->CmdBlock[0],\ (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);) goto ckc_e; } @@ -1299,7 +1419,7 @@ swlval += ptr2->length; ptr2++; } - REMOVABLEDEBUG(printk("XferredLen=%08x,NotXferLen=%08x\n",\ + REMOVABLEDEBUG(printk(KERN_INFO "XferredLen=%08x,NotXferLen=%08x\n",\ (UINT) pSRB->TotalXferredLen, (UINT) swlval);) } dc390_RequestSense( pACB, pDCB, pSRB ); @@ -1586,22 +1706,6 @@ dc390_RewaitSRB( pDCB, pSRB ); } - -static void __inline__ -dc390_EnableMsgOut2( PACB pACB, PSRB pSRB ) -{ - pSRB->MsgCnt = 1; - DC390_write8 (ScsiCmd, SET_ATN_CMD); -} - - -static void __inline__ -dc390_EnableMsgOut( PACB pACB, PSRB pSRB ) -{ - pSRB->MsgOutBuf[0] = MSG_ABORT; - dc390_EnableMsgOut2( pACB, pSRB ); - pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_; -} static void __inline__