Index: README.tmscsim =================================================================== RCS file: /home/cvsroot/dc390/README.tmscsim,v retrieving revision 2.9 retrieving revision 2.25.2.1 diff -u -r2.9 -r2.25.2.1 --- README.tmscsim 1998/12/25 18:04:20 2.9 +++ README.tmscsim 2000/01/17 22:34:36 2.25.2.1 @@ -9,6 +9,7 @@ 6. Potential improvements 7. Bug reports, debugging and updates 8. Acknowledgements +9. Copyright 1. Purpose and history @@ -25,7 +26,7 @@ Tekram DC390(T) adapter. This is where the name comes from: tm = Tekram scsi = SCSI driver, m = AMD (?) as opposed to w for the DC390W/U/F (NCR53c8X5, X=2/7) driver. Yes, there was also a driver for the latter, -tmscsimw, which supported DC390W/U/F adapters. It's not maintained any more, +tmscsiw, which supported DC390W/U/F adapters. It's not maintained any more, as the ncr53c8xx is perfectly supporting these adpaters since some time. The driver first appeared in April 1996, exclusively supported the DC390 @@ -59,7 +60,8 @@ 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. + my web page and apply the patch. Apply further patches to upgrade to the + latest version of the driver. 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 @@ -91,6 +93,8 @@ tune2fs -e remount-ro /dev/sd?? * have copies of your SCSI disk's partition tables on some safe location: dd if=/dev/sda of=/mnt/floppy/sda bs=512 count=1 + or just print it with: + fdisk -l | lpr * make sure you are able to boot Linux (e.g. from floppy disk using InitRD) if your SCSI disk gets corrupted. You can use ftp://student.physik.uni-dortmund.de/pub/linux/kernel/bootdisk.gz @@ -102,7 +106,7 @@ than the 33.33 MHz being in the PCI spec. If you want to share the IRQ with another device and the driver refuses to -do, you might succeed with changing the DC390_IRQ type in tmscsim.c to +do so, you might succeed with changing the DC390_IRQ type in tmscsim.c to SA_SHIRQ | SA_INTERRUPT. @@ -121,11 +125,12 @@ * Dynamically configurable by writing to /proc/scsi/tmscsim/? * Dynamic allocation of resources * SMP support: Locking on io_request lock (Linux 2.1/2.2) or adapter - specific locks (Linux 2.3) + specific locks (Linux 2.5?) * 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 - H = Host, C = Channel, I = SCSI ID, L = SCSI LUN.) Use with care! + (Try: echo "scsi add-single-device C B T U" >/proc/scsi/scsi + C = Controller, B = Bus, T = Target SCSI ID, U = Unit SCSI LUN.) Use + with care! * Try to use the partition table for the determination of the mapping @@ -139,20 +144,21 @@ the attached devices and their settings. Here's an example: -garloff@kg1:/home/garloff > cat /proc/scsi/tmscsim/0 -Tekram DC390/AM53C974 PCI SCSI Host Adapter, Driver Version 1.20s, 1998/08/20 -SCSI Host Nr 0, AM53C974 Adapter Nr 0 -IOPortBase 0x6200, IRQLevel 0x09 -MaxID 7, MaxLUN 8, AdapterID 7, SelTimeout 250 ms -TagMaxNum 16, Status 0, ACBFlag 0, GlitchEater 24 ns -Statistics: Nr of Cmnds 39563, Cmnds not sent directly 0, Out of SRB conds 0 - Nr of lost arbitrations 17 +garloff@kurt:/home/garloff > cat /proc/scsi/tmscsim/0 +Tekram DC390/AM53C974 PCI SCSI Host Adapter, Driver Version 2.0e 1999/08/30 +SCSI Host Nr 1, AM53C974 Adapter Nr 0 +IOPortBase 0xb000, IRQ 10 +MaxID 8, MaxLUN 8, AdapterID 6, SelTimeout 250 ms, DelayReset 1 s +TagMaxNum 16, Status 0x00, ACBFlag 0x00, GlitchEater 24 ns +Statistics: Cmnds 1470165, Cmnds not sent directly 0, Out of SRB conds 0 + Lost arbitrations 587, Sel. connected 0, Connected: No Nr of attached devices: 4, Nr of DCBs: 4 -Idx ID LUN Prty Sync DsCn SndS TagQ STOP NegoPeriod SyncSpeed SyncOffs -00 00 00 Yes Yes Yes Yes Yes No 100 ns 10.0 M 15 -01 01 00 Yes Yes Yes Yes Yes No 100 ns 10.0 M 15 -02 03 00 Yes Yes Yes Yes No No 100 ns 10.0 M 15 -03 05 00 Yes No Yes Yes No No (200 ns) +Map of attached LUNs: 01 00 00 03 01 00 00 00 +Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd +00 00 00 Yes Yes Yes Yes Yes 100 ns 10.0 M 15 16 +01 03 00 Yes Yes Yes Yes No 100 ns 10.0 M 15 01 +02 03 01 Yes Yes Yes Yes No 100 ns 10.0 M 15 01 +03 04 00 Yes Yes Yes Yes No 100 ns 10.0 M 15 01 Note that the settings MaxID and MaxLUN are not zero- but one-based, which means that a setting MaxLUN=4, will result in the support of LUNs 0..3. This @@ -178,9 +184,8 @@ The last values are only shown, if Sync is enabled. (NegoPeriod is still displayed in brackets to show the values which will be used after enabling Sync.) -The STOP parameter is for testing/debugging purposes only and should bet set -to No. Please don't fiddle with it, unless you want to get rid of the -contents of your disk. +MaxCmd ist the number of commands (=tags) which can be processed at the same +time by the device. If you want to change a setting, you can do that by writing to /proc/scsi/tmscsim/?. Basically you have to imitate the output of driver. @@ -196,8 +201,8 @@ echo "MaxLUN=8 seltimeout 200" >/proc/scsi/tmscsim/0 Note that you can only change MaxID, MaxLUN, AdapterID, SelTimeOut, - TagMaxNum, ACBFlag and GlitchEater. Don't change ACBFlag unless you - want to see what happens, if the driver hangs. + TagMaxNum, ACBFlag, GlitchEater and DelayReset. Don't change ACBFlag + unless you want to see what happens, if the driver hangs. (2) Change device settings: You write a config line to the driver. The Nr must match the ID and LUN given. If you give "-" as parameter, it is @@ -207,8 +212,8 @@ an INQUIRY on the device if necessary to check if it is capable to operate with the given settings (Sync, TagQ). Examples: - echo "0 0 0 y y y - y - 10" >/proc/scsi/tmscsim/0 - echo "3 5 0 y n y" >/proc/scsi/tmscsim/0 + echo "0 0 0 y y y - y - 10 " >/proc/scsi/tmscsim/0 + echo "3 5 0 y n y " >/proc/scsi/tmscsim/0 To give a short explanation of the first example: The first three numbers, "0 0 0" (Device index 0, SCSI ID 0, SCSI LUN 0), @@ -224,21 +229,24 @@ performance. (3) Special commands: You can force a SCSI bus reset, an INQUIRY command and - the removal of a device's DCB. + the removal or the addition of a device's DCB. This is only used for debugging when you meet problems. The parameter of - the INQUIRY and remove command is the device index as shown by the + the INQUIRY and REMOVE commands is the device index as shown by the output of /proc/scsi/tmscsim/? in the device listing in the first column - (Idx). + (Idx). ADD takes the SCSI ID and LUN. Examples: echo "reset" >/proc/scsi/tmscsim/0 echo "inquiry 1" >/proc/scsi/tmscsim/0 echo "remove 2" >/proc/scsi/tmscsim/1 + echo "add 2 3" >/proc/scsi/tmscsim/? - Note that you will meet problems when you remove a device's DCB with the + Note that you will meet problems when you REMOVE a device's DCB with the remove command if it contains partitions which are mounted. Only use it after unmounting its partitions, telling the SCSI mid-level code to remove it (scsi remove-single-device) and you really need a few bytes of memory. + The ADD command allows you to configure a device before you tell the + mid-level code to try detection. I'd suggest reviewing the output of /proc/scsi/tmscsim/? after changing @@ -269,7 +277,7 @@ DC390 EEPROM, the settings are given in a DC390 BIOS' way. Here's the syntax: -tmscsim=AdaptID,SpdIdx,DevMode,AdaptMode,TaggedCmnds +tmscsim=AdaptID,SpdIdx,DevMode,AdaptMode,TaggedCmnds,DelayReset Each of the parameters is a number, containing the described information: @@ -315,18 +323,21 @@ *3 16 4 32 +* DelayReset is the time in seconds (minus 0.5s), the adapter waits, after a + bus reset. Default is 1 (corresp. to 1.5s). + Example: modprobe tmscsim tmscsim=6,2,31 would set the adapter ID to 6, max. speed to 6.7 MHz, enable all device -features and leave the adapter features and the number of Tagged Commands -to the defaults. +features and leave the adapter features, the number of Tagged Commands +and the Delay after a reset to the defaults. -As you can see, you don't need to specify all of the five params. +As you can see, you don't need to specify all of the six params. -The defaults (7,1,31,15,3) are aggressive to allow good performance. You can -use tmscsim=7,0,31,63,4 for maximum performance, if your SCSI chain is +The defaults (7,1,31,15,3,1) are aggressive to allow good performance. You can +use tmscsim=7,0,31,63,4,0 for maximum performance, if your SCSI chain is perfect. If you meet problems, you can use tmscsim=-1 which is a shortcut -for tmscsim=7,4,9,15,2. +for tmscsim=7,4,9,15,2,10. 6. Potential improvements @@ -334,42 +345,47 @@ Most of the intended work on the driver has been done. Here are a few ideas to further improve its usability: +* Cleanly separate per-Target and per-LUN properties (DCB) * More intelligent abort() routine -* Implement new_eh code (Linux-2.1+) -* Have the mid-level code (and not the driver) handle more of the various - conditions. -* Rework command queueing in the driver +* Use new_eh code (Linux-2.1+) +* Have the mid-level (ML) code (and not the driver) handle more of the + various conditions. +* Command queueing in the driver: Eliminate Query list and use ML instead. * More user friendly boot/module param syntax Further investigation on these problems: * Driver hangs with sync readcdda (xcdroast) (most probably VIA PCI error) -Known problems: +Known problems: +Please see http://www.garloff.de/kurt/linux/dc390/problems.html -* There was a report that with a certain Scanner, the last SCSI command - won't be finished correctly. This might be a command queueing bug or a bug - in SCSI implementation of the scanner. Issueing another command to the - scanner seems to help. (Try echo "INQUIRY x" >/proc/scsi/tmscsim/?, where - x is the index (not the SCSI ID!) of the scanner. See 4.(3).) +* Changing the parameters of multi-lun by the tmscsim/? interface will + cause problems, cause these settings are mostly per Target and not per LUN + and should be updated accordingly. To be fixed for 2.0d24. +* CDRs (eg Yam CRW4416) not recognized, because some buggy devices don't + recover from a SCSI reset in time. Use a higher delay or don't issue + a SCSI bus reset on driver initialization. See problems page. + For the CRW4416S, this seems to be solved with firmware 1.0g (reported by + Jean-Yves Barbier). +* TEAC CD-532S not being recognized. (Works with 1.11). +* Scanners (eg. Astra UMAX 1220S) don't work: Disable Sync Negotiation. + If this does not help, try echo "INQUIRY t" >/proc/scsi/tmscsim/? (t + replaced by the dev index of your scanner). You may try to reset your SCSI + bus afterwards (echo "RESET" >/proc/scsi/tmscsim/?). + The problem seems to be solved as of 2.0d18, thanks to Andreas Rick. * If there is a valid partition table, the driver will use it for determing - the mapping. Other operating systems may not like this mapping, though + the mapping. If there's none, a reasonable mapping (Symbios-like) will be + assumed. Other operating systems may not like this mapping, though it's consistent with the BIOS' behaviour. Old DC390 drivers ignored the partition table and used a H/S = 64/32 or 255/63 translation. So if you want to be compatible to those, use this old mapping when creating - partition tables. -* In some situations, the driver will get stuck in an abort loop. Please - disable DsCn, if you meet this problem. Please contact me for further - debugging. -* 2.1.115+: Linux misses locks in sr_ioctl.c and scsi_ioctl.c - There used to be a patch included here, which partially solved the - problem. I suggest you contact Chiaki Ishikawa , - 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. There used - to be a patch included here to fix this, but I was told that it is fixed - in 2.0.36. + partition tables. Even worse, on bootup the DC390 might complain if other + mappings are found, so auto rebooting will fail. +* In some situations, the driver will get stuck in an abort loop. This is a + bad interaction between the Mid-Layer of Linux' SCSI code and the driver. + Try to disable DsCn, if you meet this problem. Please contact me for + further debugging. 7. Bug reports, debugging and updates @@ -394,25 +410,33 @@ The latest version of the driver can be found at: 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.) + ftp://ftp.suse.com/pub/people/garloff/linux/dc390/ 8. Acknowledgements ------------------- -Thanks to Linus Torvalds, Alan Cox, David Miller, Rik v. Riel, the FSF -people, the XFree86 team and all the others for the wonderful OS and -software. +Thanks to Linus Torvalds, Alan Cox, David Miller, the FSF people, the +XFree86 team and all the others for the wonderful OS and software. Thanks to C.L. Huang and Philip Giang (Tekram) for the initial driver release and support. Thanks to Doug Ledford, Gerard Roudier for support with SCSI coding. Thanks to a lot of people (espec. Chiaki Ishikawa, Andreas Haumer, Hubert Tonneau) for intensively testing the driver (and even risking data loss -doing this during early revisions). +doing this during early revisions). +Recently, SuSE GmbH, Nuernberg, FRG, has been paying me for the driver +development and maintenance. Special thanks! + +9. Copyright +------------ + This driver is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; version 2 of the License. + If you want to use any later version of the GNU GPL, you will probably + be allowed to, but you have to ask me and Tekram + before. ------------------------------------------------------------------------- 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 $ +Last updated 2000/01/17, driver revision 2.0d25 +$Id: README.tmscsim,v 2.25.2.1 2000/01/17 22:34:36 garloff Exp $ Index: dc390-120-kernel.diff =================================================================== RCS file: /home/cvsroot/dc390/dc390-120-kernel.diff,v retrieving revision 2.3 retrieving revision 2.5 diff -u -r2.3 -r2.5 --- dc390-120-kernel.diff 1998/12/25 18:04:20 2.3 +++ dc390-120-kernel.diff 1999/06/01 22:20:02 2.5 @@ -1,6 +1,6 @@ # dc390-kernel.diff # patches against 2.1.125 kernel for DC390/AM53C974 driver integration -# $Id: dc390-120-kernel.diff,v 2.3 1998/12/25 18:04:20 garloff Exp $ # +# $Id: dc390-120-kernel.diff,v 2.5 1999/06/01 22:20:02 garloff Exp $ # 8<---------------------------------------------------------------------- Patch for allowing omission of the non DC390 parts of the driver: Index: dc390.h =================================================================== RCS file: /home/cvsroot/dc390/dc390.h,v retrieving revision 2.12 retrieving revision 2.43.2.4 diff -u -r2.12 -r2.43.2.4 --- dc390.h 1998/12/25 17:33:27 2.12 +++ dc390.h 2000/01/17 22:23:35 2.43.2.4 @@ -4,10 +4,8 @@ * Description: Device Driver for Tekram DC-390(T) PCI SCSI * * Bus Master Host Adapter * ***********************************************************************/ -/* $Id: dc390.h,v 2.12 1998/12/25 17:33:27 garloff Exp $ */ +/* $Id: dc390.h,v 2.43.2.4 2000/01/17 22:23:35 garloff Exp $ */ -#include - /* * DC390/AMD 53C974 driver, header file */ @@ -15,13 +13,16 @@ #ifndef DC390_H #define DC390_H +#include +#ifndef KERNEL_VERSION +# define KERNEL_VERSION(a,b,c) (((a) << 16) + ((b) << 8) + (c)) +#endif + #define DC390_BANNER "Tekram DC390/AM53C974" -#define DC390_VERSION "2.0d 1998/12/25" +#define DC390_VERSION "2.0d25 2000/01/17" #if defined(HOSTS_C) || defined(MODULE) -#include - extern int DC390_detect(Scsi_Host_Template *psht); extern int DC390_queue_command(Scsi_Cmnd *cmd, void (*done)(Scsi_Cmnd *)); extern int DC390_abort(Scsi_Cmnd *cmd); @@ -34,10 +35,38 @@ # define DC390_release NULL #endif +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,30) extern struct proc_dir_entry DC390_proc_scsi_tmscsim; +#endif extern int DC390_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout); +#if LINUX_VERSION_CODE < KERNEL_VERSION (2,1,70) +# define NO_NEW_EH +#else +# define NO_NEW_EH use_new_eh_code: 0, +#endif + +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) #define DC390_T { \ + proc_name: "tmscsim", \ + proc_info: DC390_proc_info, \ + name: DC390_BANNER " V" DC390_VERSION, \ + detect: DC390_detect, \ + release: DC390_release, \ + queuecommand: DC390_queue_command, \ + abort: DC390_abort, \ + reset: DC390_reset, \ + bios_param: DC390_bios_param, \ + can_queue: 42, \ + this_id: 7, \ + sg_tablesize: SG_ALL, \ + cmd_per_lun: 8, \ + NO_NEW_EH \ + unchecked_isa_dma: 0, \ + use_clustering: DISABLE_CLUSTERING \ + } +#else +#define DC390_T { \ proc_dir: &DC390_proc_scsi_tmscsim, \ proc_info: DC390_proc_info, \ name: DC390_BANNER " V" DC390_VERSION, \ @@ -47,13 +76,15 @@ abort: DC390_abort, \ reset: DC390_reset, \ bios_param: DC390_bios_param, \ - can_queue: 17, \ + can_queue: 42, \ this_id: 7, \ sg_tablesize: SG_ALL, \ cmd_per_lun: 8, \ + NO_NEW_EH \ + unchecked_isa_dma: 0, \ use_clustering: DISABLE_CLUSTERING \ } - +#endif #endif /* defined(HOSTS_C) || defined(MODULE) */ #endif /* DC390_H */ Index: scsiiom.c =================================================================== RCS file: /home/cvsroot/dc390/scsiiom.c,v retrieving revision 2.15 retrieving revision 2.55.2.1 diff -u -r2.15 -r2.55.2.1 --- scsiiom.c 1998/12/25 17:33:27 2.15 +++ scsiiom.c 2000/01/17 22:23:03 2.55.2.1 @@ -4,15 +4,35 @@ * Description: Device Driver for Tekram DC-390 (T) PCI SCSI * * Bus Master Host Adapter * ***********************************************************************/ -/* $Id: scsiiom.c,v 2.15 1998/12/25 17:33:27 garloff Exp $ */ +/* $Id: scsiiom.c,v 2.55.2.1 2000/01/17 22:23:03 garloff Exp $ */ +static void __inline__ +dc390_freetag (PDCB pDCB, PSRB pSRB) +{ + if (pSRB->TagNumber < 255) { + pDCB->TagMask &= ~(1 << pSRB->TagNumber); /* free tag mask */ + pSRB->TagNumber = 255; + } +}; + + UCHAR dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ) { - USHORT wlval; - UCHAR bval, bval1; + UCHAR cmd; UCHAR disc_allowed, try_sync_nego; + + pSRB->ScsiPhase = SCSI_NOP0; - pSRB->TagNumber = 31; + if (pACB->Connected) + { + // Should not happen normally + printk (KERN_WARNING "DC390: Can't select when connected! (%08x,%02x)\n", + pSRB->SRBState, pSRB->SRBFlag); + pSRB->SRBState = SRB_READY; + pACB->SelConn++; + return 1; + } + DC390_write8 (Scsi_Dest_ID, pDCB->UnitSCSIID); DC390_write8 (Sync_Period, pDCB->SyncPeriod); DC390_write8 (Sync_Offset, pDCB->SyncOffset); @@ -21,151 +41,104 @@ DC390_write8 (CtrlReg4, pDCB->CtrlR4); DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); /* Flush FIFO */ DEBUG1(printk (KERN_INFO "DC390: Start SCSI command: %02x (Sync:%02x)\n",\ - pSRB->CmdBlock[0], pDCB->SyncMode);) - pSRB->ScsiPhase = SCSI_NOP0; - //pSRB->MsgOutBuf[0] = MSG_NOP; - //pSRB->MsgCnt = 0; - bval = pDCB->IdentifyMsg; - if( !(pDCB->SyncMode & EN_ATN_STOP) ) /* Don't always try send Extended messages on arbitration */ - { - if( (pSRB->CmdBlock[0] == INQUIRY) || - (pSRB->CmdBlock[0] == REQUEST_SENSE) || - (pSRB->SRBFlag & AUTO_REQSENSE) ) - { - bval &= 0xBF; /* No DisConn */ - DC390_write8 (ScsiFifo, bval); - bval1 = SEL_W_ATN; - pSRB->SRBState = SRB_START_; - 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 */ - (pSRB->CmdBlock[0] != INQUIRY) ) - { - bval1 = SEL_W_ATN_STOP; /* Try to establish SYNC nego */ - pSRB->SRBState = SRB_MSGOUT; - } - } - } - else /* TagQ ? */ - { - DC390_write8 (ScsiFifo, bval); - if(pDCB->SyncMode & EN_TAG_QUEUEING) - { - DC390_write8 (ScsiFifo, MSG_SIMPLE_QTAG); - 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 (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 (KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);) - pSRB->SRBState = SRB_START_; - } - } + pSRB->pcmd->cmnd[0], pDCB->SyncMode);) + disc_allowed = pDCB->DevMode & EN_DISCONNECT_; try_sync_nego = 0; + /* Don't disconnect on AUTO_REQSENSE, cause it might be an + * Contingent Allegiance Condition (6.6), where no tags should be used. + * All other have to be allowed to disconnect to prevent Incorrect + * Initiator Connection (6.8.2/6.5.2) */ + /* Changed KG, 99/06/06 */ + if( /*(((pSRB->pcmd->cmnd[0] == INQUIRY) || (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || + * (pSRB->pcmd->cmnd[0] == TEST_UNIT_READY)) && pACB->scan_devices) + ||*/ (pSRB->SRBFlag & AUTO_REQSENSE) ) + disc_allowed = 0; + if ( (pDCB->SyncMode & SYNC_ENABLE) && (pDCB->UnitSCSILUN == 0) && + ( ( ( (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || (pSRB->SRBFlag & AUTO_REQSENSE) ) + && !(pDCB->SyncMode & SYNC_NEGO_DONE) ) || (pSRB->pcmd->cmnd[0] == INQUIRY) ) ) + try_sync_nego = 1; + + pSRB->MsgCnt = 0; cmd = SEL_W_ATN; + DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->UnitSCSILUN)); + /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */ + if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed) + { + UCHAR tag_no = 0; + while ((1 << tag_no) & pDCB->TagMask) tag_no++; + if (tag_no >= sizeof (pDCB->TagMask)*8 || tag_no >= pDCB->MaxCommand) { + printk (KERN_WARNING "DC390: Out of tags for Dev. %02x %02x\n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN); + goto no_tag; + }; + DC390_write8 (ScsiFifo, SIMPLE_QUEUE_TAG); + pDCB->TagMask |= (1 << tag_no); pSRB->TagNumber = tag_no; + DC390_write8 (ScsiFifo, tag_no); + DEBUG1(printk (KERN_DEBUG "DC390: Select w/DisCn for Cmd %li (SRB %p), Using Tag %02x\n", pSRB->pcmd->pid, pSRB, tag_no);) + cmd = SEL_W_ATN3; + } + else /* No TagQ */ + { + no_tag: + DEBUG1(printk (KERN_DEBUG "DC390: Select w%s/DisCn for Cmd %li (SRB %p), No TagQ\n", (disc_allowed?"":"o"), pSRB->pcmd->pid, pSRB);) + }; - } - else /* ATN_STOP: Always try to establish Sync nego */ - { - if( (pSRB->CmdBlock[0] == INQUIRY) || - (pSRB->CmdBlock[0] == REQUEST_SENSE) || - (pSRB->SRBFlag & AUTO_REQSENSE) ) - { - bval &= 0xBF; /* No DisConn */ - DC390_write8 (ScsiFifo, bval); - bval1 = SEL_W_ATN; - DEBUG1(printk (KERN_DEBUG "DC390: No DisCn, No TagQ (%02x, %02x)\n", bval, bval1);) - pSRB->SRBState = SRB_START_; - /* ??? */ - if( pDCB->SyncMode & SYNC_ENABLE ) - { - if( !(pDCB->IdentifyMsg & 7) || /* LUN == 0 || Cmd != INQUIRY */ - (pSRB->CmdBlock[0] != INQUIRY) ) - { - bval1 = SEL_W_ATN_STOP; /* Try to establish Sync nego */ - pSRB->SRBState = SRB_MSGOUT; - } - } - } - else /* TagQ ? */ - { - DC390_write8 (ScsiFifo, bval); - if(pDCB->SyncMode & EN_TAG_QUEUEING) - { - pSRB->MsgOutBuf[0] = MSG_SIMPLE_QTAG; - 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 (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; - pSRB->SRBState = SRB_START_; /* ?? */ - } - else /* No TagQ */ - { - pSRB->MsgOutBuf[0] = MSG_NOP; - pSRB->MsgCnt = 1; - pSRB->SRBState = SRB_START_; - bval1 = SEL_W_ATN_STOP; - DEBUG1(printk (KERN_DEBUG "DC390: %sDisCn, No TagQ (%02x, %02x, %08lx)\n", (bval&0x40?"":"No "), bval, bval1, pDCB->TagMask);) - }; - } - } - if (bval1 != SEL_W_ATN_STOP) - { /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */ + pSRB->SRBState = SRB_START_; + + if (try_sync_nego) + { + UCHAR Sync_Off = pDCB->SyncOffset; + DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN);) + pSRB->MsgOutBuf[0] = EXTENDED_MESSAGE; + pSRB->MsgOutBuf[1] = 3; + pSRB->MsgOutBuf[2] = EXTENDED_SDTR; + pSRB->MsgOutBuf[3] = pDCB->NegoPeriod; + if (!(Sync_Off & 0x0f)) Sync_Off = SYNC_NEGO_OFFSET; + pSRB->MsgOutBuf[4] = Sync_Off; + pSRB->MsgCnt = 5; + //pSRB->SRBState = SRB_MSGOUT_; + pSRB->SRBState |= DO_SYNC_NEGO; + cmd = SEL_W_ATN_STOP; + }; + + /* Command is written in CommandPhase, if SEL_W_ATN_STOP ... */ + if (cmd != SEL_W_ATN_STOP) + { if( pSRB->SRBFlag & AUTO_REQSENSE ) { - bval = 0; DC390_write8 (ScsiFifo, REQUEST_SENSE); - DC390_write8 (ScsiFifo, pDCB->IdentifyMsg << 5); - DC390_write8 (ScsiFifo, bval); - DC390_write8 (ScsiFifo, bval); + DC390_write8 (ScsiFifo, pDCB->UnitSCSILUN << 5); + DC390_write8 (ScsiFifo, 0); + DC390_write8 (ScsiFifo, 0); DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer)); - DC390_write8 (ScsiFifo, bval); + DC390_write8 (ScsiFifo, 0); DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n");) } else /* write cmnd to bus */ { PUCHAR ptr; UCHAR i; - ptr = (PUCHAR) pSRB->CmdBlock; - for (i=0; iScsiCmdLen; i++) + ptr = (PUCHAR) pSRB->pcmd->cmnd; + for (i=0; ipcmd->cmd_len; i++) DC390_write8 (ScsiFifo, *(ptr++)); }; } - - /* Check if we can't win arbitration */ + DEBUG0(if (pACB->pActiveDCB) \ + printk (KERN_WARNING "DC390: ActiveDCB != 0\n");) + DEBUG0(if (pDCB->pActiveSRB) \ + printk (KERN_WARNING "DC390: ActiveSRB != 0\n");) + //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); if (DC390_read8 (Scsi_Status) & INTERRUPT) { + dc390_freetag (pDCB, pSRB); + DEBUG0(printk ("DC390: Interrupt during Start SCSI (pid %li, target %02i-%02i)\n", + pSRB->pcmd->pid, pSRB->pcmd->target, pSRB->pcmd->lun);) pSRB->SRBState = SRB_READY; - pDCB->TagMask &= ~( 1 << pSRB->TagNumber ); - DEBUG0(printk (KERN_WARNING "DC390: Interrupt during StartSCSI!\n");) + //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + pACB->SelLost++; return 1; - } - else - { - pSRB->ScsiPhase = SCSI_NOP1; - DEBUG0(if (pACB->pActiveDCB) \ - printk (KERN_WARNING "DC390: ActiveDCB != 0\n");) - DEBUG0(if (pDCB->pActiveSRB) \ - printk (KERN_WARNING "DC390: ActiveSRB != 0\n");) - pACB->pActiveDCB = pDCB; - pDCB->pActiveSRB = pSRB; - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); - DC390_write8 (ScsiCmd, bval1); - return 0; - } + }; + DC390_write8 (ScsiCmd, cmd); + pACB->pActiveDCB = pDCB; pDCB->pActiveSRB = pSRB; + pACB->Connected = 1; + pSRB->ScsiPhase = SCSI_NOP1; + return 0; } //#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/ @@ -198,7 +171,7 @@ }; if (dstate & DMA_XFER_DONE) { - ULONG residual, xferCnt; int ctr = 5000000; + UINT residual, xferCnt; int ctr = 6000000; if (! (DC390_read8 (DMA_Cmd) & READ_DIRECTION)) { do @@ -236,47 +209,34 @@ void __inline__ DC390_Interrupt( int irq, void *dev_id, struct pt_regs *regs) { - PACB pACB; + PACB pACB, pACB2; PDCB pDCB; PSRB pSRB; UCHAR sstatus=0; - UCHAR phase, i; + UCHAR phase; void (*stateV)( PACB, PSRB, PUCHAR ); UCHAR istate, istatus; #if DMA_INT UCHAR dstatus; #endif - DC390_AFLAGS DC390_IFLAGS DC390_DFLAGS - - pACB = dc390_pACB_start; + DC390_AFLAGS DC390_IFLAGS //DC390_DFLAGS - if (pACB == 0) + pACB = (PACB)dev_id; + for (pACB2 = dc390_pACB_start; (pACB2 && pACB2 != pACB); pACB2 = pACB2->pNextACB); + if (!pACB2) { - printk(KERN_WARNING "DC390: Interrupt on uninitialized adapter!\n"); + printk ("DC390: IRQ called with foreign dev_id %p!\n", pACB); return; } - DC390_LOCK_DRV; + + //DC390_LOCK_DRV; - for( i=0; i < dc390_adapterCnt; i++ ) - { - if( pACB->IRQLevel == (UCHAR) irq ) - { - sstatus = DC390_read8 (Scsi_Status); - if( sstatus & INTERRUPT ) - break; - else - pACB = pACB->pNextACB; - } - else - { - pACB = pACB->pNextACB; - } - } + sstatus = DC390_read8 (Scsi_Status); + if( !(sstatus & INTERRUPT) ) + { /*DC390_UNLOCK_DRV;*/ return; }; DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus);) - if( !pACB ) { DC390_UNLOCK_DRV; return; }; - #if DMA_INT DC390_LOCK_IO; DC390_LOCK_ACB; @@ -288,7 +248,7 @@ if (! (dstatus & SCSI_INTERRUPT)) { DEBUG0(printk (KERN_WARNING "DC390 Int w/o SCSI actions (only DMA?)\n");) - DC390_UNLOCK_DRV; + //DC390_UNLOCK_DRV; return; }; #else @@ -299,7 +259,7 @@ DC390_LOCK_IO; DC390_LOCK_ACB; - DC390_UNLOCK_DRV_NI; /* Allow _other_ CPUs to process IRQ (useful for shared IRQs) */ + //DC390_UNLOCK_DRV_NI; /* Allow _other_ CPUs to process IRQ (useful for shared IRQs) */ istate = DC390_read8 (Intern_State); istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */ @@ -310,23 +270,42 @@ if (sstatus & ILLEGAL_OP_ERR) { - printk ("DC390: Illegal Operation detected (%08lx)!\n", dc390_laststatus); + printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus); dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB); - }; + } - if(istatus & DISCONNECTED) + else if (istatus & INVALID_CMD) + { + printk ("DC390: Invalid Command detected (%08x)!\n", dc390_laststatus); + dc390_InvalidCmd( pACB ); + goto unlock; + } + + if (istatus & SCSI_RESET) + { + dc390_ScsiRstDetect( pACB ); + goto unlock; + } + + if (istatus & DISCONNECTED) { dc390_Disconnect( pACB ); goto unlock; } - if(istatus & RESELECTED) + if (istatus & RESELECTED) { dc390_Reselect( pACB ); goto unlock; } + + else if (istatus & (SELECTED | SEL_ATTENTION)) + { + printk (KERN_ERR "DC390: Target mode not supported!\n"); + goto unlock; + } - if( istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) ) + if (istatus & (SUCCESSFUL_OP|SERVICE_REQUEST) ) { pDCB = pACB->pActiveDCB; if (!pDCB) @@ -351,23 +330,11 @@ 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_LOCK_DRV_NI; DC390_UNLOCK_ACB; DC390_UNLOCK_IO; - DC390_UNLOCK_DRV; /* Restore initial flags */ + //DC390_UNLOCK_DRV; /* Restore initial flags */ } void @@ -384,7 +351,7 @@ { UCHAR sstatus; PSGL psgl; - ULONG ResidCnt, xferCnt; + UINT ResidCnt, xferCnt; UCHAR dstate = 0; sstatus = *psstatus; @@ -396,7 +363,7 @@ if( sstatus & COUNT_2_ZERO ) { - int ctr = 5000000; /* only try for about a tenth of a second */ + int ctr = 6000000; /* only try for about a second */ 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; @@ -415,10 +382,10 @@ } else { - ResidCnt = (ULONG) DC390_read8 (Current_Fifo) & 0x1f; - ResidCnt |= (ULONG) DC390_read8 (CtcReg_High) << 16; - ResidCnt |= (ULONG) DC390_read8 (CtcReg_Mid) << 8; - ResidCnt += (ULONG) DC390_read8 (CtcReg_Low); + ResidCnt = (UINT) DC390_read8 (Current_Fifo) & 0x1f; + ResidCnt |= (UINT) DC390_read8 (CtcReg_High) << 16; + ResidCnt |= (UINT) DC390_read8 (CtcReg_Mid) << 8; + ResidCnt += (UINT) DC390_read8 (CtcReg_Low); xferCnt = pSRB->SGToBeXferLen - ResidCnt; pSRB->SGBusAddr += xferCnt; @@ -434,7 +401,8 @@ { UCHAR sstatus, residual, bval; PSGL psgl; - ULONG ResidCnt, xferCnt, i; + UINT ResidCnt, i; + ULONG xferCnt; PUCHAR ptr; sstatus = *psstatus; @@ -446,7 +414,7 @@ if( sstatus & COUNT_2_ZERO ) { - int ctr = 5000000; /* only try for about a tenth of a second */ + int ctr = 6000000; /* only try for about a second */ int dstate = 0; 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)); @@ -455,7 +423,7 @@ DEBUG1(ResidCnt = ((ULONG) DC390_read8 (CtcReg_High) << 16) \ + ((ULONG) DC390_read8 (CtcReg_Mid) << 8) \ + ((ULONG) DC390_read8 (CtcReg_Low));) - DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%li,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);) + DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%i,ToBeXfer=%li),", ResidCnt, pSRB->SGToBeXferLen);) DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ @@ -509,12 +477,12 @@ //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD); /* | DMA_INT */ dc390_laststatus &= ~0xff000000; dc390_laststatus |= bval << 24; - DEBUG1(printk (KERN_DEBUG "Blast: Read %li times DMA_Status %02x", 0xa000-i, bval);) - ResidCnt = (ULONG) DC390_read8 (CtcReg_High); + DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval);) + ResidCnt = (UINT) DC390_read8 (CtcReg_High); ResidCnt <<= 8; - ResidCnt |= (ULONG) DC390_read8 (CtcReg_Mid); + ResidCnt |= (UINT) DC390_read8 (CtcReg_Mid); ResidCnt <<= 8; - ResidCnt |= (ULONG) DC390_read8 (CtcReg_Low); + ResidCnt |= (UINT) DC390_read8 (CtcReg_Low); xferCnt = pSRB->SGToBeXferLen - ResidCnt; pSRB->SGBusAddr += xferCnt; @@ -593,7 +561,7 @@ static void __inline__ dc390_MsgIn_reject (PACB pACB, PSRB pSRB) { - pSRB->MsgOutBuf[0] = MSG_REJECT_; + pSRB->MsgOutBuf[0] = MESSAGE_REJECT; pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; DEBUG0 (printk (KERN_INFO "DC390: Reject message\n");) } @@ -602,7 +570,7 @@ static void __inline__ dc390_EnableMsgOut_Abort ( PACB pACB, PSRB pSRB ) { - pSRB->MsgOutBuf[0] = MSG_ABORT; + pSRB->MsgOutBuf[0] = ABORT; pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_; } @@ -640,7 +608,7 @@ pSRB = pACB->pTmpSRB; pSRB->SRBState = SRB_UNEXPECT_RESEL; pDCB->pActiveSRB = pSRB; - pSRB->MsgOutBuf[0] = MSG_ABORT_TAG; + pSRB->MsgOutBuf[0] = ABORT_TAG; pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT; } return pSRB; @@ -653,7 +621,7 @@ { PDCB pDCB = pSRB->pSRBDCB; if (!(pSRB->SRBState & DO_SYNC_NEGO)) - printk ("DC390: Target %i initiates Non-Sync?\n", pDCB->UnitSCSIID); + printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->UnitSCSIID); pSRB->SRBState &= ~DO_SYNC_NEGO; pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE); pDCB->SyncPeriod = 0; @@ -677,7 +645,7 @@ if (!(pSRB->SRBState & DO_SYNC_NEGO)) { - printk ("DC390: Target %i initiates Sync: %ins %i ... answer ...\n", + printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n", pDCB->UnitSCSIID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]); /* reject */ @@ -687,12 +655,12 @@ /* Reply with corrected SDTR Message */ if (pSRB->MsgInBuf[4] > 15) { - printk ("DC390: Lower Sync Offset to 15\n"); + printk (KERN_INFO "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); + printk (KERN_INFO "DC390: Set sync nego period to %ins\n", pDCB->NegoPeriod << 2); pSRB->MsgInBuf[3] = pDCB->NegoPeriod; }; memcpy (pSRB->MsgOutBuf, pSRB->MsgInBuf, 5); @@ -731,7 +699,7 @@ 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, + printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->UnitSCSIID, 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f); } @@ -739,6 +707,56 @@ }; +/* handle RESTORE_PTR */ +static void +dc390_restore_ptr (PACB pACB, PSRB pSRB) +{ + PSGL psgl; + pSRB->TotalXferredLen = 0; + pSRB->SGIndex = 0; + if( pSRB->pcmd->use_sg ) + { + pSRB->SGcount = (UCHAR) pSRB->pcmd->use_sg; + pSRB->pSegmentList = (PSGL) pSRB->pcmd->request_buffer; + psgl = pSRB->pSegmentList; + while (pSRB->TotalXferredLen + (ULONG) psgl->length < pSRB->Saved_Ptr) + { + pSRB->TotalXferredLen += (ULONG) psgl->length; + pSRB->SGIndex++; + if( pSRB->SGIndex < pSRB->SGcount ) + { + pSRB->pSegmentList++; + psgl = pSRB->pSegmentList; + + pSRB->SGBusAddr = virt_to_bus( psgl->address ); + pSRB->SGToBeXferLen = (ULONG) psgl->length; + } + else + pSRB->SGToBeXferLen = 0; + } + pSRB->SGToBeXferLen -= (pSRB->Saved_Ptr - pSRB->TotalXferredLen); + pSRB->SGBusAddr += (pSRB->Saved_Ptr - pSRB->TotalXferredLen); + printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n", pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr); + } + else if( pSRB->pcmd->request_buffer ) + { + pSRB->SGcount = 1; + pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->Segmentx.address = (PUCHAR) pSRB->pcmd->request_buffer + pSRB->Saved_Ptr; + pSRB->Segmentx.length = pSRB->pcmd->request_bufflen - pSRB->Saved_Ptr; + printk (KERN_INFO "DC390: Pointer restored. Total %li, Bus %p\n", + pSRB->Saved_Ptr, pSRB->Segmentx.address); + } + else + { + pSRB->SGcount = 0; + printk (KERN_INFO "DC390: RESTORE_PTR message for Transfer without Scatter-Gather ??\n"); + }; + + pSRB->TotalXferredLen = pSRB->Saved_Ptr; +}; + + /* 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 ?) */ @@ -749,15 +767,15 @@ /* Check if the message is complete */ static UCHAR __inline__ -dc390_MsgIn_complete (UCHAR *msgbuf, ULONG len) +dc390_MsgIn_complete (UCHAR *msgbuf, UINT len) { - if (*msgbuf == MSG_EXTENDED) - { - if (len < 2) return 0; - if (len < msgbuf[1] + 2) return 0; - } + if (*msgbuf == EXTENDED_MESSAGE) + { + 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; + if (len < 2) return 0; return 1; } @@ -781,23 +799,23 @@ /* Now eval the msg */ switch (pSRB->MsgInBuf[0]) { - case MSG_DISCONNECT: + case DISCONNECT: pSRB->SRBState = SRB_DISCONNECT; break; - case MSG_SIMPLE_QTAG: - case MSG_HEAD_QTAG: - case MSG_ORDER_QTAG: + case SIMPLE_QUEUE_TAG: + case HEAD_OF_QUEUE_TAG: + case ORDERED_QUEUE_TAG: pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]); break; - case MSG_REJECT_: + case MESSAGE_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: + case EXTENDED_MESSAGE: /* reject every extended msg but SDTR */ if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR) dc390_MsgIn_reject (pACB, pSRB); @@ -810,15 +828,18 @@ }; // nothing has to be done - case MSG_COMPLETE: break; + case COMMAND_COMPLETE: break; - // SAVE POINTER my be ignored as we have the PSRB associated with the + // SAVE POINTER may be ignored as we have the PSRB associated with the // scsi command. Thanks, Gerard, for pointing it out. - case MSG_SAVE_PTR: break; + case SAVE_POINTERS: + pSRB->Saved_Ptr = pSRB->TotalXferredLen; + 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 + case RESTORE_POINTERS: + DEBUG0(printk ("DC390: RESTORE POINTER message received ... try to handle\n");) + dc390_restore_ptr (pACB, pSRB); + break; // reject unknown messages default: dc390_MsgIn_reject (pACB, pSRB); @@ -841,6 +862,8 @@ PSGL psgl; ULONG lval; + if (pSRB == pACB->pTmpSRB) printk (KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?)\n"); + if( pSRB->SGIndex < pSRB->SGcount ) { DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir /* | DMA_INT */); @@ -852,7 +875,7 @@ DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment.");) } lval = pSRB->SGToBeXferLen; - DEBUG1(printk (KERN_DEBUG " DC390: Transfer %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);) + DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr);) DC390_write8 (CtcReg_Low, (UCHAR) lval); lval >>= 8; DC390_write8 (CtcReg_Mid, (UCHAR) lval); @@ -918,8 +941,8 @@ DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); if( !(pSRB->SRBFlag & AUTO_REQSENSE) ) { - cnt = (UCHAR) pSRB->ScsiCmdLen; - ptr = (PUCHAR) pSRB->CmdBlock; + cnt = (UCHAR) pSRB->pcmd->cmd_len; + ptr = (PUCHAR) pSRB->pcmd->cmnd; for(i=0; i < cnt; i++) DC390_write8 (ScsiFifo, *(ptr++)); } @@ -928,11 +951,12 @@ UCHAR bval = 0; DC390_write8 (ScsiFifo, REQUEST_SENSE); pDCB = pACB->pActiveDCB; - DC390_write8 (ScsiFifo, pDCB->IdentifyMsg << 5); + DC390_write8 (ScsiFifo, pDCB->UnitSCSILUN << 5); DC390_write8 (ScsiFifo, bval); DC390_write8 (ScsiFifo, bval); DC390_write8 (ScsiFifo, sizeof(pSRB->pcmd->sense_buffer)); DC390_write8 (ScsiFifo, bval); + DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n");) } pSRB->SRBState = SRB_COMMAND; DC390_write8 (ScsiCmd, INFO_XFER_CMD); @@ -966,14 +990,14 @@ DC390_write8 (ScsiFifo, *(ptr++)); pSRB->MsgCnt = 0; if( (pDCB->DCBFlag & ABORT_DEV_) && - (pSRB->MsgOutBuf[0] == MSG_ABORT) ) + (pSRB->MsgOutBuf[0] == ABORT) ) pSRB->SRBState = SRB_ABORT_SENT; } else { - bval = MSG_ABORT; /* ??? MSG_NOP */ - if( (pSRB->CmdBlock[0] == INQUIRY ) || - (pSRB->CmdBlock[0] == REQUEST_SENSE) || + bval = ABORT; /* ??? MSG_NOP */ + if( (pSRB->pcmd->cmnd[0] == INQUIRY ) || + (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || (pSRB->SRBFlag & AUTO_REQSENSE) ) { if( pDCB->SyncMode & SYNC_ENABLE ) @@ -986,8 +1010,8 @@ else { mop1: - //printk ("DC390: Send SDTR message to %i %i ... \n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN); - DC390_write8 (ScsiFifo, MSG_EXTENDED); + printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN); + DC390_write8 (ScsiFifo, EXTENDED_MESSAGE); DC390_write8 (ScsiFifo, 3); /* ;length of extended msg */ DC390_write8 (ScsiFifo, EXTENDED_SDTR); /* ; sync nego */ DC390_write8 (ScsiFifo, pDCB->NegoPeriod); @@ -1030,13 +1054,9 @@ UCHAR bval, i, cnt; PDCB ptr; - if( !(pDCB->IdentifyMsg & 0x07) ) + if( !(pDCB->UnitSCSILUN) ) { - if( pACB->scan_devices ) - { - dc390_CurrSyncOffset = pDCB->SyncOffset; - } - else + if( !pACB->scan_devices ) { ptr = pACB->pLinkDCB; cnt = pACB->DCBCnt; @@ -1068,25 +1088,27 @@ DEBUG0(printk(KERN_INFO "DISC,");) + if (!pACB->Connected) printk(KERN_ERR "DC390: Disconnect not-connected bus?\n"); + pACB->Connected = 0; pDCB = pACB->pActiveDCB; if (!pDCB) { int j = 400; - DEBUG0(printk(KERN_WARNING "ACB:%08lx->ActiveDCB:%08lx IOPort:%04x IRQ:%02x !\n",\ - (ULONG)pACB,(ULONG)pDCB,pACB->IOPortBase,pACB->IRQLevel);) + DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\ + pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel);) while (--j) udelay (1000); DC390_read8 (INT_Status); /* Reset Pending INT */ DC390_write8 (ScsiCmd, EN_SEL_RESEL); return; } + DC390_write8 (ScsiCmd, EN_SEL_RESEL); pSRB = pDCB->pActiveSRB; pACB->pActiveDCB = 0; pSRB->ScsiPhase = SCSI_NOP0; - DC390_write8 (ScsiCmd, EN_SEL_RESEL); if( pSRB->SRBState & SRB_UNEXPECT_RESEL ) { pSRB->SRBState = 0; - dc390_DoWaitingSRB( pACB ); + dc390_Waiting_process ( pACB ); } else if( pSRB->SRBState & SRB_ABORT_SENT ) { @@ -1098,22 +1120,23 @@ for( i=0; i < cnt; i++) { psrb = pSRB->pNextSRB; - pSRB->pNextSRB = pACB->pFreeSRB; - pACB->pFreeSRB = pSRB; + dc390_Free_insert (pACB, pSRB); pSRB = psrb; } pDCB->pGoingSRB = 0; - dc390_DoWaitingSRB( pACB ); + dc390_Query_to_Waiting (pACB); + dc390_Waiting_process (pACB); } else { if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) || !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) ) { /* Selection time out */ - if( !(pACB->scan_devices) ) + if( !(1/*pACB->scan_devices*/) ) { pSRB->SRBState = SRB_READY; - dc390_RewaitSRB( pDCB, pSRB); + dc390_freetag (pDCB, pSRB); + dc390_Going_to_Waiting (pDCB, pSRB); } else { @@ -1123,15 +1146,12 @@ } else if( pSRB->SRBState & SRB_DISCONNECT ) { - dc390_DoWaitingSRB( pACB ); + dc390_Waiting_process ( pACB ); } else if( pSRB->SRBState & SRB_COMPLETED ) { disc1: - if(pDCB->MaxCommand > 1) - { - pDCB->TagMask &= (~(1 << pSRB->TagNumber)); /* free tag mask */ - } + dc390_freetag (pDCB, pSRB); pDCB->pActiveSRB = 0; pSRB->SRBState = SRB_FREE; dc390_SRBdone( pACB, pDCB, pSRB); @@ -1150,23 +1170,30 @@ UCHAR bval; DEBUG0(printk(KERN_INFO "RSEL,");) + pACB->Connected = 1; pDCB = pACB->pActiveDCB; if( pDCB ) { /* Arbitration lost but Reselection won */ - DEBUG0(printk ("(ActiveDCB != 0)");) + DEBUG0(printk ("(ActiveDCB != 0: Arb. lost but resel. won)");) pSRB = pDCB->pActiveSRB; if( !( pACB->scan_devices ) ) { pSRB->SRBState = SRB_READY; - dc390_RewaitSRB( pDCB, pSRB); + dc390_freetag (pDCB, pSRB); + dc390_Going_to_Waiting ( pDCB, pSRB); } } bval = DC390_read8 (ScsiFifo); /* get ID */ DEBUG0(printk ("Dev %02x,", bval);) - bval ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */ + if (!(bval & 1 << pACB->pScsiHost->this_id)) + printk (KERN_ERR "Reselection must select host adapter: %02x!\n", bval); + else + bval ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */ wval = 0; while (bval >>= 1) wval++; - wval |= ( (USHORT) DC390_read8 (ScsiFifo) & 7) << 8; /* get LUN */ + bval = DC390_read8 (ScsiFifo); + if (!(bval & IDENTIFY_BASE)) printk (KERN_ERR "Expect identify message!\n"); + wval |= ( (USHORT) bval & 7) << 8; /* get LUN */ DEBUG0(printk ("(ID %02x, LUN %02x),", wval & 0xff, (wval & 0xff00) >> 8);) pDCB = pACB->pLinkDCB; while( wval != *((PUSHORT) &pDCB->UnitSCSIID) ) @@ -1180,9 +1207,10 @@ } } pACB->pActiveDCB = pDCB; + /* TagQ: We expect a message soon, so never mind */ if( pDCB->SyncMode & EN_TAG_QUEUEING ) { - pSRB = pACB->pTmpSRB; /* ?? */ + pSRB = pACB->pTmpSRB; pDCB->pActiveSRB = pSRB; } else @@ -1228,19 +1256,20 @@ { PDCB pPrevDCB = pACB->pLinkDCB; - pACB->DCBmap[pDCB->UnitSCSIID] &= ~(1 << pDCB->UnitSCSILUN); if (pDCB->GoingSRBCnt > 1) { DCBDEBUG(printk (KERN_INFO "DC390: Driver won't free DCB (ID %i, LUN %i): 0x%08x because of SRBCnt %i\n",\ pDCB->UnitSCSIID, pDCB->UnitSCSILUN, (int)pDCB, pDCB->GoingSRBCnt);) return; }; + pACB->DCBmap[pDCB->UnitSCSIID] &= ~(1 << pDCB->UnitSCSILUN); if (pDCB == pACB->pLinkDCB) { if (pDCB->pNextDCB == pDCB) pDCB->pNextDCB = 0; pACB->pLinkDCB = pDCB->pNextDCB; - pACB->pLastDCB->pNextDCB = pDCB->pNextDCB; + if (pACB->pLastDCB == pDCB) pACB->pLastDCB = 0; + else if (pACB->pLastDCB) pACB->pLastDCB->pNextDCB = pDCB->pNextDCB; } else { @@ -1249,9 +1278,12 @@ if (pDCB == pACB->pLastDCB) pACB->pLastDCB = pPrevDCB; } - DCBDEBUG(printk (KERN_INFO "DC390: Driver about to free DCB (ID %i, LUN %i): 0x%08x\n",\ - pDCB->UnitSCSIID, pDCB->UnitSCSILUN, (int)pDCB);) - kfree (pDCB); if (pDCB == pACB->pActiveDCB) pACB->pActiveDCB = 0; + DCBDEBUG(printk (KERN_INFO "DC390: Driver about to free DCB (ID %i, LUN %i): %p\n",\ + pDCB->UnitSCSIID, pDCB->UnitSCSILUN, pDCB);) + if (pDCB == pACB->pActiveDCB) pACB->pActiveDCB = 0; + if (pDCB == pACB->pLinkDCB) pACB->pLinkDCB = pDCB->pNextDCB; + if (pDCB == pACB->pDCBRunRobin) pACB->pDCBRunRobin = pDCB->pNextDCB; + kfree (pDCB); pACB->DCBCnt--; /* pACB->DeviceCnt--; */ }; @@ -1280,21 +1312,12 @@ || (pDCB->DevType == TYPE_MOD)) &&*/ !dc390_tagq_blacklist (((char*)ptr)+8) ) { - pDCB->MaxCommand = pDCB->pDCBACB->TagMaxNum; + if (pDCB->MaxCommand ==1) pDCB->MaxCommand = pDCB->pDCBACB->TagMaxNum; pDCB->SyncMode |= EN_TAG_QUEUEING /* | EN_ATN_STOP */; - pDCB->TagMask = 0; + //pDCB->TagMask = 0; } else - { - /* Do we really need to check for DevType here ? */ - if ( 0 /*(pDCB->DevMode & EN_DISCONNECT_)*/ - /* && ((pDCB->DevType == TYPE_DISK) - || (pDCB->DevType == TYPE_MOD))*/ ) - pDCB->SyncMode |= EN_ATN_STOP; - else - //pDCB->SyncMode &= ~EN_ATN_STOP; - pDCB->SyncMode &= ~0; - } + pDCB->MaxCommand = 1; } }; @@ -1312,14 +1335,13 @@ void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ) { - PSRB psrb; - UCHAR bval, status, i; + UCHAR bval, status, i, DCB_removed; PSCSICMD pcmd; PSCSI_INQDATA ptr; PSGL ptr2; ULONG swlval; - pcmd = pSRB->pcmd; + pcmd = pSRB->pcmd; DCB_removed = 0; status = pSRB->TargetStatus; DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p, pid %li\n", status, pcmd->result,\ pSRB, pcmd->pid);) @@ -1327,7 +1349,7 @@ { /* Last command was a Request Sense */ pSRB->SRBFlag &= ~AUTO_REQSENSE; pSRB->AdaptStatus = 0; - pSRB->TargetStatus = SCSI_STAT_CHECKCOND; + pSRB->TargetStatus = CHECK_CONDITION << 1; #ifdef DC390_REMOVABLEDEBUG switch (pcmd->sense_buffer[2] & 0x0f) { @@ -1348,23 +1370,22 @@ status, pACB->scan_devices); break; } #endif - //pcmd->result = DRIVER_SENSE << 24 | DID_OK << 16 | status; - if(status == SCSI_STAT_CHECKCOND) + //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status); + if (status == (CHECK_CONDITION << 1)) { - pcmd->result = DID_BAD_TARGET << 16; + pcmd->result = MK_RES_LNX(0,DID_BAD_TARGET,0,/*CHECK_CONDITION*/0); goto ckc_e; } if(pSRB->RetryCnt == 0) { - (ULONG)(pSRB->CmdBlock[0]) = pSRB->Segment0[0]; - pSRB->TotalXferredLen = pSRB->Segment1[1]; + //(UINT)(pSRB->pcmd->cmnd[0]) = pSRB->Segment0[0]; + pSRB->TotalXferredLen = pSRB->SavedTotXLen; if( (pSRB->TotalXferredLen) && (pSRB->TotalXferredLen >= pcmd->underflow) ) - pcmd->result |= (DID_OK << 16); + SET_RES_DID(pcmd->result,DID_OK) else - pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) | - SCSI_STAT_CHECKCOND; - REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->CmdBlock[0],\ + pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION); + REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x,Result=%08x,XferL=%08x\n",pSRB->pcmd->cmnd[0],\ (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);) goto ckc_e; } @@ -1373,20 +1394,20 @@ pSRB->RetryCnt--; pSRB->AdaptStatus = 0; pSRB->TargetStatus = 0; - *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; - *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1]; + //*((PUINT) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; + //*((PUINT) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1]; /* Don't retry on TEST_UNIT_READY */ - if( pSRB->CmdBlock[0] == TEST_UNIT_READY /* || pSRB->CmdBlock[0] == START_STOP */) + if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */) { - pcmd->result = (DRIVER_SENSE << 24) | (DRIVER_OK << 16) - | SCSI_STAT_CHECKCOND; - REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->CmdBlock[0],\ + pcmd->result = MK_RES_LNX(DRIVER_SENSE,DID_OK,0,CHECK_CONDITION); + REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\ (UINT) pcmd->result, (UINT) pSRB->TotalXferredLen);) goto ckc_e; } - pcmd->result |= (DRIVER_SENSE << 24); - pSRB->SGcount = (UCHAR) pSRB->Segment1[0]; - pSRB->ScsiCmdLen = (UCHAR) (pSRB->Segment1[0] >> 8); + SET_RES_DRV(pcmd->result,DRIVER_SENSE); + pSRB->SGcount = (UCHAR) pSRB->SavedSGCount; + //pSRB->ScsiCmdLen = (UCHAR) (pSRB->Segment1[0] >> 8); + DEBUG0 (printk ("DC390: RETRY pid %li (%02x), target %02i-%02i\n", pcmd->pid, pcmd->cmnd[0], pcmd->target, pcmd->lun);) pSRB->SGIndex = 0; pSRB->TotalXferredLen = 0; pSRB->SGToBeXferLen = 0; @@ -1399,15 +1420,15 @@ pSRB->Segmentx.length = pcmd->request_bufflen; } if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) - dc390_RewaitSRB( pDCB, pSRB ); + dc390_Going_to_Waiting ( pDCB, pSRB ); return; } } if( status ) { - if( status == SCSI_STAT_CHECKCOND) + if( status_byte(status) == CHECK_CONDITION ) { - REMOVABLEDEBUG(printk (KERN_INFO "DC390: Scsi_Stat_CheckCond (Cmd %02x, Id %02x, LUN %02x)\n",\ + REMOVABLEDEBUG(printk (KERN_INFO "DC390: Check_Condition (Cmd %02x, Id %02x, LUN %02x)\n",\ pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN);) if( (pSRB->SGIndex < pSRB->SGcount) && (pSRB->SGcount) && (pSRB->SGToBeXferLen) ) { @@ -1425,12 +1446,13 @@ dc390_RequestSense( pACB, pDCB, pSRB ); return; } - else if( status == SCSI_STAT_QUEUEFULL ) + else if( status_byte(status) == QUEUE_FULL ) { bval = (UCHAR) pDCB->GoingSRBCnt; bval--; pDCB->MaxCommand = bval; - dc390_RewaitSRB( pDCB, pSRB ); + dc390_freetag (pDCB, pSRB); + dc390_Going_to_Waiting ( pDCB, pSRB ); pSRB->AdaptStatus = 0; pSRB->TargetStatus = 0; return; @@ -1439,17 +1461,16 @@ { pSRB->AdaptStatus = H_SEL_TIMEOUT; pSRB->TargetStatus = 0; - pcmd->result = DID_BAD_TARGET << 16; + pcmd->result = MK_RES(0,DID_NO_CONNECT,0,0); /* Devices are removed below ... */ } - else if (status == SCSI_STAT_BUSY && - (pSRB->CmdBlock[0] == TEST_UNIT_READY || pSRB->CmdBlock[0] == INQUIRY) && + else if (status_byte(status) == BUSY && + (pSRB->pcmd->cmnd[0] == TEST_UNIT_READY || pSRB->pcmd->cmnd[0] == INQUIRY) && pACB->scan_devices) { pSRB->AdaptStatus = 0; pSRB->TargetStatus = status; - pcmd->result = (ULONG) (pSRB->EndMessage << 8) - /* | (ULONG) status */; + pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0); } else { /* Another error */ @@ -1470,13 +1491,15 @@ pSRB->Segmentx.length = pcmd->request_bufflen; } if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) - dc390_RewaitSRB( pDCB, pSRB ); + dc390_Going_to_Waiting ( pDCB, pSRB ); return; } else { /* Report error */ - pcmd->result |= (DID_ERROR << 16) | (ULONG) (pSRB->EndMessage << 8) | - (ULONG) status; + //pcmd->result = MK_RES(0, DID_ERROR, pSRB->EndMessage, status); + SET_RES_DID(pcmd->result,DID_ERROR); + SET_RES_MSG(pcmd->result,pSRB->EndMessage); + SET_RES_TARGET(pcmd->result,status); } } } @@ -1486,38 +1509,41 @@ if(status & H_OVER_UNDER_RUN) { pSRB->TargetStatus = 0; - pcmd->result |= (DID_OK << 16) | (pSRB->EndMessage << 8); + SET_RES_DID(pcmd->result,DID_OK); + SET_RES_MSG(pcmd->result,pSRB->EndMessage); } else if( pSRB->SRBStatus & PARITY_ERROR) { - pcmd->result |= (DID_PARITY << 16) | (pSRB->EndMessage << 8); + //pcmd->result = MK_RES(0,DID_PARITY,pSRB->EndMessage,0); + SET_RES_DID(pcmd->result,DID_PARITY); + SET_RES_MSG(pcmd->result,pSRB->EndMessage); } else /* No error */ { pSRB->AdaptStatus = 0; pSRB->TargetStatus = 0; - pcmd->result |= (DID_OK << 16); + SET_RES_DID(pcmd->result,DID_OK); } } ckc_e: if( pACB->scan_devices ) { - if( pSRB->CmdBlock[0] == TEST_UNIT_READY ) + if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY ) { #ifdef DC390_DEBUG0 printk (KERN_INFO "DC390: Test_Unit_Ready: result: %08x", pcmd->result); - if (pcmd->result & DRIVER_SENSE << 24) printk (" (sense: %02x %02x %02x %02x)\n", + if (pcmd->result & (DRIVER_SENSE << 24)) printk (" (sense: %02x %02x %02x %02x)\n", pcmd->sense_buffer[0], pcmd->sense_buffer[1], pcmd->sense_buffer[2], pcmd->sense_buffer[3]); else printk ("\n"); #endif - if((pcmd->result != (DID_OK << 16) && !(pcmd->result & SCSI_STAT_CHECKCOND) && !(pcmd->result & SCSI_STAT_BUSY)) || - ((pcmd->result & DRIVER_SENSE << 24) && (pcmd->sense_buffer[0] & 0x70) == 0x70 && - (pcmd->sense_buffer[2] & 0xf) == ILLEGAL_REQUEST) || pcmd->result & DID_ERROR << 16) + if( (host_byte(pcmd->result) != DID_OK && !(status_byte(pcmd->result) & CHECK_CONDITION) && !(status_byte(pcmd->result) & BUSY)) || + ((driver_byte(pcmd->result) & DRIVER_SENSE) && (pcmd->sense_buffer[0] & 0x70) == 0x70 && + (pcmd->sense_buffer[2] & 0xf) == ILLEGAL_REQUEST) || host_byte(pcmd->result) & DID_ERROR ) { /* device not present: remove */ - dc390_remove_dev (pACB, pDCB); + dc390_remove_dev (pACB, pDCB); DCB_removed = 1; if( (pcmd->target == pACB->pScsiHost->max_id - 1) && ((pcmd->lun == 0) || (pcmd->lun == pACB->pScsiHost->max_lun - 1)) ) @@ -1534,8 +1560,10 @@ } } - if( pSRB->CmdBlock[0] == INQUIRY && - (pcmd->result == DID_OK << 16 || pcmd->result & SCSI_STAT_CHECKCOND) ) + //if( pSRB->pcmd->cmnd[0] == INQUIRY && + // (host_byte(pcmd->result) == DID_OK || status_byte(pcmd->result) & CHECK_CONDITION) ) + if( pSRB->pcmd->cmnd[0] == INQUIRY && + (pcmd->result == (DID_OK << 16) || status_byte(pcmd->result) & CHECK_CONDITION) ) { ptr = (PSCSI_INQDATA) (pcmd->request_buffer); if( pcmd->use_sg ) @@ -1543,7 +1571,7 @@ if ((ptr->DevType & SCSI_DEVTYPE) == TYPE_NODEV) { /* device not present: remove */ - dc390_remove_dev (pACB, pDCB); + dc390_remove_dev (pACB, pDCB); DCB_removed = 1; } else { @@ -1555,40 +1583,25 @@ (pcmd->lun == pACB->pScsiHost->max_lun - 1) ) pACB->scan_devices = 0; }; -/* dc390_ReleaseSRB( pDCB, pSRB ); */ - if(pSRB == pDCB->pGoingSRB ) - { - pDCB->pGoingSRB = pSRB->pNextSRB; - } - else - { - psrb = pDCB->pGoingSRB; - while( psrb->pNextSRB != pSRB ) - psrb = psrb->pNextSRB; - psrb->pNextSRB = pSRB->pNextSRB; - if( pSRB == pDCB->pGoingLast ) - pDCB->pGoingLast = psrb; - } - pSRB->pNextSRB = pACB->pFreeSRB; - pACB->pFreeSRB = pSRB; - pDCB->GoingSRBCnt--; + if (!DCB_removed) dc390_Going_remove (pDCB, pSRB); + /* Add to free list */ + dc390_Free_insert (pACB, pSRB); - dc390_DoWaitingSRB( pACB ); - + DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done pid %li\n", pcmd->pid);) DC390_UNLOCK_ACB_NI; - pcmd->scsi_done( pcmd ); + pcmd->scsi_done (pcmd); DC390_LOCK_ACB_NI; - if( pDCB->QIORBCnt ) - dc390_DoNextCmd( pACB, pDCB ); + dc390_Query_to_Waiting (pACB); + dc390_Waiting_process (pACB); return; } -/* Remove all SRBs and tell midlevel code DID_RESET */ +/* Remove all SRBs from Going list and inform midlevel */ void -dc390_DoingSRB_Done( PACB pACB ) +dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd ) { PDCB pDCB, pdcb; PSRB psrb, psrb2; @@ -1605,13 +1618,16 @@ { psrb2 = psrb->pNextSRB; pcmd = psrb->pcmd; - pcmd->result = DID_RESET << 16; + if (pcmd == cmd) + pcmd->result = MK_RES(0,DID_ABORT,0,0); + else + pcmd->result = MK_RES(0,DID_RESET,0,0); /* ReleaseSRB( pDCB, pSRB ); */ - psrb->pNextSRB = pACB->pFreeSRB; - pACB->pFreeSRB = psrb; + dc390_Free_insert (pACB, psrb); + DEBUG0(printk (KERN_DEBUG "DC390: DoingSRB_Done: done pid %li\n", pcmd->pid);) DC390_UNLOCK_ACB_NI; pcmd->scsi_done( pcmd ); DC390_LOCK_ACB_NI; @@ -1622,21 +1638,21 @@ pdcb->TagMask = 0; pdcb = pdcb->pNextDCB; } while( pdcb != pDCB ); + dc390_Query_to_Waiting (pACB); } static void dc390_ResetSCSIBus( PACB pACB ) { - pACB->ACBFlag |= RESET_DEV; + //DC390_write8 (ScsiCmd, RST_DEVICE_CMD); + //udelay (250); + //DC390_write8 (ScsiCmd, NOP_CMD); - DC390_write8 (ScsiCmd, RST_DEVICE_CMD); - udelay (250); - DC390_write8 (ScsiCmd, NOP_CMD); - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD); + pACB->Connected = 0; return; } @@ -1644,27 +1660,29 @@ static void dc390_ScsiRstDetect( PACB pACB ) { - printk ("DC390: Rst_Detect: laststat = %08lx\n", dc390_laststatus); + printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus); //DEBUG0(printk(KERN_INFO "RST_DETECT,");) DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); + pACB->pScsiHost->last_reset = jiffies; /* Unlock before ? */ - /* delay a second */ - { unsigned int msec = 1*1000; while (--msec) udelay(1000); } + /* delay half a second */ + { unsigned int msec = 600; while (--msec) udelay(1000); } DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + pACB->Connected = 0; if( pACB->ACBFlag & RESET_DEV ) pACB->ACBFlag |= RESET_DONE; else - { + { /* Reset was issued by sb else */ pACB->ACBFlag |= RESET_DETECT; dc390_ResetDevParam( pACB ); -/* dc390_DoingSRB_Done( pACB ); ???? */ + dc390_DoingSRB_Done( pACB, 0 ); dc390_RecoverSRB( pACB ); pACB->pActiveDCB = NULL; pACB->ACBFlag = 0; - dc390_DoWaitingSRB( pACB ); + dc390_Waiting_process( pACB ); } return; } @@ -1676,15 +1694,17 @@ PSCSICMD pcmd; REMOVABLEDEBUG(printk (KERN_INFO "DC390: RequestSense (Cmd %02x, Id %02x, LUN %02x)\n",\ - pSRB->CmdBlock[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN);) + pSRB->pcmd->cmnd[0], pDCB->UnitSCSIID, pDCB->UnitSCSILUN);) pSRB->SRBFlag |= AUTO_REQSENSE; - pSRB->Segment0[0] = (ULONG) pSRB->CmdBlock[0]; - pSRB->Segment0[1] = (ULONG) pSRB->CmdBlock[4]; - pSRB->Segment1[0] = (ULONG) ((pSRB->ScsiCmdLen << 8) + pSRB->SGcount); - pSRB->Segment1[1] = pSRB->TotalXferredLen; + //pSRB->Segment0[0] = (UINT) pSRB->CmdBlock[0]; + //pSRB->Segment0[1] = (UINT) pSRB->CmdBlock[4]; + //pSRB->Segment1[0] = ((UINT)(pSRB->pcmd->cmd_len) << 8) + pSRB->SGcount; + //pSRB->Segment1[1] = pSRB->TotalXferredLen; + pSRB->SavedSGCount = pSRB->SGcount; + pSRB->SavedTotXLen = pSRB->TotalXferredLen; pSRB->AdaptStatus = 0; - pSRB->TargetStatus = 0; /* SCSI_STAT_CHECKCOND; */ + pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */ pcmd = pSRB->pcmd; @@ -1694,16 +1714,16 @@ pSRB->SGcount = 1; pSRB->SGIndex = 0; - pSRB->CmdBlock[0] = REQUEST_SENSE; - pSRB->CmdBlock[1] = pDCB->IdentifyMsg << 5; - (USHORT) pSRB->CmdBlock[2] = 0; - (USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer); - pSRB->ScsiCmdLen = 6; + //pSRB->CmdBlock[0] = REQUEST_SENSE; + //pSRB->CmdBlock[1] = pDCB->UnitSCSILUN << 5; + //(USHORT) pSRB->CmdBlock[2] = 0; + //(USHORT) pSRB->CmdBlock[4] = sizeof(pcmd->sense_buffer); + //pSRB->ScsiCmdLen = 6; pSRB->TotalXferredLen = 0; pSRB->SGToBeXferLen = 0; if( dc390_StartSCSI( pACB, pDCB, pSRB ) ) - dc390_RewaitSRB( pDCB, pSRB ); + dc390_Going_to_Waiting ( pDCB, pSRB ); } Index: tmscsim.c =================================================================== RCS file: /home/cvsroot/dc390/tmscsim.c,v retrieving revision 2.16 retrieving revision 2.60.2.7 diff -u -r2.16 -r2.60.2.7 --- tmscsim.c 1998/12/25 17:54:44 2.16 +++ tmscsim.c 2000/01/17 22:23:03 2.60.2.7 @@ -5,11 +5,11 @@ * Bus Master Host Adapter * * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. * ***********************************************************************/ -/* (C) Copyright: put under GNU GPL in 10/96 * +/* (C) Copyright: put under GNU GPL in 10/96 (see README.tmscsim) * *************************************************************************/ -/* $Id: tmscsim.c,v 2.16 1998/12/25 17:54:44 garloff Exp $ */ +/* $Id: tmscsim.c,v 2.60.2.7 2000/01/17 22:23:03 garloff Exp $ */ /* Enhancements and bugfixes by * - * Kurt Garloff * + * Kurt Garloff * ***********************************************************************/ /* HISTORY: * * * @@ -95,8 +95,54 @@ * 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- * + * completely reworked. Handle target ini- * * tiated SDTR correctly. * + * 2.0d1 99/01/25 KG Try to handle RESTORE_PTR * + * 2.0d2 99/02/08 KG Check for failure of kmalloc, correct * + * inclusion of scsicam.h, DelayReset * + * 2.0d3 99/05/31 KG DRIVER_OK -> DID_OK, DID_NO_CONNECT, * + * detect Target mode and warn. * + * pcmd->result handling cleaned up. * + * 2.0d4 99/06/01 KG Cleaned selection process. Found bug * + * which prevented more than 16 tags. Now: * + * 24. SDTR cleanup. Cleaner multi-LUN * + * handling. Don't modify ControlRegs/FIFO * + * when connected. * + * 2.0d5 99/06/01 KG Clear DevID, Fix INQUIRY after cfg chg. * + * 2.0d6 99/06/02 KG Added ADD special command to allow cfg. * + * before detection. Reset SYNC_NEGO_DONE * + * after a bus reset. * + * 2.0d7 99/06/03 KG Fixed bugs wrt add,remove commands * + * 2.0d8 99/06/04 KG Removed copying of cmnd into CmdBlock. * + * Fixed Oops in _release(). * + * 2.0d9 99/06/06 KG Also tag queue INQUIRY, T_U_R, ... * + * Allow arb. no. of Tagged Cmnds. Max 32 * + * 2.0d1099/06/20 KG TagMaxNo changes now honoured! Queueing * + * clearified (renamed ..) TagMask handling* + * cleaned. * + * 2.0d1199/06/28 KG cmd->result now identical to 2.0d2 * + * 2.0d1299/07/04 KG Changed order of processing in IRQ * + * 2.0d1399/07/05 KG Don't update DCB fields if removed * + * 2.0d1499/07/05 KG remove_dev: Move kfree() to the end * + * 2.0d1599/07/12 KG use_new_eh_code: 0, ULONG -> UINT where * + * appropriate * + * 2.0d1699/07/13 KG Reenable StartSCSI interrupt, Retry msg * + * 2.0d1799/07/15 KG Remove debug msg. Disable recfg. when * + * there are queued cmnds * + * 2.0d1899/07/18 KG Selection timeout: Don't requeue * + * 2.0d1999/07/18 KG Abort: Only call scsi_done if dequeued * + * 2.0d2099/07/19 KG Rst_Detect: DoingSRB_Done * + * 2.0d2199/08/15 KG dev_id for request/free_irq, cmnd[0] for* + * RETRY, SRBdone does DID_ABORT for the * + * cmd passed by DC390_reset() * + * 2.0d2299/08/25 KG dev_id fixed. can_queue: 42 * + * 2.0d2399/08/25 KG Removed some debugging code. dev_id * + * now is set to pACB. Use u8,u16,u32. * + * 2.0d2499/11/14 KG Unreg. I/O if failed IRQ alloc. Call * + * done () w/ DID_BAD_TARGET in case of * + * missing DCB. We are old EH!! * + * 2.0d2500/01/15 KG 2.3.3x compat from Andreas Schultz * + * set dev_id. Disable RETRY message. * ***********************************************************************/ /* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */ @@ -108,6 +154,7 @@ //#define DC390_DCBDEBUG //#define DC390_PARSEDEBUG //#define DC390_REMOVABLEDEBUG +//#define DC390_LOCKDEBUG /* Debug definitions */ #ifdef DC390_DEBUG0 @@ -165,6 +212,7 @@ #include "constants.h" #include "sd.h" #include +#include #include "dc390.h" @@ -174,8 +222,7 @@ /* Note: Starting from 2.1.9x, the mid-level scsi code issues a * spinlock_irqsave (&io_request_lock) before calling the driver's - * routines, so we don't need to lock. - * TODO: Verify, if we are locked in every case! + * routines, so we don't need to lock, except in the IRQ handler. * The policy 3, let the midlevel scsi code do the io_request_locks * and us locking on a driver specific lock, shouldn't hurt anybody; it * just causes a minor performance degradation for setting the locks. @@ -188,22 +235,24 @@ * undef : traditional save_flags; cli; restore_flags; */ -//#define DEBUG_SPINLOCKS 2 /* Set to 0, 1 or 2 in include/asm/spinlock.h */ +//#define DEBUG_SPINLOCKS 2 /* Set to 0, 1 or 2 in include/linux/spinlock.h */ -#define LinuxVersionCode(v, p, s) (((v)<<16)+((p)<<8)+(s)) - -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) # include +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) +# include +#else # include #endif +#endif -#if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,93) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) # define USE_SPINLOCKS 1 # define NEW_PCI 1 #else # undef NEW_PCI -# if LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30) +# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) # define USE_SPINLOCKS 2 # endif #endif @@ -319,7 +368,11 @@ # define PCI_PRESENT pci_present () # define PCI_SET_MASTER pci_set_master (pdev) # define PCI_FIND_DEVICE(vend, id) (pdev = pci_find_device (vend, id, pdev)) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,10) +# define PCI_GET_IO_AND_IRQ io_port = pdev->resource[0].start; irq = pdev->irq +#else # define PCI_GET_IO_AND_IRQ io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; irq = pdev->irq +#endif #else # include # define PDEV pbus, pdevfn @@ -368,7 +421,7 @@ void dc390_Disconnect( PACB pACB ); void dc390_Reselect( PACB pACB ); void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ); -void dc390_DoingSRB_Done( PACB pACB ); +void dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd ); static void dc390_ScsiRstDetect( PACB pACB ); static void dc390_ResetSCSIBus( PACB pACB ); static void __inline__ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ); @@ -378,7 +431,7 @@ void do_DC390_Interrupt( int, void *, struct pt_regs *); int dc390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, UCHAR index ); -void dc390_initDCB( PACB pACB, PDCB *ppDCB, PSCSICMD cmd ); +void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun); void dc390_updateDCB (PACB pACB, PDCB pDCB); #ifdef MODULE @@ -392,10 +445,9 @@ //static PSH dc390_pSH_current = NULL; static PACB dc390_pACB_start= NULL; static PACB dc390_pACB_current = NULL; -static UCHAR dc390_adapterCnt = 0; -static UCHAR dc390_CurrSyncOffset = 0; static ULONG dc390_lastabortedpid = 0; -static ULONG dc390_laststatus = 0; +static UINT dc390_laststatus = 0; +static UCHAR dc390_adapterCnt = 0; #ifndef CONFIG_SCSI_DC390T_NOGENSUPP /* Startup values, to be overriden on the commandline */ @@ -407,16 +459,16 @@ # ifdef CONFIG_SCSI_MULTI_LUN | LUN_CHECK # endif - , 3 /* 16 Tags per LUN */}; + , 3 /* 16 Tags per LUN */, 1 /* s delay after Reset */ }; -# if defined(MODULE) && LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30) -MODULE_PARM(tmscsim, "1-5i"); -MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1)"); +# if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) +MODULE_PARM(tmscsim, "1-6i"); +MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)"); # endif #endif /* CONFIG_SCSI_DC390T_NOGENSUPP */ -#if defined(MODULE) && LINUX_VERSION_CODE >= LinuxVersionCode(2,1,30) +#if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30) MODULE_AUTHOR("C.L. Huang / Kurt Garloff"); MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters"); MODULE_SUPPORTED_DEVICE("sd,sr,sg,st"); @@ -482,11 +534,12 @@ UCHAR dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN]; UCHAR dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20}; +#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,30) struct proc_dir_entry DC390_proc_scsi_tmscsim ={ PROC_SCSI_DC390T, 7 ,"tmscsim", S_IFDIR | S_IRUGO | S_IXUGO, 2 }; - +#endif /*********************************************************************** * Functions for access to DC390 EEPROM @@ -518,29 +571,29 @@ ptr = (PUCHAR) dc390_eepromBuf[index]; /* Adapter Settings */ - ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0]; /* Adapter ID */ + 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 */ + ptr[EE_DELAY] = tmscsim[5]; /* Reset delay */ + ptr[EE_TAG_CMD_NUM] = (UCHAR)tmscsim[4]; /* Tagged Cmds */ /* 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 */ + 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]);) + PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x %08x\n", tmscsim[0],\ + tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4], tmscsim[5]);) 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; + tmscsim[4] = 2; tmscsim[5] = 10; printk (KERN_INFO "DC390: Using safe settings.\n"); } else @@ -548,6 +601,7 @@ /* 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; + if (tmscsim[5] > 180) tmscsim[5] = 180; }; }; /* Override defaults on cmdline: @@ -555,11 +609,14 @@ */ 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) + int i, im = ints[0]; + if (im > 6) + { printk (KERN_NOTICE "DC390: ignore extra params!\n"); + im = 6; + }; + for (i = 0; i < im; i++) + tmscsim[i] = ints[i+1]; /* dc390_checkparams (); */ }; #endif /* CONFIG_SCSI_DC390T_NOGENSUPP */ @@ -651,6 +708,12 @@ } +static void __init dc390_interpret_delay (UCHAR index) +{ + char interpd [] = {1,2,5,10,15,30,60,120}; + dc390_eepromBuf[index][EE_DELAY] = interpd [dc390_eepromBuf[index][EE_DELAY]]; +}; + static UCHAR __init dc390_CheckEEpromCheckSum( PDEVDECL, UCHAR index ) { UCHAR i; @@ -661,6 +724,8 @@ 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); + dc390_interpret_delay (index); + wval = 0; for(i=0; i<0x40; i++, ptr++) wval += *ptr; @@ -673,65 +738,93 @@ * (DCBs, SRBs, Queueing) * **********************************************************************/ -static PDCB __inline__ dc390_findDCB ( PACB pACB, Scsi_Cmnd *cmd) +static PDCB __inline__ dc390_findDCB ( PACB pACB, UCHAR id, UCHAR lun) { PDCB pDCB = pACB->pLinkDCB; if (!pDCB) return 0; - while (pDCB->UnitSCSIID != cmd->target || pDCB->UnitSCSILUN != cmd->lun) + while (pDCB->UnitSCSIID != id || pDCB->UnitSCSILUN != lun) { pDCB = pDCB->pNextDCB; if (pDCB == pACB->pLinkDCB) { - printk (KERN_WARNING "DC390: DCB not found (DCB=%08x, DCBmap[%2x]=%2x)\n", - (int)pDCB, cmd->target, pACB->DCBmap[cmd->target]); + DCBDEBUG(printk (KERN_WARNING "DC390: DCB not found (DCB=%p, DCBmap[%2x]=%2x)\n", + pDCB, id, pACB->DCBmap[id]);) return 0; } }; - DCBDEBUG1( printk (KERN_DEBUG "DCB %08x (%02x,%02x) found.\n", \ - (int)pDCB, pDCB->UnitSCSIID, pDCB->UnitSCSILUN);) + DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n", \ + pDCB, pDCB->UnitSCSIID, pDCB->UnitSCSILUN);) return pDCB; }; -static void dc390_QLinkcmd( PSCSICMD cmd, PDCB pDCB ) -{ - PSCSICMD pcmd; +/* Queueing philosphy: + * There are a couple of lists: + * - Query: Contains the Scsi Commands not yet turned into SRBs (per ACB) + * - Waiting: Contains a list of SRBs not yet sent (per DCB) + * - Free: List of free SRB slots + * + * If there are no waiting commands for the DCB, the new one is sent to the bus + * otherwise the oldest one is taken from the Waiting list and the new one is + * queued to the Waiting List + * + * Lists are managed using two pointers and eventually a counter + */ - if( !pDCB->QIORBCnt ) + +#if 0 +/* Look for a SCSI cmd in a SRB queue */ +static PSRB dc390_find_cmd_in_SRBq (PSCSICMD cmd, PSRB queue) +{ + PSRB q = queue; + while (q) { - pDCB->pQIORBhead = cmd; - pDCB->pQIORBtail = cmd; - pDCB->QIORBCnt++; - cmd->next = NULL; + if (q->pcmd == cmd) return q; + q = q->pNextSRB; + if (q == queue) return 0; } + return q; +}; +#endif + + +/* Append to Query List */ +static void dc390_Query_append( PSCSICMD cmd, PACB pACB ) +{ + DEBUG0(printk ("DC390: Append cmd %li to Query\n", cmd->pid);) + if( !pACB->QueryCnt ) + pACB->pQueryHead = cmd; else - { - pcmd = pDCB->pQIORBtail; - pcmd->next = cmd; - pDCB->pQIORBtail = cmd; - pDCB->QIORBCnt++; - cmd->next = NULL; - } + pACB->pQueryTail->next = cmd; + pACB->pQueryTail = cmd; + pACB->QueryCnt++; + pACB->CmdOutOfSRB++; + cmd->next = NULL; } -static __inline__ PSCSICMD dc390_Getcmd( PDCB pDCB ) +/* Return next cmd from Query list */ +static PSCSICMD dc390_Query_get ( PACB pACB ) { PSCSICMD pcmd; - pcmd = pDCB->pQIORBhead; - pDCB->pQIORBhead = pcmd->next; + pcmd = pACB->pQueryHead; + if (!pcmd) return pcmd; + DEBUG0(printk ("DC390: Get cmd %li from Query\n", pcmd->pid);) + pACB->pQueryHead = pcmd->next; pcmd->next = NULL; - pDCB->QIORBCnt--; - + if (!pACB->pQueryHead) pACB->pQueryTail = NULL; + pACB->QueryCnt--; return( pcmd ); } -static __inline__ PSRB dc390_GetSRB( PACB pACB ) +/* Return next free SRB */ +static __inline__ PSRB dc390_Free_get ( PACB pACB ) { PSRB pSRB; pSRB = pACB->pFreeSRB; + DEBUG0(printk ("DC390: Get Free SRB %p\n", pSRB);) if( pSRB ) { pACB->pFreeSRB = pSRB->pNextSRB; @@ -740,130 +833,128 @@ return( pSRB ); } - -static __inline__ void dc390_RewaitSRB0( PDCB pDCB, PSRB pSRB ) +/* Insert SRB oin top of free list */ +static __inline__ void dc390_Free_insert (PACB pACB, PSRB pSRB) { - PSRB psrb1; + DEBUG0(printk ("DC390: Free SRB %p\n", pSRB);) + pSRB->pNextSRB = pACB->pFreeSRB; + pACB->pFreeSRB = pSRB; +} - if( (psrb1 = pDCB->pWaitingSRB) ) - { - pSRB->pNextSRB = psrb1; - } - else - { - pSRB->pNextSRB = NULL; + +/* Inserts a SRB to the top of the Waiting list */ +static __inline__ void dc390_Waiting_insert ( PDCB pDCB, PSRB pSRB ) +{ + DEBUG0(printk ("DC390: 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; } -static void dc390_RewaitSRB( PDCB pDCB, PSRB pSRB ) +/* Queue SRB to waiting list */ +static __inline__ void dc390_Waiting_append ( PDCB pDCB, PSRB pSRB) { - PSRB psrb1; - UCHAR bval; - - pDCB->GoingSRBCnt--; pDCB->pDCBACB->SelLost++; - DEBUG0(printk(KERN_INFO "DC390: RewaitSRB (%p, %p) pid = %li\n", pDCB, pSRB, pSRB->pcmd->pid);) - psrb1 = pDCB->pGoingSRB; - if( pSRB == psrb1 ) - { - pDCB->pGoingSRB = psrb1->pNextSRB; - } - else - { - while( pSRB != psrb1->pNextSRB ) - psrb1 = psrb1->pNextSRB; - psrb1->pNextSRB = pSRB->pNextSRB; - if( pSRB == pDCB->pGoingLast ) - pDCB->pGoingLast = psrb1; - } - if( (psrb1 = pDCB->pWaitingSRB) ) - { - pSRB->pNextSRB = psrb1; - pDCB->pWaitingSRB = pSRB; - } + DEBUG0(printk ("DC390: Append pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid);) + if( pDCB->pWaitingSRB ) + pDCB->pWaitLast->pNextSRB = pSRB; else - { - pSRB->pNextSRB = NULL; pDCB->pWaitingSRB = pSRB; - pDCB->pWaitLast = pSRB; - } - bval = pSRB->TagNumber; - pDCB->TagMask &= (~(1 << bval)); /* Free TAG number */ + pDCB->pWaitLast = pSRB; + pSRB->pNextSRB = NULL; + pDCB->pDCBACB->CmdInQ++; } - -static void dc390_DoWaitingSRB( PACB pACB ) +static __inline__ void dc390_Going_append (PDCB pDCB, PSRB pSRB) { - PDCB ptr, ptr1; - PSRB pSRB; + pDCB->GoingSRBCnt++; + DEBUG0(printk("DC390: 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; - if( !(pACB->pActiveDCB) && !(pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) - { - ptr = pACB->pDCBRunRobin; - if( !ptr ) - { - ptr = pACB->pLinkDCB; - pACB->pDCBRunRobin = ptr; - } - ptr1 = ptr; - for( ;ptr1; ) - { - pACB->pDCBRunRobin = ptr1->pNextDCB; - if( !( ptr1->MaxCommand > ptr1->GoingSRBCnt ) || - !( pSRB = ptr1->pWaitingSRB ) ) - { - if(pACB->pDCBRunRobin == ptr) - break; - ptr1 = ptr1->pNextDCB; - } - else - { - if( !dc390_StartSCSI(pACB, ptr1, pSRB) ) - { - ptr1->GoingSRBCnt++; - if( ptr1->pWaitLast == pSRB ) - { - ptr1->pWaitingSRB = NULL; - ptr1->pWaitLast = NULL; - } - else - { - ptr1->pWaitingSRB = pSRB->pNextSRB; - } - pSRB->pNextSRB = NULL; - - if( ptr1->pGoingSRB ) - ptr1->pGoingLast->pNextSRB = pSRB; - else - ptr1->pGoingSRB = pSRB; - ptr1->pGoingLast = pSRB; - } - break; - } - } - } - return; -} + pDCB->pGoingLast = pSRB; + /* No next one in sent list */ + pSRB->pNextSRB = NULL; +}; +static __inline__ void dc390_Going_remove (PDCB pDCB, PSRB pSRB) +{ + DEBUG0(printk("DC390: Remove SRB %p from Going\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 "DC390: Remove non-ex. SRB %p from Going!\n", pSRB); return; } + psrb->pNextSRB = pSRB->pNextSRB; + if (pSRB == pDCB->pGoingLast) + pDCB->pGoingLast = psrb; + } + pDCB->GoingSRBCnt--; +}; -static __inline__ void dc390_SRBwaiting( PDCB pDCB, PSRB pSRB) +/* Moves SRB from Going list to the top of Waiting list */ +static void dc390_Going_to_Waiting ( PDCB pDCB, PSRB pSRB ) { - if( pDCB->pWaitingSRB ) - { - pDCB->pWaitLast->pNextSRB = pSRB; - pSRB->pNextSRB = NULL; - } - else - { - pDCB->pWaitingSRB = pSRB; - } - pDCB->pWaitLast = pSRB; + DEBUG0(printk(KERN_INFO "DC390: Going_to_Waiting (SRB %p) pid = %li\n", pSRB, pSRB->pcmd->pid);) + /* Remove SRB from Going */ + dc390_Going_remove (pDCB, pSRB); + /* Insert on top of Waiting */ + dc390_Waiting_insert (pDCB, pSRB); + /* Tag Mask must be freed elsewhere ! (KG, 99/06/18) */ +} + +/* Moves first SRB from Waiting list to Going list */ +static __inline__ void dc390_Waiting_to_Going ( PDCB pDCB, PSRB pSRB ) +{ + /* Remove from waiting list */ + DEBUG0(printk("DC390: Remove SRB %p from head of Waiting\n", pSRB);) + pDCB->pWaitingSRB = pSRB->pNextSRB; + if( !pDCB->pWaitingSRB ) pDCB->pWaitLast = NULL; + dc390_Going_append (pDCB, pSRB); } +/* Send the next command from the waiting list to the bus */ +static void dc390_Waiting_process ( PACB pACB ) +{ + PDCB ptr, ptr1; + PSRB pSRB; + + if( (pACB->pActiveDCB) || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) + return; + 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( !dc390_StartSCSI(pACB, ptr1, pSRB) ) + dc390_Waiting_to_Going (ptr1, pSRB); + break; + } + } while (ptr1 != ptr); + return; +} /*********************************************************************** * Function: static void dc390_SendSRB (PACB pACB, PSRB pSRB) @@ -877,41 +968,32 @@ PDCB pDCB; pDCB = pSRB->pSRBDCB; - if( !(pDCB->MaxCommand > pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || + if( (pDCB->MaxCommand <= pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV)) ) { - dc390_SRBwaiting(pDCB, pSRB); - goto SND_EXIT; + dc390_Waiting_append (pDCB, pSRB); + dc390_Waiting_process (pACB); + return; } +#if 0 if( pDCB->pWaitingSRB ) { - dc390_SRBwaiting(pDCB, pSRB); + dc390_Waiting_append (pDCB, pSRB); /* pSRB = GetWaitingSRB(pDCB); */ /* non-existent */ pSRB = pDCB->pWaitingSRB; + /* Remove from waiting list */ pDCB->pWaitingSRB = pSRB->pNextSRB; pSRB->pNextSRB = NULL; - } - - if( !dc390_StartSCSI(pACB, pDCB, pSRB) ) - { - pDCB->GoingSRBCnt++; - if( pDCB->pGoingSRB ) - { - pDCB->pGoingLast->pNextSRB = pSRB; - pDCB->pGoingLast = pSRB; - } - else - { - pDCB->pGoingSRB = pSRB; - pDCB->pGoingLast = pSRB; - } + if (!pDCB->pWaitingSRB) pDCB->pWaitLast = NULL; } +#endif + + if (!dc390_StartSCSI(pACB, pDCB, pSRB)) + dc390_Going_append (pDCB, pSRB); else - dc390_RewaitSRB0( pDCB, pSRB ); + dc390_Waiting_insert (pDCB, pSRB); -SND_EXIT: - return; } /*********************************************************************** @@ -926,8 +1008,8 @@ { pSRB->pSRBDCB = pDCB; pSRB->pcmd = pcmd; - pSRB->ScsiCmdLen = pcmd->cmd_len; - memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len); + //pSRB->ScsiCmdLen = pcmd->cmd_len; + //memcpy (pSRB->CmdBlock, pcmd->cmnd, pcmd->cmd_len); if( pcmd->use_sg ) { @@ -960,8 +1042,39 @@ pSRB->SGToBeXferLen = 0; pSRB->ScsiPhase = 0; pSRB->EndMessage = 0; + pSRB->TagNumber = 255; }; +/* Put cmnd from Query to Waiting list and send next Waiting cmnd */ +static void dc390_Query_to_Waiting (PACB pACB) +{ + Scsi_Cmnd *pcmd; + PSRB pSRB; + PDCB pDCB; + + if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) + return; + + while (pACB->QueryCnt) + { + pSRB = dc390_Free_get ( pACB ); + if (!pSRB) return; + pcmd = dc390_Query_get ( pACB ); + if (!pcmd) { dc390_Free_insert (pACB, pSRB); return; }; /* should not happen */ + pDCB = dc390_findDCB (pACB, pcmd->target, pcmd->lun); + if (!pDCB) + { + dc390_Free_insert (pACB, pSRB); + printk (KERN_ERR "DC390: Command in queue to non-existing device!\n"); + pcmd->result = MK_RES(DRIVER_ERROR,DID_ERROR,0,0); + DC390_UNLOCK_ACB_NI; + pcmd->done (pcmd); + DC390_LOCK_ACB_NI; + }; + dc390_BuildSRB (pcmd, pDCB, pSRB); + dc390_Waiting_append ( pDCB, pSRB ); + } +} /*********************************************************************** * Function : static int DC390_queue_command (Scsi_Cmnd *cmd, @@ -984,7 +1097,6 @@ int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) { - Scsi_Cmnd *pcmd; PDCB pDCB; PSRB pSRB; DC390_AFLAGS @@ -992,7 +1104,7 @@ DEBUG0(/* if(pACB->scan_devices) */ \ - printk(KERN_INFO "DC390: Queue Cmd=%02x,ID=%d,LUN=%d (pid=%li)\n",\ + printk(KERN_INFO "DC390: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li)\n",\ cmd->cmnd[0],cmd->target,cmd->lun,cmd->pid);) DC390_LOCK_ACB; @@ -1022,14 +1134,15 @@ if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY) && !(pACB->DCBmap[cmd->target] & (1 << cmd->lun)) ) { - pACB->DCBmap[cmd->target] |= (1 << cmd->lun); pACB->scan_devices = 1; - dc390_initDCB( pACB, &pDCB, cmd ); + dc390_initDCB( pACB, &pDCB, cmd->target, cmd->lun ); if (!pDCB) { - printk (KERN_ERR "DC390: kmalloc for DCB failed, ID=%2x\n", cmd->target); + printk (KERN_ERR "DC390: kmalloc for DCB failed, target %02x lun %02x\n", + cmd->target, cmd->lun); DC390_UNLOCK_ACB; + printk ("DC390: No DCB in queuecommand!\n"); done(cmd); return(0); }; @@ -1045,10 +1158,13 @@ } else { - pDCB = dc390_findDCB (pACB, cmd); + pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun); if (!pDCB) { /* should never happen */ + printk (KERN_ERR "DC390: no DCB failed, target %02x lun %02x\n", + cmd->target, cmd->lun); DC390_UNLOCK_ACB; + printk ("DC390: No DCB in queuecommand (2)!\n"); done(cmd); return(0); }; @@ -1057,54 +1173,48 @@ pACB->Cmds++; cmd->scsi_done = done; cmd->result = 0; + + dc390_Query_to_Waiting (pACB); - if( pDCB->QIORBCnt ) /* Unsent commands ? */ + if( pACB->QueryCnt ) /* Unsent commands ? */ { - dc390_QLinkcmd( cmd, pDCB ); - pcmd = dc390_Getcmd( pDCB ); /* Get first command */ - pACB->CmdInQ++; + DEBUG0(printk ("DC390: QueryCnt != 0\n");) + dc390_Query_append ( cmd, pACB ); + dc390_Waiting_process (pACB); } - else - pcmd = cmd; - - pSRB = dc390_GetSRB( pACB ); - - if( !pSRB ) + else if (pDCB->pWaitingSRB) { - dc390_QLinkcmd( pcmd, pDCB ); /* Queue command at the end */ - pACB->CmdOutOfSRB++; - DC390_UNLOCK_ACB; - return(0); + pSRB = dc390_Free_get ( pACB ); + DEBUG0(if (!pSRB) printk ("DC390: No free SRB but Waiting\n"); else printk ("DC390: Free SRB w/ Waiting\n");) + if (!pSRB) dc390_Query_append (cmd, pACB); + else + { + dc390_BuildSRB (cmd, pDCB, pSRB); + dc390_Waiting_append (pDCB, pSRB); + } + dc390_Waiting_process (pACB); } - - dc390_BuildSRB (pcmd, pDCB, pSRB); - dc390_SendSRB( pACB, pSRB ); + else + { + pSRB = dc390_Free_get ( pACB ); + DEBUG0(if (!pSRB) printk ("DC390: No free SRB w/o Waiting\n"); else printk ("DC390: Free SRB w/o Waiting\n");) + if (!pSRB) + { + dc390_Query_append (cmd, pACB); + dc390_Waiting_process (pACB); + } + else + { + dc390_BuildSRB (cmd, pDCB, pSRB); + dc390_SendSRB (pACB, pSRB); + }; + }; DC390_UNLOCK_ACB; - DEBUG1(printk (KERN_DEBUG " ... command (%02x) queued successfully.\n", pcmd->cmnd[0]);) + DEBUG1(printk (KERN_DEBUG " ... command (pid %li) queued successfully.\n", cmd->pid);) return(0); } - -static void dc390_DoNextCmd( PACB pACB, PDCB pDCB ) -{ - Scsi_Cmnd *pcmd; - PSRB pSRB; - - if( pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) - return; - - pcmd = dc390_Getcmd( pDCB ); - pSRB = dc390_GetSRB( pACB ); - if( !pSRB ) - dc390_QLinkcmd( pcmd, pDCB ); - else - { - dc390_BuildSRB (pcmd, pDCB, pSRB); - dc390_SendSRB( pACB, pSRB ); - }; -} - /* We ignore mapping problems, as we expect everybody to respect * valid partition tables. Waiting for complaints ;-) */ @@ -1244,12 +1354,12 @@ if (pSRB) { - printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08lx, Phase %02x\n", + printk ("DC390: SRB: Xferred %08lx, Remain %08lx, State %08x, Phase %02x\n", pSRB->TotalXferredLen, pSRB->SGToBeXferLen, pSRB->SRBState, pSRB->ScsiPhase); printk ("DC390: AdpaterStatus: %02x, SRB Status %02x\n", pSRB->AdaptStatus, pSRB->SRBStatus); }; - printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08lx\n", dc390_laststatus); + printk ("DC390: Status of last IRQ (DMA/SC/Int/IRQ): %08x\n", dc390_laststatus); printk ("DC390: Register dump: SCSI block:\n"); printk ("DC390: XferCnt Cmd Stat IntS IRQS FFIS Ctl1 Ctl2 Ctl3 Ctl4\n"); printk ("DC390: %06x %02x %02x %02x", @@ -1259,6 +1369,12 @@ 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); + if (DC390_read8(Current_Fifo) & 0x1f) + { + printk ("DC390: FIFO:"); + while (DC390_read8(Current_Fifo) & 0x1f) printk (" %02x", DC390_read8(ScsiFifo)); + printk ("\n"); + }; 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", @@ -1288,44 +1404,40 @@ { PDCB pDCB; PSRB pSRB, psrb; - ULONG count, i; - PSCSICMD pcmd, pcmd1; + UINT count, i; + PSCSICMD pcmd; int status; - ULONG sbac; + //ULONG sbac; DC390_AFLAGS PACB pACB = (PACB) cmd->host->hostdata; DC390_LOCK_ACB; - - pDCB = dc390_findDCB (pACB, cmd); - /* abort() is too buggy at the moment. If it's called we are in trouble anyway. - * so let's dump some info into the syslog at least. (KG, 98/08/20) */ - if (pDCB) pSRB = pDCB->pActiveSRB; else pSRB = 0; - printk ("DC390: Abort command (pid %li, DCB %p, SRB %p)\n", - cmd->pid, pDCB, pSRB); - dc390_dumpinfo (pACB, pDCB, pSRB); - if( !pDCB ) goto NOT_RUN; + printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n", + cmd->pid, cmd->target, cmd->lun); - if( pDCB->QIORBCnt ) + /* First scan Query list */ + if( pACB->QueryCnt ) { - pcmd = pDCB->pQIORBhead; + pcmd = pACB->pQueryHead; if( pcmd == cmd ) { - pDCB->pQIORBhead = pcmd->next; + /* Found: Dequeue */ + pACB->pQueryHead = pcmd->next; pcmd->next = NULL; - pDCB->QIORBCnt--; + if (cmd == pACB->pQueryTail) pACB->pQueryTail = NULL; + pACB->QueryCnt--; status = SCSI_ABORT_SUCCESS; goto ABO_X; } - for( count = pDCB->QIORBCnt, i=0; iQueryCnt, i=0; inext == cmd ) { - pcmd1 = pcmd->next; - pcmd->next = pcmd1->next; - pcmd1->next = NULL; - pDCB->QIORBCnt--; + pcmd->next = cmd->next; + cmd->next = NULL; + if (cmd == pACB->pQueryTail) pACB->pQueryTail = NULL; + pACB->QueryCnt--; status = SCSI_ABORT_SUCCESS; goto ABO_X; } @@ -1336,14 +1448,20 @@ } } + pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun); + if( !pDCB ) goto NOT_RUN; + if (pDCB) pSRB = pDCB->pActiveSRB; else pSRB = 0; + /* Added 98/07/02 KG */ pSRB = pDCB->pActiveSRB; if (pSRB && pSRB->pcmd == cmd ) goto ON_GOING; - + pSRB = pDCB->pWaitingSRB; if( !pSRB ) goto ON_GOING; + + /* Now scan Waiting queue */ if( pSRB->pcmd == cmd ) { pDCB->pWaitingSRB = pSRB->pNextSRB; @@ -1363,16 +1481,20 @@ pSRB = psrb->pNextSRB; psrb->pNextSRB = pSRB->pNextSRB; if( pSRB == pDCB->pWaitLast ) - pDCB->pWaitLast = psrb; /* No check for psrb == NULL ? */ + pDCB->pWaitLast = psrb; IN_WAIT: - pSRB->pNextSRB = pACB->pFreeSRB; - pACB->pFreeSRB = pSRB; + dc390_Free_insert (pACB, pSRB); cmd->next = NULL; status = SCSI_ABORT_SUCCESS; goto ABO_X; } + /* SRB has already been sent ! */ ON_GOING: + /* abort() is too stupid for already sent commands at the moment. + * If it's called we are in trouble anyway, so let's dump some info + * into the syslog at least. (KG, 98/08/20,99/06/20) */ + dc390_dumpinfo (pACB, pDCB, pSRB); pSRB = pDCB->pGoingSRB; pDCB->DCBFlag |= ABORT_DEV_; /* Now for the hard part: The command is currently processed */ @@ -1403,12 +1525,13 @@ ABO_X: cmd->result = DID_ABORT << 16; printk(KERN_INFO "DC390: Aborted pid %li with status %i\n", cmd->pid, status); +#if 0 if (cmd->pid == dc390_lastabortedpid) /* repeated failure ? */ { /* Let's do something to help the bus getting clean again */ DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); DC390_write8 (ScsiCmd, DMA_COMMAND); - //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); //DC390_write8 (ScsiCmd, RESET_ATN_CMD); DC390_write8 (ScsiCmd, NOP_CMD); //udelay (10000); @@ -1433,10 +1556,11 @@ sbac = DC390_read32 (DMA_ScsiBusCtrl); printk ("%08lx\n", sbac); }; +#endif dc390_lastabortedpid = cmd->pid; DC390_UNLOCK_ACB; //do_DC390_Interrupt (pACB->IRQLevel, 0, 0); - cmd->scsi_done(cmd); + if (status == SCSI_ABORT_SUCCESS) cmd->scsi_done(cmd); return( status ); } @@ -1453,12 +1577,15 @@ pDCB->SyncMode &= ~SYNC_NEGO_DONE; pDCB->SyncPeriod = 0; pDCB->SyncOffset = 0; + pDCB->TagMask = 0; pDCB->CtrlR3 = FAST_CLK; pDCB->CtrlR4 &= NEGATE_REQACKDATA | CTRL4_RESERVED | NEGATE_REQACK; pDCB->CtrlR4 |= pACB->glitch_cfg; pDCB = pDCB->pNextDCB; } while( pdcb != pDCB ); + pACB->ACBFlag &= ~(RESET_DEV | RESET_DONE | RESET_DETECT); + } @@ -1466,7 +1593,7 @@ { PDCB pDCB, pdcb; PSRB psrb, psrb2; - ULONG cnt, i; + UINT cnt, i; pDCB = pACB->pLinkDCB; if( !pDCB ) return; @@ -1506,14 +1633,15 @@ * Purpose : perform a hard reset on the SCSI bus * * Inputs : cmd - command which caused the SCSI RESET + * resetFlags - how hard to try * * Returns : 0 on success. ***********************************************************************/ -int DC390_reset(Scsi_Cmnd *cmd, unsigned int resetFlags) +int DC390_reset (Scsi_Cmnd *cmd, unsigned int resetFlags) { UCHAR bval; - ULONG i; + UINT i; DC390_AFLAGS PACB pACB = (PACB) cmd->host->hostdata; @@ -1522,18 +1650,21 @@ DC390_LOCK_ACB; bval = DC390_read8 (CtrlReg1); bval |= DIS_INT_ON_SCSI_RST; - DC390_write8 (CtrlReg1, bval); /* disable interrupt */ + DC390_write8 (CtrlReg1, bval); /* disable IRQ on bus reset */ + pACB->ACBFlag |= RESET_DEV; dc390_ResetSCSIBus( pACB ); + pACB->pScsiHost->last_reset = jiffies; + + dc390_ResetDevParam( pACB ); /* Unlock ? */ - for( i=0; i<600; i++ ) + for( i=0; i<(500 + 1000*dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]); i++ ) udelay(1000); DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); DC390_read8 (INT_Status); /* Reset Pending INT */ - dc390_ResetDevParam( pACB ); - dc390_DoingSRB_Done( pACB ); + dc390_DoingSRB_Done( pACB, cmd ); /* dc390_RecoverSRB (pACB); */ pACB->pActiveDCB = NULL; @@ -1542,10 +1673,10 @@ bval &= ~DIS_INT_ON_SCSI_RST; DC390_write8 (CtrlReg1, bval); /* re-enable interrupt */ - dc390_DoWaitingSRB( pACB ); + dc390_Waiting_process( pACB ); - DC390_UNLOCK_ACB; printk("done\n"); + DC390_UNLOCK_ACB; return( SCSI_RESET_SUCCESS ); } @@ -1555,22 +1686,22 @@ /*********************************************************************** * Function : static void dc390_initDCB() * - * Purpose : initialize the internal structures for a given DCB + * Purpose : initialize the internal structures for a DCB (to be malloced) * - * Inputs : cmd - pointer to this scsi cmd request block structure + * Inputs : SCSI id and lun ***********************************************************************/ -void dc390_initDCB( PACB pACB, PDCB *ppDCB, PSCSICMD cmd ) +void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun ) { PEEprom prom; UCHAR index; - PDCB pDCB; + PDCB pDCB, pDCB2; pDCB = kmalloc (sizeof(DC390_DCB), GFP_ATOMIC); - DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): 0x%08x\n", \ - cmd->target, cmd->lun, (int)pDCB);) + DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): %p\n" \ + id, lun, pDCB);) - *ppDCB = pDCB; + *ppDCB = pDCB; pDCB2 = 0; if (!pDCB) return; if( pACB->DCBCnt == 0 ) { @@ -1584,13 +1715,12 @@ pACB->DCBCnt++; - pACB->pLastDCB = pDCB; pDCB->pNextDCB = pACB->pLinkDCB; + pACB->pLastDCB = pDCB; pDCB->pDCBACB = pACB; - pDCB->QIORBCnt = 0; - pDCB->UnitSCSIID = cmd->target; - pDCB->UnitSCSILUN = cmd->lun; + pDCB->UnitSCSIID = id; + pDCB->UnitSCSILUN = lun; pDCB->pWaitingSRB = NULL; pDCB->pGoingSRB = NULL; pDCB->GoingSRBCnt = 0; @@ -1600,21 +1730,40 @@ index = pACB->AdapterIndex; pDCB->DCBFlag = 0; - prom = (PEEprom) &dc390_eepromBuf[index][cmd->target << 2]; - pDCB->DevMode = prom->EE_MODE1; + /* Is there a corresp. LUN==0 device ? */ + if (lun != 0) + pDCB2 = dc390_findDCB (pACB, id, 0); + prom = (PEEprom) &dc390_eepromBuf[index][id << 2]; + /* Some values are for all LUNs: Copy them */ + /* In a clean way: We would have an own structure for a SCSI-ID */ + if (pDCB2) + { + pDCB->DevMode = pDCB2->DevMode; + pDCB->SyncMode = pDCB2->SyncMode; + pDCB->SyncPeriod = pDCB2->SyncPeriod; + pDCB->SyncOffset = pDCB2->SyncOffset; + pDCB->NegoPeriod = pDCB2->NegoPeriod; + + pDCB->CtrlR3 = pDCB2->CtrlR3; + pDCB->CtrlR4 = pDCB2->CtrlR4; + } + else + { + pDCB->DevMode = prom->EE_MODE1; + pDCB->SyncMode = 0; + pDCB->SyncPeriod = 0; + pDCB->SyncOffset = 0; + pDCB->NegoPeriod = (dc390_clock_period1[prom->EE_SPEED] * 25) >> 2; + + pDCB->CtrlR3 = FAST_CLK; + + pDCB->CtrlR4 = pACB->glitch_cfg | CTRL4_RESERVED; + if( dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) + pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK; + } - pDCB->SyncMode = 0; + pACB->DCBmap[id] |= (1 << lun); dc390_updateDCB(pACB, pDCB); - - pDCB->SyncPeriod = 0; - pDCB->SyncOffset = 0; - pDCB->NegoPeriod = (dc390_clock_period1[prom->EE_SPEED] * 25) >> 2; - - pDCB->CtrlR3 = FAST_CLK; - - pDCB->CtrlR4 = pACB->glitch_cfg | CTRL4_RESERVED; - if( dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) - pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK; } /*********************************************************************** @@ -1625,24 +1774,26 @@ void dc390_updateDCB (PACB pACB, PDCB pDCB) { - pDCB->IdentifyMsg = IDENTIFY (pDCB->DevMode & EN_DISCONNECT_, pDCB->UnitSCSILUN); - - if (pDCB->DevMode & TAG_QUEUEING_) pDCB->SyncMode &= EN_TAG_QUEUEING | SYNC_NEGO_DONE | EN_ATN_STOP; - else pDCB->SyncMode &= SYNC_NEGO_DONE | EN_ATN_STOP; - - if( pDCB->DevMode & SYNC_NEGO_ && (!(pDCB->UnitSCSILUN) || dc390_CurrSyncOffset) ) - pDCB->SyncMode |= SYNC_ENABLE; - else - { + pDCB->SyncMode &= EN_TAG_QUEUEING | SYNC_NEGO_DONE /*| EN_ATN_STOP*/; + if (pDCB->DevMode & TAG_QUEUEING_) { + //if (pDCB->SyncMode & EN_TAG_QUEUEING) pDCB->MaxCommand = pACB->TagMaxNum; + } else { + pDCB->SyncMode &= ~EN_TAG_QUEUEING; + pDCB->MaxCommand = 1; + }; + + if( pDCB->DevMode & SYNC_NEGO_ ) + pDCB->SyncMode |= SYNC_ENABLE; + else { pDCB->SyncMode &= ~(SYNC_NEGO_DONE | SYNC_ENABLE); pDCB->SyncOffset &= ~0x0f; - }; - - if (! (pDCB->DevMode & EN_DISCONNECT_)) pDCB->SyncMode &= ~EN_ATN_STOP; - + }; + + //if (! (pDCB->DevMode & EN_DISCONNECT_)) pDCB->SyncMode &= ~EN_ATN_STOP; + pDCB->CtrlR1 = pACB->pScsiHost->this_id; if( pDCB->DevMode & PARITY_CHK_ ) - pDCB->CtrlR1 |= PARITY_ERR_REPO; + pDCB->CtrlR1 |= PARITY_ERR_REPO; }; @@ -1680,12 +1831,12 @@ void dc390_linkSRB( PACB pACB ) { - ULONG count, i; + UINT count, i; count = pACB->SRBCount; - for( i=0; i< count; i++) + for( i=0; iSRB_array[i].pNextSRB = &pACB->SRB_array[i+1]; else pACB->SRB_array[i].pNextSRB = NULL; @@ -1715,7 +1866,9 @@ psh->io_port = io_port; psh->n_io_port = 0x80; psh->irq = Irq; - + psh->base = (char*)io_port; + psh->dma_channel = -1; + pACB = (PACB) psh->hostdata; DC390_LOCKA_INIT; DC390_LOCK_ACB; @@ -1740,6 +1893,8 @@ pACB->pActiveDCB = NULL; pACB->pFreeSRB = pACB->SRB_array; pACB->SRBCount = MAX_SRB_CNT; + pACB->QueryCnt = 0; + pACB->pQueryHead = NULL; pACB->AdapterIndex = index; pACB->status = 0; psh->this_id = dc390_eepromBuf[index][EE_ADAPT_SCSI_ID]; @@ -1758,7 +1913,8 @@ pACB->DCBmap[i] = 0; pACB->sel_timeout = SEL_TIMEOUT; pACB->glitch_cfg = EATER_25NS; - pACB->Cmds = pACB->CmdInQ = pACB->CmdOutOfSRB = pACB->SelLost = 0; + pACB->Cmds = pACB->CmdInQ = pACB->CmdOutOfSRB = 0; + pACB->SelLost = pACB->SelConn = 0; } @@ -1776,22 +1932,11 @@ int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index) { PACB pACB, pACB2; - UCHAR used_irq = 0, dstate; + UCHAR 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; - } - if (check_region (io_port, psh->n_io_port)) { printk(KERN_ERR "DC390: register IO ports error!\n"); @@ -1802,14 +1947,12 @@ DC390_read8_ (INT_Status, io_port); /* Reset Pending INT */ - if( !used_irq ) - { - if( (i = request_irq(Irq, do_DC390_Interrupt, DC390_IRQ, "tmscsim", NULL) )) - { - printk(KERN_ERR "DC390: register IRQ error!\n"); - return( -1 ); - } - } + if( (i = request_irq(Irq, do_DC390_Interrupt, DC390_IRQ, "tmscsim", pACB) )) + { + printk(KERN_ERR "DC390: register IRQ error!\n"); + release_region (io_port, psh->n_io_port); + return( -1 ); + } if( !dc390_pACB_start ) { @@ -1831,8 +1974,9 @@ if (pACB->Gmode2 & RST_SCSI_BUS) { dc390_ResetSCSIBus( pACB ); + pACB->pScsiHost->last_reset = jiffies; /* Unlock before ? */ - for( i=0; i<600; i++ ) + for( i=0; i<(500 + 1000*dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]); i++ ) udelay(1000); }; pACB->ACBFlag = 0; @@ -1845,6 +1989,7 @@ DC390_write8 (CtrlReg3, FAST_CLK); /* fast clock */ DC390_write8 (CtrlReg4, pACB->glitch_cfg | /* glitch eater */ (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ? NEGATE_REQACKDATA : 0); /* Negation */ + DC390_write8 (CtcReg_High, 0); /* Clear Transfer Count High: ID */ DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); @@ -1890,9 +2035,9 @@ dc390_checkparams (); period = dc390_clock_period1[tmscsim[1]]; printk (KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz)," - " DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i)\n", tmscsim[0], tmscsim[1], - 40 / period, ((40%period)*10 + period/2) / period, - (UCHAR)tmscsim[2], (UCHAR)tmscsim[3], tmscsim[4], 2 << (tmscsim[4])); + " DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n", + tmscsim[0], tmscsim[1], 40 / period, ((40%period)*10 + period/2) / period, + (UCHAR)tmscsim[2], (UCHAR)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]); dc390_EEpromDefaults (index); #endif }; @@ -2024,8 +2169,11 @@ printk (KERN_ERR "DC390: No PCI BIOS found!\n"); if (dc390_adapterCnt) +#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30) + psht->proc_name = "tmscsim"; +#else psht->proc_dir = &DC390_proc_scsi_tmscsim; - +#endif printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt); DC390_UNLOCK_DRV; return( dc390_adapterCnt ); @@ -2047,7 +2195,7 @@ if (cmd->result) { PACB pACB = (PACB)cmd->host->hostdata; - PDCB pDCB = dc390_findDCB (pACB, cmd); + PDCB pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun); printk ("DC390: Unsetting DsCn, Sync and TagQ!\n"); if (pDCB) { @@ -2055,7 +2203,6 @@ dc390_updateDCB (pACB, pDCB); }; }; - kfree (cmd->buffer); kfree (cmd); }; @@ -2063,11 +2210,11 @@ { char* buffer; Scsi_Cmnd* cmd; - buffer = kmalloc (256, GFP_ATOMIC); - cmd = kmalloc (sizeof (Scsi_Cmnd), GFP_ATOMIC); + cmd = kmalloc (sizeof(Scsi_Cmnd) + 256, GFP_ATOMIC); + if (!cmd) { printk ("DC390: kmalloc failed in inquiry!\n"); return; }; + buffer = (char*)cmd + sizeof(Scsi_Cmnd); - memset (buffer, 0, 256); - memset (cmd, 0, sizeof(Scsi_Cmnd)); + memset (cmd, 0, sizeof(Scsi_Cmnd) + 256); cmd->cmnd[0] = INQUIRY; cmd->cmnd[1] = (pDCB->UnitSCSILUN << 5) & 0xe0; cmd->cmnd[4] = 0xff; @@ -2087,6 +2234,7 @@ cmd->request.rq_status = RQ_SCSI_BUSY; + pDCB->SyncMode &= ~SYNC_NEGO_DONE; printk (KERN_INFO "DC390: Queue INQUIRY command to dev ID %02x LUN %02x\n", pDCB->UnitSCSIID, pDCB->UnitSCSILUN); DC390_queue_command (cmd, dc390_inquiry_done); @@ -2209,6 +2357,7 @@ if (!memcmp (pos, "RESET", 5)) goto reset; else if (!memcmp (pos, "INQUIRY", 7)) goto inquiry; else if (!memcmp (pos, "REMOVE", 6)) goto remove; + else if (!memcmp (pos, "ADD", 3)) goto add; if (isdigit (*pos)) { @@ -2232,6 +2381,13 @@ goto einv2; }; + if (pDCB->pWaitingSRB || pDCB->pGoingSRB) + { + printk ("DC390: Cannot change dev (%i-%i) cfg: Pending requests\n", + pDCB->UnitSCSIID, pDCB->UnitSCSILUN); + goto einv; + }; + olddevmode = pDCB->DevMode; YESNO (pos, pDCB->DevMode, PARITY_CHK_); needs_inquiry++; @@ -2244,8 +2400,7 @@ needs_inquiry++; YESNO (pos, pDCB->DevMode, TAG_QUEUEING_); if ((olddevmode & TAG_QUEUEING_) == (pDCB->DevMode & TAG_QUEUEING_)) needs_inquiry--; - YESNO (pos, pDCB->SyncMode, EN_ATN_STOP); - + dc390_updateDCB (pACB, pDCB); if (!pos) goto ok; @@ -2265,7 +2420,7 @@ else pos = strtok (0, " \t\n:=,;."); if (!pos) goto ok; - /* Speed: NegoPeriod */ + /* Sync Speed in MHz */ if (*pos != '-') { SCANF (pos, p0, dum, 1, 13); @@ -2280,11 +2435,11 @@ for (; p0-pos > 1; p0--) dum /= 10; pDCB->NegoPeriod = (100000/(100*dumold + dum)) >> 2; if (pDCB->NegoPeriod < 19) pDCB->NegoPeriod = 19; - if (pDCB->NegoPeriod != olddevmode) needs_inquiry++; pos = strtok (0, " \t\n:=,;"); if (!pos) goto ok; }; if (*pos == 'M') pos = strtok (0, " \t\n:=,;"); + if (pDCB->NegoPeriod != olddevmode) needs_inquiry++; } else pos = strtok (0, " \t\n:=,;"); /* dc390_updateDCB (pACB, pDCB); */ @@ -2299,7 +2454,20 @@ if (pDCB->SyncOffset > olddevmode) needs_inquiry++; } else pos = strtok (0, " \t\n:=,;"); + if (!pos) goto ok; dc390_updateDCB (pACB, pDCB); + + //olddevmode = pDCB->MaxCommand; + /* MaxCommand (Tags) */ + if (*pos != '-') + { + SCANF (pos, p0, dum, 1, 32 /*pACB->TagMaxNum*/); + if (pDCB->SyncMode & EN_TAG_QUEUEING) + pDCB->MaxCommand = dum; + else printk (KERN_INFO "DC390: Can't set MaxCmd larger than one without Tag Queueing!\n"); + } + else pos = strtok (0, " \t\n:=,;"); + } else { @@ -2309,18 +2477,19 @@ /* Adapter setting */ SEARCH (pos, p0, pACB->pScsiHost->max_id, "MAXID", 8); SEARCH (pos, p0, pACB->pScsiHost->max_lun, "MAXLUN", 8); - SEARCH (pos, p0, pACB->pScsiHost->this_id, "ADAPTERID", 7); + SEARCH (pos, p0, pACB->pScsiHost->this_id, "ADAPTERID", 7); SEARCH (pos, p0, pACB->TagMaxNum, "TAGMAXNUM", 32); SEARCH (pos, p0, pACB->ACBFlag, "ACBFLAG", 255); SEARCH3 (pos, p0, dum, "GLITCHEATER", 40, 1000, "NS"); SEARCH3 (pos, p0, pACB->sel_timeout, "SELTIMEOUT", 400, 163, "MS"); + SEARCH3 (pos, p0, dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY], "DELAYRESET", 180, 100, "S"); ok2: pACB->glitch_cfg = NS_TO_GLITCH (dum); if (pACB->sel_timeout < 60) pACB->sel_timeout = 60; - dum = 0; while (1 << dum <= pACB->TagMaxNum) dum ++; - pACB->TagMaxNum &= (1 << --dum); - if (pos == p1) goto einv; + //dum = 0; while (1 << dum <= pACB->TagMaxNum) dum ++; + //pACB->TagMaxNum &= (1 << --dum); dc390_updateDCBs (pACB); + if (pos == p1) goto einv; } if (pos) goto next; @@ -2373,12 +2542,28 @@ for (dum = 0; dum < dev; dum++) pDCB = pDCB->pNextDCB; printk (KERN_NOTICE " DC390: Remove DCB for Dev(Idx) %i SCSI ID %i LUN %i\n", dev, pDCB->UnitSCSIID, pDCB->UnitSCSILUN); + /* TO DO: We should make sure no pending commands are left */ dc390_remove_dev (pACB, pDCB); DC390_UNLOCK_ACB; DC390_UNLOCK_IO; }; return (length); + add: + { + int id, lun; + pos = strtok (0, " \t\n.:;="); + if (pos) { SCANF (pos, p0, id, 0, 7); } else goto einv; + if (pos) { SCANF (pos, p0, lun, 0, 7); } else goto einv; + pDCB = dc390_findDCB (pACB, id, lun); + if (pDCB) { printk ("DC390: ADD: Device already existing\n"); goto einv; }; + dc390_initDCB (pACB, &pDCB, id, lun); + DC390_UNLOCK_ACB; + dc390_inquiry (pACB, pDCB); + DC390_UNLOCK_IO; + }; + return (length); + einv_dev: printk (KERN_WARNING "DC390: Ignore cmnd to illegal Dev(Idx) %i. Valid range: 0 - %i.\n", dev, pACB->DCBCnt - 1); @@ -2453,22 +2638,27 @@ SPRINTF("SCSI Host Nr %i, ", shpnt->host_no); SPRINTF("%s Adapter Nr %i\n", dc390_adapname, pACB->AdapterIndex); SPRINTF("IOPortBase 0x%04x, ", pACB->IOPortBase); - SPRINTF("IRQLevel 0x%02x\n", pACB->IRQLevel); + SPRINTF("IRQ %02i\n", pACB->IRQLevel); SPRINTF("MaxID %i, MaxLUN %i, ", shpnt->max_id, shpnt->max_lun); - SPRINTF("AdapterID %i, SelTimeout %i ms\n", - shpnt->this_id, (pACB->sel_timeout*164)/100); + SPRINTF("AdapterID %i, SelTimeout %i ms, DelayReset %i s\n", + shpnt->this_id, (pACB->sel_timeout*164)/100, + dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY]); - SPRINTF("TagMaxNum %i, Status %i, ACBFlag %i, GlitchEater %i ns\n", + SPRINTF("TagMaxNum %i, Status 0x%02x, ACBFlag 0x%02x, GlitchEater %i ns\n", pACB->TagMaxNum, pACB->status, pACB->ACBFlag, GLITCH_TO_NS(pACB->glitch_cfg)*12); - SPRINTF("Statistics: Cmnds %li, Cmnds not sent directly %li, Out of SRB conds %li\n", + SPRINTF("Statistics: Cmnds %li, Cmnds not sent directly %i, Out of SRB conds %i\n", pACB->Cmds, pACB->CmdInQ, pACB->CmdOutOfSRB); - SPRINTF(" Lost arbitrations %li\n", pACB->SelLost); + SPRINTF(" Lost arbitrations %i, Sel. connected %i, Connected: %s\n", + pACB->SelLost, pACB->SelConn, pACB->Connected? "Yes": "No"); SPRINTF("Nr of attached devices: %i, Nr of DCBs: %i\n", pACB->DeviceCnt, pACB->DCBCnt); + SPRINTF("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n", + pACB->DCBmap[0], pACB->DCBmap[1], pACB->DCBmap[2], pACB->DCBmap[3], + pACB->DCBmap[4], pACB->DCBmap[5], pACB->DCBmap[6], pACB->DCBmap[7]); - SPRINTF("Idx ID LUN Prty Sync DsCn SndS TagQ STOP NegoPeriod SyncSpeed SyncOffs\n"); + SPRINTF("Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs MaxCmd\n"); pDCB = pACB->pLinkDCB; for (dev = 0; dev < pACB->DCBCnt; dev++) @@ -2477,20 +2667,19 @@ YESNO(pDCB->DevMode & PARITY_CHK_); YESNO(pDCB->SyncMode & SYNC_NEGO_DONE); YESNO(pDCB->DevMode & EN_DISCONNECT_); - //YESNO(pDCB->SyncMode & EN_ATN_STOP); YESNO(pDCB->DevMode & SEND_START_); YESNO(pDCB->SyncMode & EN_TAG_QUEUEING); - YESNO(pDCB->SyncMode & EN_ATN_STOP); if (pDCB->SyncOffset & 0x0f) { int sp = pDCB->SyncPeriod; if (! (pDCB->CtrlR3 & FAST_SCSI)) sp++; SPRINTF(" %03i ns ", (pDCB->NegoPeriod) << 2); spd = 40/(sp); spd1 = 40%(sp); spd1 = (spd1 * 10 + sp/2) / (sp); - SPRINTF(" %2i.%1i M %02i\n", spd, spd1, (pDCB->SyncOffset & 0x0f)); + SPRINTF(" %2i.%1i M %02i", spd, spd1, (pDCB->SyncOffset & 0x0f)); } - else SPRINTF(" (%03i ns)\n", (pDCB->NegoPeriod) << 2); + else SPRINTF(" (%03i ns) ", (pDCB->NegoPeriod) << 2); /* Add more info ...*/ + SPRINTF (" %02i\n", pDCB->MaxCommand); pDCB = pDCB->pNextDCB; } @@ -2527,7 +2716,7 @@ printk(KERN_INFO "DC390: shutdown\n"); - pACB->ACBFlag = RESET_DONE; + pACB->ACBFlag = RESET_DEV; bval = DC390_read8 (CtrlReg1); bval |= DIS_INT_ON_SCSI_RST; DC390_write8 (CtrlReg1, bval); /* disable interrupt */ @@ -2547,41 +2736,30 @@ do { nDCB = pDCB->pNextDCB; - DCBDEBUG(printk (KERN_INFO "DC390: Free DCB (ID %i, LUN %i): 0x%08x\n",\ - pDCB->UnitSCSIID, pDCB->UnitSCSILUN, (int)pDCB);) - kfree (pDCB); + DCBDEBUG(printk (KERN_INFO "DC390: Free DCB (ID %i, LUN %i): %p\n",\ + pDCB->UnitSCSIID, pDCB->UnitSCSILUN, pDCB);) + //kfree (pDCB); + dc390_remove_dev (pACB, pDCB); pDCB = nDCB; - } while (pDCB && pDCB != pACB->pLinkDCB); + } while (pDCB && pDCB != pACB->pLinkDCB && pACB->pLinkDCB); }; int DC390_release(struct Scsi_Host *host) { - int irq_count; - PACB pACB; DC390_AFLAGS DC390_IFLAGS -#if USE_SPINLOCKS > 1 PACB pACB = (PACB)(host->hostdata); -#endif DC390_LOCK_IO; DC390_LOCK_ACB; + /* TO DO: We should check for outstanding commands first. */ dc390_shutdown (host); if (host->irq != IRQ_NONE) { - for (irq_count = 0, pACB = dc390_pACB_start; - pACB; pACB = pACB->pNextACB) - { - if ( pACB->IRQLevel == host->irq ) - ++irq_count; - } - if (irq_count == 1) - { - DEBUG0(printk(KERN_INFO "DC390: Free IRQ %i\n",host->irq);) - free_irq(host->irq,NULL); - } + DEBUG0(printk(KERN_INFO "DC390: Free IRQ %i\n",host->irq);) + free_irq (host->irq, pACB); } release_region(host->io_port,host->n_io_port); Index: tmscsim.h =================================================================== RCS file: /home/cvsroot/dc390/tmscsim.h,v retrieving revision 2.4 retrieving revision 2.15 diff -u -r2.4 -r2.15 --- tmscsim.h 1998/12/25 17:33:27 2.4 +++ tmscsim.h 1999/08/26 19:48:57 2.15 @@ -3,33 +3,37 @@ ;* TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter * ;* Device Driver * ;***********************************************************************/ -/* $Id: tmscsim.h,v 2.4 1998/12/25 17:33:27 garloff Exp $ */ +/* $Id: tmscsim.h,v 2.15 1999/08/26 19:48:57 garloff Exp $ */ #ifndef _TMSCSIM_H #define _TMSCSIM_H +#include + #define IRQ_NONE 255 #define MAX_ADAPTER_NUM 4 -#define MAX_SG_LIST_BUF 16 -#define MAX_CMD_PER_LUN 8 -#define MAX_CMD_QUEUE 2*MAX_CMD_PER_LUN+1 +#define MAX_SG_LIST_BUF 16 /* Not used */ +#define MAX_CMD_PER_LUN 32 +#define MAX_CMD_QUEUE MAX_CMD_PER_LUN+MAX_CMD_PER_LUN/2+1 #define MAX_SCSI_ID 8 #define MAX_SRB_CNT MAX_CMD_QUEUE+1 /* Max number of started commands */ -#define END_SCAN 2 #define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */ + +#define END_SCAN 2 -typedef unsigned char UCHAR; -typedef unsigned short USHORT; -typedef unsigned long ULONG; -typedef unsigned int UINT; +typedef u8 UCHAR; /* 8 bits */ +typedef u16 USHORT; /* 16 bits */ +typedef u32 UINT; /* 32 bits */ +typedef unsigned long ULONG; /* 32/64 bits */ typedef UCHAR *PUCHAR; typedef USHORT *PUSHORT; +typedef UINT *PUINT; typedef ULONG *PULONG; -typedef Scsi_Host_Template *PSHT; -typedef struct Scsi_Host *PSH; +typedef Scsi_Host_Template *PSHT; +typedef struct Scsi_Host *PSH; typedef Scsi_Device *PSCSIDEV; typedef Scsi_Cmnd *PSCSICMD; typedef void *PVOID; @@ -72,48 +76,49 @@ */ struct _SRB { -UCHAR CmdBlock[12]; +//UCHAR CmdBlock[12]; struct _SRB *pNextSRB; struct _DCB *pSRBDCB; PSCSICMD pcmd; PSGL pSegmentList; -ULONG Segment0[2]; -ULONG Segment1[2]; +/* 0x10: */ +SGL Segmentx; /* make a one entry of S/G list table */ -/* 0x2c:*/ -ULONG TotalXferredLen; +/* 0x1c: */ ULONG SGBusAddr; /*;a segment starting address as seen by AM53C974A*/ ULONG SGToBeXferLen; /*; to be xfer length */ -ULONG SRBState; - -/* 0x3c: */ -UCHAR MsgInBuf[6]; -UCHAR MsgOutBuf[6]; - -/* 0x48: */ -SGL Segmentx; /* make a one entry of S/G list table */ - -UCHAR ScsiCmdLen; -UCHAR ScsiPhase; +ULONG TotalXferredLen; +ULONG SavedTotXLen; +UINT SRBState; +/* 0x30: */ +UCHAR SRBStatus; +UCHAR SRBFlag; /*; b0-AutoReqSense,b6-Read,b7-write */ + /*; b4-settimeout,b5-Residual valid */ UCHAR AdaptStatus; UCHAR TargetStatus; -/* 0x58: */ +UCHAR ScsiPhase; +UCHAR TagNumber; +UCHAR SGIndex; +UCHAR SGcount; + +/* 0x38: */ UCHAR MsgCnt; UCHAR EndMessage; UCHAR RetryCnt; -UCHAR SRBFlag; /*; b0-AutoReqSense,b6-Read,b7-write */ - /*; b4-settimeout,b5-Residual valid */ -UCHAR TagNumber; -UCHAR SGcount; -UCHAR SGIndex; -UCHAR SRBStatus; - //UCHAR IORBFlag; /*;81h-Reset, 2-retry */ +UCHAR SavedSGCount; + +ULONG Saved_Ptr; -/* 0x60: */ +/* 0x40: */ +UCHAR MsgInBuf[6]; +UCHAR MsgOutBuf[6]; + +//UCHAR IORBFlag; /*;81h-Reset, 2-retry */ +/* 0x4c: */ }; @@ -129,48 +134,47 @@ struct _DCB *pNextDCB; struct _ACB *pDCBACB; -PSCSICMD pQIORBhead; -PSCSICMD pQIORBtail; -PSCSICMD AboIORBhead; -PSCSICMD AboIORBtail; -ULONG QIORBCnt; -ULONG AboIORBcnt; +/* Aborted Commands */ +//PSCSICMD AboIORBhead; +//PSCSICMD AboIORBtail; +//ULONG AboIORBcnt; -/* 0x20: */ +/* 0x08: */ +/* Queued SRBs */ PSRB pWaitingSRB; PSRB pWaitLast; PSRB pGoingSRB; PSRB pGoingLast; PSRB pActiveSRB; +UCHAR WaitSRBCnt; /* Not used */ UCHAR GoingSRBCnt; -UCHAR WaitSRBCnt; /* ??? */ + UCHAR DevType; UCHAR MaxCommand; -/* 0x38: */ -ULONG TagMask; +/* 0x20: */ +UINT TagMask; UCHAR UnitSCSIID; /*; SCSI Target ID (SCSI Only) */ UCHAR UnitSCSILUN; /*; SCSI Log. Unit (SCSI Only) */ UCHAR DevMode; -UCHAR IdentifyMsg; +UCHAR DCBFlag; UCHAR CtrlR1; UCHAR CtrlR3; UCHAR CtrlR4; - -UCHAR DCBFlag; +UCHAR pad; -/* 0x44: */ +/* 0x2c: */ UCHAR SyncMode; /*; 0:async mode */ UCHAR NegoPeriod; /*;for nego. */ UCHAR SyncPeriod; /*;for reg. */ UCHAR SyncOffset; /*;for reg. and nego.(low nibble) */ -/* 0x48:*/ +/* 0x30:*/ //UCHAR InqDataBuf[8]; //UCHAR CapacityBuf[8]; -/* 0x58: */ +///* 0x40: */ }; typedef struct _DCB DC390_DCB, *PDCB; @@ -201,15 +205,23 @@ PDCB pLinkDCB; PDCB pLastDCB; PDCB pDCBRunRobin; + PDCB pActiveDCB; PSRB pFreeSRB; PSRB pTmpSRB; /* 0x2c: */ +ULONG QueryCnt; +PSCSICMD pQueryHead; +PSCSICMD pQueryTail; +/* 0x38: */ UCHAR msgin123[4]; UCHAR DCBmap[MAX_SCSI_ID]; +UCHAR Connected; +UCHAR pad; +/* 0x3c: */ #if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(__SMP__) || DEBUG_SPINLOCKS > 0) spinlock_t lock; #endif @@ -220,18 +232,19 @@ UCHAR Ignore_IRQ; /* Not used */ PDEVDECL1; /* Pointer to PCI cfg. space */ -/* 0x40/0x3c: */ +/* 0x4c/0x48: */ ULONG Cmds; -ULONG CmdInQ; -ULONG CmdOutOfSRB; -ULONG SelLost; +UINT SelLost; +UINT SelConn; +UINT CmdInQ; +UINT CmdOutOfSRB; -/* 0x50/0x4c: */ +/* 0x60/0x5c: */ DC390_SRB TmpSRB; -/* 0xb4/0xb0: */ -DC390_SRB SRB_array[MAX_SRB_CNT]; /* 18 SRBs */ -/* 0x7bc/0x7b8: */ +/* 0xc4/0xc0: */ +DC390_SRB SRB_array[MAX_SRB_CNT]; /* 50 SRBs */ +/* 0xf9c/0xf98: */ }; typedef struct _ACB DC390_ACB, *PACB; @@ -339,21 +352,29 @@ #define H_BAD_CCB_OR_SG 0x1A #define H_ABORT 0x0FF -/*; SCSI Status byte codes*/ /* Twice the values defined in scsi/scsi.h */ -#define SCSI_STAT_GOOD 0x0 /*; Good status */ -#define SCSI_STAT_CHECKCOND 0x02 /*; SCSI Check Condition */ -#define SCSI_STAT_CONDMET 0x04 /*; Condition Met */ -#define SCSI_STAT_BUSY 0x08 /*; Target busy status */ -#define SCSI_STAT_INTER 0x10 /*; Intermediate status */ -#define SCSI_STAT_INTERCONDMET 0x14 /*; Intermediate condition met */ -#define SCSI_STAT_RESCONFLICT 0x18 /*; Reservation conflict */ -#define SCSI_STAT_CMDTERM 0x22 /*; Command Terminated */ -#define SCSI_STAT_QUEUEFULL 0x28 /*; Queue Full */ +/*; SCSI Status byte codes*/ +/* The values defined in include/scsi/scsi.h, to be shifted << 1 */ #define SCSI_STAT_UNEXP_BUS_F 0xFD /*; Unexpect Bus Free */ #define SCSI_STAT_BUS_RST_DETECT 0xFE /*; Scsi Bus Reset detected */ #define SCSI_STAT_SEL_TIMEOUT 0xFF /*; Selection Time out */ +/* cmd->result */ +#define RES_TARGET 0x000000FF /* Target State */ +#define RES_TARGET_LNX STATUS_MASK /* Only official ... */ +#define RES_ENDMSG 0x0000FF00 /* End Message */ +#define RES_DID 0x00FF0000 /* DID_ codes */ +#define RES_DRV 0xFF000000 /* DRIVER_ codes */ + +#define MK_RES(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt)) +#define MK_RES_LNX(drv,did,msg,tgt) ((int)(drv)<<24 | (int)(did)<<16 | (int)(msg)<<8 | (int)(tgt)<<1) + +#define SET_RES_TARGET(who,tgt) { who &= ~RES_TARGET; who |= (int)(tgt); } +#define SET_RES_TARGET_LNX(who,tgt) { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } +#define SET_RES_MSG(who,msg) { who &= ~RES_ENDMSG; who |= (int)(msg) << 8; } +#define SET_RES_DID(who,did) { who &= ~RES_DID; who |= (int)(did) << 16; } +#define SET_RES_DRV(who,drv) { who &= ~RES_DRV; who |= (int)(drv) << 24; } + /*;---Sync_Mode */ #define SYNC_DISABLE 0 #define SYNC_ENABLE BIT0 @@ -374,32 +395,9 @@ #define SCSI_NOP1 5 #define SCSI_MSG_OUT 6 #define SCSI_MSG_IN 7 - -/*;----SCSI MSG BYTE*/ /* see scsi/scsi.h */ -#define MSG_COMPLETE 0x00 -#define MSG_EXTENDED 0x01 -#define MSG_SAVE_PTR 0x02 -#define MSG_RESTORE_PTR 0x03 -#define MSG_DISCONNECT 0x04 -#define MSG_INITIATOR_ERROR 0x05 -#define MSG_ABORT 0x06 -#define MSG_REJECT_ 0x07 -#define MSG_NOP 0x08 -#define MSG_PARITY_ERROR 0x09 -#define MSG_LINK_CMD_COMPL 0x0A -#define MSG_LINK_CMD_COMPL_FLG 0x0B -#define MSG_BUS_RESET 0x0C -#define MSG_ABORT_TAG 0x0D -#define MSG_SIMPLE_QTAG 0x20 -#define MSG_HEAD_QTAG 0x21 -#define MSG_ORDER_QTAG 0x22 -#define MSG_IDENTIFY 0x80 -#define MSG_HOST_ID 0x0C0 -/* cmd->result */ -#define STATUS_MASK_ 0xFF -#define MSG_MASK 0xFF00 -#define RETURN_MASK 0xFF0000 +/*;----SCSI MSG BYTE*/ /* see scsi/scsi.h */ /* One is missing ! */ +#define ABORT_TAG 0x0d /* ** Inquiry Data format