Index: dc390/README.tmscsim =================================================================== RCS file: /usr/local/cvsroot/dc390/README.tmscsim,v retrieving revision 2.9 retrieving revision 2.18 diff -u -r2.9 -r2.18 --- dc390/README.tmscsim 1998/12/25 18:04:20 2.9 +++ dc390/README.tmscsim 1999/06/01 22:39:13 2.18 @@ -9,6 +9,7 @@ 6. Potential improvements 7. Bug reports, debugging and updates 8. Acknowledgements +9. Copyright 1. Purpose and history @@ -140,19 +141,19 @@ 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 +Tekram DC390/AM53C974 PCI SCSI Host Adapter, Driver Version 2.0d2, 1999/02/20 SCSI Host Nr 0, AM53C974 Adapter Nr 0 IOPortBase 0x6200, IRQLevel 0x09 -MaxID 7, MaxLUN 8, AdapterID 7, SelTimeout 250 ms +MaxID 7, MaxLUN 8, AdapterID 7, SelTimeout 250 ms, DelayReset 1 s 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 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) +Idx ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs +00 00 00 Yes Yes Yes Yes Yes 100 ns 10.0 M 15 +01 01 00 Yes Yes Yes Yes Yes 100 ns 10.0 M 15 +02 03 00 Yes Yes Yes Yes No 100 ns 10.0 M 15 +03 05 00 Yes No Yes Yes No (200 ns) 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 +179,6 @@ 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. 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 +194,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 +205,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 +222,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 +270,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 +316,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,6 +338,7 @@ 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 @@ -409,10 +414,21 @@ 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). +Lately, 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 1999/06/02, driver revision 2.0d6 +$Id: README.tmscsim,v 2.18 1999/06/01 22:39:13 garloff Exp $ Index: dc390/dc390-120-kernel.diff =================================================================== RCS file: /usr/local/cvsroot/dc390/dc390-120-kernel.diff,v retrieving revision 2.3 retrieving revision 2.5 diff -u -r2.3 -r2.5 --- dc390/dc390-120-kernel.diff 1998/12/25 18:04:20 2.3 +++ dc390/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/dc390.h =================================================================== RCS file: /usr/local/cvsroot/dc390/dc390.h,v retrieving revision 2.12 retrieving revision 2.24 diff -u -r2.12 -r2.24 --- dc390/dc390.h 1998/12/25 17:33:27 2.12 +++ dc390/dc390.h 1999/06/03 21:34:31 2.24 @@ -4,7 +4,7 @@ * 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.24 1999/06/03 21:34:31 garloff Exp $ */ #include @@ -16,11 +16,9 @@ #define DC390_H #define DC390_BANNER "Tekram DC390/AM53C974" -#define DC390_VERSION "2.0d 1998/12/25" +#define DC390_VERSION "2.0d8 1999/06/03" #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 *)); Index: dc390/scsiiom.c =================================================================== RCS file: /usr/local/cvsroot/dc390/scsiiom.c,v retrieving revision 2.15 retrieving revision 2.31 diff -u -r2.15 -r2.31 --- dc390/scsiiom.c 1998/12/25 17:33:27 2.15 +++ dc390/scsiiom.c 1999/06/04 09:07:05 2.31 @@ -4,15 +4,25 @@ * 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.31 1999/06/04 09:07:05 garloff Exp $ */ 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) + { + DEBUG0(printk (KERN_WARNING "DC390: Can't select when connected! (%08lx,%02x)\n", + pSRB->SRBState, pSRB->SRBFlag);) + pSRB->SRBState = SRB_READY; + pACB->SelLost++; + return 1; + } + DC390_write8 (Scsi_Dest_ID, pDCB->UnitSCSIID); DC390_write8 (Sync_Period, pDCB->SyncPeriod); DC390_write8 (Sync_Offset, pDCB->SyncOffset); @@ -21,151 +31,91 @@ 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; + /* Be conservative: Don't disconnect for REQ_SENSE, TEST_U_READY, INQ */ + /* Changed KG, 99/06/01 */ + 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->SyncMode & SYNC_NEGO_DONE) + && (pDCB->UnitSCSILUN == 0) && + ( (pSRB->pcmd->cmnd[0] == INQUIRY) || (pSRB->pcmd->cmnd[0] == REQUEST_SENSE) || + (pSRB->SRBFlag & AUTO_REQSENSE) ) ) + 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 */ + 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");) + //cmd = SEL_W_ATN_STOP; } 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 */ - if (DC390_read8 (Scsi_Status) & INTERRUPT) - { - pSRB->SRBState = SRB_READY; - pDCB->TagMask &= ~( 1 << pSRB->TagNumber ); - DEBUG0(printk (KERN_WARNING "DC390: Interrupt during StartSCSI!\n");) - 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; - } + 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, cmd); + pACB->Connected = 1; + return 0; } //#define DMA_INT EN_DMA_INT /*| EN_PAGE_INT*/ @@ -363,6 +313,12 @@ goto unlock; } + if(istatus & (SELECTED | SEL_ATTENTION)) + { + printk (KERN_ERR "DC390: Target mode not supported!\n"); + goto unlock; + } + unlock: DC390_LOCK_DRV_NI; DC390_UNLOCK_ACB; @@ -593,7 +549,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 +558,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 +596,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 +609,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 +633,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 +643,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 +687,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 +695,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 ?) */ @@ -751,7 +757,7 @@ static UCHAR __inline__ dc390_MsgIn_complete (UCHAR *msgbuf, ULONG len) { - if (*msgbuf == MSG_EXTENDED) + if (*msgbuf == EXTENDED_MESSAGE) { if (len < 2) return 0; if (len < msgbuf[1] + 2) return 0; @@ -781,23 +787,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 +816,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 +850,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 +863,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 +929,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,7 +939,7 @@ 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)); @@ -966,14 +977,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 +997,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,7 +1041,7 @@ UCHAR bval, i, cnt; PDCB ptr; - if( !(pDCB->IdentifyMsg & 0x07) ) + if( !(pDCB->UnitSCSILUN) ) { if( pACB->scan_devices ) { @@ -1068,21 +1079,23 @@ 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",\ + DEBUG0(printk(KERN_ERR "ACB:%08lx->ActiveDCB:%08lx IOPort:%04x IRQ:%02x !\n",\ (ULONG)pACB,(ULONG)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; @@ -1110,7 +1123,7 @@ 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); @@ -1150,10 +1163,11 @@ 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 ) ) { @@ -1163,10 +1177,15 @@ } 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 +1199,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 +1248,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; + if (pACB->pLastDCB) pACB->pLastDCB->pNextDCB = pDCB->pNextDCB; } else { @@ -1249,8 +1270,8 @@ 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);) + DCBDEBUG(printk (KERN_INFO "DC390: Driver about to free DCB (ID %i, LUN %i): %p\n",\ + pDCB->UnitSCSIID, pDCB->UnitSCSILUN, pDCB);) kfree (pDCB); if (pDCB == pACB->pActiveDCB) pACB->pActiveDCB = 0; pACB->DCBCnt--; /* pACB->DeviceCnt--; */ @@ -1327,7 +1348,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 +1369,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); goto ckc_e; } if(pSRB->RetryCnt == 0) { - (ULONG)(pSRB->CmdBlock[0]) = pSRB->Segment0[0]; - pSRB->TotalXferredLen = pSRB->Segment1[1]; + //(ULONG)(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 +1393,19 @@ pSRB->RetryCnt--; pSRB->AdaptStatus = 0; pSRB->TargetStatus = 0; - *((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; - *((PULONG) &(pSRB->CmdBlock[4])) = pSRB->Segment0[1]; + //*((PULONG) &(pSRB->CmdBlock[0])) = pSRB->Segment0[0]; + //*((PULONG) &(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); pSRB->SGIndex = 0; pSRB->TotalXferredLen = 0; pSRB->SGToBeXferLen = 0; @@ -1405,9 +1424,9 @@ } 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,7 +1444,7 @@ dc390_RequestSense( pACB, pDCB, pSRB ); return; } - else if( status == SCSI_STAT_QUEUEFULL ) + else if( status_byte(status) == QUEUE_FULL ) { bval = (UCHAR) pDCB->GoingSRBCnt; bval--; @@ -1439,17 +1458,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 */ @@ -1475,8 +1493,7 @@ } else { /* Report error */ - pcmd->result |= (DID_ERROR << 16) | (ULONG) (pSRB->EndMessage << 8) | - (ULONG) status; + pcmd->result = MK_RES(0, DID_ERROR, pSRB->EndMessage, status); } } } @@ -1486,24 +1503,25 @@ 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); } 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); @@ -1512,9 +1530,9 @@ 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); @@ -1534,8 +1552,8 @@ } } - 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) ) { ptr = (PSCSI_INQDATA) (pcmd->request_buffer); if( pcmd->use_sg ) @@ -1605,7 +1623,7 @@ { psrb2 = psrb->pNextSRB; pcmd = psrb->pcmd; - pcmd->result = DID_RESET << 16; + pcmd->result = MK_RES(0,DID_RESET,0,0); /* ReleaseSRB( pDCB, pSRB ); */ @@ -1628,8 +1646,6 @@ static void dc390_ResetSCSIBus( PACB pACB ) { - pACB->ACBFlag |= RESET_DEV; - DC390_write8 (ScsiCmd, RST_DEVICE_CMD); udelay (250); DC390_write8 (ScsiCmd, NOP_CMD); @@ -1637,6 +1653,7 @@ DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); DC390_write8 (DMA_Cmd, DMA_IDLE_CMD); DC390_write8 (ScsiCmd, RST_SCSI_BUS_CMD); + pACB->Connected = 0; return; } @@ -1648,10 +1665,12 @@ //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); } + { unsigned int msec = 500; while (--msec) udelay(1000); } DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD); + pACB->Connected = 0; if( pACB->ACBFlag & RESET_DEV ) pACB->ACBFlag |= RESET_DONE; @@ -1676,15 +1695,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] = (ULONG) pSRB->CmdBlock[0]; + //pSRB->Segment0[1] = (ULONG) pSRB->CmdBlock[4]; + //pSRB->Segment1[0] = ((ULONG)(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,11 +1715,11 @@ 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; Index: dc390/tmscsim.c =================================================================== RCS file: /usr/local/cvsroot/dc390/tmscsim.c,v retrieving revision 2.16 retrieving revision 2.38 diff -u -r2.16 -r2.38 --- dc390/tmscsim.c 1998/12/25 17:54:44 2.16 +++ dc390/tmscsim.c 1999/06/04 09:07:05 2.38 @@ -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.38 1999/06/04 09:07:05 garloff Exp $ */ /* Enhancements and bugfixes by * - * Kurt Garloff * + * Kurt Garloff * ***********************************************************************/ /* HISTORY: * * * @@ -95,8 +95,26 @@ * 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(). * ***********************************************************************/ /* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */ @@ -165,6 +183,7 @@ #include "constants.h" #include "sd.h" #include +#include #include "dc390.h" @@ -378,7 +397,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 @@ -407,11 +426,11 @@ # 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)"); +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 */ @@ -518,29 +537,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 +567,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 +575,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 +674,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 +690,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,21 +704,21 @@ * (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; }; @@ -764,7 +795,7 @@ PSRB psrb1; UCHAR bval; - pDCB->GoingSRBCnt--; pDCB->pDCBACB->SelLost++; + 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 ) @@ -926,8 +957,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 ) { @@ -1022,10 +1053,9 @@ 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); @@ -1045,7 +1075,7 @@ } else { - pDCB = dc390_findDCB (pACB, cmd); + pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun); if (!pDCB) { /* should never happen */ DC390_UNLOCK_ACB; @@ -1259,6 +1289,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", @@ -1297,7 +1333,7 @@ DC390_LOCK_ACB; - pDCB = dc390_findDCB (pACB, cmd); + pDCB = dc390_findDCB (pACB, cmd->target, cmd->lun); /* 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; @@ -1408,7 +1444,7 @@ /* 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); @@ -1459,6 +1495,8 @@ pDCB = pDCB->pNextDCB; } while( pdcb != pDCB ); + pACB->ACBFlag &= ~(RESET_DEV | RESET_DONE | RESET_DETECT); + } @@ -1524,9 +1562,11 @@ bval |= DIS_INT_ON_SCSI_RST; DC390_write8 (CtrlReg1, bval); /* disable interrupt */ + pACB->ACBFlag |= RESET_DEV; dc390_ResetSCSIBus( pACB ); + pACB->pScsiHost->last_reset = jiffies; /* 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); @@ -1555,22 +1595,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 +1624,13 @@ 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 +1640,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,8 +1684,6 @@ 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; @@ -1831,8 +1888,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 +1903,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 +1949,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 }; @@ -2047,7 +2106,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) { @@ -2064,7 +2123,9 @@ char* buffer; Scsi_Cmnd* cmd; buffer = kmalloc (256, GFP_ATOMIC); + if (!buffer) { printk ("DC390: kmalloc (buffer) failed!\n"); return; }; cmd = kmalloc (sizeof (Scsi_Cmnd), GFP_ATOMIC); + if (!cmd) { printk ("DC390: kmalloc (cmd) failed!\n"); kfree (buffer); return; }; memset (buffer, 0, 256); memset (cmd, 0, sizeof(Scsi_Cmnd)); @@ -2087,6 +2148,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 +2271,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)) { @@ -2244,8 +2307,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; @@ -2314,6 +2376,7 @@ 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; @@ -2379,6 +2442,21 @@ }; 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 +2531,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", pACB->Cmds, pACB->CmdInQ, pACB->CmdOutOfSRB); - SPRINTF(" Lost arbitrations %li\n", pACB->SelLost); + SPRINTF(" Lost arbitrations %li, Connected: %s\n", + pACB->SelLost, 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\n"); pDCB = pACB->pLinkDCB; for (dev = 0; dev < pACB->DCBCnt; dev++) @@ -2477,10 +2560,8 @@ 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++; @@ -2527,7 +2608,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,11 +2628,12 @@ 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); }; @@ -2567,6 +2649,7 @@ DC390_LOCK_IO; DC390_LOCK_ACB; + /* TO DO: We should check for outstanding commands first. */ dc390_shutdown (host); if (host->irq != IRQ_NONE) Index: dc390/tmscsim.h =================================================================== RCS file: /usr/local/cvsroot/dc390/tmscsim.h,v retrieving revision 2.4 retrieving revision 2.10 diff -u -r2.4 -r2.10 --- dc390/tmscsim.h 1998/12/25 17:33:27 2.4 +++ dc390/tmscsim.h 1999/06/03 21:34:31 2.10 @@ -3,7 +3,7 @@ ;* 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.10 1999/06/03 21:34:31 garloff Exp $ */ #ifndef _TMSCSIM_H #define _TMSCSIM_H @@ -11,15 +11,16 @@ #define IRQ_NONE 255 #define MAX_ADAPTER_NUM 4 -#define MAX_SG_LIST_BUF 16 -#define MAX_CMD_PER_LUN 8 +#define MAX_SG_LIST_BUF 16 /* Not used */ +#define MAX_CMD_PER_LUN 24 #define MAX_CMD_QUEUE 2*MAX_CMD_PER_LUN+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; @@ -72,48 +73,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:*/ +/* 0x1c: */ ULONG TotalXferredLen; +ULONG SavedTotXLen; 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; - +/* 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; + +/* 0x40: */ +UCHAR MsgInBuf[6]; +UCHAR MsgOutBuf[6]; -/* 0x60: */ +//UCHAR IORBFlag; /*;81h-Reset, 2-retry */ +/* 0x4c: */ }; @@ -153,13 +155,12 @@ 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: */ UCHAR SyncMode; /*; 0:async mode */ @@ -201,6 +202,7 @@ PDCB pLinkDCB; PDCB pLastDCB; PDCB pDCBRunRobin; + PDCB pActiveDCB; PSRB pFreeSRB; PSRB pTmpSRB; @@ -209,7 +211,10 @@ UCHAR msgin123[4]; UCHAR DCBmap[MAX_SCSI_ID]; +UCHAR Connected; +UCHAR pad; +/* 0x30: */ #if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(__SMP__) || DEBUG_SPINLOCKS > 0) spinlock_t lock; #endif @@ -339,21 +344,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 @@ -375,31 +388,8 @@ #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