* [PATCH 12/12] Replace tmscsim by am53c974
2014-11-21 12:41 [PATCHv2 " Hannes Reinecke
@ 2014-11-21 12:41 ` Hannes Reinecke
2014-11-23 13:22 ` Guennadi Liakhovetski
0 siblings, 1 reply; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-21 12:41 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo Bonzini, Guennadi Liakhovetski,
David S. Miller, linux-scsi, Hannes Reinecke
The am53c974 is a re-implementation of the tmscsim driver,
and provides the same functionality.
So remove the tmscsim driver and make am53c974 an alias to tmscsim.
Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
MAINTAINERS | 7 +-
drivers/scsi/Kconfig | 16 -
drivers/scsi/Makefile | 1 -
drivers/scsi/am53c974.c | 1 +
drivers/scsi/tmscsim.c | 2626 -----------------------------------------------
drivers/scsi/tmscsim.h | 549 ----------
6 files changed, 4 insertions(+), 3196 deletions(-)
delete mode 100644 drivers/scsi/tmscsim.c
delete mode 100644 drivers/scsi/tmscsim.h
diff --git a/MAINTAINERS b/MAINTAINERS
index d206f37..d780e46 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2862,11 +2862,10 @@ F: Documentation/networking/dmfe.txt
F: drivers/net/ethernet/dec/tulip/dmfe.c
DC390/AM53C974 SCSI driver
-M: Kurt Garloff <garloff@suse.de>
-W: http://www.garloff.de/kurt/linux/dc390/
-M: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+M: Hannes Reinecke <hare@suse.de>
+L: linux-scsi@vger.kernel.org
S: Maintained
-F: drivers/scsi/tmscsim.*
+F: drivers/scsi/am53c974.c
DC395x SCSI driver
M: Oliver Neukum <oliver@neukum.org>
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 519c3ef..f871a80 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1341,22 +1341,6 @@ config SCSI_DC395x
To compile this driver as a module, choose M here: the
module will be called dc395x.
-config SCSI_DC390T
- tristate "Tekram DC390(T) and Am53/79C974 SCSI support"
- depends on PCI && SCSI
- ---help---
- This driver supports PCI SCSI host adapters based on the Am53C974A
- chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
- PCscsi/PCnet (Am53/79C974) solutions.
-
- Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
-
- Note that this driver does NOT support Tekram DC390W/U/F, which are
- based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
-
- To compile this driver as a module, choose M here: the
- module will be called tmscsim.
-
config SCSI_AM53C974
tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
depends on PCI && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 79a6571..a9f3fa8 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -100,7 +100,6 @@ obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
obj-$(CONFIG_SCSI_EATA) += eata.o
obj-$(CONFIG_SCSI_DC395x) += dc395x.o
-obj-$(CONFIG_SCSI_DC390T) += tmscsim.o
obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o
obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
index 55622eb..5ce2bb2 100644
--- a/drivers/scsi/am53c974.c
+++ b/drivers/scsi/am53c974.c
@@ -572,6 +572,7 @@ MODULE_DESCRIPTION("AM53C974 SCSI driver");
MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_ALIAS("tmscsim");
module_param(am53c974_fenab, bool, 0444);
MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
deleted file mode 100644
index 844c9a0..0000000
--- a/drivers/scsi/tmscsim.c
+++ /dev/null
@@ -1,2626 +0,0 @@
-/************************************************************************
- * FILE NAME : TMSCSIM.C *
- * BY : C.L. Huang, ching@tekram.com.tw *
- * Description: Device Driver for Tekram DC-390(T) PCI SCSI *
- * Bus Master Host Adapter *
- * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. *
- ************************************************************************
- * (C) Copyright: put under GNU GPL in 10/96 *
- * (see Documentation/scsi/tmscsim.txt) *
- ************************************************************************
- * $Id: tmscsim.c,v 2.60.2.30 2000/12/20 01:07:12 garloff Exp $ *
- * Enhancements and bugfixes by *
- * Kurt Garloff <kurt@garloff.de> <garloff@suse.de> *
- ************************************************************************
- * HISTORY: *
- * *
- * REV# DATE NAME DESCRIPTION *
- * 1.00 96/04/24 CLH First release *
- * 1.01 96/06/12 CLH Fixed bug of Media Change for Removable *
- * Device, scan all LUN. Support Pre2.0.10 *
- * 1.02 96/06/18 CLH Fixed bug of Command timeout ... *
- * 1.03 96/09/25 KG Added tmscsim_proc_info() *
- * 1.04 96/10/11 CLH Updating for support KV 2.0.x *
- * 1.05 96/10/18 KG Fixed bug in DC390_abort(null ptr deref)*
- * 1.06 96/10/25 KG Fixed module support *
- * 1.07 96/11/09 KG Fixed tmscsim_proc_info() *
- * 1.08 96/11/18 KG Fixed null ptr in DC390_Disconnect() *
- * 1.09 96/11/30 KG Added register the allocated IO space *
- * 1.10 96/12/05 CLH Modified tmscsim_proc_info(), and reset *
- * pending interrupt in DC390_detect() *
- * 1.11 97/02/05 KG/CLH Fixeds problem with partitions greater *
- * than 1GB *
- * 1.12 98/02/15 MJ Rewritten PCI probing *
- * 1.13 98/04/08 KG Support for non DC390, __initfunc decls,*
- * changed max devs from 10 to 16 *
- * 1.14a 98/05/05 KG Dynamic DCB allocation, add-single-dev *
- * for LUNs if LUN_SCAN (BIOS) not set *
- * runtime config using /proc interface *
- * 1.14b 98/05/06 KG eliminated cli (); sti (); spinlocks *
- * 1.14c 98/05/07 KG 2.0.x compatibility *
- * 1.20a 98/05/07 KG changed names of funcs to be consistent *
- * DC390_ (entry points), dc390_ (internal)*
- * reworked locking *
- * 1.20b 98/05/12 KG bugs: version, kfree, _ctmp *
- * debug output *
- * 1.20c 98/05/12 KG bugs: kfree, parsing, EEpromDefaults *
- * 1.20d 98/05/14 KG bugs: list linkage, clear flag after *
- * reset on startup, code cleanup *
- * 1.20e 98/05/15 KG spinlock comments, name space cleanup *
- * pLastDCB now part of ACB structure *
- * added stats, timeout for 2.1, TagQ bug *
- * RESET and INQUIRY interface commands *
- * 1.20f 98/05/18 KG spinlocks fixes, max_lun fix, free DCBs *
- * for missing LUNs, pending int *
- * 1.20g 98/05/19 KG Clean up: Avoid short *
- * 1.20h 98/05/21 KG Remove AdaptSCSIID, max_lun ... *
- * 1.20i 98/05/21 KG Aiiie: Bug with TagQMask *
- * 1.20j 98/05/24 KG Handle STAT_BUSY, handle pACB->pLinkDCB *
- * == 0 in remove_dev and DoingSRB_Done *
- * 1.20k 98/05/25 KG DMA_INT (experimental) *
- * 1.20l 98/05/27 KG remove DMA_INT; DMA_IDLE cmds added; *
- * 1.20m 98/06/10 KG glitch configurable; made some global *
- * vars part of ACB; use DC390_readX *
- * 1.20n 98/06/11 KG startup params *
- * 1.20o 98/06/15 KG added TagMaxNum to boot/module params *
- * Device Nr -> Idx, TagMaxNum power of 2 *
- * 1.20p 98/06/17 KG Docu updates. Reset depends on settings *
- * pci_set_master added; 2.0.xx: pcibios_* *
- * used instead of MechNum things ... *
- * 1.20q 98/06/23 KG Changed defaults. Added debug code for *
- * removable media and fixed it. TagMaxNum *
- * fixed for DC390. Locking: ACB, DRV for *
- * better IRQ sharing. Spelling: Queueing *
- * Parsing and glitch_cfg changes. Display *
- * real SyncSpeed value. Made DisConn *
- * functional (!) *
- * 1.20r 98/06/30 KG Debug macros, allow disabling DsCn, set *
- * BIT4 in CtrlR4, EN_PAGE_INT, 2.0 module *
- * param -1 fixed. *
- * 1.20s 98/08/20 KG Debug info on abort(), try to check PCI,*
- * phys_to_bus instead of phys_to_virt, *
- * fixed sel. process, fixed locking, *
- * added MODULE_XXX infos, changed IRQ *
- * request flags, disable DMA_INT *
- * 1.20t 98/09/07 KG TagQ report fixed; Write Erase DMA Stat;*
- * initfunc -> __init; better abort; *
- * Timeout for XFER_DONE & BLAST_COMPLETE; *
- * Allow up to 33 commands being processed *
- * 2.0a 98/10/14 KG Max Cmnds back to 17. DMA_Stat clearing *
- * all flags. Clear within while() loops *
- * in DataIn_0/Out_0. Null ptr in dumpinfo *
- * for pSRB==0. Better locking during init.*
- * bios_param() now respects part. table. *
- * 2.0b 98/10/24 KG Docu fixes. Timeout Msg in DMA Blast. *
- * Disallow illegal idx in INQUIRY/REMOVE *
- * 2.0c 98/11/19 KG Cleaned up detect/init for SMP boxes, *
- * Write Erase DMA (1.20t) caused problems *
- * 2.0d 98/12/25 KG Christmas release ;-) Message handling *
- * 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 unique_id. Disable RETRY message. *
- * 2.0d2600/01/29 KG Go to new EH. *
- * 2.0d2700/01/31 KG ... but maintain 2.0 compat. *
- * and fix DCB freeing *
- * 2.0d2800/02/14 KG Queue statistics fixed, dump special cmd*
- * Waiting_Timer for failed StartSCSI *
- * New EH: Don't return cmnds to ML on RST *
- * Use old EH (don't have new EH fns yet) *
- * Reset: Unlock, but refuse to queue *
- * 2.3 __setup function *
- * 2.0e 00/05/22 KG Return residual for 2.3 *
- * 2.0e1 00/05/25 KG Compile fixes for 2.3.99 *
- * 2.0e2 00/05/27 KG Jeff Garzik's pci_enable_device() *
- * 2.0e3 00/09/29 KG Some 2.4 changes. Don't try Sync Nego *
- * before INQUIRY has reported ability. *
- * Recognise INQUIRY as scanning command. *
- * 2.0e4 00/10/13 KG Allow compilation into 2.4 kernel *
- * 2.0e5 00/11/17 KG Store Inq.flags in DCB *
- * 2.0e6 00/11/22 KG 2.4 init function (Thx to O.Schumann) *
- * 2.4 PCI device table (Thx to A.Richter) *
- * 2.0e7 00/11/28 KG Allow overriding of BIOS settings *
- * 2.0f 00/12/20 KG Handle failed INQUIRYs during scan *
- * 2.1a 03/11/29 GL, KG Initial fixing for 2.6. Convert to *
- * use the current PCI-mapping API, update *
- * command-queuing. *
- * 2.1b 04/04/13 GL Fix for 64-bit platforms *
- * 2.1b1 04/01/31 GL (applied 05.04) Remove internal *
- * command-queuing. *
- * 2.1b2 04/02/01 CH (applied 05.04) Fix error-handling *
- * 2.1c 04/05/23 GL Update to use the new pci_driver API, *
- * some scsi EH updates, more cleanup. *
- * 2.1d 04/05/27 GL Moved setting of scan_devices to *
- * slave_alloc/_configure/_destroy, as *
- * suggested by CH. *
- ***********************************************************************/
-
-/* DEBUG options */
-//#define DC390_DEBUG0
-//#define DC390_DEBUG1
-//#define DC390_DCBDEBUG
-//#define DC390_PARSEDEBUG
-//#define DC390_REMOVABLEDEBUG
-//#define DC390_LOCKDEBUG
-
-//#define NOP do{}while(0)
-#define C_NOP
-
-/* Debug definitions */
-#ifdef DC390_DEBUG0
-# define DEBUG0(x) x
-#else
-# define DEBUG0(x) C_NOP
-#endif
-#ifdef DC390_DEBUG1
-# define DEBUG1(x) x
-#else
-# define DEBUG1(x) C_NOP
-#endif
-#ifdef DC390_DCBDEBUG
-# define DCBDEBUG(x) x
-#else
-# define DCBDEBUG(x) C_NOP
-#endif
-#ifdef DC390_PARSEDEBUG
-# define PARSEDEBUG(x) x
-#else
-# define PARSEDEBUG(x) C_NOP
-#endif
-#ifdef DC390_REMOVABLEDEBUG
-# define REMOVABLEDEBUG(x) x
-#else
-# define REMOVABLEDEBUG(x) C_NOP
-#endif
-#define DCBDEBUG1(x) C_NOP
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsicam.h>
-#include <scsi/scsi_tcq.h>
-
-#define DC390_BANNER "Tekram DC390/AM53C974"
-#define DC390_VERSION "2.1d 2004-05-27"
-
-#define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI
-
-#include "tmscsim.h"
-
-
-static void dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-
-static void dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB );
-static void dc390_Disconnect( struct dc390_acb* pACB );
-static void dc390_Reselect( struct dc390_acb* pACB );
-static void dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB );
-static void dc390_ScsiRstDetect( struct dc390_acb* pACB );
-static void dc390_EnableMsgOut_Abort(struct dc390_acb*, struct dc390_srb*);
-static void dc390_dumpinfo(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB);
-static void dc390_ResetDevParam(struct dc390_acb* pACB);
-
-static u32 dc390_laststatus = 0;
-static u8 dc390_adapterCnt = 0;
-
-static int disable_clustering;
-module_param(disable_clustering, int, S_IRUGO);
-MODULE_PARM_DESC(disable_clustering, "If you experience problems with your devices, try setting to 1");
-
-/* Startup values, to be overriden on the commandline */
-static int tmscsim[] = {-2, -2, -2, -2, -2, -2};
-
-module_param_array(tmscsim, int, NULL, 0);
-MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)");
-MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
-MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
-
-static void *dc390_phase0[]={
- dc390_DataOut_0,
- dc390_DataIn_0,
- dc390_Command_0,
- dc390_Status_0,
- dc390_Nop_0,
- dc390_Nop_0,
- dc390_MsgOut_0,
- dc390_MsgIn_0,
- dc390_Nop_1
- };
-
-static void *dc390_phase1[]={
- dc390_DataOutPhase,
- dc390_DataInPhase,
- dc390_CommandPhase,
- dc390_StatusPhase,
- dc390_Nop_0,
- dc390_Nop_0,
- dc390_MsgOutPhase,
- dc390_MsgInPhase,
- dc390_Nop_1
- };
-
-#ifdef DC390_DEBUG1
-static char* dc390_p0_str[] = {
- "dc390_DataOut_0",
- "dc390_DataIn_0",
- "dc390_Command_0",
- "dc390_Status_0",
- "dc390_Nop_0",
- "dc390_Nop_0",
- "dc390_MsgOut_0",
- "dc390_MsgIn_0",
- "dc390_Nop_1"
- };
-
-static char* dc390_p1_str[] = {
- "dc390_DataOutPhase",
- "dc390_DataInPhase",
- "dc390_CommandPhase",
- "dc390_StatusPhase",
- "dc390_Nop_0",
- "dc390_Nop_0",
- "dc390_MsgOutPhase",
- "dc390_MsgInPhase",
- "dc390_Nop_1"
- };
-#endif
-
-static u8 dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
-static u8 dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
-static u8 dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
-
-/***********************************************************************
- * Functions for the management of the internal structures
- * (DCBs, SRBs, Queueing)
- *
- **********************************************************************/
-static void inline dc390_start_segment(struct dc390_srb* pSRB)
-{
- struct scatterlist *psgl = pSRB->pSegmentList;
-
- /* start new sg segment */
- pSRB->SGBusAddr = sg_dma_address(psgl);
- pSRB->SGToBeXferLen = sg_dma_len(psgl);
-}
-
-static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue)
-{
- unsigned long xfer = pSRB->SGToBeXferLen - residue;
-
- /* xfer more bytes transferred */
- pSRB->SGBusAddr += xfer;
- pSRB->TotalXferredLen += xfer;
- pSRB->SGToBeXferLen = residue;
-
- return xfer;
-}
-
-static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
-{
- struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
- while (pDCB->TargetID != id || pDCB->TargetLUN != lun)
- {
- pDCB = pDCB->pNextDCB;
- if (pDCB == pACB->pLinkDCB)
- return NULL;
- }
- DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n", \
- pDCB, pDCB->TargetID, pDCB->TargetLUN));
- return pDCB;
-}
-
-/* Insert SRB oin top of free list */
-static __inline__ void dc390_Free_insert (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
- DEBUG0(printk ("DC390: Free SRB %p\n", pSRB));
- pSRB->pNextSRB = pACB->pFreeSRB;
- pACB->pFreeSRB = pSRB;
-}
-
-static __inline__ void dc390_Going_append (struct dc390_dcb* pDCB, struct dc390_srb* 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;
-
- pDCB->pGoingLast = pSRB;
- /* No next one in sent list */
- pSRB->pNextSRB = NULL;
-}
-
-static __inline__ void dc390_Going_remove (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
- DEBUG0(printk("DC390: Remove SRB %p from Going\n", pSRB));
- if (pSRB == pDCB->pGoingSRB)
- pDCB->pGoingSRB = pSRB->pNextSRB;
- else
- {
- struct dc390_srb* 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 struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length)
-{
- sg_init_one(sg, addr, length);
- return sg;
-}
-
-/* Create pci mapping */
-static int dc390_pci_map (struct dc390_srb* pSRB)
-{
- int error = 0;
- struct scsi_cmnd *pcmd = pSRB->pcmd;
- struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
- dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp));
-
- /* Map sense buffer */
- if (pSRB->SRBFlag & AUTO_REQSENSE) {
- pSRB->pSegmentList = dc390_sg_build_single(&pSRB->Segmentx, pcmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
- pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, 1,
- DMA_FROM_DEVICE);
- cmdp->saved_dma_handle = sg_dma_address(pSRB->pSegmentList);
-
- /* TODO: error handling */
- if (pSRB->SGcount != 1)
- error = 1;
- DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __func__, pcmd->sense_buffer, cmdp->saved_dma_handle));
- /* Map SG list */
- } else if (scsi_sg_count(pcmd)) {
- int nseg;
-
- nseg = scsi_dma_map(pcmd);
-
- pSRB->pSegmentList = scsi_sglist(pcmd);
- pSRB->SGcount = nseg;
-
- /* TODO: error handling */
- if (nseg < 0)
- error = 1;
- DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
- __func__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
- /* Map single segment */
- } else
- pSRB->SGcount = 0;
-
- return error;
-}
-
-/* Remove pci mapping */
-static void dc390_pci_unmap (struct dc390_srb* pSRB)
-{
- struct scsi_cmnd *pcmd = pSRB->pcmd;
- struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
- DEBUG1(dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp)));
-
- if (pSRB->SRBFlag) {
- pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
- DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __func__, cmdp->saved_dma_handle));
- } else {
- scsi_dma_unmap(pcmd);
- DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
- __func__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
- }
-}
-
-static void __inline__
-dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
- if (pSRB->TagNumber != SCSI_NO_TAG) {
- pDCB->TagMask &= ~(1 << pSRB->TagNumber); /* free tag mask */
- pSRB->TagNumber = SCSI_NO_TAG;
- }
-}
-
-
-static int
-dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
- struct scsi_cmnd *scmd = pSRB->pcmd;
- struct scsi_device *sdev = scmd->device;
- u8 cmd, disc_allowed, try_sync_nego;
-
- pSRB->ScsiPhase = SCSI_NOP0;
-
- 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;
- }
- if (time_before (jiffies, pACB->last_reset))
- {
- DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n"));
- return 1;
- }
- /* KG: Moved pci mapping here */
- dc390_pci_map(pSRB);
- /* TODO: error handling */
- DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
- DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
- DC390_write8 (CtrlReg1, pDCB->CtrlR1);
- DC390_write8 (CtrlReg3, pDCB->CtrlR3);
- 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",\
- scmd->cmnd[0], pDCB->SyncMode));
-
- /* 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->SRBFlag & AUTO_REQSENSE))
- disc_allowed = pDCB->DevMode & EN_DISCONNECT_;
- else
- disc_allowed = 0;
-
- if ((pDCB->SyncMode & SYNC_ENABLE) && pDCB->TargetLUN == 0 && sdev->sdtr &&
- (((scmd->cmnd[0] == REQUEST_SENSE || (pSRB->SRBFlag & AUTO_REQSENSE)) &&
- !(pDCB->SyncMode & SYNC_NEGO_DONE)) || scmd->cmnd[0] == INQUIRY))
- try_sync_nego = 1;
- else
- try_sync_nego = 0;
-
- pSRB->MsgCnt = 0;
- cmd = SEL_W_ATN;
- DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->TargetLUN));
- /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */
- if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed && (scmd->flags & SCMD_TAGGED)) {
- DC390_write8(ScsiFifo, MSG_SIMPLE_TAG);
- pDCB->TagMask |= 1 << scmd->request->tag;
- pSRB->TagNumber = scmd->request->tag;
- DC390_write8(ScsiFifo, scmd->request->tag);
- DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for SRB %p, block tag %02x\n", pSRB, tag[1]));
- cmd = SEL_W_ATN3;
- } else {
- /* No TagQ */
-//no_tag:
- DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for SRB %p, No TagQ\n", disc_allowed ? "" : "o", pSRB));
- }
-
- pSRB->SRBState = SRB_START_;
-
- if (try_sync_nego)
- {
- u8 Sync_Off = pDCB->SyncOffset;
- DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN));
- 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 )
- {
- DC390_write8 (ScsiFifo, REQUEST_SENSE);
- DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
- DC390_write8 (ScsiFifo, 0);
- DC390_write8 (ScsiFifo, 0);
- DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
- DC390_write8 (ScsiFifo, 0);
- DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n"));
- }
- else /* write cmnd to bus */
- {
- u8 *ptr; u8 i;
- ptr = (u8 *)scmd->cmnd;
- for (i = 0; i < scmd->cmd_len; i++)
- DC390_write8 (ScsiFifo, *(ptr++));
- }
- }
- 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 (target %02i-%02i)\n",
- scmd->device->id, (u8)scmd->device->lun));
- pSRB->SRBState = SRB_READY;
- //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- pACB->SelLost++;
- return 1;
- }
- DC390_write8 (ScsiCmd, cmd);
- pACB->pActiveDCB = pDCB;
- pDCB->pActiveSRB = pSRB;
- pACB->Connected = 1;
- pSRB->ScsiPhase = SCSI_NOP1;
- return 0;
-}
-
-
-static void __inline__
-dc390_InvalidCmd(struct dc390_acb* pACB)
-{
- if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT))
- DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
-}
-
-
-static irqreturn_t __inline__
-DC390_Interrupt(void *dev_id)
-{
- struct dc390_acb *pACB = dev_id;
- struct dc390_dcb *pDCB;
- struct dc390_srb *pSRB;
- u8 sstatus=0;
- u8 phase;
- void (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *);
- u8 istate, istatus;
-
- sstatus = DC390_read8 (Scsi_Status);
- if( !(sstatus & INTERRUPT) )
- return IRQ_NONE;
-
- DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
-
- //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
- //dstatus = DC390_read8 (DMA_Status);
- //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
- spin_lock_irq(pACB->pScsiHost->host_lock);
-
- istate = DC390_read8 (Intern_State);
- istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
-
- DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus));
- dc390_laststatus &= ~0x00ffffff;
- dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
-
- if (sstatus & ILLEGAL_OP_ERR)
- {
- printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus);
- dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
- }
-
- 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)
- {
- 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) )
- {
- pDCB = pACB->pActiveDCB;
- if (!pDCB)
- {
- printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
- goto unlock;
- }
- pSRB = pDCB->pActiveSRB;
- if( pDCB->DCBFlag & ABORT_DEV_ )
- dc390_EnableMsgOut_Abort (pACB, pSRB);
-
- phase = pSRB->ScsiPhase;
- DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus));
- stateV = (void *) dc390_phase0[phase];
- ( *stateV )( pACB, pSRB, &sstatus );
-
- pSRB->ScsiPhase = sstatus & 7;
- phase = (u8) sstatus & 7;
- DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus));
- stateV = (void *) dc390_phase1[phase];
- ( *stateV )( pACB, pSRB, &sstatus );
- }
-
- unlock:
- spin_unlock_irq(pACB->pScsiHost->host_lock);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id)
-{
- irqreturn_t ret;
- DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq));
- /* Locking is done in DC390_Interrupt */
- ret = DC390_Interrupt(dev_id);
- DEBUG1(printk (".. IRQ returned\n"));
- return ret;
-}
-
-static void
-dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- u8 sstatus;
- u32 ResidCnt;
- u8 dstate = 0;
-
- sstatus = *psstatus;
-
- if( !(pSRB->SRBState & SRB_XFERPAD) )
- {
- if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) )
- pSRB->SRBStatus |= PARITY_ERROR;
-
- if( sstatus & COUNT_2_ZERO )
- {
- unsigned long timeout = jiffies + HZ;
-
- /* Function called from the ISR with the host_lock held and interrupts disabled */
- if (pSRB->SGToBeXferLen)
- while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
- spin_unlock_irq(pACB->pScsiHost->host_lock);
- udelay(50);
- spin_lock_irq(pACB->pScsiHost->host_lock);
- }
- if (!time_before(jiffies, timeout))
- printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n",
- DC390_read32 (DMA_Wk_ByteCntr));
- dc390_laststatus &= ~0xff000000;
- dc390_laststatus |= dstate << 24;
- pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
- pSRB->SGIndex++;
- if( pSRB->SGIndex < pSRB->SGcount )
- {
- pSRB->pSegmentList++;
-
- dc390_start_segment(pSRB);
- }
- else
- pSRB->SGToBeXferLen = 0;
- }
- else
- {
- ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
- (((u32) DC390_read8 (CtcReg_High) << 16) |
- ((u32) DC390_read8 (CtcReg_Mid) << 8) |
- (u32) DC390_read8 (CtcReg_Low));
-
- dc390_advance_segment(pSRB, ResidCnt);
- }
- }
- if ((*psstatus & 7) != SCSI_DATA_OUT)
- {
- DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD);
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- }
-}
-
-static void
-dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- u8 sstatus, residual, bval;
- u32 ResidCnt, i;
- unsigned long xferCnt;
-
- sstatus = *psstatus;
-
- if( !(pSRB->SRBState & SRB_XFERPAD) )
- {
- if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR))
- pSRB->SRBStatus |= PARITY_ERROR;
-
- if( sstatus & COUNT_2_ZERO )
- {
- int dstate = 0;
- unsigned long timeout = jiffies + HZ;
-
- /* Function called from the ISR with the host_lock held and interrupts disabled */
- if (pSRB->SGToBeXferLen)
- while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
- spin_unlock_irq(pACB->pScsiHost->host_lock);
- udelay(50);
- spin_lock_irq(pACB->pScsiHost->host_lock);
- }
- if (!time_before(jiffies, timeout)) {
- printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n",
- DC390_read32 (DMA_Wk_ByteCntr));
- printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
- }
- dc390_laststatus &= ~0xff000000;
- dc390_laststatus |= dstate << 24;
- DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16) \
- + ((unsigned long) DC390_read8 (CtcReg_Mid) << 8) \
- + ((unsigned long) DC390_read8 (CtcReg_Low)));
- DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%u,ToBeXfer=%lu),", ResidCnt, pSRB->SGToBeXferLen));
-
- DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
-
- pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
- pSRB->SGIndex++;
- if( pSRB->SGIndex < pSRB->SGcount )
- {
- pSRB->pSegmentList++;
-
- dc390_start_segment(pSRB);
- }
- else
- pSRB->SGToBeXferLen = 0;
- }
- else /* phase changed */
- {
- residual = 0;
- bval = DC390_read8 (Current_Fifo);
- while( bval & 0x1f )
- {
- DEBUG1(printk (KERN_DEBUG "Check for residuals,"));
- if( (bval & 0x1f) == 1 )
- {
- for(i=0; i < 0x100; i++)
- {
- bval = DC390_read8 (Current_Fifo);
- if( !(bval & 0x1f) )
- goto din_1;
- else if( i == 0x0ff )
- {
- residual = 1; /* ;1 residual byte */
- goto din_1;
- }
- }
- }
- else
- bval = DC390_read8 (Current_Fifo);
- }
-din_1:
- DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
- for (i = 0xa000; i; i--)
- {
- bval = DC390_read8 (DMA_Status);
- if (bval & BLAST_COMPLETE)
- break;
- }
- /* It seems a DMA Blast abort isn't that bad ... */
- if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
- //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
- dc390_laststatus &= ~0xff000000;
- dc390_laststatus |= bval << 24;
-
- DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
- ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
- ((u32) DC390_read8 (CtcReg_Mid) << 8)) |
- (u32) DC390_read8 (CtcReg_Low);
-
- xferCnt = dc390_advance_segment(pSRB, ResidCnt);
-
- if (residual) {
- size_t count = 1;
- size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList);
- unsigned long flags;
- u8 *ptr;
-
- bval = DC390_read8 (ScsiFifo); /* get one residual byte */
-
- local_irq_save(flags);
- ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
- if (likely(ptr)) {
- *(ptr + offset) = bval;
- scsi_kunmap_atomic_sg(ptr);
- }
- local_irq_restore(flags);
- WARN_ON(!ptr);
-
- /* 1 more byte read */
- xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
- }
- DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
- pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
- }
- }
- if ((*psstatus & 7) != SCSI_DATA_IN)
- {
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
- }
-}
-
-static void
-dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-static void
-dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-
- pSRB->TargetStatus = DC390_read8 (ScsiFifo);
- //udelay (1);
- pSRB->EndMessage = DC390_read8 (ScsiFifo); /* get message */
-
- *psstatus = SCSI_NOP0;
- pSRB->SRBState = SRB_COMPLETED;
- DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
-}
-
-static void
-dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
- *psstatus = SCSI_NOP0;
- //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-
-static void __inline__
-dc390_reprog (struct dc390_acb* pACB, struct dc390_dcb* pDCB)
-{
- DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
- DC390_write8 (CtrlReg3, pDCB->CtrlR3);
- DC390_write8 (CtrlReg4, pDCB->CtrlR4);
- dc390_SetXferRate (pACB, pDCB);
-}
-
-
-#ifdef DC390_DEBUG0
-static void
-dc390_printMsg (u8 *MsgBuf, u8 len)
-{
- int i;
- printk (" %02x", MsgBuf[0]);
- for (i = 1; i < len; i++)
- printk (" %02x", MsgBuf[i]);
- printk ("\n");
-}
-#endif
-
-#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
-
-/* reject_msg */
-static void __inline__
-dc390_MsgIn_reject (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
- pSRB->MsgOutBuf[0] = MESSAGE_REJECT;
- pSRB->MsgCnt = 1;
- DC390_ENABLE_MSGOUT;
- DEBUG0 (printk (KERN_INFO "DC390: Reject message\n"));
-}
-
-/* abort command */
-static void
-dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB )
-{
- pSRB->MsgOutBuf[0] = ABORT;
- pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
- pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
-}
-
-static struct dc390_srb*
-dc390_MsgIn_QTag (struct dc390_acb* pACB, struct dc390_dcb* pDCB, s8 tag)
-{
- struct dc390_srb* pSRB = pDCB->pGoingSRB;
-
- if (pSRB)
- {
- struct scsi_cmnd *scmd = scsi_find_tag(pSRB->pcmd->device, tag);
- pSRB = (struct dc390_srb *)scmd->host_scribble;
-
- if (pDCB->DCBFlag & ABORT_DEV_)
- {
- pSRB->SRBState = SRB_ABORT_SENT;
- dc390_EnableMsgOut_Abort( pACB, pSRB );
- }
-
- if (!(pSRB->SRBState & SRB_DISCONNECT))
- goto mingx0;
-
- pDCB->pActiveSRB = pSRB;
- pSRB->SRBState = SRB_DATA_XFER;
- }
- else
- {
- mingx0:
- pSRB = pACB->pTmpSRB;
- pSRB->SRBState = SRB_UNEXPECT_RESEL;
- pDCB->pActiveSRB = pSRB;
- pSRB->MsgOutBuf[0] = ABORT_TAG;
- pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
- }
- return pSRB;
-}
-
-
-/* set async transfer mode */
-static void
-dc390_MsgIn_set_async (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
- struct dc390_dcb* pDCB = pSRB->pSRBDCB;
- if (!(pSRB->SRBState & DO_SYNC_NEGO))
- printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID);
- pSRB->SRBState &= ~DO_SYNC_NEGO;
- pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
- pDCB->SyncPeriod = 0;
- pDCB->SyncOffset = 0;
- //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
- pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */
- pDCB->CtrlR4 &= 0x3f;
- pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
- dc390_reprog (pACB, pDCB);
-}
-
-/* set sync transfer mode */
-static void
-dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
- u8 bval;
- u16 wval, wval1;
- struct dc390_dcb* pDCB = pSRB->pSRBDCB;
- u8 oldsyncperiod = pDCB->SyncPeriod;
- u8 oldsyncoffset = pDCB->SyncOffset;
-
- if (!(pSRB->SRBState & DO_SYNC_NEGO))
- {
- printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n",
- pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
-
- /* reject */
- //dc390_MsgIn_reject (pACB, pSRB);
- //return dc390_MsgIn_set_async (pACB, pSRB);
-
- /* Reply with corrected SDTR Message */
- if (pSRB->MsgInBuf[4] > 15)
- {
- printk (KERN_INFO "DC390: Lower Sync Offset to 15\n");
- pSRB->MsgInBuf[4] = 15;
- }
- if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
- {
- 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);
- pSRB->MsgCnt = 5;
- DC390_ENABLE_MSGOUT;
- }
-
- pSRB->SRBState &= ~DO_SYNC_NEGO;
- pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
- pDCB->SyncOffset &= 0x0f0;
- pDCB->SyncOffset |= pSRB->MsgInBuf[4];
- pDCB->NegoPeriod = pSRB->MsgInBuf[3];
-
- wval = (u16) pSRB->MsgInBuf[3];
- wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */
- if( (wval1 * 25) != wval) wval1++;
- bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */
-
- pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */
- if (pACB->glitch_cfg != NS_TO_GLITCH(0))
- pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
- else
- pDCB->CtrlR4 |= NS_TO_GLITCH(0);
- if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
-
- if (wval1 >= 8)
- {
- wval1--; /* Timing computation differs by 1 from FAST_SCSI */
- bval = FAST_CLK; /* fast clock / normal scsi */
- pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
- }
-
- pDCB->CtrlR3 = bval;
- pDCB->SyncPeriod = (u8)wval1;
-
- if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0)
- {
- if (! (bval & FAST_SCSI)) wval1++;
- printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID,
- 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
- }
-
- dc390_reprog (pACB, pDCB);
-}
-
-
-/* handle RESTORE_PTR */
-/* This doesn't look very healthy... to-be-fixed */
-static void
-dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
- struct scsi_cmnd *pcmd = pSRB->pcmd;
- struct scatterlist *psgl;
- pSRB->TotalXferredLen = 0;
- pSRB->SGIndex = 0;
- if (scsi_sg_count(pcmd)) {
- size_t saved;
- pSRB->pSegmentList = scsi_sglist(pcmd);
- psgl = pSRB->pSegmentList;
- //dc390_pci_sync(pSRB);
-
- while (pSRB->TotalXferredLen + (unsigned long) sg_dma_len(psgl) < pSRB->Saved_Ptr)
- {
- pSRB->TotalXferredLen += (unsigned long) sg_dma_len(psgl);
- pSRB->SGIndex++;
- if( pSRB->SGIndex < pSRB->SGcount )
- {
- pSRB->pSegmentList++;
-
- dc390_start_segment(pSRB);
- }
- else
- pSRB->SGToBeXferLen = 0;
- }
-
- saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
- pSRB->SGToBeXferLen -= saved;
- pSRB->SGBusAddr += saved;
- printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
- pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
-
- } 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 Successful Operation IRQ before asserting ACK for
- * the last byte (how does it know whether it's the last ?) */
-/* The old code handled it in another way, indicating, that on
- * every message byte an IRQ is generated and every byte has to
- * be manually ACKed. Hmmm ? (KG, 98/11/28) */
-/* The old implementation was correct. Sigh! */
-
-/* Check if the message is complete */
-static u8 __inline__
-dc390_MsgIn_complete (u8 *msgbuf, u32 len)
-{
- 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;
- return 1;
-}
-
-
-
-/* read and eval received messages */
-static void
-dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- struct dc390_dcb* pDCB = pACB->pActiveDCB;
-
- /* Read the msg */
-
- pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
- //pSRB->SRBState = 0;
-
- /* Msg complete ? */
- if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
- {
- DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen));
- /* Now eval the msg */
- switch (pSRB->MsgInBuf[0])
- {
- case DISCONNECT:
- pSRB->SRBState = SRB_DISCONNECT; break;
-
- case SIMPLE_QUEUE_TAG:
- case HEAD_OF_QUEUE_TAG:
- case ORDERED_QUEUE_TAG:
- pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
- break;
-
- 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 EXTENDED_MESSAGE:
- /* reject every extended msg but SDTR */
- if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
- dc390_MsgIn_reject (pACB, pSRB);
- else
- {
- if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
- dc390_MsgIn_set_async (pACB, pSRB);
- else
- dc390_MsgIn_set_sync (pACB, pSRB);
- }
-
- // nothing has to be done
- case COMMAND_COMPLETE: break;
-
- // SAVE POINTER may be ignored as we have the struct dc390_srb* associated with the
- // scsi command. Thanks, Gerard, for pointing it out.
- case SAVE_POINTERS:
- pSRB->Saved_Ptr = pSRB->TotalXferredLen;
- break;
- // The device might want to restart transfer with a RESTORE
- 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);
- }
-
- /* Clear counter and MsgIn state */
- pSRB->SRBState &= ~SRB_MSGIN;
- pACB->MsgLen = 0;
- }
-
- *psstatus = SCSI_NOP0;
- DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
- //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-
-static void
-dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
-{
- unsigned long lval;
- struct dc390_dcb* pDCB = pACB->pActiveDCB;
-
- if (pSRB == pACB->pTmpSRB)
- {
- if (pDCB)
- printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN);
- else
- printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
-
- /* Try to recover - some broken disks react badly to tagged INQUIRY */
- if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) {
- pSRB = pDCB->pGoingSRB;
- pDCB->pActiveSRB = pSRB;
- } else {
- pSRB->pSRBDCB = pDCB;
- dc390_EnableMsgOut_Abort(pACB, pSRB);
- if (pDCB)
- pDCB->DCBFlag |= ABORT_DEV;
- return;
- }
- }
-
- if( pSRB->SGIndex < pSRB->SGcount )
- {
- DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
- if( !pSRB->SGToBeXferLen )
- {
- dc390_start_segment(pSRB);
-
- DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
- }
- lval = pSRB->SGToBeXferLen;
- DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr));
- DC390_write8 (CtcReg_Low, (u8) lval);
- lval >>= 8;
- DC390_write8 (CtcReg_Mid, (u8) lval);
- lval >>= 8;
- DC390_write8 (CtcReg_High, (u8) lval);
-
- DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
- DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
-
- //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
- pSRB->SRBState = SRB_DATA_XFER;
-
- DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
-
- DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
- //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT));
- //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status)));
- //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT));
- }
- else /* xfer pad */
- {
- if( pSRB->SGcount )
- {
- pSRB->AdaptStatus = H_OVER_UNDER_RUN;
- pSRB->SRBStatus |= OVER_RUN;
- DEBUG0(printk (KERN_WARNING " DC390: Overrun -"));
- }
- DEBUG0(printk (KERN_WARNING " Clear transfer pad \n"));
- DC390_write8 (CtcReg_Low, 0);
- DC390_write8 (CtcReg_Mid, 0);
- DC390_write8 (CtcReg_High, 0);
-
- pSRB->SRBState |= SRB_XFERPAD;
- DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
-/*
- DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
- DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
-*/
- }
-}
-
-
-static void
-dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);
-}
-
-static void
-dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
-}
-
-static void
-dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- struct dc390_dcb* pDCB;
- u8 i, cnt;
- u8 *ptr;
-
- DC390_write8 (ScsiCmd, RESET_ATN_CMD);
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
- {
- cnt = (u8) pSRB->pcmd->cmd_len;
- ptr = (u8 *) pSRB->pcmd->cmnd;
- for(i=0; i < cnt; i++)
- DC390_write8 (ScsiFifo, *(ptr++));
- }
- else
- {
- DC390_write8 (ScsiFifo, REQUEST_SENSE);
- pDCB = pACB->pActiveDCB;
- DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
- DC390_write8 (ScsiFifo, 0);
- DC390_write8 (ScsiFifo, 0);
- DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
- DC390_write8 (ScsiFifo, 0);
- DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n"));
- }
- pSRB->SRBState = SRB_COMMAND;
- DC390_write8 (ScsiCmd, INFO_XFER_CMD);
-}
-
-static void
-dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- pSRB->SRBState = SRB_STATUS;
- DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
- //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-static void
-dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- u8 bval, i, cnt;
- u8 *ptr;
- struct dc390_dcb* pDCB;
-
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- pDCB = pACB->pActiveDCB;
- if( !(pSRB->SRBState & SRB_MSGOUT) )
- {
- cnt = pSRB->MsgCnt;
- if( cnt )
- {
- ptr = (u8 *) pSRB->MsgOutBuf;
- for(i=0; i < cnt; i++)
- DC390_write8 (ScsiFifo, *(ptr++));
- pSRB->MsgCnt = 0;
- if( (pDCB->DCBFlag & ABORT_DEV_) &&
- (pSRB->MsgOutBuf[0] == ABORT) )
- pSRB->SRBState = SRB_ABORT_SENT;
- }
- else
- {
- 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 )
- goto mop1;
- }
- DC390_write8 (ScsiFifo, bval);
- }
- DC390_write8 (ScsiCmd, INFO_XFER_CMD);
- }
- else
- {
-mop1:
- printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);
- 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);
- if (pDCB->SyncOffset & 0x0f)
- DC390_write8 (ScsiFifo, pDCB->SyncOffset);
- else
- DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);
- pSRB->SRBState |= DO_SYNC_NEGO;
- DC390_write8 (ScsiCmd, INFO_XFER_CMD);
- }
-}
-
-static void
-dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- if( !(pSRB->SRBState & SRB_MSGIN) )
- {
- pSRB->SRBState &= ~SRB_DISCONNECT;
- pSRB->SRBState |= SRB_MSGIN;
- }
- DC390_write8 (ScsiCmd, INFO_XFER_CMD);
- //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-static void
-dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-static void
-dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-
-static void
-dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB )
-{
- u8 bval, i, cnt;
- struct dc390_dcb* ptr;
-
- if( !(pDCB->TargetLUN) )
- {
- if( !pACB->scan_devices )
- {
- ptr = pACB->pLinkDCB;
- cnt = pACB->DCBCnt;
- bval = pDCB->TargetID;
- for(i=0; i<cnt; i++)
- {
- if( ptr->TargetID == bval )
- {
- ptr->SyncPeriod = pDCB->SyncPeriod;
- ptr->SyncOffset = pDCB->SyncOffset;
- ptr->CtrlR3 = pDCB->CtrlR3;
- ptr->CtrlR4 = pDCB->CtrlR4;
- ptr->SyncMode = pDCB->SyncMode;
- }
- ptr = ptr->pNextDCB;
- }
- }
- }
- return;
-}
-
-
-static void
-dc390_Disconnect( struct dc390_acb* pACB )
-{
- struct dc390_dcb *pDCB;
- struct dc390_srb *pSRB, *psrb;
- u8 i, cnt;
-
- 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)
- {
- DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
- pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel));
- mdelay(400);
- 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 = NULL;
- pSRB->ScsiPhase = SCSI_NOP0;
- if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
- pSRB->SRBState = 0;
- else if( pSRB->SRBState & SRB_ABORT_SENT )
- {
- pDCB->TagMask = 0;
- pDCB->DCBFlag = 0;
- cnt = pDCB->GoingSRBCnt;
- pDCB->GoingSRBCnt = 0;
- pSRB = pDCB->pGoingSRB;
- for( i=0; i < cnt; i++)
- {
- psrb = pSRB->pNextSRB;
- dc390_Free_insert (pACB, pSRB);
- pSRB = psrb;
- }
- pDCB->pGoingSRB = NULL;
- }
- else
- {
- if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
- !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
- { /* Selection time out */
- pSRB->AdaptStatus = H_SEL_TIMEOUT;
- pSRB->TargetStatus = 0;
- goto disc1;
- }
- else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED))
- {
-disc1:
- dc390_freetag (pDCB, pSRB);
- pDCB->pActiveSRB = NULL;
- pSRB->SRBState = SRB_FREE;
- dc390_SRBdone( pACB, pDCB, pSRB);
- }
- }
- pACB->MsgLen = 0;
-}
-
-
-static void
-dc390_Reselect( struct dc390_acb* pACB )
-{
- struct dc390_dcb* pDCB;
- struct dc390_srb* pSRB;
- u8 id, lun;
-
- DEBUG0(printk(KERN_INFO "RSEL,"));
- pACB->Connected = 1;
- pDCB = pACB->pActiveDCB;
- if( pDCB )
- { /* Arbitration lost but Reselection won */
- DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n"));
- pSRB = pDCB->pActiveSRB;
- if( !( pACB->scan_devices ) )
- {
- struct scsi_cmnd *pcmd = pSRB->pcmd;
- scsi_set_resid(pcmd, scsi_bufflen(pcmd));
- SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
- dc390_Going_remove(pDCB, pSRB);
- dc390_Free_insert(pACB, pSRB);
- pcmd->scsi_done (pcmd);
- DEBUG0(printk(KERN_DEBUG"DC390: Return SRB %p to free\n", pSRB));
- }
- }
- /* Get ID */
- lun = DC390_read8 (ScsiFifo);
- DEBUG0(printk ("Dev %02x,", lun));
- if (!(lun & (1 << pACB->pScsiHost->this_id)))
- printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun);
- else
- lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */
- id = 0; while (lun >>= 1) id++;
- /* Get LUN */
- lun = DC390_read8 (ScsiFifo);
- if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n");
- lun &= 7;
- DEBUG0(printk ("(%02i-%i),", id, lun));
- pDCB = dc390_findDCB (pACB, id, lun);
- if (!pDCB)
- {
- printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n",
- id, lun);
- return;
- }
- pACB->pActiveDCB = pDCB;
- /* TagQ: We expect a message soon, so never mind the exact SRB */
- if( pDCB->SyncMode & EN_TAG_QUEUEING )
- {
- pSRB = pACB->pTmpSRB;
- pDCB->pActiveSRB = pSRB;
- }
- else
- {
- pSRB = pDCB->pActiveSRB;
- if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
- {
- pSRB= pACB->pTmpSRB;
- pSRB->SRBState = SRB_UNEXPECT_RESEL;
- printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n",
- id, lun);
- pDCB->pActiveSRB = pSRB;
- dc390_EnableMsgOut_Abort ( pACB, pSRB );
- }
- else
- {
- if( pDCB->DCBFlag & ABORT_DEV_ )
- {
- pSRB->SRBState = SRB_ABORT_SENT;
- printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n",
- id, lun);
- dc390_EnableMsgOut_Abort( pACB, pSRB );
- }
- else
- pSRB->SRBState = SRB_DATA_XFER;
- }
- }
-
- DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber));
- pSRB->ScsiPhase = SCSI_NOP0;
- DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
- DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
- DC390_write8 (CtrlReg1, pDCB->CtrlR1);
- DC390_write8 (CtrlReg3, pDCB->CtrlR3);
- DC390_write8 (CtrlReg4, pDCB->CtrlR4); /* ; Glitch eater */
- DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); /* ;to release the /ACK signal */
-}
-
-static int __inline__
-dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
- struct scsi_cmnd *pcmd;
-
- pcmd = pSRB->pcmd;
-
- REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
- pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
-
- pSRB->SRBFlag |= AUTO_REQSENSE;
- pSRB->SavedTotXLen = pSRB->TotalXferredLen;
- pSRB->AdaptStatus = 0;
- pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
-
- /* We are called from SRBdone, original PCI mapping has been removed
- * already, new one is set up from StartSCSI */
- pSRB->SGIndex = 0;
-
- pSRB->TotalXferredLen = 0;
- pSRB->SGToBeXferLen = 0;
- return dc390_StartSCSI(pACB, pDCB, pSRB);
-}
-
-
-static void
-dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
- u8 status;
- struct scsi_cmnd *pcmd;
-
- pcmd = pSRB->pcmd;
- /* KG: Moved pci_unmap here */
- dc390_pci_unmap(pSRB);
-
- status = pSRB->TargetStatus;
-
- DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p\n", status, pcmd->result, pSRB));
- if(pSRB->SRBFlag & AUTO_REQSENSE)
- { /* Last command was a Request Sense */
- pSRB->SRBFlag &= ~AUTO_REQSENSE;
- pSRB->AdaptStatus = 0;
- pSRB->TargetStatus = SAM_STAT_CHECK_CONDITION;
-
- //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
- if (status == SAM_STAT_CHECK_CONDITION)
- pcmd->result = MK_RES_LNX(0, DID_BAD_TARGET, 0, /*CHECK_CONDITION*/0);
- else /* Retry */
- {
- if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
- {
- /* Don't retry on TEST_UNIT_READY */
- pcmd->result = MK_RES_LNX(DRIVER_SENSE, DID_OK, 0, SAM_STAT_CHECK_CONDITION);
- REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
- (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
- } else {
- SET_RES_DRV(pcmd->result, DRIVER_SENSE);
- //pSRB->ScsiCmdLen = (u8) (pSRB->Segment1[0] >> 8);
- DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
- pSRB->TotalXferredLen = 0;
- SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
- }
- }
- goto cmd_done;
- }
- if( status )
- {
- if (status == SAM_STAT_CHECK_CONDITION)
- {
- if (dc390_RequestSense(pACB, pDCB, pSRB)) {
- SET_RES_DID(pcmd->result, DID_ERROR);
- goto cmd_done;
- }
- return;
- }
- else if (status == SAM_STAT_TASK_SET_FULL)
- {
- scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
- DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
- pSRB->TotalXferredLen = 0;
- SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
- }
- else if (status == SAM_STAT_BUSY &&
- (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
- pACB->scan_devices)
- {
- pSRB->AdaptStatus = 0;
- pSRB->TargetStatus = status;
- pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0);
- }
- else
- { /* Another error */
- pSRB->TotalXferredLen = 0;
- SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
- goto cmd_done;
- }
- }
- else
- { /* Target status == 0 */
- status = pSRB->AdaptStatus;
- if (status == H_OVER_UNDER_RUN)
- {
- pSRB->TargetStatus = 0;
- SET_RES_DID(pcmd->result,DID_OK);
- SET_RES_MSG(pcmd->result,pSRB->EndMessage);
- }
- else if (status == H_SEL_TIMEOUT)
- {
- pcmd->result = MK_RES(0, DID_NO_CONNECT, 0, 0);
- /* Devices are removed below ... */
- }
- else if( pSRB->SRBStatus & PARITY_ERROR)
- {
- //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;
- SET_RES_DID(pcmd->result,DID_OK);
- }
- }
-
-cmd_done:
- scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen);
-
- dc390_Going_remove (pDCB, pSRB);
- /* Add to free list */
- dc390_Free_insert (pACB, pSRB);
-
- DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done\n"));
- pcmd->scsi_done (pcmd);
-
- return;
-}
-
-
-/* Remove all SRBs from Going list and inform midlevel */
-static void
-dc390_DoingSRB_Done(struct dc390_acb* pACB, struct scsi_cmnd *cmd)
-{
- struct dc390_dcb *pDCB, *pdcb;
- struct dc390_srb *psrb, *psrb2;
- int i;
- struct scsi_cmnd *pcmd;
-
- pDCB = pACB->pLinkDCB;
- pdcb = pDCB;
- if (! pdcb) return;
- do
- {
- psrb = pdcb->pGoingSRB;
- for (i = 0; i < pdcb->GoingSRBCnt; i++)
- {
- psrb2 = psrb->pNextSRB;
- pcmd = psrb->pcmd;
- dc390_Free_insert (pACB, psrb);
- psrb = psrb2;
- }
- pdcb->GoingSRBCnt = 0;
- pdcb->pGoingSRB = NULL;
- pdcb->TagMask = 0;
- pdcb = pdcb->pNextDCB;
- } while( pdcb != pDCB );
-}
-
-
-static void
-dc390_ResetSCSIBus( struct dc390_acb* pACB )
-{
- //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;
-}
-
-static void
-dc390_ScsiRstDetect( struct dc390_acb* pACB )
-{
- printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus);
- //DEBUG0(printk(KERN_INFO "RST_DETECT,"));
-
- DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
- /* Unlock before ? */
- /* delay half a second */
- udelay (1000);
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- pACB->last_reset = jiffies + 5*HZ/2
- + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
- 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, NULL);
- //dc390_RecoverSRB( pACB );
- pACB->pActiveDCB = NULL;
- pACB->ACBFlag = 0;
- }
- return;
-}
-
-static int DC390_queuecommand_lck(struct scsi_cmnd *cmd,
- void (*done)(struct scsi_cmnd *))
-{
- struct scsi_device *sdev = cmd->device;
- struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
- struct dc390_dcb *dcb = sdev->hostdata;
- struct dc390_srb *srb;
-
- if (sdev->queue_depth <= dcb->GoingSRBCnt)
- goto device_busy;
- if (acb->pActiveDCB)
- goto host_busy;
- if (acb->ACBFlag & (RESET_DETECT|RESET_DONE|RESET_DEV))
- goto host_busy;
-
- srb = acb->pFreeSRB;
- if (unlikely(srb == NULL))
- goto host_busy;
-
- cmd->scsi_done = done;
- cmd->result = 0;
- acb->Cmds++;
-
- acb->pFreeSRB = srb->pNextSRB;
- srb->pNextSRB = NULL;
-
- srb->pSRBDCB = dcb;
- srb->pcmd = cmd;
- cmd->host_scribble = (char *)srb;
-
- srb->SGIndex = 0;
- srb->AdaptStatus = 0;
- srb->TargetStatus = 0;
- srb->MsgCnt = 0;
-
- srb->SRBStatus = 0;
- srb->SRBFlag = 0;
- srb->SRBState = 0;
- srb->TotalXferredLen = 0;
- srb->SGBusAddr = 0;
- srb->SGToBeXferLen = 0;
- srb->ScsiPhase = 0;
- srb->EndMessage = 0;
- srb->TagNumber = SCSI_NO_TAG;
-
- if (dc390_StartSCSI(acb, dcb, srb)) {
- dc390_Free_insert(acb, srb);
- goto host_busy;
- }
-
- dc390_Going_append(dcb, srb);
-
- return 0;
-
- host_busy:
- return SCSI_MLQUEUE_HOST_BUSY;
-
- device_busy:
- return SCSI_MLQUEUE_DEVICE_BUSY;
-}
-
-static DEF_SCSI_QCMD(DC390_queuecommand)
-
-static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
- struct pci_dev *pdev;
- u16 pstat;
-
- if (!pDCB) pDCB = pACB->pActiveDCB;
- if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB;
-
- if (pSRB)
- {
- 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): %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",
- DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16),
- DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State));
- printk (" %02x %02x %02x %02x %02x %02x\n",
- DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),
- DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));
- DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
- 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",
- DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr),
- DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr),
- DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl));
- DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
- pdev = pACB->pdev;
- pci_read_config_word(pdev, PCI_STATUS, &pstat);
- printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
- printk ("DC390: In case of driver trouble read Documentation/scsi/tmscsim.txt\n");
-}
-
-
-static int DC390_abort(struct scsi_cmnd *cmd)
-{
- struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
- struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
-
- scmd_printk(KERN_WARNING, cmd, "DC390: Abort command\n");
-
- /* 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, NULL);
-
- pDCB->DCBFlag |= ABORT_DEV_;
- printk(KERN_INFO "DC390: Aborted.\n");
-
- return FAILED;
-}
-
-
-static void dc390_ResetDevParam( struct dc390_acb* pACB )
-{
- struct dc390_dcb *pDCB, *pdcb;
-
- pDCB = pACB->pLinkDCB;
- if (! pDCB) return;
- pdcb = pDCB;
- do
- {
- 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);
-
-}
-
-static int DC390_bus_reset (struct scsi_cmnd *cmd)
-{
- struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata;
- u8 bval;
-
- spin_lock_irq(cmd->device->host->host_lock);
-
- bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
- DC390_write8(CtrlReg1, bval); /* disable IRQ on bus reset */
-
- pACB->ACBFlag |= RESET_DEV;
- dc390_ResetSCSIBus(pACB);
-
- dc390_ResetDevParam(pACB);
- mdelay(1);
- pACB->last_reset = jiffies + 3*HZ/2
- + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
-
- DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
- DC390_read8(INT_Status); /* Reset Pending INT */
-
- dc390_DoingSRB_Done(pACB, cmd);
-
- pACB->pActiveDCB = NULL;
- pACB->ACBFlag = 0;
-
- bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
- DC390_write8(CtrlReg1, bval); /* re-enable interrupt */
-
- spin_unlock_irq(cmd->device->host->host_lock);
-
- return SUCCESS;
-}
-
-/**
- * dc390_slave_alloc - Called by the scsi mid layer to tell us about a new
- * scsi device that we need to deal with.
- *
- * @scsi_device: The new scsi device that we need to handle.
- */
-static int dc390_slave_alloc(struct scsi_device *scsi_device)
-{
- struct dc390_acb *pACB = (struct dc390_acb*) scsi_device->host->hostdata;
- struct dc390_dcb *pDCB, *pDCB2 = NULL;
- uint id = scsi_device->id;
- uint lun = scsi_device->lun;
-
- pDCB = kzalloc(sizeof(struct dc390_dcb), GFP_KERNEL);
- if (!pDCB)
- return -ENOMEM;
-
- if (!pACB->DCBCnt++) {
- pACB->pLinkDCB = pDCB;
- pACB->pDCBRunRobin = pDCB;
- } else {
- pACB->pLastDCB->pNextDCB = pDCB;
- }
-
- pDCB->pNextDCB = pACB->pLinkDCB;
- pACB->pLastDCB = pDCB;
-
- pDCB->pDCBACB = pACB;
- pDCB->TargetID = id;
- pDCB->TargetLUN = lun;
-
- /*
- * Some values are for all LUNs: Copy them
- * In a clean way: We would have an own structure for a SCSI-ID
- */
- if (lun && (pDCB2 = dc390_findDCB(pACB, id, 0))) {
- pDCB->DevMode = pDCB2->DevMode;
- pDCB->SyncMode = pDCB2->SyncMode & SYNC_NEGO_DONE;
- pDCB->SyncPeriod = pDCB2->SyncPeriod;
- pDCB->SyncOffset = pDCB2->SyncOffset;
- pDCB->NegoPeriod = pDCB2->NegoPeriod;
-
- pDCB->CtrlR3 = pDCB2->CtrlR3;
- pDCB->CtrlR4 = pDCB2->CtrlR4;
- } else {
- u8 index = pACB->AdapterIndex;
- PEEprom prom = (PEEprom) &dc390_eepromBuf[index][id << 2];
-
- pDCB->DevMode = prom->EE_MODE1;
- 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;
- }
-
- if (pDCB->DevMode & SYNC_NEGO_)
- pDCB->SyncMode |= SYNC_ENABLE;
- else {
- pDCB->SyncMode = 0;
- pDCB->SyncOffset &= ~0x0f;
- }
-
- pDCB->CtrlR1 = pACB->pScsiHost->this_id;
- if (pDCB->DevMode & PARITY_CHK_)
- pDCB->CtrlR1 |= PARITY_ERR_REPO;
-
- pACB->scan_devices = 1;
- scsi_device->hostdata = pDCB;
- return 0;
-}
-
-/**
- * dc390_slave_destroy - Called by the scsi mid layer to tell us about a
- * device that is going away.
- *
- * @scsi_device: The scsi device that we need to remove.
- */
-static void dc390_slave_destroy(struct scsi_device *scsi_device)
-{
- struct dc390_acb* pACB = (struct dc390_acb*) scsi_device->host->hostdata;
- struct dc390_dcb* pDCB = (struct dc390_dcb*) scsi_device->hostdata;
- struct dc390_dcb* pPrevDCB = pACB->pLinkDCB;
-
- pACB->scan_devices = 0;
-
- BUG_ON(pDCB->GoingSRBCnt > 1);
-
- if (pDCB == pACB->pLinkDCB) {
- if (pACB->pLastDCB == pDCB) {
- pDCB->pNextDCB = NULL;
- pACB->pLastDCB = NULL;
- }
- pACB->pLinkDCB = pDCB->pNextDCB;
- } else {
- while (pPrevDCB->pNextDCB != pDCB)
- pPrevDCB = pPrevDCB->pNextDCB;
- pPrevDCB->pNextDCB = pDCB->pNextDCB;
- if (pDCB == pACB->pLastDCB)
- pACB->pLastDCB = pPrevDCB;
- }
-
- if (pDCB == pACB->pActiveDCB)
- pACB->pActiveDCB = NULL;
- if (pDCB == pACB->pLinkDCB)
- pACB->pLinkDCB = pDCB->pNextDCB;
- if (pDCB == pACB->pDCBRunRobin)
- pACB->pDCBRunRobin = pDCB->pNextDCB;
- kfree(pDCB);
-
- pACB->DCBCnt--;
-}
-
-static int dc390_slave_configure(struct scsi_device *sdev)
-{
- struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
- struct dc390_dcb *dcb = (struct dc390_dcb *)sdev->hostdata;
-
- acb->scan_devices = 0;
-
- /*
- * XXX: Note that while this driver used to called scsi_activate_tcq,
- * it never actually set a tag type, so emulate the old behavior.
- */
- scsi_set_tag_type(sdev, 0);
-
- if (sdev->tagged_supported && (dcb->DevMode & TAG_QUEUEING_)) {
- dcb->SyncMode |= EN_TAG_QUEUEING;
- scsi_adjust_queue_depth(sdev, acb->TagMaxNum);
- }
-
- return 0;
-}
-
-static struct scsi_host_template driver_template = {
- .module = THIS_MODULE,
- .proc_name = "tmscsim",
- .name = DC390_BANNER " V" DC390_VERSION,
- .slave_alloc = dc390_slave_alloc,
- .slave_configure = dc390_slave_configure,
- .slave_destroy = dc390_slave_destroy,
- .queuecommand = DC390_queuecommand,
- .eh_abort_handler = DC390_abort,
- .eh_bus_reset_handler = DC390_bus_reset,
- .can_queue = 1,
- .this_id = 7,
- .sg_tablesize = SG_ALL,
- .cmd_per_lun = 1,
- .use_clustering = ENABLE_CLUSTERING,
- .max_sectors = 0x4000, /* 8MiB = 16 * 1024 * 512 */
- .use_blk_tags = 1,
-};
-
-/***********************************************************************
- * Functions for access to DC390 EEPROM
- * and some to emulate it
- *
- **********************************************************************/
-
-static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
-{
- u8 carryFlag = 1, j = 0x80, bval;
- int i;
-
- for (i = 0; i < 9; i++) {
- if (carryFlag) {
- pci_write_config_byte(pdev, 0x80, 0x40);
- bval = 0xc0;
- } else
- bval = 0x80;
-
- udelay(160);
- pci_write_config_byte(pdev, 0x80, bval);
- udelay(160);
- pci_write_config_byte(pdev, 0x80, 0);
- udelay(160);
-
- carryFlag = (cmd & j) ? 1 : 0;
- j >>= 1;
- }
-}
-
-static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
-{
- int i;
- u16 wval = 0;
- u8 bval;
-
- for (i = 0; i < 16; i++) {
- wval <<= 1;
-
- pci_write_config_byte(pdev, 0x80, 0x80);
- udelay(160);
- pci_write_config_byte(pdev, 0x80, 0x40);
- udelay(160);
- pci_read_config_byte(pdev, 0x00, &bval);
-
- if (bval == 0x22)
- wval |= 1;
- }
-
- return wval;
-}
-
-static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
-{
- u8 cmd = EEPROM_READ, i;
-
- for (i = 0; i < 0x40; i++) {
- pci_write_config_byte(pdev, 0xc0, 0);
- udelay(160);
-
- dc390_eeprom_prepare_read(pdev, cmd++);
- *ptr++ = dc390_eeprom_get_data(pdev);
-
- pci_write_config_byte(pdev, 0x80, 0);
- pci_write_config_byte(pdev, 0x80, 0);
- udelay(160);
- }
-}
-
-/* Override EEprom values with explicitly set values */
-static void dc390_eeprom_override(u8 index)
-{
- u8 *ptr = (u8 *) dc390_eepromBuf[index], id;
-
- /* Adapter Settings */
- if (tmscsim[0] != -2)
- ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0]; /* Adapter ID */
- if (tmscsim[3] != -2)
- ptr[EE_MODE2] = (u8)tmscsim[3];
- if (tmscsim[5] != -2)
- ptr[EE_DELAY] = tmscsim[5]; /* Reset delay */
- if (tmscsim[4] != -2)
- ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4]; /* Tagged Cmds */
-
- /* Device Settings */
- for (id = 0; id < MAX_SCSI_ID; id++) {
- if (tmscsim[2] != -2)
- ptr[id << 2] = (u8)tmscsim[2]; /* EE_MODE1 */
- if (tmscsim[1] != -2)
- ptr[(id << 2) + 1] = (u8)tmscsim[1]; /* EE_Speed */
- }
-}
-
-static int tmscsim_def[] = {
- 7,
- 0 /* 10MHz */,
- PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_,
- MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION | LUN_CHECK,
- 3 /* 16 Tags per LUN */,
- 1 /* s delay after Reset */,
-};
-
-/* Copy defaults over set values where missing */
-static void dc390_fill_with_defaults (void)
-{
- int i;
-
- for (i = 0; i < 6; i++) {
- if (tmscsim[i] < 0 || tmscsim[i] > 255)
- tmscsim[i] = tmscsim_def[i];
- }
-
- /* Sanity checks */
- if (tmscsim[0] > 7)
- tmscsim[0] = 7;
- if (tmscsim[1] > 7)
- tmscsim[1] = 4;
- if (tmscsim[4] > 5)
- tmscsim[4] = 4;
- if (tmscsim[5] > 180)
- tmscsim[5] = 180;
-}
-
-static void dc390_check_eeprom(struct pci_dev *pdev, u8 index)
-{
- u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120};
- u8 EEbuf[128];
- u16 *ptr = (u16 *)EEbuf, wval = 0;
- int i;
-
- dc390_read_eeprom(pdev, ptr);
- memcpy(dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
- memcpy(&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID],
- &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
-
- dc390_eepromBuf[index][EE_DELAY] = interpd[dc390_eepromBuf[index][EE_DELAY]];
-
- for (i = 0; i < 0x40; i++, ptr++)
- wval += *ptr;
-
- /* no Tekram EEprom found */
- if (wval != 0x1234) {
- int speed;
-
- printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
-
- /*
- * XXX(hch): bogus, because we might have tekram and
- * non-tekram hbas in a single machine.
- */
- dc390_fill_with_defaults();
-
- speed = dc390_clock_speed[tmscsim[1]];
- printk(KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz), "
- "DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n",
- tmscsim[0], tmscsim[1], speed / 10, speed % 10,
- (u8)tmscsim[2], (u8)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
- }
-}
-
-static void dc390_init_hw(struct dc390_acb *pACB, u8 index)
-{
- struct Scsi_Host *shost = pACB->pScsiHost;
- u8 dstate;
-
- /* Disable SCSI bus reset interrupt */
- DC390_write8(CtrlReg1, DIS_INT_ON_SCSI_RST | shost->this_id);
-
- if (pACB->Gmode2 & RST_SCSI_BUS) {
- dc390_ResetSCSIBus(pACB);
- udelay(1000);
- pACB->last_reset = jiffies + HZ/2 +
- HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
- }
-
- pACB->ACBFlag = 0;
-
- /* Reset Pending INT */
- DC390_read8(INT_Status);
-
- /* 250ms selection timeout */
- DC390_write8(Scsi_TimeOut, SEL_TIMEOUT);
-
- /* Conversion factor = 0 , 40MHz clock */
- DC390_write8(Clk_Factor, CLK_FREQ_40MHZ);
-
- /* NOP cmd - clear command register */
- DC390_write8(ScsiCmd, NOP_CMD);
-
- /* Enable Feature and SCSI-2 */
- DC390_write8(CtrlReg2, EN_FEATURE+EN_SCSI2_CMD);
-
- /* Fast clock */
- DC390_write8(CtrlReg3, FAST_CLK);
-
- /* Negation */
- DC390_write8(CtrlReg4, pACB->glitch_cfg | /* glitch eater */
- (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ?
- NEGATE_REQACKDATA : 0);
-
- /* Clear Transfer Count High: ID */
- DC390_write8(CtcReg_High, 0);
- DC390_write8(DMA_Cmd, DMA_IDLE_CMD);
- DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
- DC390_write32(DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
- dstate = DC390_read8(DMA_Status);
- DC390_write8(DMA_Status, dstate);
-}
-
-static int dc390_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
- struct dc390_acb *pACB;
- struct Scsi_Host *shost;
- unsigned long io_port;
- int error = -ENODEV, i;
-
- if (pci_enable_device(pdev))
- goto out;
-
- pci_set_master(pdev);
-
- error = -ENOMEM;
- if (disable_clustering)
- driver_template.use_clustering = DISABLE_CLUSTERING;
- shost = scsi_host_alloc(&driver_template, sizeof(struct dc390_acb));
- if (!shost)
- goto out_disable_device;
-
- pACB = (struct dc390_acb *)shost->hostdata;
- memset(pACB, 0, sizeof(struct dc390_acb));
-
- dc390_check_eeprom(pdev, dc390_adapterCnt);
- dc390_eeprom_override(dc390_adapterCnt);
-
- io_port = pci_resource_start(pdev, 0);
-
- shost->this_id = dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID];
- shost->io_port = io_port;
- shost->n_io_port = 0x80;
- shost->irq = pdev->irq;
- shost->base = io_port;
- shost->unique_id = io_port;
-
- pACB->last_reset = jiffies;
- pACB->pScsiHost = shost;
- pACB->IOPortBase = (u16) io_port;
- pACB->IRQLevel = pdev->irq;
-
- shost->max_id = 8;
-
- if (shost->max_id - 1 ==
- dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID])
- shost->max_id--;
-
- if (dc390_eepromBuf[dc390_adapterCnt][EE_MODE2] & LUN_CHECK)
- shost->max_lun = 8;
- else
- shost->max_lun = 1;
-
- pACB->pFreeSRB = pACB->SRB_array;
- pACB->SRBCount = MAX_SRB_CNT;
- pACB->AdapterIndex = dc390_adapterCnt;
- pACB->TagMaxNum =
- 2 << dc390_eepromBuf[dc390_adapterCnt][EE_TAG_CMD_NUM];
- pACB->Gmode2 = dc390_eepromBuf[dc390_adapterCnt][EE_MODE2];
-
- for (i = 0; i < pACB->SRBCount-1; i++)
- pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
- pACB->SRB_array[pACB->SRBCount-1].pNextSRB = NULL;
- pACB->pTmpSRB = &pACB->TmpSRB;
-
- pACB->sel_timeout = SEL_TIMEOUT;
- pACB->glitch_cfg = EATER_25NS;
- pACB->pdev = pdev;
-
- if (!request_region(io_port, shost->n_io_port, "tmscsim")) {
- printk(KERN_ERR "DC390: register IO ports error!\n");
- goto out_host_put;
- }
-
- /* Reset Pending INT */
- DC390_read8_(INT_Status, io_port);
-
- if (request_irq(pdev->irq, do_DC390_Interrupt, IRQF_SHARED,
- "tmscsim", pACB)) {
- printk(KERN_ERR "DC390: register IRQ error!\n");
- goto out_release_region;
- }
-
- dc390_init_hw(pACB, dc390_adapterCnt);
-
- dc390_adapterCnt++;
-
- pci_set_drvdata(pdev, shost);
-
- error = scsi_add_host(shost, &pdev->dev);
- if (error)
- goto out_free_irq;
- scsi_scan_host(shost);
- return 0;
-
- out_free_irq:
- free_irq(pdev->irq, pACB);
- out_release_region:
- release_region(io_port, shost->n_io_port);
- out_host_put:
- scsi_host_put(shost);
- out_disable_device:
- pci_disable_device(pdev);
- out:
- return error;
-}
-
-/**
- * dc390_remove_one - Called to remove a single instance of the adapter.
- *
- * @dev: The PCI device to remove.
- */
-static void dc390_remove_one(struct pci_dev *dev)
-{
- struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
- unsigned long iflags;
- struct dc390_acb* pACB = (struct dc390_acb*) scsi_host->hostdata;
- u8 bval;
-
- scsi_remove_host(scsi_host);
-
- spin_lock_irqsave(scsi_host->host_lock, iflags);
- pACB->ACBFlag = RESET_DEV;
- bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
- DC390_write8 (CtrlReg1, bval); /* disable interrupt */
- if (pACB->Gmode2 & RST_SCSI_BUS)
- dc390_ResetSCSIBus(pACB);
- spin_unlock_irqrestore(scsi_host->host_lock, iflags);
-
- free_irq(scsi_host->irq, pACB);
- release_region(scsi_host->io_port, scsi_host->n_io_port);
-
- pci_disable_device(dev);
- scsi_host_put(scsi_host);
-}
-
-static struct pci_device_id tmscsim_pci_tbl[] = {
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { }
-};
-MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);
-
-static struct pci_driver dc390_driver = {
- .name = "tmscsim",
- .id_table = tmscsim_pci_tbl,
- .probe = dc390_probe_one,
- .remove = dc390_remove_one,
-};
-
-static int __init dc390_module_init(void)
-{
- if (!disable_clustering) {
- printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n");
- printk(KERN_INFO " with \"disable_clustering=1\" and report to maintainers\n");
- }
-
- if (tmscsim[0] == -1 || tmscsim[0] > 15) {
- tmscsim[0] = 7;
- tmscsim[1] = 4;
- tmscsim[2] = PARITY_CHK_ | TAG_QUEUEING_;
- tmscsim[3] = MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION;
- tmscsim[4] = 2;
- tmscsim[5] = 10;
- printk (KERN_INFO "DC390: Using safe settings.\n");
- }
-
- return pci_register_driver(&dc390_driver);
-}
-
-static void __exit dc390_module_exit(void)
-{
- pci_unregister_driver(&dc390_driver);
-}
-
-module_init(dc390_module_init);
-module_exit(dc390_module_exit);
-
-#ifndef MODULE
-static int __init dc390_setup (char *str)
-{
- int ints[8],i, im;
-
- get_options(str, ARRAY_SIZE(ints), ints);
- 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 (); */
- return 1;
-}
-
-__setup("tmscsim=", dc390_setup);
-#endif
diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
deleted file mode 100644
index c9ad4bb..0000000
--- a/drivers/scsi/tmscsim.h
+++ /dev/null
@@ -1,549 +0,0 @@
-/***********************************************************************
-;* File Name : TMSCSIM.H *
-;* TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter *
-;* Device Driver *
-;***********************************************************************/
-/* $Id: tmscsim.h,v 2.15.2.3 2000/11/17 20:52:27 garloff Exp $ */
-
-#ifndef _TMSCSIM_H
-#define _TMSCSIM_H
-
-#include <linux/types.h>
-
-#define MAX_ADAPTER_NUM 4
-#define MAX_SG_LIST_BUF 16 /* Not used */
-#define MAX_SCSI_ID 8
-#define MAX_SRB_CNT 50 /* Max number of started commands */
-
-#define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */
-
-/*
-;-----------------------------------------------------------------------
-; SCSI Request Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_srb
-{
-//u8 CmdBlock[12];
-
-struct dc390_srb *pNextSRB;
-struct dc390_dcb *pSRBDCB;
-struct scsi_cmnd *pcmd;
-struct scatterlist *pSegmentList;
-
-struct scatterlist Segmentx; /* make a one entry of S/G list table */
-
-unsigned long SGBusAddr; /*;a segment starting address as seen by AM53C974A
- in CPU endianness. We're only getting 32-bit bus
- addresses by default */
-unsigned long SGToBeXferLen; /*; to be xfer length */
-unsigned long TotalXferredLen;
-unsigned long SavedTotXLen;
-unsigned long Saved_Ptr;
-u32 SRBState;
-
-u8 SRBStatus;
-u8 SRBFlag; /*; b0-AutoReqSense,b6-Read,b7-write */
- /*; b4-settimeout,b5-Residual valid */
-u8 AdaptStatus;
-u8 TargetStatus;
-
-u8 ScsiPhase;
-s8 TagNumber;
-u8 SGIndex;
-u8 SGcount;
-
-u8 MsgCnt;
-u8 EndMessage;
-
-u8 MsgInBuf[6];
-u8 MsgOutBuf[6];
-
-//u8 IORBFlag; /*;81h-Reset, 2-retry */
-};
-
-
-/*
-;-----------------------------------------------------------------------
-; Device Control Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_dcb
-{
-struct dc390_dcb *pNextDCB;
-struct dc390_acb *pDCBACB;
-
-/* Queued SRBs */
-struct dc390_srb *pGoingSRB;
-struct dc390_srb *pGoingLast;
-struct dc390_srb *pActiveSRB;
-u8 GoingSRBCnt;
-
-u32 TagMask;
-
-u8 TargetID; /*; SCSI Target ID (SCSI Only) */
-u8 TargetLUN; /*; SCSI Log. Unit (SCSI Only) */
-u8 DevMode;
-u8 DCBFlag;
-
-u8 CtrlR1;
-u8 CtrlR3;
-u8 CtrlR4;
-
-u8 SyncMode; /*; 0:async mode */
-u8 NegoPeriod; /*;for nego. */
-u8 SyncPeriod; /*;for reg. */
-u8 SyncOffset; /*;for reg. and nego.(low nibble) */
-};
-
-
-/*
-;-----------------------------------------------------------------------
-; Adapter Control Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_acb
-{
-struct Scsi_Host *pScsiHost;
-u16 IOPortBase;
-u8 IRQLevel;
-u8 status;
-
-u8 SRBCount;
-u8 AdapterIndex; /*; nth Adapter this driver */
-u8 DCBCnt;
-
-u8 TagMaxNum;
-u8 ACBFlag;
-u8 Gmode2;
-u8 scan_devices;
-
-struct dc390_dcb *pLinkDCB;
-struct dc390_dcb *pLastDCB;
-struct dc390_dcb *pDCBRunRobin;
-
-struct dc390_dcb *pActiveDCB;
-struct dc390_srb *pFreeSRB;
-struct dc390_srb *pTmpSRB;
-
-u8 msgin123[4];
-u8 Connected;
-u8 pad;
-
-#if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(CONFIG_SMP) || DEBUG_SPINLOCKS > 0)
-spinlock_t lock;
-#endif
-u8 sel_timeout;
-u8 glitch_cfg;
-
-u8 MsgLen;
-u8 Ignore_IRQ; /* Not used */
-
-struct pci_dev *pdev;
-
-unsigned long last_reset;
-unsigned long Cmds;
-u32 SelLost;
-u32 SelConn;
-u32 CmdInQ;
-u32 CmdOutOfSRB;
-
-struct dc390_srb TmpSRB;
-struct dc390_srb SRB_array[MAX_SRB_CNT]; /* 50 SRBs */
-};
-
-
-/*;-----------------------------------------------------------------------*/
-
-
-#define BIT31 0x80000000
-#define BIT30 0x40000000
-#define BIT29 0x20000000
-#define BIT28 0x10000000
-#define BIT27 0x08000000
-#define BIT26 0x04000000
-#define BIT25 0x02000000
-#define BIT24 0x01000000
-#define BIT23 0x00800000
-#define BIT22 0x00400000
-#define BIT21 0x00200000
-#define BIT20 0x00100000
-#define BIT19 0x00080000
-#define BIT18 0x00040000
-#define BIT17 0x00020000
-#define BIT16 0x00010000
-#define BIT15 0x00008000
-#define BIT14 0x00004000
-#define BIT13 0x00002000
-#define BIT12 0x00001000
-#define BIT11 0x00000800
-#define BIT10 0x00000400
-#define BIT9 0x00000200
-#define BIT8 0x00000100
-#define BIT7 0x00000080
-#define BIT6 0x00000040
-#define BIT5 0x00000020
-#define BIT4 0x00000010
-#define BIT3 0x00000008
-#define BIT2 0x00000004
-#define BIT1 0x00000002
-#define BIT0 0x00000001
-
-/*;---UnitCtrlFlag */
-#define UNIT_ALLOCATED BIT0
-#define UNIT_INFO_CHANGED BIT1
-#define FORMATING_MEDIA BIT2
-#define UNIT_RETRY BIT3
-
-/*;---UnitFlags */
-#define DASD_SUPPORT BIT0
-#define SCSI_SUPPORT BIT1
-#define ASPI_SUPPORT BIT2
-
-/*;----SRBState machine definition */
-#define SRB_FREE 0
-#define SRB_WAIT BIT0
-#define SRB_READY BIT1
-#define SRB_MSGOUT BIT2 /*;arbitration+msg_out 1st byte*/
-#define SRB_MSGIN BIT3
-#define SRB_MSGIN_MULTI BIT4
-#define SRB_COMMAND BIT5
-#define SRB_START_ BIT6 /*;arbitration+msg_out+command_out*/
-#define SRB_DISCONNECT BIT7
-#define SRB_DATA_XFER BIT8
-#define SRB_XFERPAD BIT9
-#define SRB_STATUS BIT10
-#define SRB_COMPLETED BIT11
-#define SRB_ABORT_SENT BIT12
-#define DO_SYNC_NEGO BIT13
-#define SRB_UNEXPECT_RESEL BIT14
-
-/*;---SRBstatus */
-#define SRB_OK BIT0
-#define ABORTION BIT1
-#define OVER_RUN BIT2
-#define UNDER_RUN BIT3
-#define PARITY_ERROR BIT4
-#define SRB_ERROR BIT5
-
-/*;---ACBFlag */
-#define RESET_DEV BIT0
-#define RESET_DETECT BIT1
-#define RESET_DONE BIT2
-
-/*;---DCBFlag */
-#define ABORT_DEV_ BIT0
-
-/*;---SRBFlag */
-#define DATAOUT BIT7
-#define DATAIN BIT6
-#define RESIDUAL_VALID BIT5
-#define ENABLE_TIMER BIT4
-#define RESET_DEV0 BIT2
-#define ABORT_DEV BIT1
-#define AUTO_REQSENSE BIT0
-
-/*;---Adapter status */
-#define H_STATUS_GOOD 0
-#define H_SEL_TIMEOUT 0x11
-#define H_OVER_UNDER_RUN 0x12
-#define H_UNEXP_BUS_FREE 0x13
-#define H_TARGET_PHASE_F 0x14
-#define H_INVALID_CCB_OP 0x16
-#define H_LINK_CCB_BAD 0x17
-#define H_BAD_TARGET_DIR 0x18
-#define H_DUPLICATE_CCB 0x19
-#define H_BAD_CCB_OR_SG 0x1A
-#define H_ABORT 0x0FF
-
-/* 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))
-
-#define SET_RES_TARGET(who, tgt) do { who &= ~RES_TARGET; who |= (int)(tgt); } while (0)
-#define SET_RES_TARGET_LNX(who, tgt) do { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } while (0)
-#define SET_RES_MSG(who, msg) do { who &= ~RES_ENDMSG; who |= (int)(msg) << 8; } while (0)
-#define SET_RES_DID(who, did) do { who &= ~RES_DID; who |= (int)(did) << 16; } while (0)
-#define SET_RES_DRV(who, drv) do { who &= ~RES_DRV; who |= (int)(drv) << 24; } while (0)
-
-/*;---Sync_Mode */
-#define SYNC_DISABLE 0
-#define SYNC_ENABLE BIT0
-#define SYNC_NEGO_DONE BIT1
-#define WIDE_ENABLE BIT2 /* Not used ;-) */
-#define WIDE_NEGO_DONE BIT3 /* Not used ;-) */
-#define EN_TAG_QUEUEING BIT4
-#define EN_ATN_STOP BIT5
-
-#define SYNC_NEGO_OFFSET 15
-
-/*;---SCSI bus phase*/
-#define SCSI_DATA_OUT 0
-#define SCSI_DATA_IN 1
-#define SCSI_COMMAND 2
-#define SCSI_STATUS_ 3
-#define SCSI_NOP0 4
-#define SCSI_NOP1 5
-#define SCSI_MSG_OUT 6
-#define SCSI_MSG_IN 7
-
-/*;----SCSI MSG BYTE*/ /* see scsi/scsi.h */ /* One is missing ! */
-#define ABORT_TAG 0x0d
-
-/*
- * SISC query queue
- */
-typedef struct {
- dma_addr_t saved_dma_handle;
-} dc390_cmd_scp_t;
-
-/*
-;==========================================================
-; EEPROM byte offset
-;==========================================================
-*/
-typedef struct _EEprom
-{
-u8 EE_MODE1;
-u8 EE_SPEED;
-u8 xx1;
-u8 xx2;
-} EEprom, *PEEprom;
-
-#define REAL_EE_ADAPT_SCSI_ID 64
-#define REAL_EE_MODE2 65
-#define REAL_EE_DELAY 66
-#define REAL_EE_TAG_CMD_NUM 67
-
-#define EE_ADAPT_SCSI_ID 32
-#define EE_MODE2 33
-#define EE_DELAY 34
-#define EE_TAG_CMD_NUM 35
-
-#define EE_LEN 40
-
-/*; EE_MODE1 bits definition*/
-#define PARITY_CHK_ BIT0
-#define SYNC_NEGO_ BIT1
-#define EN_DISCONNECT_ BIT2
-#define SEND_START_ BIT3
-#define TAG_QUEUEING_ BIT4
-
-/*; EE_MODE2 bits definition*/
-#define MORE2_DRV BIT0
-#define GREATER_1G BIT1
-#define RST_SCSI_BUS BIT2
-#define ACTIVE_NEGATION BIT3
-#define NO_SEEK BIT4
-#define LUN_CHECK BIT5
-
-#define ENABLE_CE 1
-#define DISABLE_CE 0
-#define EEPROM_READ 0x80
-
-/*
-;==========================================================
-; AMD 53C974 Registers bit Definition
-;==========================================================
-*/
-/*
-;====================
-; SCSI Register
-;====================
-*/
-
-/*; Command Reg.(+0CH) (rw) */
-#define DMA_COMMAND BIT7
-#define NOP_CMD 0
-#define CLEAR_FIFO_CMD 1
-#define RST_DEVICE_CMD 2
-#define RST_SCSI_BUS_CMD 3
-
-#define INFO_XFER_CMD 0x10
-#define INITIATOR_CMD_CMPLTE 0x11
-#define MSG_ACCEPTED_CMD 0x12
-#define XFER_PAD_BYTE 0x18
-#define SET_ATN_CMD 0x1A
-#define RESET_ATN_CMD 0x1B
-
-#define SEL_WO_ATN 0x41 /* currently not used */
-#define SEL_W_ATN 0x42
-#define SEL_W_ATN_STOP 0x43
-#define SEL_W_ATN3 0x46
-#define EN_SEL_RESEL 0x44
-#define DIS_SEL_RESEL 0x45 /* currently not used */
-#define RESEL 0x40 /* " */
-#define RESEL_ATN3 0x47 /* " */
-
-#define DATA_XFER_CMD INFO_XFER_CMD
-
-
-/*; SCSI Status Reg.(+10H) (r) */
-#define INTERRUPT BIT7
-#define ILLEGAL_OP_ERR BIT6
-#define PARITY_ERR BIT5
-#define COUNT_2_ZERO BIT4
-#define GROUP_CODE_VALID BIT3
-#define SCSI_PHASE_MASK (BIT2+BIT1+BIT0)
-/* BIT2: MSG phase; BIT1: C/D physe; BIT0: I/O phase */
-
-/*; Interrupt Status Reg.(+14H) (r) */
-#define SCSI_RESET BIT7
-#define INVALID_CMD BIT6
-#define DISCONNECTED BIT5
-#define SERVICE_REQUEST BIT4
-#define SUCCESSFUL_OP BIT3
-#define RESELECTED BIT2
-#define SEL_ATTENTION BIT1
-#define SELECTED BIT0
-
-/*; Internal State Reg.(+18H) (r) */
-#define SYNC_OFFSET_FLAG BIT3
-#define INTRN_STATE_MASK (BIT2+BIT1+BIT0)
-/* 0x04: Sel. successful (w/o stop), 0x01: Sel. successful (w/ stop) */
-
-/*; Clock Factor Reg.(+24H) (w) */
-#define CLK_FREQ_40MHZ 0
-#define CLK_FREQ_35MHZ (BIT2+BIT1+BIT0)
-#define CLK_FREQ_30MHZ (BIT2+BIT1)
-#define CLK_FREQ_25MHZ (BIT2+BIT0)
-#define CLK_FREQ_20MHZ BIT2
-#define CLK_FREQ_15MHZ (BIT1+BIT0)
-#define CLK_FREQ_10MHZ BIT1
-
-/*; Control Reg. 1(+20H) (rw) */
-#define EXTENDED_TIMING BIT7
-#define DIS_INT_ON_SCSI_RST BIT6
-#define PARITY_ERR_REPO BIT4
-#define SCSI_ID_ON_BUS (BIT2+BIT1+BIT0) /* host adapter ID */
-
-/*; Control Reg. 2(+2CH) (rw) */
-#define EN_FEATURE BIT6
-#define EN_SCSI2_CMD BIT3
-
-/*; Control Reg. 3(+30H) (rw) */
-#define ID_MSG_CHECK BIT7
-#define EN_QTAG_MSG BIT6
-#define EN_GRP2_CMD BIT5
-#define FAST_SCSI BIT4 /* ;10MB/SEC */
-#define FAST_CLK BIT3 /* ;25 - 40 MHZ */
-
-/*; Control Reg. 4(+34H) (rw) */
-#define EATER_12NS 0
-#define EATER_25NS BIT7
-#define EATER_35NS BIT6
-#define EATER_0NS (BIT7+BIT6)
-#define REDUCED_POWER BIT5
-#define CTRL4_RESERVED BIT4 /* must be 1 acc. to AM53C974.c */
-#define NEGATE_REQACKDATA BIT2
-#define NEGATE_REQACK BIT3
-
-#define GLITCH_TO_NS(x) (((~x>>6 & 2) >> 1) | ((x>>6 & 1) << 1 ^ (x>>6 & 2)))
-#define NS_TO_GLITCH(y) (((~y<<7) | ~((y<<6) ^ ((y<<5 & 1<<6) | ~0x40))) & 0xc0)
-
-/*
-;====================
-; DMA Register
-;====================
-*/
-/*; DMA Command Reg.(+40H) (rw) */
-#define READ_DIRECTION BIT7
-#define WRITE_DIRECTION 0
-#define EN_DMA_INT BIT6
-#define EN_PAGE_INT BIT5 /* page transfer interrupt enable */
-#define MAP_TO_MDL BIT4
-#define DIAGNOSTIC BIT2
-#define DMA_IDLE_CMD 0
-#define DMA_BLAST_CMD BIT0
-#define DMA_ABORT_CMD BIT1
-#define DMA_START_CMD (BIT1+BIT0)
-
-/*; DMA Status Reg.(+54H) (r) */
-#define PCI_MS_ABORT BIT6
-#define BLAST_COMPLETE BIT5
-#define SCSI_INTERRUPT BIT4
-#define DMA_XFER_DONE BIT3
-#define DMA_XFER_ABORT BIT2
-#define DMA_XFER_ERROR BIT1
-#define POWER_DOWN BIT0
-
-/*; DMA SCSI Bus and Ctrl.(+70H) */
-#define EN_INT_ON_PCI_ABORT BIT25
-#define WRT_ERASE_DMA_STAT BIT24
-#define PW_DOWN_CTRL BIT21
-#define SCSI_BUSY BIT20
-#define SCLK BIT19
-#define SCAM BIT18
-#define SCSI_LINES 0x0003ffff
-
-/*
-;==========================================================
-; SCSI Chip register address offset
-;==========================================================
-;Registers are rw unless declared otherwise
-*/
-#define CtcReg_Low 0x00 /* r curr. transfer count */
-#define CtcReg_Mid 0x04 /* r */
-#define CtcReg_High 0x38 /* r */
-#define ScsiFifo 0x08
-#define ScsiCmd 0x0C
-#define Scsi_Status 0x10 /* r */
-#define INT_Status 0x14 /* r */
-#define Sync_Period 0x18 /* w */
-#define Sync_Offset 0x1C /* w */
-#define Clk_Factor 0x24 /* w */
-#define CtrlReg1 0x20
-#define CtrlReg2 0x2C
-#define CtrlReg3 0x30
-#define CtrlReg4 0x34
-#define DMA_Cmd 0x40
-#define DMA_XferCnt 0x44 /* rw starting transfer count (32 bit) */
-#define DMA_XferAddr 0x48 /* rw starting physical address (32 bit) */
-#define DMA_Wk_ByteCntr 0x4C /* r working byte counter */
-#define DMA_Wk_AddrCntr 0x50 /* r working address counter */
-#define DMA_Status 0x54 /* r */
-#define DMA_MDL_Addr 0x58 /* rw starting MDL address */
-#define DMA_Wk_MDL_Cntr 0x5C /* r working MDL counter */
-#define DMA_ScsiBusCtrl 0x70 /* rw SCSI Bus, PCI/DMA Ctrl */
-
-#define StcReg_Low CtcReg_Low /* w start transfer count */
-#define StcReg_Mid CtcReg_Mid /* w */
-#define StcReg_High CtcReg_High /* w */
-#define Scsi_Dest_ID Scsi_Status /* w */
-#define Scsi_TimeOut INT_Status /* w */
-#define Intern_State Sync_Period /* r */
-#define Current_Fifo Sync_Offset /* r Curr. FIFO / int. state */
-
-
-#define DC390_read8(address) \
- (inb (pACB->IOPortBase + (address)))
-
-#define DC390_read8_(address, base) \
- (inb ((u16)(base) + (address)))
-
-#define DC390_read16(address) \
- (inw (pACB->IOPortBase + (address)))
-
-#define DC390_read32(address) \
- (inl (pACB->IOPortBase + (address)))
-
-#define DC390_write8(address,value) \
- outb ((value), pACB->IOPortBase + (address))
-
-#define DC390_write8_(address,value,base) \
- outb ((value), (u16)(base) + (address))
-
-#define DC390_write16(address,value) \
- outw ((value), pACB->IOPortBase + (address))
-
-#define DC390_write32(address,value) \
- outl ((value), pACB->IOPortBase + (address))
-
-
-#endif /* _TMSCSIM_H */
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCH 12/12] Replace tmscsim by am53c974
2014-11-21 12:41 ` [PATCH 12/12] Replace tmscsim by am53c974 Hannes Reinecke
@ 2014-11-23 13:22 ` Guennadi Liakhovetski
2014-11-23 18:45 ` David Miller
0 siblings, 1 reply; 17+ messages in thread
From: Guennadi Liakhovetski @ 2014-11-23 13:22 UTC (permalink / raw)
To: Hannes Reinecke
Cc: James Bottomley, Christoph Hellwig, Paolo Bonzini,
David S. Miller, linux-scsi
On Fri, 21 Nov 2014, Hannes Reinecke wrote:
> The am53c974 is a re-implementation of the tmscsim driver,
> and provides the same functionality.
> So remove the tmscsim driver and make am53c974 an alias to tmscsim.
>
> Cc: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> Signed-off-by: Hannes Reinecke <hare@suse.de>
> ---
> MAINTAINERS | 7 +-
> drivers/scsi/Kconfig | 16 -
> drivers/scsi/Makefile | 1 -
> drivers/scsi/am53c974.c | 1 +
> drivers/scsi/tmscsim.c | 2626 -----------------------------------------------
> drivers/scsi/tmscsim.h | 549 ----------
> 6 files changed, 4 insertions(+), 3196 deletions(-)
> delete mode 100644 drivers/scsi/tmscsim.c
> delete mode 100644 drivers/scsi/tmscsim.h
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index d206f37..d780e46 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -2862,11 +2862,10 @@ F: Documentation/networking/dmfe.txt
> F: drivers/net/ethernet/dec/tulip/dmfe.c
>
> DC390/AM53C974 SCSI driver
> -M: Kurt Garloff <garloff@suse.de>
> -W: http://www.garloff.de/kurt/linux/dc390/
> -M: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
> +M: Hannes Reinecke <hare@suse.de>
> +L: linux-scsi@vger.kernel.org
> S: Maintained
> -F: drivers/scsi/tmscsim.*
> +F: drivers/scsi/am53c974.c
>
> DC395x SCSI driver
> M: Oliver Neukum <oliver@neukum.org>
Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Thanks
Guennadi
> diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
> index 519c3ef..f871a80 100644
> --- a/drivers/scsi/Kconfig
> +++ b/drivers/scsi/Kconfig
> @@ -1341,22 +1341,6 @@ config SCSI_DC395x
> To compile this driver as a module, choose M here: the
> module will be called dc395x.
>
> -config SCSI_DC390T
> - tristate "Tekram DC390(T) and Am53/79C974 SCSI support"
> - depends on PCI && SCSI
> - ---help---
> - This driver supports PCI SCSI host adapters based on the Am53C974A
> - chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
> - PCscsi/PCnet (Am53/79C974) solutions.
> -
> - Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
> -
> - Note that this driver does NOT support Tekram DC390W/U/F, which are
> - based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
> -
> - To compile this driver as a module, choose M here: the
> - module will be called tmscsim.
> -
> config SCSI_AM53C974
> tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
> depends on PCI && SCSI
> diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
> index 79a6571..a9f3fa8 100644
> --- a/drivers/scsi/Makefile
> +++ b/drivers/scsi/Makefile
> @@ -100,7 +100,6 @@ obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
> obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
> obj-$(CONFIG_SCSI_EATA) += eata.o
> obj-$(CONFIG_SCSI_DC395x) += dc395x.o
> -obj-$(CONFIG_SCSI_DC390T) += tmscsim.o
> obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o
> obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
> obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
> diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
> index 55622eb..5ce2bb2 100644
> --- a/drivers/scsi/am53c974.c
> +++ b/drivers/scsi/am53c974.c
> @@ -572,6 +572,7 @@ MODULE_DESCRIPTION("AM53C974 SCSI driver");
> MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
> MODULE_LICENSE("GPL");
> MODULE_VERSION(DRV_MODULE_VERSION);
> +MODULE_ALIAS("tmscsim");
>
> module_param(am53c974_fenab, bool, 0444);
> MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
> diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
> deleted file mode 100644
> index 844c9a0..0000000
> --- a/drivers/scsi/tmscsim.c
> +++ /dev/null
> @@ -1,2626 +0,0 @@
> -/************************************************************************
> - * FILE NAME : TMSCSIM.C *
> - * BY : C.L. Huang, ching@tekram.com.tw *
> - * Description: Device Driver for Tekram DC-390(T) PCI SCSI *
> - * Bus Master Host Adapter *
> - * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. *
> - ************************************************************************
> - * (C) Copyright: put under GNU GPL in 10/96 *
> - * (see Documentation/scsi/tmscsim.txt) *
> - ************************************************************************
> - * $Id: tmscsim.c,v 2.60.2.30 2000/12/20 01:07:12 garloff Exp $ *
> - * Enhancements and bugfixes by *
> - * Kurt Garloff <kurt@garloff.de> <garloff@suse.de> *
> - ************************************************************************
> - * HISTORY: *
> - * *
> - * REV# DATE NAME DESCRIPTION *
> - * 1.00 96/04/24 CLH First release *
> - * 1.01 96/06/12 CLH Fixed bug of Media Change for Removable *
> - * Device, scan all LUN. Support Pre2.0.10 *
> - * 1.02 96/06/18 CLH Fixed bug of Command timeout ... *
> - * 1.03 96/09/25 KG Added tmscsim_proc_info() *
> - * 1.04 96/10/11 CLH Updating for support KV 2.0.x *
> - * 1.05 96/10/18 KG Fixed bug in DC390_abort(null ptr deref)*
> - * 1.06 96/10/25 KG Fixed module support *
> - * 1.07 96/11/09 KG Fixed tmscsim_proc_info() *
> - * 1.08 96/11/18 KG Fixed null ptr in DC390_Disconnect() *
> - * 1.09 96/11/30 KG Added register the allocated IO space *
> - * 1.10 96/12/05 CLH Modified tmscsim_proc_info(), and reset *
> - * pending interrupt in DC390_detect() *
> - * 1.11 97/02/05 KG/CLH Fixeds problem with partitions greater *
> - * than 1GB *
> - * 1.12 98/02/15 MJ Rewritten PCI probing *
> - * 1.13 98/04/08 KG Support for non DC390, __initfunc decls,*
> - * changed max devs from 10 to 16 *
> - * 1.14a 98/05/05 KG Dynamic DCB allocation, add-single-dev *
> - * for LUNs if LUN_SCAN (BIOS) not set *
> - * runtime config using /proc interface *
> - * 1.14b 98/05/06 KG eliminated cli (); sti (); spinlocks *
> - * 1.14c 98/05/07 KG 2.0.x compatibility *
> - * 1.20a 98/05/07 KG changed names of funcs to be consistent *
> - * DC390_ (entry points), dc390_ (internal)*
> - * reworked locking *
> - * 1.20b 98/05/12 KG bugs: version, kfree, _ctmp *
> - * debug output *
> - * 1.20c 98/05/12 KG bugs: kfree, parsing, EEpromDefaults *
> - * 1.20d 98/05/14 KG bugs: list linkage, clear flag after *
> - * reset on startup, code cleanup *
> - * 1.20e 98/05/15 KG spinlock comments, name space cleanup *
> - * pLastDCB now part of ACB structure *
> - * added stats, timeout for 2.1, TagQ bug *
> - * RESET and INQUIRY interface commands *
> - * 1.20f 98/05/18 KG spinlocks fixes, max_lun fix, free DCBs *
> - * for missing LUNs, pending int *
> - * 1.20g 98/05/19 KG Clean up: Avoid short *
> - * 1.20h 98/05/21 KG Remove AdaptSCSIID, max_lun ... *
> - * 1.20i 98/05/21 KG Aiiie: Bug with TagQMask *
> - * 1.20j 98/05/24 KG Handle STAT_BUSY, handle pACB->pLinkDCB *
> - * == 0 in remove_dev and DoingSRB_Done *
> - * 1.20k 98/05/25 KG DMA_INT (experimental) *
> - * 1.20l 98/05/27 KG remove DMA_INT; DMA_IDLE cmds added; *
> - * 1.20m 98/06/10 KG glitch configurable; made some global *
> - * vars part of ACB; use DC390_readX *
> - * 1.20n 98/06/11 KG startup params *
> - * 1.20o 98/06/15 KG added TagMaxNum to boot/module params *
> - * Device Nr -> Idx, TagMaxNum power of 2 *
> - * 1.20p 98/06/17 KG Docu updates. Reset depends on settings *
> - * pci_set_master added; 2.0.xx: pcibios_* *
> - * used instead of MechNum things ... *
> - * 1.20q 98/06/23 KG Changed defaults. Added debug code for *
> - * removable media and fixed it. TagMaxNum *
> - * fixed for DC390. Locking: ACB, DRV for *
> - * better IRQ sharing. Spelling: Queueing *
> - * Parsing and glitch_cfg changes. Display *
> - * real SyncSpeed value. Made DisConn *
> - * functional (!) *
> - * 1.20r 98/06/30 KG Debug macros, allow disabling DsCn, set *
> - * BIT4 in CtrlR4, EN_PAGE_INT, 2.0 module *
> - * param -1 fixed. *
> - * 1.20s 98/08/20 KG Debug info on abort(), try to check PCI,*
> - * phys_to_bus instead of phys_to_virt, *
> - * fixed sel. process, fixed locking, *
> - * added MODULE_XXX infos, changed IRQ *
> - * request flags, disable DMA_INT *
> - * 1.20t 98/09/07 KG TagQ report fixed; Write Erase DMA Stat;*
> - * initfunc -> __init; better abort; *
> - * Timeout for XFER_DONE & BLAST_COMPLETE; *
> - * Allow up to 33 commands being processed *
> - * 2.0a 98/10/14 KG Max Cmnds back to 17. DMA_Stat clearing *
> - * all flags. Clear within while() loops *
> - * in DataIn_0/Out_0. Null ptr in dumpinfo *
> - * for pSRB==0. Better locking during init.*
> - * bios_param() now respects part. table. *
> - * 2.0b 98/10/24 KG Docu fixes. Timeout Msg in DMA Blast. *
> - * Disallow illegal idx in INQUIRY/REMOVE *
> - * 2.0c 98/11/19 KG Cleaned up detect/init for SMP boxes, *
> - * Write Erase DMA (1.20t) caused problems *
> - * 2.0d 98/12/25 KG Christmas release ;-) Message handling *
> - * 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 unique_id. Disable RETRY message. *
> - * 2.0d2600/01/29 KG Go to new EH. *
> - * 2.0d2700/01/31 KG ... but maintain 2.0 compat. *
> - * and fix DCB freeing *
> - * 2.0d2800/02/14 KG Queue statistics fixed, dump special cmd*
> - * Waiting_Timer for failed StartSCSI *
> - * New EH: Don't return cmnds to ML on RST *
> - * Use old EH (don't have new EH fns yet) *
> - * Reset: Unlock, but refuse to queue *
> - * 2.3 __setup function *
> - * 2.0e 00/05/22 KG Return residual for 2.3 *
> - * 2.0e1 00/05/25 KG Compile fixes for 2.3.99 *
> - * 2.0e2 00/05/27 KG Jeff Garzik's pci_enable_device() *
> - * 2.0e3 00/09/29 KG Some 2.4 changes. Don't try Sync Nego *
> - * before INQUIRY has reported ability. *
> - * Recognise INQUIRY as scanning command. *
> - * 2.0e4 00/10/13 KG Allow compilation into 2.4 kernel *
> - * 2.0e5 00/11/17 KG Store Inq.flags in DCB *
> - * 2.0e6 00/11/22 KG 2.4 init function (Thx to O.Schumann) *
> - * 2.4 PCI device table (Thx to A.Richter) *
> - * 2.0e7 00/11/28 KG Allow overriding of BIOS settings *
> - * 2.0f 00/12/20 KG Handle failed INQUIRYs during scan *
> - * 2.1a 03/11/29 GL, KG Initial fixing for 2.6. Convert to *
> - * use the current PCI-mapping API, update *
> - * command-queuing. *
> - * 2.1b 04/04/13 GL Fix for 64-bit platforms *
> - * 2.1b1 04/01/31 GL (applied 05.04) Remove internal *
> - * command-queuing. *
> - * 2.1b2 04/02/01 CH (applied 05.04) Fix error-handling *
> - * 2.1c 04/05/23 GL Update to use the new pci_driver API, *
> - * some scsi EH updates, more cleanup. *
> - * 2.1d 04/05/27 GL Moved setting of scan_devices to *
> - * slave_alloc/_configure/_destroy, as *
> - * suggested by CH. *
> - ***********************************************************************/
> -
> -/* DEBUG options */
> -//#define DC390_DEBUG0
> -//#define DC390_DEBUG1
> -//#define DC390_DCBDEBUG
> -//#define DC390_PARSEDEBUG
> -//#define DC390_REMOVABLEDEBUG
> -//#define DC390_LOCKDEBUG
> -
> -//#define NOP do{}while(0)
> -#define C_NOP
> -
> -/* Debug definitions */
> -#ifdef DC390_DEBUG0
> -# define DEBUG0(x) x
> -#else
> -# define DEBUG0(x) C_NOP
> -#endif
> -#ifdef DC390_DEBUG1
> -# define DEBUG1(x) x
> -#else
> -# define DEBUG1(x) C_NOP
> -#endif
> -#ifdef DC390_DCBDEBUG
> -# define DCBDEBUG(x) x
> -#else
> -# define DCBDEBUG(x) C_NOP
> -#endif
> -#ifdef DC390_PARSEDEBUG
> -# define PARSEDEBUG(x) x
> -#else
> -# define PARSEDEBUG(x) C_NOP
> -#endif
> -#ifdef DC390_REMOVABLEDEBUG
> -# define REMOVABLEDEBUG(x) x
> -#else
> -# define REMOVABLEDEBUG(x) C_NOP
> -#endif
> -#define DCBDEBUG1(x) C_NOP
> -
> -#include <linux/module.h>
> -#include <linux/delay.h>
> -#include <linux/signal.h>
> -#include <linux/errno.h>
> -#include <linux/kernel.h>
> -#include <linux/ioport.h>
> -#include <linux/pci.h>
> -#include <linux/proc_fs.h>
> -#include <linux/string.h>
> -#include <linux/mm.h>
> -#include <linux/blkdev.h>
> -#include <linux/timer.h>
> -#include <linux/interrupt.h>
> -#include <linux/init.h>
> -#include <linux/spinlock.h>
> -#include <linux/slab.h>
> -#include <asm/io.h>
> -
> -#include <scsi/scsi.h>
> -#include <scsi/scsi_cmnd.h>
> -#include <scsi/scsi_device.h>
> -#include <scsi/scsi_host.h>
> -#include <scsi/scsicam.h>
> -#include <scsi/scsi_tcq.h>
> -
> -#define DC390_BANNER "Tekram DC390/AM53C974"
> -#define DC390_VERSION "2.1d 2004-05-27"
> -
> -#define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI
> -
> -#include "tmscsim.h"
> -
> -
> -static void dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -static void dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
> -
> -static void dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB );
> -static void dc390_Disconnect( struct dc390_acb* pACB );
> -static void dc390_Reselect( struct dc390_acb* pACB );
> -static void dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB );
> -static void dc390_ScsiRstDetect( struct dc390_acb* pACB );
> -static void dc390_EnableMsgOut_Abort(struct dc390_acb*, struct dc390_srb*);
> -static void dc390_dumpinfo(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB);
> -static void dc390_ResetDevParam(struct dc390_acb* pACB);
> -
> -static u32 dc390_laststatus = 0;
> -static u8 dc390_adapterCnt = 0;
> -
> -static int disable_clustering;
> -module_param(disable_clustering, int, S_IRUGO);
> -MODULE_PARM_DESC(disable_clustering, "If you experience problems with your devices, try setting to 1");
> -
> -/* Startup values, to be overriden on the commandline */
> -static int tmscsim[] = {-2, -2, -2, -2, -2, -2};
> -
> -module_param_array(tmscsim, int, NULL, 0);
> -MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)");
> -MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
> -MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
> -MODULE_LICENSE("GPL");
> -MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
> -
> -static void *dc390_phase0[]={
> - dc390_DataOut_0,
> - dc390_DataIn_0,
> - dc390_Command_0,
> - dc390_Status_0,
> - dc390_Nop_0,
> - dc390_Nop_0,
> - dc390_MsgOut_0,
> - dc390_MsgIn_0,
> - dc390_Nop_1
> - };
> -
> -static void *dc390_phase1[]={
> - dc390_DataOutPhase,
> - dc390_DataInPhase,
> - dc390_CommandPhase,
> - dc390_StatusPhase,
> - dc390_Nop_0,
> - dc390_Nop_0,
> - dc390_MsgOutPhase,
> - dc390_MsgInPhase,
> - dc390_Nop_1
> - };
> -
> -#ifdef DC390_DEBUG1
> -static char* dc390_p0_str[] = {
> - "dc390_DataOut_0",
> - "dc390_DataIn_0",
> - "dc390_Command_0",
> - "dc390_Status_0",
> - "dc390_Nop_0",
> - "dc390_Nop_0",
> - "dc390_MsgOut_0",
> - "dc390_MsgIn_0",
> - "dc390_Nop_1"
> - };
> -
> -static char* dc390_p1_str[] = {
> - "dc390_DataOutPhase",
> - "dc390_DataInPhase",
> - "dc390_CommandPhase",
> - "dc390_StatusPhase",
> - "dc390_Nop_0",
> - "dc390_Nop_0",
> - "dc390_MsgOutPhase",
> - "dc390_MsgInPhase",
> - "dc390_Nop_1"
> - };
> -#endif
> -
> -static u8 dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
> -static u8 dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
> -static u8 dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
> -
> -/***********************************************************************
> - * Functions for the management of the internal structures
> - * (DCBs, SRBs, Queueing)
> - *
> - **********************************************************************/
> -static void inline dc390_start_segment(struct dc390_srb* pSRB)
> -{
> - struct scatterlist *psgl = pSRB->pSegmentList;
> -
> - /* start new sg segment */
> - pSRB->SGBusAddr = sg_dma_address(psgl);
> - pSRB->SGToBeXferLen = sg_dma_len(psgl);
> -}
> -
> -static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue)
> -{
> - unsigned long xfer = pSRB->SGToBeXferLen - residue;
> -
> - /* xfer more bytes transferred */
> - pSRB->SGBusAddr += xfer;
> - pSRB->TotalXferredLen += xfer;
> - pSRB->SGToBeXferLen = residue;
> -
> - return xfer;
> -}
> -
> -static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
> -{
> - struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
> - while (pDCB->TargetID != id || pDCB->TargetLUN != lun)
> - {
> - pDCB = pDCB->pNextDCB;
> - if (pDCB == pACB->pLinkDCB)
> - return NULL;
> - }
> - DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n", \
> - pDCB, pDCB->TargetID, pDCB->TargetLUN));
> - return pDCB;
> -}
> -
> -/* Insert SRB oin top of free list */
> -static __inline__ void dc390_Free_insert (struct dc390_acb* pACB, struct dc390_srb* pSRB)
> -{
> - DEBUG0(printk ("DC390: Free SRB %p\n", pSRB));
> - pSRB->pNextSRB = pACB->pFreeSRB;
> - pACB->pFreeSRB = pSRB;
> -}
> -
> -static __inline__ void dc390_Going_append (struct dc390_dcb* pDCB, struct dc390_srb* 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;
> -
> - pDCB->pGoingLast = pSRB;
> - /* No next one in sent list */
> - pSRB->pNextSRB = NULL;
> -}
> -
> -static __inline__ void dc390_Going_remove (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> -{
> - DEBUG0(printk("DC390: Remove SRB %p from Going\n", pSRB));
> - if (pSRB == pDCB->pGoingSRB)
> - pDCB->pGoingSRB = pSRB->pNextSRB;
> - else
> - {
> - struct dc390_srb* 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 struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length)
> -{
> - sg_init_one(sg, addr, length);
> - return sg;
> -}
> -
> -/* Create pci mapping */
> -static int dc390_pci_map (struct dc390_srb* pSRB)
> -{
> - int error = 0;
> - struct scsi_cmnd *pcmd = pSRB->pcmd;
> - struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
> - dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp));
> -
> - /* Map sense buffer */
> - if (pSRB->SRBFlag & AUTO_REQSENSE) {
> - pSRB->pSegmentList = dc390_sg_build_single(&pSRB->Segmentx, pcmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
> - pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, 1,
> - DMA_FROM_DEVICE);
> - cmdp->saved_dma_handle = sg_dma_address(pSRB->pSegmentList);
> -
> - /* TODO: error handling */
> - if (pSRB->SGcount != 1)
> - error = 1;
> - DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __func__, pcmd->sense_buffer, cmdp->saved_dma_handle));
> - /* Map SG list */
> - } else if (scsi_sg_count(pcmd)) {
> - int nseg;
> -
> - nseg = scsi_dma_map(pcmd);
> -
> - pSRB->pSegmentList = scsi_sglist(pcmd);
> - pSRB->SGcount = nseg;
> -
> - /* TODO: error handling */
> - if (nseg < 0)
> - error = 1;
> - DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
> - __func__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
> - /* Map single segment */
> - } else
> - pSRB->SGcount = 0;
> -
> - return error;
> -}
> -
> -/* Remove pci mapping */
> -static void dc390_pci_unmap (struct dc390_srb* pSRB)
> -{
> - struct scsi_cmnd *pcmd = pSRB->pcmd;
> - struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
> - DEBUG1(dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp)));
> -
> - if (pSRB->SRBFlag) {
> - pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
> - DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __func__, cmdp->saved_dma_handle));
> - } else {
> - scsi_dma_unmap(pcmd);
> - DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
> - __func__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
> - }
> -}
> -
> -static void __inline__
> -dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> -{
> - if (pSRB->TagNumber != SCSI_NO_TAG) {
> - pDCB->TagMask &= ~(1 << pSRB->TagNumber); /* free tag mask */
> - pSRB->TagNumber = SCSI_NO_TAG;
> - }
> -}
> -
> -
> -static int
> -dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
> -{
> - struct scsi_cmnd *scmd = pSRB->pcmd;
> - struct scsi_device *sdev = scmd->device;
> - u8 cmd, disc_allowed, try_sync_nego;
> -
> - pSRB->ScsiPhase = SCSI_NOP0;
> -
> - 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;
> - }
> - if (time_before (jiffies, pACB->last_reset))
> - {
> - DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n"));
> - return 1;
> - }
> - /* KG: Moved pci mapping here */
> - dc390_pci_map(pSRB);
> - /* TODO: error handling */
> - DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
> - DC390_write8 (Sync_Period, pDCB->SyncPeriod);
> - DC390_write8 (Sync_Offset, pDCB->SyncOffset);
> - DC390_write8 (CtrlReg1, pDCB->CtrlR1);
> - DC390_write8 (CtrlReg3, pDCB->CtrlR3);
> - 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",\
> - scmd->cmnd[0], pDCB->SyncMode));
> -
> - /* 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->SRBFlag & AUTO_REQSENSE))
> - disc_allowed = pDCB->DevMode & EN_DISCONNECT_;
> - else
> - disc_allowed = 0;
> -
> - if ((pDCB->SyncMode & SYNC_ENABLE) && pDCB->TargetLUN == 0 && sdev->sdtr &&
> - (((scmd->cmnd[0] == REQUEST_SENSE || (pSRB->SRBFlag & AUTO_REQSENSE)) &&
> - !(pDCB->SyncMode & SYNC_NEGO_DONE)) || scmd->cmnd[0] == INQUIRY))
> - try_sync_nego = 1;
> - else
> - try_sync_nego = 0;
> -
> - pSRB->MsgCnt = 0;
> - cmd = SEL_W_ATN;
> - DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->TargetLUN));
> - /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */
> - if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed && (scmd->flags & SCMD_TAGGED)) {
> - DC390_write8(ScsiFifo, MSG_SIMPLE_TAG);
> - pDCB->TagMask |= 1 << scmd->request->tag;
> - pSRB->TagNumber = scmd->request->tag;
> - DC390_write8(ScsiFifo, scmd->request->tag);
> - DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for SRB %p, block tag %02x\n", pSRB, tag[1]));
> - cmd = SEL_W_ATN3;
> - } else {
> - /* No TagQ */
> -//no_tag:
> - DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for SRB %p, No TagQ\n", disc_allowed ? "" : "o", pSRB));
> - }
> -
> - pSRB->SRBState = SRB_START_;
> -
> - if (try_sync_nego)
> - {
> - u8 Sync_Off = pDCB->SyncOffset;
> - DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN));
> - 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 )
> - {
> - DC390_write8 (ScsiFifo, REQUEST_SENSE);
> - DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
> - DC390_write8 (ScsiFifo, 0);
> - DC390_write8 (ScsiFifo, 0);
> - DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
> - DC390_write8 (ScsiFifo, 0);
> - DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n"));
> - }
> - else /* write cmnd to bus */
> - {
> - u8 *ptr; u8 i;
> - ptr = (u8 *)scmd->cmnd;
> - for (i = 0; i < scmd->cmd_len; i++)
> - DC390_write8 (ScsiFifo, *(ptr++));
> - }
> - }
> - 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 (target %02i-%02i)\n",
> - scmd->device->id, (u8)scmd->device->lun));
> - pSRB->SRBState = SRB_READY;
> - //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> - pACB->SelLost++;
> - return 1;
> - }
> - DC390_write8 (ScsiCmd, cmd);
> - pACB->pActiveDCB = pDCB;
> - pDCB->pActiveSRB = pSRB;
> - pACB->Connected = 1;
> - pSRB->ScsiPhase = SCSI_NOP1;
> - return 0;
> -}
> -
> -
> -static void __inline__
> -dc390_InvalidCmd(struct dc390_acb* pACB)
> -{
> - if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT))
> - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
> -}
> -
> -
> -static irqreturn_t __inline__
> -DC390_Interrupt(void *dev_id)
> -{
> - struct dc390_acb *pACB = dev_id;
> - struct dc390_dcb *pDCB;
> - struct dc390_srb *pSRB;
> - u8 sstatus=0;
> - u8 phase;
> - void (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *);
> - u8 istate, istatus;
> -
> - sstatus = DC390_read8 (Scsi_Status);
> - if( !(sstatus & INTERRUPT) )
> - return IRQ_NONE;
> -
> - DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
> -
> - //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
> - //dstatus = DC390_read8 (DMA_Status);
> - //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
> -
> - spin_lock_irq(pACB->pScsiHost->host_lock);
> -
> - istate = DC390_read8 (Intern_State);
> - istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
> -
> - DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus));
> - dc390_laststatus &= ~0x00ffffff;
> - dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
> -
> - if (sstatus & ILLEGAL_OP_ERR)
> - {
> - printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus);
> - dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
> - }
> -
> - 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)
> - {
> - 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) )
> - {
> - pDCB = pACB->pActiveDCB;
> - if (!pDCB)
> - {
> - printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
> - goto unlock;
> - }
> - pSRB = pDCB->pActiveSRB;
> - if( pDCB->DCBFlag & ABORT_DEV_ )
> - dc390_EnableMsgOut_Abort (pACB, pSRB);
> -
> - phase = pSRB->ScsiPhase;
> - DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus));
> - stateV = (void *) dc390_phase0[phase];
> - ( *stateV )( pACB, pSRB, &sstatus );
> -
> - pSRB->ScsiPhase = sstatus & 7;
> - phase = (u8) sstatus & 7;
> - DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus));
> - stateV = (void *) dc390_phase1[phase];
> - ( *stateV )( pACB, pSRB, &sstatus );
> - }
> -
> - unlock:
> - spin_unlock_irq(pACB->pScsiHost->host_lock);
> - return IRQ_HANDLED;
> -}
> -
> -static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id)
> -{
> - irqreturn_t ret;
> - DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq));
> - /* Locking is done in DC390_Interrupt */
> - ret = DC390_Interrupt(dev_id);
> - DEBUG1(printk (".. IRQ returned\n"));
> - return ret;
> -}
> -
> -static void
> -dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> - u8 sstatus;
> - u32 ResidCnt;
> - u8 dstate = 0;
> -
> - sstatus = *psstatus;
> -
> - if( !(pSRB->SRBState & SRB_XFERPAD) )
> - {
> - if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) )
> - pSRB->SRBStatus |= PARITY_ERROR;
> -
> - if( sstatus & COUNT_2_ZERO )
> - {
> - unsigned long timeout = jiffies + HZ;
> -
> - /* Function called from the ISR with the host_lock held and interrupts disabled */
> - if (pSRB->SGToBeXferLen)
> - while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
> - spin_unlock_irq(pACB->pScsiHost->host_lock);
> - udelay(50);
> - spin_lock_irq(pACB->pScsiHost->host_lock);
> - }
> - if (!time_before(jiffies, timeout))
> - printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n",
> - DC390_read32 (DMA_Wk_ByteCntr));
> - dc390_laststatus &= ~0xff000000;
> - dc390_laststatus |= dstate << 24;
> - pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
> - pSRB->SGIndex++;
> - if( pSRB->SGIndex < pSRB->SGcount )
> - {
> - pSRB->pSegmentList++;
> -
> - dc390_start_segment(pSRB);
> - }
> - else
> - pSRB->SGToBeXferLen = 0;
> - }
> - else
> - {
> - ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
> - (((u32) DC390_read8 (CtcReg_High) << 16) |
> - ((u32) DC390_read8 (CtcReg_Mid) << 8) |
> - (u32) DC390_read8 (CtcReg_Low));
> -
> - dc390_advance_segment(pSRB, ResidCnt);
> - }
> - }
> - if ((*psstatus & 7) != SCSI_DATA_OUT)
> - {
> - DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD);
> - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> - }
> -}
> -
> -static void
> -dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> - u8 sstatus, residual, bval;
> - u32 ResidCnt, i;
> - unsigned long xferCnt;
> -
> - sstatus = *psstatus;
> -
> - if( !(pSRB->SRBState & SRB_XFERPAD) )
> - {
> - if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR))
> - pSRB->SRBStatus |= PARITY_ERROR;
> -
> - if( sstatus & COUNT_2_ZERO )
> - {
> - int dstate = 0;
> - unsigned long timeout = jiffies + HZ;
> -
> - /* Function called from the ISR with the host_lock held and interrupts disabled */
> - if (pSRB->SGToBeXferLen)
> - while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
> - spin_unlock_irq(pACB->pScsiHost->host_lock);
> - udelay(50);
> - spin_lock_irq(pACB->pScsiHost->host_lock);
> - }
> - if (!time_before(jiffies, timeout)) {
> - printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n",
> - DC390_read32 (DMA_Wk_ByteCntr));
> - printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
> - }
> - dc390_laststatus &= ~0xff000000;
> - dc390_laststatus |= dstate << 24;
> - DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16) \
> - + ((unsigned long) DC390_read8 (CtcReg_Mid) << 8) \
> - + ((unsigned long) DC390_read8 (CtcReg_Low)));
> - DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%u,ToBeXfer=%lu),", ResidCnt, pSRB->SGToBeXferLen));
> -
> - DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
> -
> - pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
> - pSRB->SGIndex++;
> - if( pSRB->SGIndex < pSRB->SGcount )
> - {
> - pSRB->pSegmentList++;
> -
> - dc390_start_segment(pSRB);
> - }
> - else
> - pSRB->SGToBeXferLen = 0;
> - }
> - else /* phase changed */
> - {
> - residual = 0;
> - bval = DC390_read8 (Current_Fifo);
> - while( bval & 0x1f )
> - {
> - DEBUG1(printk (KERN_DEBUG "Check for residuals,"));
> - if( (bval & 0x1f) == 1 )
> - {
> - for(i=0; i < 0x100; i++)
> - {
> - bval = DC390_read8 (Current_Fifo);
> - if( !(bval & 0x1f) )
> - goto din_1;
> - else if( i == 0x0ff )
> - {
> - residual = 1; /* ;1 residual byte */
> - goto din_1;
> - }
> - }
> - }
> - else
> - bval = DC390_read8 (Current_Fifo);
> - }
> -din_1:
> - DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
> - for (i = 0xa000; i; i--)
> - {
> - bval = DC390_read8 (DMA_Status);
> - if (bval & BLAST_COMPLETE)
> - break;
> - }
> - /* It seems a DMA Blast abort isn't that bad ... */
> - if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
> - //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
> - dc390_laststatus &= ~0xff000000;
> - dc390_laststatus |= bval << 24;
> -
> - DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
> - ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
> - ((u32) DC390_read8 (CtcReg_Mid) << 8)) |
> - (u32) DC390_read8 (CtcReg_Low);
> -
> - xferCnt = dc390_advance_segment(pSRB, ResidCnt);
> -
> - if (residual) {
> - size_t count = 1;
> - size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList);
> - unsigned long flags;
> - u8 *ptr;
> -
> - bval = DC390_read8 (ScsiFifo); /* get one residual byte */
> -
> - local_irq_save(flags);
> - ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
> - if (likely(ptr)) {
> - *(ptr + offset) = bval;
> - scsi_kunmap_atomic_sg(ptr);
> - }
> - local_irq_restore(flags);
> - WARN_ON(!ptr);
> -
> - /* 1 more byte read */
> - xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
> - }
> - DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
> - pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
> - }
> - }
> - if ((*psstatus & 7) != SCSI_DATA_IN)
> - {
> - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> - DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
> - }
> -}
> -
> -static void
> -dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -}
> -
> -static void
> -dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -
> - pSRB->TargetStatus = DC390_read8 (ScsiFifo);
> - //udelay (1);
> - pSRB->EndMessage = DC390_read8 (ScsiFifo); /* get message */
> -
> - *psstatus = SCSI_NOP0;
> - pSRB->SRBState = SRB_COMPLETED;
> - DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
> -}
> -
> -static void
> -dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> - if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
> - *psstatus = SCSI_NOP0;
> - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -}
> -
> -
> -static void __inline__
> -dc390_reprog (struct dc390_acb* pACB, struct dc390_dcb* pDCB)
> -{
> - DC390_write8 (Sync_Period, pDCB->SyncPeriod);
> - DC390_write8 (Sync_Offset, pDCB->SyncOffset);
> - DC390_write8 (CtrlReg3, pDCB->CtrlR3);
> - DC390_write8 (CtrlReg4, pDCB->CtrlR4);
> - dc390_SetXferRate (pACB, pDCB);
> -}
> -
> -
> -#ifdef DC390_DEBUG0
> -static void
> -dc390_printMsg (u8 *MsgBuf, u8 len)
> -{
> - int i;
> - printk (" %02x", MsgBuf[0]);
> - for (i = 1; i < len; i++)
> - printk (" %02x", MsgBuf[i]);
> - printk ("\n");
> -}
> -#endif
> -
> -#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
> -
> -/* reject_msg */
> -static void __inline__
> -dc390_MsgIn_reject (struct dc390_acb* pACB, struct dc390_srb* pSRB)
> -{
> - pSRB->MsgOutBuf[0] = MESSAGE_REJECT;
> - pSRB->MsgCnt = 1;
> - DC390_ENABLE_MSGOUT;
> - DEBUG0 (printk (KERN_INFO "DC390: Reject message\n"));
> -}
> -
> -/* abort command */
> -static void
> -dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB )
> -{
> - pSRB->MsgOutBuf[0] = ABORT;
> - pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
> - pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
> -}
> -
> -static struct dc390_srb*
> -dc390_MsgIn_QTag (struct dc390_acb* pACB, struct dc390_dcb* pDCB, s8 tag)
> -{
> - struct dc390_srb* pSRB = pDCB->pGoingSRB;
> -
> - if (pSRB)
> - {
> - struct scsi_cmnd *scmd = scsi_find_tag(pSRB->pcmd->device, tag);
> - pSRB = (struct dc390_srb *)scmd->host_scribble;
> -
> - if (pDCB->DCBFlag & ABORT_DEV_)
> - {
> - pSRB->SRBState = SRB_ABORT_SENT;
> - dc390_EnableMsgOut_Abort( pACB, pSRB );
> - }
> -
> - if (!(pSRB->SRBState & SRB_DISCONNECT))
> - goto mingx0;
> -
> - pDCB->pActiveSRB = pSRB;
> - pSRB->SRBState = SRB_DATA_XFER;
> - }
> - else
> - {
> - mingx0:
> - pSRB = pACB->pTmpSRB;
> - pSRB->SRBState = SRB_UNEXPECT_RESEL;
> - pDCB->pActiveSRB = pSRB;
> - pSRB->MsgOutBuf[0] = ABORT_TAG;
> - pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
> - }
> - return pSRB;
> -}
> -
> -
> -/* set async transfer mode */
> -static void
> -dc390_MsgIn_set_async (struct dc390_acb* pACB, struct dc390_srb* pSRB)
> -{
> - struct dc390_dcb* pDCB = pSRB->pSRBDCB;
> - if (!(pSRB->SRBState & DO_SYNC_NEGO))
> - printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID);
> - pSRB->SRBState &= ~DO_SYNC_NEGO;
> - pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
> - pDCB->SyncPeriod = 0;
> - pDCB->SyncOffset = 0;
> - //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
> - pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */
> - pDCB->CtrlR4 &= 0x3f;
> - pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
> - dc390_reprog (pACB, pDCB);
> -}
> -
> -/* set sync transfer mode */
> -static void
> -dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
> -{
> - u8 bval;
> - u16 wval, wval1;
> - struct dc390_dcb* pDCB = pSRB->pSRBDCB;
> - u8 oldsyncperiod = pDCB->SyncPeriod;
> - u8 oldsyncoffset = pDCB->SyncOffset;
> -
> - if (!(pSRB->SRBState & DO_SYNC_NEGO))
> - {
> - printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n",
> - pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
> -
> - /* reject */
> - //dc390_MsgIn_reject (pACB, pSRB);
> - //return dc390_MsgIn_set_async (pACB, pSRB);
> -
> - /* Reply with corrected SDTR Message */
> - if (pSRB->MsgInBuf[4] > 15)
> - {
> - printk (KERN_INFO "DC390: Lower Sync Offset to 15\n");
> - pSRB->MsgInBuf[4] = 15;
> - }
> - if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
> - {
> - 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);
> - pSRB->MsgCnt = 5;
> - DC390_ENABLE_MSGOUT;
> - }
> -
> - pSRB->SRBState &= ~DO_SYNC_NEGO;
> - pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
> - pDCB->SyncOffset &= 0x0f0;
> - pDCB->SyncOffset |= pSRB->MsgInBuf[4];
> - pDCB->NegoPeriod = pSRB->MsgInBuf[3];
> -
> - wval = (u16) pSRB->MsgInBuf[3];
> - wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */
> - if( (wval1 * 25) != wval) wval1++;
> - bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */
> -
> - pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */
> - if (pACB->glitch_cfg != NS_TO_GLITCH(0))
> - pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
> - else
> - pDCB->CtrlR4 |= NS_TO_GLITCH(0);
> - if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
> -
> - if (wval1 >= 8)
> - {
> - wval1--; /* Timing computation differs by 1 from FAST_SCSI */
> - bval = FAST_CLK; /* fast clock / normal scsi */
> - pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
> - }
> -
> - pDCB->CtrlR3 = bval;
> - pDCB->SyncPeriod = (u8)wval1;
> -
> - if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0)
> - {
> - if (! (bval & FAST_SCSI)) wval1++;
> - printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID,
> - 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
> - }
> -
> - dc390_reprog (pACB, pDCB);
> -}
> -
> -
> -/* handle RESTORE_PTR */
> -/* This doesn't look very healthy... to-be-fixed */
> -static void
> -dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
> -{
> - struct scsi_cmnd *pcmd = pSRB->pcmd;
> - struct scatterlist *psgl;
> - pSRB->TotalXferredLen = 0;
> - pSRB->SGIndex = 0;
> - if (scsi_sg_count(pcmd)) {
> - size_t saved;
> - pSRB->pSegmentList = scsi_sglist(pcmd);
> - psgl = pSRB->pSegmentList;
> - //dc390_pci_sync(pSRB);
> -
> - while (pSRB->TotalXferredLen + (unsigned long) sg_dma_len(psgl) < pSRB->Saved_Ptr)
> - {
> - pSRB->TotalXferredLen += (unsigned long) sg_dma_len(psgl);
> - pSRB->SGIndex++;
> - if( pSRB->SGIndex < pSRB->SGcount )
> - {
> - pSRB->pSegmentList++;
> -
> - dc390_start_segment(pSRB);
> - }
> - else
> - pSRB->SGToBeXferLen = 0;
> - }
> -
> - saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
> - pSRB->SGToBeXferLen -= saved;
> - pSRB->SGBusAddr += saved;
> - printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
> - pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
> -
> - } 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 Successful Operation IRQ before asserting ACK for
> - * the last byte (how does it know whether it's the last ?) */
> -/* The old code handled it in another way, indicating, that on
> - * every message byte an IRQ is generated and every byte has to
> - * be manually ACKed. Hmmm ? (KG, 98/11/28) */
> -/* The old implementation was correct. Sigh! */
> -
> -/* Check if the message is complete */
> -static u8 __inline__
> -dc390_MsgIn_complete (u8 *msgbuf, u32 len)
> -{
> - 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;
> - return 1;
> -}
> -
> -
> -
> -/* read and eval received messages */
> -static void
> -dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> - struct dc390_dcb* pDCB = pACB->pActiveDCB;
> -
> - /* Read the msg */
> -
> - pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
> - //pSRB->SRBState = 0;
> -
> - /* Msg complete ? */
> - if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
> - {
> - DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen));
> - /* Now eval the msg */
> - switch (pSRB->MsgInBuf[0])
> - {
> - case DISCONNECT:
> - pSRB->SRBState = SRB_DISCONNECT; break;
> -
> - case SIMPLE_QUEUE_TAG:
> - case HEAD_OF_QUEUE_TAG:
> - case ORDERED_QUEUE_TAG:
> - pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
> - break;
> -
> - 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 EXTENDED_MESSAGE:
> - /* reject every extended msg but SDTR */
> - if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
> - dc390_MsgIn_reject (pACB, pSRB);
> - else
> - {
> - if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
> - dc390_MsgIn_set_async (pACB, pSRB);
> - else
> - dc390_MsgIn_set_sync (pACB, pSRB);
> - }
> -
> - // nothing has to be done
> - case COMMAND_COMPLETE: break;
> -
> - // SAVE POINTER may be ignored as we have the struct dc390_srb* associated with the
> - // scsi command. Thanks, Gerard, for pointing it out.
> - case SAVE_POINTERS:
> - pSRB->Saved_Ptr = pSRB->TotalXferredLen;
> - break;
> - // The device might want to restart transfer with a RESTORE
> - 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);
> - }
> -
> - /* Clear counter and MsgIn state */
> - pSRB->SRBState &= ~SRB_MSGIN;
> - pACB->MsgLen = 0;
> - }
> -
> - *psstatus = SCSI_NOP0;
> - DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
> - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -}
> -
> -
> -static void
> -dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
> -{
> - unsigned long lval;
> - struct dc390_dcb* pDCB = pACB->pActiveDCB;
> -
> - if (pSRB == pACB->pTmpSRB)
> - {
> - if (pDCB)
> - printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN);
> - else
> - printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
> -
> - /* Try to recover - some broken disks react badly to tagged INQUIRY */
> - if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) {
> - pSRB = pDCB->pGoingSRB;
> - pDCB->pActiveSRB = pSRB;
> - } else {
> - pSRB->pSRBDCB = pDCB;
> - dc390_EnableMsgOut_Abort(pACB, pSRB);
> - if (pDCB)
> - pDCB->DCBFlag |= ABORT_DEV;
> - return;
> - }
> - }
> -
> - if( pSRB->SGIndex < pSRB->SGcount )
> - {
> - DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
> - if( !pSRB->SGToBeXferLen )
> - {
> - dc390_start_segment(pSRB);
> -
> - DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
> - }
> - lval = pSRB->SGToBeXferLen;
> - DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr));
> - DC390_write8 (CtcReg_Low, (u8) lval);
> - lval >>= 8;
> - DC390_write8 (CtcReg_Mid, (u8) lval);
> - lval >>= 8;
> - DC390_write8 (CtcReg_High, (u8) lval);
> -
> - DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
> - DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
> -
> - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
> - pSRB->SRBState = SRB_DATA_XFER;
> -
> - DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
> -
> - DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
> - //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT));
> - //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status)));
> - //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT));
> - }
> - else /* xfer pad */
> - {
> - if( pSRB->SGcount )
> - {
> - pSRB->AdaptStatus = H_OVER_UNDER_RUN;
> - pSRB->SRBStatus |= OVER_RUN;
> - DEBUG0(printk (KERN_WARNING " DC390: Overrun -"));
> - }
> - DEBUG0(printk (KERN_WARNING " Clear transfer pad \n"));
> - DC390_write8 (CtcReg_Low, 0);
> - DC390_write8 (CtcReg_Mid, 0);
> - DC390_write8 (CtcReg_High, 0);
> -
> - pSRB->SRBState |= SRB_XFERPAD;
> - DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
> -/*
> - DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
> - DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
> -*/
> - }
> -}
> -
> -
> -static void
> -dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> - dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);
> -}
> -
> -static void
> -dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> - dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
> -}
> -
> -static void
> -dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> - struct dc390_dcb* pDCB;
> - u8 i, cnt;
> - u8 *ptr;
> -
> - DC390_write8 (ScsiCmd, RESET_ATN_CMD);
> - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> - if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
> - {
> - cnt = (u8) pSRB->pcmd->cmd_len;
> - ptr = (u8 *) pSRB->pcmd->cmnd;
> - for(i=0; i < cnt; i++)
> - DC390_write8 (ScsiFifo, *(ptr++));
> - }
> - else
> - {
> - DC390_write8 (ScsiFifo, REQUEST_SENSE);
> - pDCB = pACB->pActiveDCB;
> - DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
> - DC390_write8 (ScsiFifo, 0);
> - DC390_write8 (ScsiFifo, 0);
> - DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
> - DC390_write8 (ScsiFifo, 0);
> - DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n"));
> - }
> - pSRB->SRBState = SRB_COMMAND;
> - DC390_write8 (ScsiCmd, INFO_XFER_CMD);
> -}
> -
> -static void
> -dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> - pSRB->SRBState = SRB_STATUS;
> - DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
> - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -}
> -
> -static void
> -dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> - u8 bval, i, cnt;
> - u8 *ptr;
> - struct dc390_dcb* pDCB;
> -
> - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> - pDCB = pACB->pActiveDCB;
> - if( !(pSRB->SRBState & SRB_MSGOUT) )
> - {
> - cnt = pSRB->MsgCnt;
> - if( cnt )
> - {
> - ptr = (u8 *) pSRB->MsgOutBuf;
> - for(i=0; i < cnt; i++)
> - DC390_write8 (ScsiFifo, *(ptr++));
> - pSRB->MsgCnt = 0;
> - if( (pDCB->DCBFlag & ABORT_DEV_) &&
> - (pSRB->MsgOutBuf[0] == ABORT) )
> - pSRB->SRBState = SRB_ABORT_SENT;
> - }
> - else
> - {
> - 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 )
> - goto mop1;
> - }
> - DC390_write8 (ScsiFifo, bval);
> - }
> - DC390_write8 (ScsiCmd, INFO_XFER_CMD);
> - }
> - else
> - {
> -mop1:
> - printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);
> - 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);
> - if (pDCB->SyncOffset & 0x0f)
> - DC390_write8 (ScsiFifo, pDCB->SyncOffset);
> - else
> - DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);
> - pSRB->SRBState |= DO_SYNC_NEGO;
> - DC390_write8 (ScsiCmd, INFO_XFER_CMD);
> - }
> -}
> -
> -static void
> -dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> - if( !(pSRB->SRBState & SRB_MSGIN) )
> - {
> - pSRB->SRBState &= ~SRB_DISCONNECT;
> - pSRB->SRBState |= SRB_MSGIN;
> - }
> - DC390_write8 (ScsiCmd, INFO_XFER_CMD);
> - //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> -}
> -
> -static void
> -dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -}
> -
> -static void
> -dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
> -{
> -}
> -
> -
> -static void
> -dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB )
> -{
> - u8 bval, i, cnt;
> - struct dc390_dcb* ptr;
> -
> - if( !(pDCB->TargetLUN) )
> - {
> - if( !pACB->scan_devices )
> - {
> - ptr = pACB->pLinkDCB;
> - cnt = pACB->DCBCnt;
> - bval = pDCB->TargetID;
> - for(i=0; i<cnt; i++)
> - {
> - if( ptr->TargetID == bval )
> - {
> - ptr->SyncPeriod = pDCB->SyncPeriod;
> - ptr->SyncOffset = pDCB->SyncOffset;
> - ptr->CtrlR3 = pDCB->CtrlR3;
> - ptr->CtrlR4 = pDCB->CtrlR4;
> - ptr->SyncMode = pDCB->SyncMode;
> - }
> - ptr = ptr->pNextDCB;
> - }
> - }
> - }
> - return;
> -}
> -
> -
> -static void
> -dc390_Disconnect( struct dc390_acb* pACB )
> -{
> - struct dc390_dcb *pDCB;
> - struct dc390_srb *pSRB, *psrb;
> - u8 i, cnt;
> -
> - 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)
> - {
> - DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
> - pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel));
> - mdelay(400);
> - 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 = NULL;
> - pSRB->ScsiPhase = SCSI_NOP0;
> - if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
> - pSRB->SRBState = 0;
> - else if( pSRB->SRBState & SRB_ABORT_SENT )
> - {
> - pDCB->TagMask = 0;
> - pDCB->DCBFlag = 0;
> - cnt = pDCB->GoingSRBCnt;
> - pDCB->GoingSRBCnt = 0;
> - pSRB = pDCB->pGoingSRB;
> - for( i=0; i < cnt; i++)
> - {
> - psrb = pSRB->pNextSRB;
> - dc390_Free_insert (pACB, pSRB);
> - pSRB = psrb;
> - }
> - pDCB->pGoingSRB = NULL;
> - }
> - else
> - {
> - if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
> - !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
> - { /* Selection time out */
> - pSRB->AdaptStatus = H_SEL_TIMEOUT;
> - pSRB->TargetStatus = 0;
> - goto disc1;
> - }
> - else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED))
> - {
> -disc1:
> - dc390_freetag (pDCB, pSRB);
> - pDCB->pActiveSRB = NULL;
> - pSRB->SRBState = SRB_FREE;
> - dc390_SRBdone( pACB, pDCB, pSRB);
> - }
> - }
> - pACB->MsgLen = 0;
> -}
> -
> -
> -static void
> -dc390_Reselect( struct dc390_acb* pACB )
> -{
> - struct dc390_dcb* pDCB;
> - struct dc390_srb* pSRB;
> - u8 id, lun;
> -
> - DEBUG0(printk(KERN_INFO "RSEL,"));
> - pACB->Connected = 1;
> - pDCB = pACB->pActiveDCB;
> - if( pDCB )
> - { /* Arbitration lost but Reselection won */
> - DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n"));
> - pSRB = pDCB->pActiveSRB;
> - if( !( pACB->scan_devices ) )
> - {
> - struct scsi_cmnd *pcmd = pSRB->pcmd;
> - scsi_set_resid(pcmd, scsi_bufflen(pcmd));
> - SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
> - dc390_Going_remove(pDCB, pSRB);
> - dc390_Free_insert(pACB, pSRB);
> - pcmd->scsi_done (pcmd);
> - DEBUG0(printk(KERN_DEBUG"DC390: Return SRB %p to free\n", pSRB));
> - }
> - }
> - /* Get ID */
> - lun = DC390_read8 (ScsiFifo);
> - DEBUG0(printk ("Dev %02x,", lun));
> - if (!(lun & (1 << pACB->pScsiHost->this_id)))
> - printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun);
> - else
> - lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */
> - id = 0; while (lun >>= 1) id++;
> - /* Get LUN */
> - lun = DC390_read8 (ScsiFifo);
> - if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n");
> - lun &= 7;
> - DEBUG0(printk ("(%02i-%i),", id, lun));
> - pDCB = dc390_findDCB (pACB, id, lun);
> - if (!pDCB)
> - {
> - printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n",
> - id, lun);
> - return;
> - }
> - pACB->pActiveDCB = pDCB;
> - /* TagQ: We expect a message soon, so never mind the exact SRB */
> - if( pDCB->SyncMode & EN_TAG_QUEUEING )
> - {
> - pSRB = pACB->pTmpSRB;
> - pDCB->pActiveSRB = pSRB;
> - }
> - else
> - {
> - pSRB = pDCB->pActiveSRB;
> - if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
> - {
> - pSRB= pACB->pTmpSRB;
> - pSRB->SRBState = SRB_UNEXPECT_RESEL;
> - printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n",
> - id, lun);
> - pDCB->pActiveSRB = pSRB;
> - dc390_EnableMsgOut_Abort ( pACB, pSRB );
> - }
> - else
> - {
> - if( pDCB->DCBFlag & ABORT_DEV_ )
> - {
> - pSRB->SRBState = SRB_ABORT_SENT;
> - printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n",
> - id, lun);
> - dc390_EnableMsgOut_Abort( pACB, pSRB );
> - }
> - else
> - pSRB->SRBState = SRB_DATA_XFER;
> - }
> - }
> -
> - DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber));
> - pSRB->ScsiPhase = SCSI_NOP0;
> - DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
> - DC390_write8 (Sync_Period, pDCB->SyncPeriod);
> - DC390_write8 (Sync_Offset, pDCB->SyncOffset);
> - DC390_write8 (CtrlReg1, pDCB->CtrlR1);
> - DC390_write8 (CtrlReg3, pDCB->CtrlR3);
> - DC390_write8 (CtrlReg4, pDCB->CtrlR4); /* ; Glitch eater */
> - DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); /* ;to release the /ACK signal */
> -}
> -
> -static int __inline__
> -dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> -{
> - struct scsi_cmnd *pcmd;
> -
> - pcmd = pSRB->pcmd;
> -
> - REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
> - pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
> -
> - pSRB->SRBFlag |= AUTO_REQSENSE;
> - pSRB->SavedTotXLen = pSRB->TotalXferredLen;
> - pSRB->AdaptStatus = 0;
> - pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
> -
> - /* We are called from SRBdone, original PCI mapping has been removed
> - * already, new one is set up from StartSCSI */
> - pSRB->SGIndex = 0;
> -
> - pSRB->TotalXferredLen = 0;
> - pSRB->SGToBeXferLen = 0;
> - return dc390_StartSCSI(pACB, pDCB, pSRB);
> -}
> -
> -
> -static void
> -dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
> -{
> - u8 status;
> - struct scsi_cmnd *pcmd;
> -
> - pcmd = pSRB->pcmd;
> - /* KG: Moved pci_unmap here */
> - dc390_pci_unmap(pSRB);
> -
> - status = pSRB->TargetStatus;
> -
> - DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p\n", status, pcmd->result, pSRB));
> - if(pSRB->SRBFlag & AUTO_REQSENSE)
> - { /* Last command was a Request Sense */
> - pSRB->SRBFlag &= ~AUTO_REQSENSE;
> - pSRB->AdaptStatus = 0;
> - pSRB->TargetStatus = SAM_STAT_CHECK_CONDITION;
> -
> - //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
> - if (status == SAM_STAT_CHECK_CONDITION)
> - pcmd->result = MK_RES_LNX(0, DID_BAD_TARGET, 0, /*CHECK_CONDITION*/0);
> - else /* Retry */
> - {
> - if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
> - {
> - /* Don't retry on TEST_UNIT_READY */
> - pcmd->result = MK_RES_LNX(DRIVER_SENSE, DID_OK, 0, SAM_STAT_CHECK_CONDITION);
> - REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
> - (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
> - } else {
> - SET_RES_DRV(pcmd->result, DRIVER_SENSE);
> - //pSRB->ScsiCmdLen = (u8) (pSRB->Segment1[0] >> 8);
> - DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
> - pSRB->TotalXferredLen = 0;
> - SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
> - }
> - }
> - goto cmd_done;
> - }
> - if( status )
> - {
> - if (status == SAM_STAT_CHECK_CONDITION)
> - {
> - if (dc390_RequestSense(pACB, pDCB, pSRB)) {
> - SET_RES_DID(pcmd->result, DID_ERROR);
> - goto cmd_done;
> - }
> - return;
> - }
> - else if (status == SAM_STAT_TASK_SET_FULL)
> - {
> - scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
> - DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
> - pSRB->TotalXferredLen = 0;
> - SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
> - }
> - else if (status == SAM_STAT_BUSY &&
> - (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
> - pACB->scan_devices)
> - {
> - pSRB->AdaptStatus = 0;
> - pSRB->TargetStatus = status;
> - pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0);
> - }
> - else
> - { /* Another error */
> - pSRB->TotalXferredLen = 0;
> - SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
> - goto cmd_done;
> - }
> - }
> - else
> - { /* Target status == 0 */
> - status = pSRB->AdaptStatus;
> - if (status == H_OVER_UNDER_RUN)
> - {
> - pSRB->TargetStatus = 0;
> - SET_RES_DID(pcmd->result,DID_OK);
> - SET_RES_MSG(pcmd->result,pSRB->EndMessage);
> - }
> - else if (status == H_SEL_TIMEOUT)
> - {
> - pcmd->result = MK_RES(0, DID_NO_CONNECT, 0, 0);
> - /* Devices are removed below ... */
> - }
> - else if( pSRB->SRBStatus & PARITY_ERROR)
> - {
> - //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;
> - SET_RES_DID(pcmd->result,DID_OK);
> - }
> - }
> -
> -cmd_done:
> - scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen);
> -
> - dc390_Going_remove (pDCB, pSRB);
> - /* Add to free list */
> - dc390_Free_insert (pACB, pSRB);
> -
> - DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done\n"));
> - pcmd->scsi_done (pcmd);
> -
> - return;
> -}
> -
> -
> -/* Remove all SRBs from Going list and inform midlevel */
> -static void
> -dc390_DoingSRB_Done(struct dc390_acb* pACB, struct scsi_cmnd *cmd)
> -{
> - struct dc390_dcb *pDCB, *pdcb;
> - struct dc390_srb *psrb, *psrb2;
> - int i;
> - struct scsi_cmnd *pcmd;
> -
> - pDCB = pACB->pLinkDCB;
> - pdcb = pDCB;
> - if (! pdcb) return;
> - do
> - {
> - psrb = pdcb->pGoingSRB;
> - for (i = 0; i < pdcb->GoingSRBCnt; i++)
> - {
> - psrb2 = psrb->pNextSRB;
> - pcmd = psrb->pcmd;
> - dc390_Free_insert (pACB, psrb);
> - psrb = psrb2;
> - }
> - pdcb->GoingSRBCnt = 0;
> - pdcb->pGoingSRB = NULL;
> - pdcb->TagMask = 0;
> - pdcb = pdcb->pNextDCB;
> - } while( pdcb != pDCB );
> -}
> -
> -
> -static void
> -dc390_ResetSCSIBus( struct dc390_acb* pACB )
> -{
> - //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;
> -}
> -
> -static void
> -dc390_ScsiRstDetect( struct dc390_acb* pACB )
> -{
> - printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus);
> - //DEBUG0(printk(KERN_INFO "RST_DETECT,"));
> -
> - DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
> - /* Unlock before ? */
> - /* delay half a second */
> - udelay (1000);
> - DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
> - pACB->last_reset = jiffies + 5*HZ/2
> - + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
> - 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, NULL);
> - //dc390_RecoverSRB( pACB );
> - pACB->pActiveDCB = NULL;
> - pACB->ACBFlag = 0;
> - }
> - return;
> -}
> -
> -static int DC390_queuecommand_lck(struct scsi_cmnd *cmd,
> - void (*done)(struct scsi_cmnd *))
> -{
> - struct scsi_device *sdev = cmd->device;
> - struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
> - struct dc390_dcb *dcb = sdev->hostdata;
> - struct dc390_srb *srb;
> -
> - if (sdev->queue_depth <= dcb->GoingSRBCnt)
> - goto device_busy;
> - if (acb->pActiveDCB)
> - goto host_busy;
> - if (acb->ACBFlag & (RESET_DETECT|RESET_DONE|RESET_DEV))
> - goto host_busy;
> -
> - srb = acb->pFreeSRB;
> - if (unlikely(srb == NULL))
> - goto host_busy;
> -
> - cmd->scsi_done = done;
> - cmd->result = 0;
> - acb->Cmds++;
> -
> - acb->pFreeSRB = srb->pNextSRB;
> - srb->pNextSRB = NULL;
> -
> - srb->pSRBDCB = dcb;
> - srb->pcmd = cmd;
> - cmd->host_scribble = (char *)srb;
> -
> - srb->SGIndex = 0;
> - srb->AdaptStatus = 0;
> - srb->TargetStatus = 0;
> - srb->MsgCnt = 0;
> -
> - srb->SRBStatus = 0;
> - srb->SRBFlag = 0;
> - srb->SRBState = 0;
> - srb->TotalXferredLen = 0;
> - srb->SGBusAddr = 0;
> - srb->SGToBeXferLen = 0;
> - srb->ScsiPhase = 0;
> - srb->EndMessage = 0;
> - srb->TagNumber = SCSI_NO_TAG;
> -
> - if (dc390_StartSCSI(acb, dcb, srb)) {
> - dc390_Free_insert(acb, srb);
> - goto host_busy;
> - }
> -
> - dc390_Going_append(dcb, srb);
> -
> - return 0;
> -
> - host_busy:
> - return SCSI_MLQUEUE_HOST_BUSY;
> -
> - device_busy:
> - return SCSI_MLQUEUE_DEVICE_BUSY;
> -}
> -
> -static DEF_SCSI_QCMD(DC390_queuecommand)
> -
> -static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
> -{
> - struct pci_dev *pdev;
> - u16 pstat;
> -
> - if (!pDCB) pDCB = pACB->pActiveDCB;
> - if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB;
> -
> - if (pSRB)
> - {
> - 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): %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",
> - DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16),
> - DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State));
> - printk (" %02x %02x %02x %02x %02x %02x\n",
> - DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),
> - DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));
> - DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
> - 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",
> - DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr),
> - DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr),
> - DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl));
> - DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
> -
> - pdev = pACB->pdev;
> - pci_read_config_word(pdev, PCI_STATUS, &pstat);
> - printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
> - printk ("DC390: In case of driver trouble read Documentation/scsi/tmscsim.txt\n");
> -}
> -
> -
> -static int DC390_abort(struct scsi_cmnd *cmd)
> -{
> - struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
> - struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
> -
> - scmd_printk(KERN_WARNING, cmd, "DC390: Abort command\n");
> -
> - /* 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, NULL);
> -
> - pDCB->DCBFlag |= ABORT_DEV_;
> - printk(KERN_INFO "DC390: Aborted.\n");
> -
> - return FAILED;
> -}
> -
> -
> -static void dc390_ResetDevParam( struct dc390_acb* pACB )
> -{
> - struct dc390_dcb *pDCB, *pdcb;
> -
> - pDCB = pACB->pLinkDCB;
> - if (! pDCB) return;
> - pdcb = pDCB;
> - do
> - {
> - 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);
> -
> -}
> -
> -static int DC390_bus_reset (struct scsi_cmnd *cmd)
> -{
> - struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata;
> - u8 bval;
> -
> - spin_lock_irq(cmd->device->host->host_lock);
> -
> - bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
> - DC390_write8(CtrlReg1, bval); /* disable IRQ on bus reset */
> -
> - pACB->ACBFlag |= RESET_DEV;
> - dc390_ResetSCSIBus(pACB);
> -
> - dc390_ResetDevParam(pACB);
> - mdelay(1);
> - pACB->last_reset = jiffies + 3*HZ/2
> - + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
> -
> - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
> - DC390_read8(INT_Status); /* Reset Pending INT */
> -
> - dc390_DoingSRB_Done(pACB, cmd);
> -
> - pACB->pActiveDCB = NULL;
> - pACB->ACBFlag = 0;
> -
> - bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
> - DC390_write8(CtrlReg1, bval); /* re-enable interrupt */
> -
> - spin_unlock_irq(cmd->device->host->host_lock);
> -
> - return SUCCESS;
> -}
> -
> -/**
> - * dc390_slave_alloc - Called by the scsi mid layer to tell us about a new
> - * scsi device that we need to deal with.
> - *
> - * @scsi_device: The new scsi device that we need to handle.
> - */
> -static int dc390_slave_alloc(struct scsi_device *scsi_device)
> -{
> - struct dc390_acb *pACB = (struct dc390_acb*) scsi_device->host->hostdata;
> - struct dc390_dcb *pDCB, *pDCB2 = NULL;
> - uint id = scsi_device->id;
> - uint lun = scsi_device->lun;
> -
> - pDCB = kzalloc(sizeof(struct dc390_dcb), GFP_KERNEL);
> - if (!pDCB)
> - return -ENOMEM;
> -
> - if (!pACB->DCBCnt++) {
> - pACB->pLinkDCB = pDCB;
> - pACB->pDCBRunRobin = pDCB;
> - } else {
> - pACB->pLastDCB->pNextDCB = pDCB;
> - }
> -
> - pDCB->pNextDCB = pACB->pLinkDCB;
> - pACB->pLastDCB = pDCB;
> -
> - pDCB->pDCBACB = pACB;
> - pDCB->TargetID = id;
> - pDCB->TargetLUN = lun;
> -
> - /*
> - * Some values are for all LUNs: Copy them
> - * In a clean way: We would have an own structure for a SCSI-ID
> - */
> - if (lun && (pDCB2 = dc390_findDCB(pACB, id, 0))) {
> - pDCB->DevMode = pDCB2->DevMode;
> - pDCB->SyncMode = pDCB2->SyncMode & SYNC_NEGO_DONE;
> - pDCB->SyncPeriod = pDCB2->SyncPeriod;
> - pDCB->SyncOffset = pDCB2->SyncOffset;
> - pDCB->NegoPeriod = pDCB2->NegoPeriod;
> -
> - pDCB->CtrlR3 = pDCB2->CtrlR3;
> - pDCB->CtrlR4 = pDCB2->CtrlR4;
> - } else {
> - u8 index = pACB->AdapterIndex;
> - PEEprom prom = (PEEprom) &dc390_eepromBuf[index][id << 2];
> -
> - pDCB->DevMode = prom->EE_MODE1;
> - 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;
> - }
> -
> - if (pDCB->DevMode & SYNC_NEGO_)
> - pDCB->SyncMode |= SYNC_ENABLE;
> - else {
> - pDCB->SyncMode = 0;
> - pDCB->SyncOffset &= ~0x0f;
> - }
> -
> - pDCB->CtrlR1 = pACB->pScsiHost->this_id;
> - if (pDCB->DevMode & PARITY_CHK_)
> - pDCB->CtrlR1 |= PARITY_ERR_REPO;
> -
> - pACB->scan_devices = 1;
> - scsi_device->hostdata = pDCB;
> - return 0;
> -}
> -
> -/**
> - * dc390_slave_destroy - Called by the scsi mid layer to tell us about a
> - * device that is going away.
> - *
> - * @scsi_device: The scsi device that we need to remove.
> - */
> -static void dc390_slave_destroy(struct scsi_device *scsi_device)
> -{
> - struct dc390_acb* pACB = (struct dc390_acb*) scsi_device->host->hostdata;
> - struct dc390_dcb* pDCB = (struct dc390_dcb*) scsi_device->hostdata;
> - struct dc390_dcb* pPrevDCB = pACB->pLinkDCB;
> -
> - pACB->scan_devices = 0;
> -
> - BUG_ON(pDCB->GoingSRBCnt > 1);
> -
> - if (pDCB == pACB->pLinkDCB) {
> - if (pACB->pLastDCB == pDCB) {
> - pDCB->pNextDCB = NULL;
> - pACB->pLastDCB = NULL;
> - }
> - pACB->pLinkDCB = pDCB->pNextDCB;
> - } else {
> - while (pPrevDCB->pNextDCB != pDCB)
> - pPrevDCB = pPrevDCB->pNextDCB;
> - pPrevDCB->pNextDCB = pDCB->pNextDCB;
> - if (pDCB == pACB->pLastDCB)
> - pACB->pLastDCB = pPrevDCB;
> - }
> -
> - if (pDCB == pACB->pActiveDCB)
> - pACB->pActiveDCB = NULL;
> - if (pDCB == pACB->pLinkDCB)
> - pACB->pLinkDCB = pDCB->pNextDCB;
> - if (pDCB == pACB->pDCBRunRobin)
> - pACB->pDCBRunRobin = pDCB->pNextDCB;
> - kfree(pDCB);
> -
> - pACB->DCBCnt--;
> -}
> -
> -static int dc390_slave_configure(struct scsi_device *sdev)
> -{
> - struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
> - struct dc390_dcb *dcb = (struct dc390_dcb *)sdev->hostdata;
> -
> - acb->scan_devices = 0;
> -
> - /*
> - * XXX: Note that while this driver used to called scsi_activate_tcq,
> - * it never actually set a tag type, so emulate the old behavior.
> - */
> - scsi_set_tag_type(sdev, 0);
> -
> - if (sdev->tagged_supported && (dcb->DevMode & TAG_QUEUEING_)) {
> - dcb->SyncMode |= EN_TAG_QUEUEING;
> - scsi_adjust_queue_depth(sdev, acb->TagMaxNum);
> - }
> -
> - return 0;
> -}
> -
> -static struct scsi_host_template driver_template = {
> - .module = THIS_MODULE,
> - .proc_name = "tmscsim",
> - .name = DC390_BANNER " V" DC390_VERSION,
> - .slave_alloc = dc390_slave_alloc,
> - .slave_configure = dc390_slave_configure,
> - .slave_destroy = dc390_slave_destroy,
> - .queuecommand = DC390_queuecommand,
> - .eh_abort_handler = DC390_abort,
> - .eh_bus_reset_handler = DC390_bus_reset,
> - .can_queue = 1,
> - .this_id = 7,
> - .sg_tablesize = SG_ALL,
> - .cmd_per_lun = 1,
> - .use_clustering = ENABLE_CLUSTERING,
> - .max_sectors = 0x4000, /* 8MiB = 16 * 1024 * 512 */
> - .use_blk_tags = 1,
> -};
> -
> -/***********************************************************************
> - * Functions for access to DC390 EEPROM
> - * and some to emulate it
> - *
> - **********************************************************************/
> -
> -static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
> -{
> - u8 carryFlag = 1, j = 0x80, bval;
> - int i;
> -
> - for (i = 0; i < 9; i++) {
> - if (carryFlag) {
> - pci_write_config_byte(pdev, 0x80, 0x40);
> - bval = 0xc0;
> - } else
> - bval = 0x80;
> -
> - udelay(160);
> - pci_write_config_byte(pdev, 0x80, bval);
> - udelay(160);
> - pci_write_config_byte(pdev, 0x80, 0);
> - udelay(160);
> -
> - carryFlag = (cmd & j) ? 1 : 0;
> - j >>= 1;
> - }
> -}
> -
> -static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
> -{
> - int i;
> - u16 wval = 0;
> - u8 bval;
> -
> - for (i = 0; i < 16; i++) {
> - wval <<= 1;
> -
> - pci_write_config_byte(pdev, 0x80, 0x80);
> - udelay(160);
> - pci_write_config_byte(pdev, 0x80, 0x40);
> - udelay(160);
> - pci_read_config_byte(pdev, 0x00, &bval);
> -
> - if (bval == 0x22)
> - wval |= 1;
> - }
> -
> - return wval;
> -}
> -
> -static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
> -{
> - u8 cmd = EEPROM_READ, i;
> -
> - for (i = 0; i < 0x40; i++) {
> - pci_write_config_byte(pdev, 0xc0, 0);
> - udelay(160);
> -
> - dc390_eeprom_prepare_read(pdev, cmd++);
> - *ptr++ = dc390_eeprom_get_data(pdev);
> -
> - pci_write_config_byte(pdev, 0x80, 0);
> - pci_write_config_byte(pdev, 0x80, 0);
> - udelay(160);
> - }
> -}
> -
> -/* Override EEprom values with explicitly set values */
> -static void dc390_eeprom_override(u8 index)
> -{
> - u8 *ptr = (u8 *) dc390_eepromBuf[index], id;
> -
> - /* Adapter Settings */
> - if (tmscsim[0] != -2)
> - ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0]; /* Adapter ID */
> - if (tmscsim[3] != -2)
> - ptr[EE_MODE2] = (u8)tmscsim[3];
> - if (tmscsim[5] != -2)
> - ptr[EE_DELAY] = tmscsim[5]; /* Reset delay */
> - if (tmscsim[4] != -2)
> - ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4]; /* Tagged Cmds */
> -
> - /* Device Settings */
> - for (id = 0; id < MAX_SCSI_ID; id++) {
> - if (tmscsim[2] != -2)
> - ptr[id << 2] = (u8)tmscsim[2]; /* EE_MODE1 */
> - if (tmscsim[1] != -2)
> - ptr[(id << 2) + 1] = (u8)tmscsim[1]; /* EE_Speed */
> - }
> -}
> -
> -static int tmscsim_def[] = {
> - 7,
> - 0 /* 10MHz */,
> - PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_,
> - MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION | LUN_CHECK,
> - 3 /* 16 Tags per LUN */,
> - 1 /* s delay after Reset */,
> -};
> -
> -/* Copy defaults over set values where missing */
> -static void dc390_fill_with_defaults (void)
> -{
> - int i;
> -
> - for (i = 0; i < 6; i++) {
> - if (tmscsim[i] < 0 || tmscsim[i] > 255)
> - tmscsim[i] = tmscsim_def[i];
> - }
> -
> - /* Sanity checks */
> - if (tmscsim[0] > 7)
> - tmscsim[0] = 7;
> - if (tmscsim[1] > 7)
> - tmscsim[1] = 4;
> - if (tmscsim[4] > 5)
> - tmscsim[4] = 4;
> - if (tmscsim[5] > 180)
> - tmscsim[5] = 180;
> -}
> -
> -static void dc390_check_eeprom(struct pci_dev *pdev, u8 index)
> -{
> - u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120};
> - u8 EEbuf[128];
> - u16 *ptr = (u16 *)EEbuf, wval = 0;
> - int i;
> -
> - dc390_read_eeprom(pdev, ptr);
> - memcpy(dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
> - memcpy(&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID],
> - &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
> -
> - dc390_eepromBuf[index][EE_DELAY] = interpd[dc390_eepromBuf[index][EE_DELAY]];
> -
> - for (i = 0; i < 0x40; i++, ptr++)
> - wval += *ptr;
> -
> - /* no Tekram EEprom found */
> - if (wval != 0x1234) {
> - int speed;
> -
> - printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
> -
> - /*
> - * XXX(hch): bogus, because we might have tekram and
> - * non-tekram hbas in a single machine.
> - */
> - dc390_fill_with_defaults();
> -
> - speed = dc390_clock_speed[tmscsim[1]];
> - printk(KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz), "
> - "DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n",
> - tmscsim[0], tmscsim[1], speed / 10, speed % 10,
> - (u8)tmscsim[2], (u8)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
> - }
> -}
> -
> -static void dc390_init_hw(struct dc390_acb *pACB, u8 index)
> -{
> - struct Scsi_Host *shost = pACB->pScsiHost;
> - u8 dstate;
> -
> - /* Disable SCSI bus reset interrupt */
> - DC390_write8(CtrlReg1, DIS_INT_ON_SCSI_RST | shost->this_id);
> -
> - if (pACB->Gmode2 & RST_SCSI_BUS) {
> - dc390_ResetSCSIBus(pACB);
> - udelay(1000);
> - pACB->last_reset = jiffies + HZ/2 +
> - HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
> - }
> -
> - pACB->ACBFlag = 0;
> -
> - /* Reset Pending INT */
> - DC390_read8(INT_Status);
> -
> - /* 250ms selection timeout */
> - DC390_write8(Scsi_TimeOut, SEL_TIMEOUT);
> -
> - /* Conversion factor = 0 , 40MHz clock */
> - DC390_write8(Clk_Factor, CLK_FREQ_40MHZ);
> -
> - /* NOP cmd - clear command register */
> - DC390_write8(ScsiCmd, NOP_CMD);
> -
> - /* Enable Feature and SCSI-2 */
> - DC390_write8(CtrlReg2, EN_FEATURE+EN_SCSI2_CMD);
> -
> - /* Fast clock */
> - DC390_write8(CtrlReg3, FAST_CLK);
> -
> - /* Negation */
> - DC390_write8(CtrlReg4, pACB->glitch_cfg | /* glitch eater */
> - (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ?
> - NEGATE_REQACKDATA : 0);
> -
> - /* Clear Transfer Count High: ID */
> - DC390_write8(CtcReg_High, 0);
> - DC390_write8(DMA_Cmd, DMA_IDLE_CMD);
> - DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
> - DC390_write32(DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
> -
> - dstate = DC390_read8(DMA_Status);
> - DC390_write8(DMA_Status, dstate);
> -}
> -
> -static int dc390_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
> -{
> - struct dc390_acb *pACB;
> - struct Scsi_Host *shost;
> - unsigned long io_port;
> - int error = -ENODEV, i;
> -
> - if (pci_enable_device(pdev))
> - goto out;
> -
> - pci_set_master(pdev);
> -
> - error = -ENOMEM;
> - if (disable_clustering)
> - driver_template.use_clustering = DISABLE_CLUSTERING;
> - shost = scsi_host_alloc(&driver_template, sizeof(struct dc390_acb));
> - if (!shost)
> - goto out_disable_device;
> -
> - pACB = (struct dc390_acb *)shost->hostdata;
> - memset(pACB, 0, sizeof(struct dc390_acb));
> -
> - dc390_check_eeprom(pdev, dc390_adapterCnt);
> - dc390_eeprom_override(dc390_adapterCnt);
> -
> - io_port = pci_resource_start(pdev, 0);
> -
> - shost->this_id = dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID];
> - shost->io_port = io_port;
> - shost->n_io_port = 0x80;
> - shost->irq = pdev->irq;
> - shost->base = io_port;
> - shost->unique_id = io_port;
> -
> - pACB->last_reset = jiffies;
> - pACB->pScsiHost = shost;
> - pACB->IOPortBase = (u16) io_port;
> - pACB->IRQLevel = pdev->irq;
> -
> - shost->max_id = 8;
> -
> - if (shost->max_id - 1 ==
> - dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID])
> - shost->max_id--;
> -
> - if (dc390_eepromBuf[dc390_adapterCnt][EE_MODE2] & LUN_CHECK)
> - shost->max_lun = 8;
> - else
> - shost->max_lun = 1;
> -
> - pACB->pFreeSRB = pACB->SRB_array;
> - pACB->SRBCount = MAX_SRB_CNT;
> - pACB->AdapterIndex = dc390_adapterCnt;
> - pACB->TagMaxNum =
> - 2 << dc390_eepromBuf[dc390_adapterCnt][EE_TAG_CMD_NUM];
> - pACB->Gmode2 = dc390_eepromBuf[dc390_adapterCnt][EE_MODE2];
> -
> - for (i = 0; i < pACB->SRBCount-1; i++)
> - pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
> - pACB->SRB_array[pACB->SRBCount-1].pNextSRB = NULL;
> - pACB->pTmpSRB = &pACB->TmpSRB;
> -
> - pACB->sel_timeout = SEL_TIMEOUT;
> - pACB->glitch_cfg = EATER_25NS;
> - pACB->pdev = pdev;
> -
> - if (!request_region(io_port, shost->n_io_port, "tmscsim")) {
> - printk(KERN_ERR "DC390: register IO ports error!\n");
> - goto out_host_put;
> - }
> -
> - /* Reset Pending INT */
> - DC390_read8_(INT_Status, io_port);
> -
> - if (request_irq(pdev->irq, do_DC390_Interrupt, IRQF_SHARED,
> - "tmscsim", pACB)) {
> - printk(KERN_ERR "DC390: register IRQ error!\n");
> - goto out_release_region;
> - }
> -
> - dc390_init_hw(pACB, dc390_adapterCnt);
> -
> - dc390_adapterCnt++;
> -
> - pci_set_drvdata(pdev, shost);
> -
> - error = scsi_add_host(shost, &pdev->dev);
> - if (error)
> - goto out_free_irq;
> - scsi_scan_host(shost);
> - return 0;
> -
> - out_free_irq:
> - free_irq(pdev->irq, pACB);
> - out_release_region:
> - release_region(io_port, shost->n_io_port);
> - out_host_put:
> - scsi_host_put(shost);
> - out_disable_device:
> - pci_disable_device(pdev);
> - out:
> - return error;
> -}
> -
> -/**
> - * dc390_remove_one - Called to remove a single instance of the adapter.
> - *
> - * @dev: The PCI device to remove.
> - */
> -static void dc390_remove_one(struct pci_dev *dev)
> -{
> - struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
> - unsigned long iflags;
> - struct dc390_acb* pACB = (struct dc390_acb*) scsi_host->hostdata;
> - u8 bval;
> -
> - scsi_remove_host(scsi_host);
> -
> - spin_lock_irqsave(scsi_host->host_lock, iflags);
> - pACB->ACBFlag = RESET_DEV;
> - bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
> - DC390_write8 (CtrlReg1, bval); /* disable interrupt */
> - if (pACB->Gmode2 & RST_SCSI_BUS)
> - dc390_ResetSCSIBus(pACB);
> - spin_unlock_irqrestore(scsi_host->host_lock, iflags);
> -
> - free_irq(scsi_host->irq, pACB);
> - release_region(scsi_host->io_port, scsi_host->n_io_port);
> -
> - pci_disable_device(dev);
> - scsi_host_put(scsi_host);
> -}
> -
> -static struct pci_device_id tmscsim_pci_tbl[] = {
> - { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974,
> - PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
> - { }
> -};
> -MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);
> -
> -static struct pci_driver dc390_driver = {
> - .name = "tmscsim",
> - .id_table = tmscsim_pci_tbl,
> - .probe = dc390_probe_one,
> - .remove = dc390_remove_one,
> -};
> -
> -static int __init dc390_module_init(void)
> -{
> - if (!disable_clustering) {
> - printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n");
> - printk(KERN_INFO " with \"disable_clustering=1\" and report to maintainers\n");
> - }
> -
> - if (tmscsim[0] == -1 || tmscsim[0] > 15) {
> - tmscsim[0] = 7;
> - tmscsim[1] = 4;
> - tmscsim[2] = PARITY_CHK_ | TAG_QUEUEING_;
> - tmscsim[3] = MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION;
> - tmscsim[4] = 2;
> - tmscsim[5] = 10;
> - printk (KERN_INFO "DC390: Using safe settings.\n");
> - }
> -
> - return pci_register_driver(&dc390_driver);
> -}
> -
> -static void __exit dc390_module_exit(void)
> -{
> - pci_unregister_driver(&dc390_driver);
> -}
> -
> -module_init(dc390_module_init);
> -module_exit(dc390_module_exit);
> -
> -#ifndef MODULE
> -static int __init dc390_setup (char *str)
> -{
> - int ints[8],i, im;
> -
> - get_options(str, ARRAY_SIZE(ints), ints);
> - 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 (); */
> - return 1;
> -}
> -
> -__setup("tmscsim=", dc390_setup);
> -#endif
> diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
> deleted file mode 100644
> index c9ad4bb..0000000
> --- a/drivers/scsi/tmscsim.h
> +++ /dev/null
> @@ -1,549 +0,0 @@
> -/***********************************************************************
> -;* File Name : TMSCSIM.H *
> -;* TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter *
> -;* Device Driver *
> -;***********************************************************************/
> -/* $Id: tmscsim.h,v 2.15.2.3 2000/11/17 20:52:27 garloff Exp $ */
> -
> -#ifndef _TMSCSIM_H
> -#define _TMSCSIM_H
> -
> -#include <linux/types.h>
> -
> -#define MAX_ADAPTER_NUM 4
> -#define MAX_SG_LIST_BUF 16 /* Not used */
> -#define MAX_SCSI_ID 8
> -#define MAX_SRB_CNT 50 /* Max number of started commands */
> -
> -#define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */
> -
> -/*
> -;-----------------------------------------------------------------------
> -; SCSI Request Block
> -;-----------------------------------------------------------------------
> -*/
> -struct dc390_srb
> -{
> -//u8 CmdBlock[12];
> -
> -struct dc390_srb *pNextSRB;
> -struct dc390_dcb *pSRBDCB;
> -struct scsi_cmnd *pcmd;
> -struct scatterlist *pSegmentList;
> -
> -struct scatterlist Segmentx; /* make a one entry of S/G list table */
> -
> -unsigned long SGBusAddr; /*;a segment starting address as seen by AM53C974A
> - in CPU endianness. We're only getting 32-bit bus
> - addresses by default */
> -unsigned long SGToBeXferLen; /*; to be xfer length */
> -unsigned long TotalXferredLen;
> -unsigned long SavedTotXLen;
> -unsigned long Saved_Ptr;
> -u32 SRBState;
> -
> -u8 SRBStatus;
> -u8 SRBFlag; /*; b0-AutoReqSense,b6-Read,b7-write */
> - /*; b4-settimeout,b5-Residual valid */
> -u8 AdaptStatus;
> -u8 TargetStatus;
> -
> -u8 ScsiPhase;
> -s8 TagNumber;
> -u8 SGIndex;
> -u8 SGcount;
> -
> -u8 MsgCnt;
> -u8 EndMessage;
> -
> -u8 MsgInBuf[6];
> -u8 MsgOutBuf[6];
> -
> -//u8 IORBFlag; /*;81h-Reset, 2-retry */
> -};
> -
> -
> -/*
> -;-----------------------------------------------------------------------
> -; Device Control Block
> -;-----------------------------------------------------------------------
> -*/
> -struct dc390_dcb
> -{
> -struct dc390_dcb *pNextDCB;
> -struct dc390_acb *pDCBACB;
> -
> -/* Queued SRBs */
> -struct dc390_srb *pGoingSRB;
> -struct dc390_srb *pGoingLast;
> -struct dc390_srb *pActiveSRB;
> -u8 GoingSRBCnt;
> -
> -u32 TagMask;
> -
> -u8 TargetID; /*; SCSI Target ID (SCSI Only) */
> -u8 TargetLUN; /*; SCSI Log. Unit (SCSI Only) */
> -u8 DevMode;
> -u8 DCBFlag;
> -
> -u8 CtrlR1;
> -u8 CtrlR3;
> -u8 CtrlR4;
> -
> -u8 SyncMode; /*; 0:async mode */
> -u8 NegoPeriod; /*;for nego. */
> -u8 SyncPeriod; /*;for reg. */
> -u8 SyncOffset; /*;for reg. and nego.(low nibble) */
> -};
> -
> -
> -/*
> -;-----------------------------------------------------------------------
> -; Adapter Control Block
> -;-----------------------------------------------------------------------
> -*/
> -struct dc390_acb
> -{
> -struct Scsi_Host *pScsiHost;
> -u16 IOPortBase;
> -u8 IRQLevel;
> -u8 status;
> -
> -u8 SRBCount;
> -u8 AdapterIndex; /*; nth Adapter this driver */
> -u8 DCBCnt;
> -
> -u8 TagMaxNum;
> -u8 ACBFlag;
> -u8 Gmode2;
> -u8 scan_devices;
> -
> -struct dc390_dcb *pLinkDCB;
> -struct dc390_dcb *pLastDCB;
> -struct dc390_dcb *pDCBRunRobin;
> -
> -struct dc390_dcb *pActiveDCB;
> -struct dc390_srb *pFreeSRB;
> -struct dc390_srb *pTmpSRB;
> -
> -u8 msgin123[4];
> -u8 Connected;
> -u8 pad;
> -
> -#if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(CONFIG_SMP) || DEBUG_SPINLOCKS > 0)
> -spinlock_t lock;
> -#endif
> -u8 sel_timeout;
> -u8 glitch_cfg;
> -
> -u8 MsgLen;
> -u8 Ignore_IRQ; /* Not used */
> -
> -struct pci_dev *pdev;
> -
> -unsigned long last_reset;
> -unsigned long Cmds;
> -u32 SelLost;
> -u32 SelConn;
> -u32 CmdInQ;
> -u32 CmdOutOfSRB;
> -
> -struct dc390_srb TmpSRB;
> -struct dc390_srb SRB_array[MAX_SRB_CNT]; /* 50 SRBs */
> -};
> -
> -
> -/*;-----------------------------------------------------------------------*/
> -
> -
> -#define BIT31 0x80000000
> -#define BIT30 0x40000000
> -#define BIT29 0x20000000
> -#define BIT28 0x10000000
> -#define BIT27 0x08000000
> -#define BIT26 0x04000000
> -#define BIT25 0x02000000
> -#define BIT24 0x01000000
> -#define BIT23 0x00800000
> -#define BIT22 0x00400000
> -#define BIT21 0x00200000
> -#define BIT20 0x00100000
> -#define BIT19 0x00080000
> -#define BIT18 0x00040000
> -#define BIT17 0x00020000
> -#define BIT16 0x00010000
> -#define BIT15 0x00008000
> -#define BIT14 0x00004000
> -#define BIT13 0x00002000
> -#define BIT12 0x00001000
> -#define BIT11 0x00000800
> -#define BIT10 0x00000400
> -#define BIT9 0x00000200
> -#define BIT8 0x00000100
> -#define BIT7 0x00000080
> -#define BIT6 0x00000040
> -#define BIT5 0x00000020
> -#define BIT4 0x00000010
> -#define BIT3 0x00000008
> -#define BIT2 0x00000004
> -#define BIT1 0x00000002
> -#define BIT0 0x00000001
> -
> -/*;---UnitCtrlFlag */
> -#define UNIT_ALLOCATED BIT0
> -#define UNIT_INFO_CHANGED BIT1
> -#define FORMATING_MEDIA BIT2
> -#define UNIT_RETRY BIT3
> -
> -/*;---UnitFlags */
> -#define DASD_SUPPORT BIT0
> -#define SCSI_SUPPORT BIT1
> -#define ASPI_SUPPORT BIT2
> -
> -/*;----SRBState machine definition */
> -#define SRB_FREE 0
> -#define SRB_WAIT BIT0
> -#define SRB_READY BIT1
> -#define SRB_MSGOUT BIT2 /*;arbitration+msg_out 1st byte*/
> -#define SRB_MSGIN BIT3
> -#define SRB_MSGIN_MULTI BIT4
> -#define SRB_COMMAND BIT5
> -#define SRB_START_ BIT6 /*;arbitration+msg_out+command_out*/
> -#define SRB_DISCONNECT BIT7
> -#define SRB_DATA_XFER BIT8
> -#define SRB_XFERPAD BIT9
> -#define SRB_STATUS BIT10
> -#define SRB_COMPLETED BIT11
> -#define SRB_ABORT_SENT BIT12
> -#define DO_SYNC_NEGO BIT13
> -#define SRB_UNEXPECT_RESEL BIT14
> -
> -/*;---SRBstatus */
> -#define SRB_OK BIT0
> -#define ABORTION BIT1
> -#define OVER_RUN BIT2
> -#define UNDER_RUN BIT3
> -#define PARITY_ERROR BIT4
> -#define SRB_ERROR BIT5
> -
> -/*;---ACBFlag */
> -#define RESET_DEV BIT0
> -#define RESET_DETECT BIT1
> -#define RESET_DONE BIT2
> -
> -/*;---DCBFlag */
> -#define ABORT_DEV_ BIT0
> -
> -/*;---SRBFlag */
> -#define DATAOUT BIT7
> -#define DATAIN BIT6
> -#define RESIDUAL_VALID BIT5
> -#define ENABLE_TIMER BIT4
> -#define RESET_DEV0 BIT2
> -#define ABORT_DEV BIT1
> -#define AUTO_REQSENSE BIT0
> -
> -/*;---Adapter status */
> -#define H_STATUS_GOOD 0
> -#define H_SEL_TIMEOUT 0x11
> -#define H_OVER_UNDER_RUN 0x12
> -#define H_UNEXP_BUS_FREE 0x13
> -#define H_TARGET_PHASE_F 0x14
> -#define H_INVALID_CCB_OP 0x16
> -#define H_LINK_CCB_BAD 0x17
> -#define H_BAD_TARGET_DIR 0x18
> -#define H_DUPLICATE_CCB 0x19
> -#define H_BAD_CCB_OR_SG 0x1A
> -#define H_ABORT 0x0FF
> -
> -/* 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))
> -
> -#define SET_RES_TARGET(who, tgt) do { who &= ~RES_TARGET; who |= (int)(tgt); } while (0)
> -#define SET_RES_TARGET_LNX(who, tgt) do { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } while (0)
> -#define SET_RES_MSG(who, msg) do { who &= ~RES_ENDMSG; who |= (int)(msg) << 8; } while (0)
> -#define SET_RES_DID(who, did) do { who &= ~RES_DID; who |= (int)(did) << 16; } while (0)
> -#define SET_RES_DRV(who, drv) do { who &= ~RES_DRV; who |= (int)(drv) << 24; } while (0)
> -
> -/*;---Sync_Mode */
> -#define SYNC_DISABLE 0
> -#define SYNC_ENABLE BIT0
> -#define SYNC_NEGO_DONE BIT1
> -#define WIDE_ENABLE BIT2 /* Not used ;-) */
> -#define WIDE_NEGO_DONE BIT3 /* Not used ;-) */
> -#define EN_TAG_QUEUEING BIT4
> -#define EN_ATN_STOP BIT5
> -
> -#define SYNC_NEGO_OFFSET 15
> -
> -/*;---SCSI bus phase*/
> -#define SCSI_DATA_OUT 0
> -#define SCSI_DATA_IN 1
> -#define SCSI_COMMAND 2
> -#define SCSI_STATUS_ 3
> -#define SCSI_NOP0 4
> -#define SCSI_NOP1 5
> -#define SCSI_MSG_OUT 6
> -#define SCSI_MSG_IN 7
> -
> -/*;----SCSI MSG BYTE*/ /* see scsi/scsi.h */ /* One is missing ! */
> -#define ABORT_TAG 0x0d
> -
> -/*
> - * SISC query queue
> - */
> -typedef struct {
> - dma_addr_t saved_dma_handle;
> -} dc390_cmd_scp_t;
> -
> -/*
> -;==========================================================
> -; EEPROM byte offset
> -;==========================================================
> -*/
> -typedef struct _EEprom
> -{
> -u8 EE_MODE1;
> -u8 EE_SPEED;
> -u8 xx1;
> -u8 xx2;
> -} EEprom, *PEEprom;
> -
> -#define REAL_EE_ADAPT_SCSI_ID 64
> -#define REAL_EE_MODE2 65
> -#define REAL_EE_DELAY 66
> -#define REAL_EE_TAG_CMD_NUM 67
> -
> -#define EE_ADAPT_SCSI_ID 32
> -#define EE_MODE2 33
> -#define EE_DELAY 34
> -#define EE_TAG_CMD_NUM 35
> -
> -#define EE_LEN 40
> -
> -/*; EE_MODE1 bits definition*/
> -#define PARITY_CHK_ BIT0
> -#define SYNC_NEGO_ BIT1
> -#define EN_DISCONNECT_ BIT2
> -#define SEND_START_ BIT3
> -#define TAG_QUEUEING_ BIT4
> -
> -/*; EE_MODE2 bits definition*/
> -#define MORE2_DRV BIT0
> -#define GREATER_1G BIT1
> -#define RST_SCSI_BUS BIT2
> -#define ACTIVE_NEGATION BIT3
> -#define NO_SEEK BIT4
> -#define LUN_CHECK BIT5
> -
> -#define ENABLE_CE 1
> -#define DISABLE_CE 0
> -#define EEPROM_READ 0x80
> -
> -/*
> -;==========================================================
> -; AMD 53C974 Registers bit Definition
> -;==========================================================
> -*/
> -/*
> -;====================
> -; SCSI Register
> -;====================
> -*/
> -
> -/*; Command Reg.(+0CH) (rw) */
> -#define DMA_COMMAND BIT7
> -#define NOP_CMD 0
> -#define CLEAR_FIFO_CMD 1
> -#define RST_DEVICE_CMD 2
> -#define RST_SCSI_BUS_CMD 3
> -
> -#define INFO_XFER_CMD 0x10
> -#define INITIATOR_CMD_CMPLTE 0x11
> -#define MSG_ACCEPTED_CMD 0x12
> -#define XFER_PAD_BYTE 0x18
> -#define SET_ATN_CMD 0x1A
> -#define RESET_ATN_CMD 0x1B
> -
> -#define SEL_WO_ATN 0x41 /* currently not used */
> -#define SEL_W_ATN 0x42
> -#define SEL_W_ATN_STOP 0x43
> -#define SEL_W_ATN3 0x46
> -#define EN_SEL_RESEL 0x44
> -#define DIS_SEL_RESEL 0x45 /* currently not used */
> -#define RESEL 0x40 /* " */
> -#define RESEL_ATN3 0x47 /* " */
> -
> -#define DATA_XFER_CMD INFO_XFER_CMD
> -
> -
> -/*; SCSI Status Reg.(+10H) (r) */
> -#define INTERRUPT BIT7
> -#define ILLEGAL_OP_ERR BIT6
> -#define PARITY_ERR BIT5
> -#define COUNT_2_ZERO BIT4
> -#define GROUP_CODE_VALID BIT3
> -#define SCSI_PHASE_MASK (BIT2+BIT1+BIT0)
> -/* BIT2: MSG phase; BIT1: C/D physe; BIT0: I/O phase */
> -
> -/*; Interrupt Status Reg.(+14H) (r) */
> -#define SCSI_RESET BIT7
> -#define INVALID_CMD BIT6
> -#define DISCONNECTED BIT5
> -#define SERVICE_REQUEST BIT4
> -#define SUCCESSFUL_OP BIT3
> -#define RESELECTED BIT2
> -#define SEL_ATTENTION BIT1
> -#define SELECTED BIT0
> -
> -/*; Internal State Reg.(+18H) (r) */
> -#define SYNC_OFFSET_FLAG BIT3
> -#define INTRN_STATE_MASK (BIT2+BIT1+BIT0)
> -/* 0x04: Sel. successful (w/o stop), 0x01: Sel. successful (w/ stop) */
> -
> -/*; Clock Factor Reg.(+24H) (w) */
> -#define CLK_FREQ_40MHZ 0
> -#define CLK_FREQ_35MHZ (BIT2+BIT1+BIT0)
> -#define CLK_FREQ_30MHZ (BIT2+BIT1)
> -#define CLK_FREQ_25MHZ (BIT2+BIT0)
> -#define CLK_FREQ_20MHZ BIT2
> -#define CLK_FREQ_15MHZ (BIT1+BIT0)
> -#define CLK_FREQ_10MHZ BIT1
> -
> -/*; Control Reg. 1(+20H) (rw) */
> -#define EXTENDED_TIMING BIT7
> -#define DIS_INT_ON_SCSI_RST BIT6
> -#define PARITY_ERR_REPO BIT4
> -#define SCSI_ID_ON_BUS (BIT2+BIT1+BIT0) /* host adapter ID */
> -
> -/*; Control Reg. 2(+2CH) (rw) */
> -#define EN_FEATURE BIT6
> -#define EN_SCSI2_CMD BIT3
> -
> -/*; Control Reg. 3(+30H) (rw) */
> -#define ID_MSG_CHECK BIT7
> -#define EN_QTAG_MSG BIT6
> -#define EN_GRP2_CMD BIT5
> -#define FAST_SCSI BIT4 /* ;10MB/SEC */
> -#define FAST_CLK BIT3 /* ;25 - 40 MHZ */
> -
> -/*; Control Reg. 4(+34H) (rw) */
> -#define EATER_12NS 0
> -#define EATER_25NS BIT7
> -#define EATER_35NS BIT6
> -#define EATER_0NS (BIT7+BIT6)
> -#define REDUCED_POWER BIT5
> -#define CTRL4_RESERVED BIT4 /* must be 1 acc. to AM53C974.c */
> -#define NEGATE_REQACKDATA BIT2
> -#define NEGATE_REQACK BIT3
> -
> -#define GLITCH_TO_NS(x) (((~x>>6 & 2) >> 1) | ((x>>6 & 1) << 1 ^ (x>>6 & 2)))
> -#define NS_TO_GLITCH(y) (((~y<<7) | ~((y<<6) ^ ((y<<5 & 1<<6) | ~0x40))) & 0xc0)
> -
> -/*
> -;====================
> -; DMA Register
> -;====================
> -*/
> -/*; DMA Command Reg.(+40H) (rw) */
> -#define READ_DIRECTION BIT7
> -#define WRITE_DIRECTION 0
> -#define EN_DMA_INT BIT6
> -#define EN_PAGE_INT BIT5 /* page transfer interrupt enable */
> -#define MAP_TO_MDL BIT4
> -#define DIAGNOSTIC BIT2
> -#define DMA_IDLE_CMD 0
> -#define DMA_BLAST_CMD BIT0
> -#define DMA_ABORT_CMD BIT1
> -#define DMA_START_CMD (BIT1+BIT0)
> -
> -/*; DMA Status Reg.(+54H) (r) */
> -#define PCI_MS_ABORT BIT6
> -#define BLAST_COMPLETE BIT5
> -#define SCSI_INTERRUPT BIT4
> -#define DMA_XFER_DONE BIT3
> -#define DMA_XFER_ABORT BIT2
> -#define DMA_XFER_ERROR BIT1
> -#define POWER_DOWN BIT0
> -
> -/*; DMA SCSI Bus and Ctrl.(+70H) */
> -#define EN_INT_ON_PCI_ABORT BIT25
> -#define WRT_ERASE_DMA_STAT BIT24
> -#define PW_DOWN_CTRL BIT21
> -#define SCSI_BUSY BIT20
> -#define SCLK BIT19
> -#define SCAM BIT18
> -#define SCSI_LINES 0x0003ffff
> -
> -/*
> -;==========================================================
> -; SCSI Chip register address offset
> -;==========================================================
> -;Registers are rw unless declared otherwise
> -*/
> -#define CtcReg_Low 0x00 /* r curr. transfer count */
> -#define CtcReg_Mid 0x04 /* r */
> -#define CtcReg_High 0x38 /* r */
> -#define ScsiFifo 0x08
> -#define ScsiCmd 0x0C
> -#define Scsi_Status 0x10 /* r */
> -#define INT_Status 0x14 /* r */
> -#define Sync_Period 0x18 /* w */
> -#define Sync_Offset 0x1C /* w */
> -#define Clk_Factor 0x24 /* w */
> -#define CtrlReg1 0x20
> -#define CtrlReg2 0x2C
> -#define CtrlReg3 0x30
> -#define CtrlReg4 0x34
> -#define DMA_Cmd 0x40
> -#define DMA_XferCnt 0x44 /* rw starting transfer count (32 bit) */
> -#define DMA_XferAddr 0x48 /* rw starting physical address (32 bit) */
> -#define DMA_Wk_ByteCntr 0x4C /* r working byte counter */
> -#define DMA_Wk_AddrCntr 0x50 /* r working address counter */
> -#define DMA_Status 0x54 /* r */
> -#define DMA_MDL_Addr 0x58 /* rw starting MDL address */
> -#define DMA_Wk_MDL_Cntr 0x5C /* r working MDL counter */
> -#define DMA_ScsiBusCtrl 0x70 /* rw SCSI Bus, PCI/DMA Ctrl */
> -
> -#define StcReg_Low CtcReg_Low /* w start transfer count */
> -#define StcReg_Mid CtcReg_Mid /* w */
> -#define StcReg_High CtcReg_High /* w */
> -#define Scsi_Dest_ID Scsi_Status /* w */
> -#define Scsi_TimeOut INT_Status /* w */
> -#define Intern_State Sync_Period /* r */
> -#define Current_Fifo Sync_Offset /* r Curr. FIFO / int. state */
> -
> -
> -#define DC390_read8(address) \
> - (inb (pACB->IOPortBase + (address)))
> -
> -#define DC390_read8_(address, base) \
> - (inb ((u16)(base) + (address)))
> -
> -#define DC390_read16(address) \
> - (inw (pACB->IOPortBase + (address)))
> -
> -#define DC390_read32(address) \
> - (inl (pACB->IOPortBase + (address)))
> -
> -#define DC390_write8(address,value) \
> - outb ((value), pACB->IOPortBase + (address))
> -
> -#define DC390_write8_(address,value,base) \
> - outb ((value), (u16)(base) + (address))
> -
> -#define DC390_write16(address,value) \
> - outw ((value), pACB->IOPortBase + (address))
> -
> -#define DC390_write32(address,value) \
> - outl ((value), pACB->IOPortBase + (address))
> -
> -
> -#endif /* _TMSCSIM_H */
> --
> 1.8.5.2
>
^ permalink raw reply [flat|nested] 17+ messages in thread
* Re: [PATCH 12/12] Replace tmscsim by am53c974
2014-11-23 13:22 ` Guennadi Liakhovetski
@ 2014-11-23 18:45 ` David Miller
0 siblings, 0 replies; 17+ messages in thread
From: David Miller @ 2014-11-23 18:45 UTC (permalink / raw)
To: g.liakhovetski; +Cc: hare, jbottomley, hch, pbonzini, linux-scsi
Please do not _EVER_ quote an entire huge patch just to add a signoff
or ACK.
This wastes tons of mailing list resources because it means that
the entire huge patch is sent once again to every single recipient
on the mailing list.
Instead, just at most quote the commit message, then add your
ACK, and remove the patch from the quoted material entirely.
Thanks.
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCHv3 00/12] Re-implement am53c974 driver
@ 2014-11-24 14:37 Hannes Reinecke
2014-11-24 14:37 ` [PATCH 01/12] esp_scsi: spellcheck 'driver' Hannes Reinecke
` (12 more replies)
0 siblings, 13 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
Hi all,
having found some issues with the current tmscsim driver
I looked at the code and found is really awkward to clean
up.
Seeing that the am53c974 chip is actually based on the
'ESP' chip design I've re-implemented it based on the
common esp_scsi routines. This new driver
(cunningly named 'am53c974') provides all features
found on the tmscsim driver, with the goal of obsoleting
the old tmscsim driver.
Tested with Tekram DC390 and qemu esp-scsi.
Changes to v1:
- Include suggestions from Paolo Bonzini
- Remove the tmscsim driver
- Update MAINTAINERS file
Changes to v2:
- Include review from David Miller
- Include review from Christoph Hellwig
- Add Reviewed-by/Acked-by tags where applicable
Hannes Reinecke (11):
esp_scsi: spellcheck 'driver'
esp_scsi: make number of tags configurable
esp_scsi: convert to dev_printk
esp_scsi: debug event and command
esp_scsi: read status registers
esp_scsi: use FIFO for command submission
scsi: add 'am53c974' driver
am53c974: BLAST residual handling
esp: correctly detect am53c974
esp: enable CONFIG2_FENAB for am53c974
Replace tmscsim by am53c974
Paolo Bonzini (1):
esp_scsi: let DMA driver provide a config2 value
MAINTAINERS | 7 +-
drivers/scsi/Kconfig | 8 +-
drivers/scsi/Makefile | 2 +-
drivers/scsi/am53c974.c | 586 +++++++++++
drivers/scsi/esp_scsi.c | 411 +++++---
drivers/scsi/esp_scsi.h | 22 +-
drivers/scsi/tmscsim.c | 2626 -----------------------------------------------
drivers/scsi/tmscsim.h | 549 ----------
8 files changed, 859 insertions(+), 3352 deletions(-)
create mode 100644 drivers/scsi/am53c974.c
delete mode 100644 drivers/scsi/tmscsim.c
delete mode 100644 drivers/scsi/tmscsim.h
--
1.8.5.2
^ permalink raw reply [flat|nested] 17+ messages in thread
* [PATCH 01/12] esp_scsi: spellcheck 'driver'
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 02/12] esp_scsi: make number of tags configurable Hannes Reinecke
` (11 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/esp_scsi.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index cd68805..b5862e4 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -1,4 +1,4 @@
-/* esp_scsi.h: Defines and structures for the ESP drier.
+/* esp_scsi.h: Defines and structures for the ESP driver.
*
* Copyright (C) 2007 David S. Miller (davem@davemloft.net)
*/
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 02/12] esp_scsi: make number of tags configurable
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
2014-11-24 14:37 ` [PATCH 01/12] esp_scsi: spellcheck 'driver' Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 03/12] esp_scsi: convert to dev_printk Hannes Reinecke
` (10 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
Add a field 'num_tags' to the esp structure to allow drivers
to overwrite the number of avialable tags if required.
Default is ESP_DEFAULT_TAGS.
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/esp_scsi.c | 12 ++++++------
drivers/scsi/esp_scsi.h | 3 +--
2 files changed, 7 insertions(+), 8 deletions(-)
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 38c23e0..a2e7868 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -2317,6 +2317,10 @@ int scsi_esp_register(struct esp *esp, struct device *dev)
static int instance;
int err;
+ if (!esp->num_tags)
+ esp->num_tags = ESP_DEFAULT_TAGS;
+ else if (esp->num_tags >= ESP_MAX_TAG)
+ esp->num_tags = ESP_MAX_TAG - 1;
esp->host->transportt = esp_transport_template;
esp->host->max_lun = ESP_MAX_LUN;
esp->host->cmd_per_lun = 2;
@@ -2403,12 +2407,8 @@ static int esp_slave_configure(struct scsi_device *dev)
struct esp *esp = shost_priv(dev->host);
struct esp_target_data *tp = &esp->target[dev->id];
- if (dev->tagged_supported) {
- /* XXX make this configurable somehow XXX */
- int goal_tags = min(ESP_DEFAULT_TAGS, ESP_MAX_TAG);
-
- scsi_adjust_queue_depth(dev, goal_tags);
- }
+ if (dev->tagged_supported)
+ scsi_adjust_queue_depth(dev, esp->num_tags);
tp->flags |= ESP_TGT_DISCONNECT;
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index b5862e4..975d293 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -283,7 +283,6 @@ struct esp_cmd_entry {
struct completion *eh_done;
};
-/* XXX make this configurable somehow XXX */
#define ESP_DEFAULT_TAGS 16
#define ESP_MAX_TARGET 16
@@ -445,7 +444,7 @@ struct esp {
u8 prev_soff;
u8 prev_stp;
u8 prev_cfg3;
- u8 __pad;
+ u8 num_tags;
struct list_head esp_cmd_pool;
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 03/12] esp_scsi: convert to dev_printk
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
2014-11-24 14:37 ` [PATCH 01/12] esp_scsi: spellcheck 'driver' Hannes Reinecke
2014-11-24 14:37 ` [PATCH 02/12] esp_scsi: make number of tags configurable Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 04/12] esp_scsi: debug event and command Hannes Reinecke
` (9 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
Use dev_printk functions for correct device annotations.
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/esp_scsi.c | 212 ++++++++++++++++++++++++------------------------
1 file changed, 106 insertions(+), 106 deletions(-)
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index a2e7868..10a3d17 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -52,52 +52,52 @@ static u32 esp_debug;
#define esp_log_intr(f, a...) \
do { if (esp_debug & ESP_DEBUG_INTR) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_reset(f, a...) \
do { if (esp_debug & ESP_DEBUG_RESET) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_msgin(f, a...) \
do { if (esp_debug & ESP_DEBUG_MSGIN) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_msgout(f, a...) \
do { if (esp_debug & ESP_DEBUG_MSGOUT) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_cmddone(f, a...) \
do { if (esp_debug & ESP_DEBUG_CMDDONE) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_disconnect(f, a...) \
do { if (esp_debug & ESP_DEBUG_DISCONNECT) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_datastart(f, a...) \
do { if (esp_debug & ESP_DEBUG_DATASTART) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_datadone(f, a...) \
do { if (esp_debug & ESP_DEBUG_DATADONE) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_reconnect(f, a...) \
do { if (esp_debug & ESP_DEBUG_RECONNECT) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_log_autosense(f, a...) \
do { if (esp_debug & ESP_DEBUG_AUTOSENSE) \
- printk(f, ## a); \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
#define esp_read8(REG) esp->ops->esp_read8(esp, REG)
@@ -150,19 +150,17 @@ static void esp_dump_cmd_log(struct esp *esp)
int idx = esp->esp_event_cur;
int stop = idx;
- printk(KERN_INFO PFX "esp%d: Dumping command log\n",
- esp->host->unique_id);
+ shost_printk(KERN_INFO, esp->host, "Dumping command log\n");
do {
struct esp_event_ent *p = &esp->esp_event_log[idx];
- printk(KERN_INFO PFX "esp%d: ent[%d] %s ",
- esp->host->unique_id, idx,
- p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT");
-
- printk("val[%02x] sreg[%02x] seqreg[%02x] "
- "sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n",
- p->val, p->sreg, p->seqreg,
- p->sreg2, p->ireg, p->select_state, p->event);
+ shost_printk(KERN_INFO, esp->host,
+ "ent[%d] %s val[%02x] sreg[%02x] seqreg[%02x] "
+ "sreg2[%02x] ireg[%02x] ss[%02x] event[%02x]\n",
+ idx,
+ p->type == ESP_EVENT_TYPE_CMD ? "CMD" : "EVENT",
+ p->val, p->sreg, p->seqreg,
+ p->sreg2, p->ireg, p->select_state, p->event);
idx = (idx + 1) & (ESP_EVENT_LOG_SZ - 1);
} while (idx != stop);
@@ -176,9 +174,8 @@ static void esp_flush_fifo(struct esp *esp)
while (esp_read8(ESP_FFLAGS) & ESP_FF_FBYTES) {
if (--lim == 0) {
- printk(KERN_ALERT PFX "esp%d: ESP_FF_BYTES "
- "will not clear!\n",
- esp->host->unique_id);
+ shost_printk(KERN_ALERT, esp->host,
+ "ESP_FF_BYTES will not clear!\n");
break;
}
udelay(1);
@@ -383,12 +380,11 @@ static void esp_advance_dma(struct esp *esp, struct esp_cmd_entry *ent,
p->cur_residue -= len;
p->tot_residue -= len;
if (p->cur_residue < 0 || p->tot_residue < 0) {
- printk(KERN_ERR PFX "esp%d: Data transfer overflow.\n",
- esp->host->unique_id);
- printk(KERN_ERR PFX "esp%d: cur_residue[%d] tot_residue[%d] "
- "len[%u]\n",
- esp->host->unique_id,
- p->cur_residue, p->tot_residue, len);
+ shost_printk(KERN_ERR, esp->host,
+ "Data transfer overflow.\n");
+ shost_printk(KERN_ERR, esp->host,
+ "cur_residue[%d] tot_residue[%d] len[%u]\n",
+ p->cur_residue, p->tot_residue, len);
p->cur_residue = 0;
p->tot_residue = 0;
}
@@ -604,9 +600,8 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
if (!ent->sense_ptr) {
- esp_log_autosense("esp%d: Doing auto-sense for "
- "tgt[%d] lun[%d]\n",
- esp->host->unique_id, tgt, lun);
+ esp_log_autosense("Doing auto-sense for tgt[%d] lun[%d]\n",
+ tgt, lun);
ent->sense_ptr = cmd->sense_buffer;
ent->sense_dma = esp->ops->map_single(esp,
@@ -953,8 +948,8 @@ static int esp_check_gross_error(struct esp *esp)
* - DMA programmed with wrong direction
* - improper phase change
*/
- printk(KERN_ERR PFX "esp%d: Gross error sreg[%02x]\n",
- esp->host->unique_id, esp->sreg);
+ shost_printk(KERN_ERR, esp->host,
+ "Gross error sreg[%02x]\n", esp->sreg);
/* XXX Reset the chip. XXX */
return 1;
}
@@ -982,14 +977,13 @@ static int esp_check_spur_intr(struct esp *esp)
* ESP is not, the only possibility is a DMA error.
*/
if (!esp->ops->dma_error(esp)) {
- printk(KERN_ERR PFX "esp%d: Spurious irq, "
- "sreg=%02x.\n",
- esp->host->unique_id, esp->sreg);
+ shost_printk(KERN_ERR, esp->host,
+ "Spurious irq, sreg=%02x.\n",
+ esp->sreg);
return -1;
}
- printk(KERN_ERR PFX "esp%d: DMA error\n",
- esp->host->unique_id);
+ shost_printk(KERN_ERR, esp->host, "DMA error\n");
/* XXX Reset the chip. XXX */
return -1;
@@ -1002,7 +996,7 @@ static int esp_check_spur_intr(struct esp *esp)
static void esp_schedule_reset(struct esp *esp)
{
- esp_log_reset("ESP: esp_schedule_reset() from %pf\n",
+ esp_log_reset("esp_schedule_reset() from %pf\n",
__builtin_return_address(0));
esp->flags |= ESP_FLAG_RESETTING;
esp_event(esp, ESP_EVENT_RESET);
@@ -1019,20 +1013,20 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
int i;
if (!lp->num_tagged) {
- printk(KERN_ERR PFX "esp%d: Reconnect w/num_tagged==0\n",
- esp->host->unique_id);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect w/num_tagged==0\n");
return NULL;
}
- esp_log_reconnect("ESP: reconnect tag, ");
+ esp_log_reconnect("reconnect tag, ");
for (i = 0; i < ESP_QUICKIRQ_LIMIT; i++) {
if (esp->ops->irq_pending(esp))
break;
}
if (i == ESP_QUICKIRQ_LIMIT) {
- printk(KERN_ERR PFX "esp%d: Reconnect IRQ1 timeout\n",
- esp->host->unique_id);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect IRQ1 timeout\n");
return NULL;
}
@@ -1043,14 +1037,14 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
i, esp->ireg, esp->sreg);
if (esp->ireg & ESP_INTR_DC) {
- printk(KERN_ERR PFX "esp%d: Reconnect, got disconnect.\n",
- esp->host->unique_id);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect, got disconnect.\n");
return NULL;
}
if ((esp->sreg & ESP_STAT_PMASK) != ESP_MIP) {
- printk(KERN_ERR PFX "esp%d: Reconnect, not MIP sreg[%02x].\n",
- esp->host->unique_id, esp->sreg);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect, not MIP sreg[%02x].\n", esp->sreg);
return NULL;
}
@@ -1073,8 +1067,7 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
udelay(1);
}
if (i == ESP_RESELECT_TAG_LIMIT) {
- printk(KERN_ERR PFX "esp%d: Reconnect IRQ2 timeout\n",
- esp->host->unique_id);
+ shost_printk(KERN_ERR, esp->host, "Reconnect IRQ2 timeout\n");
return NULL;
}
esp->ops->dma_drain(esp);
@@ -1087,17 +1080,17 @@ static struct esp_cmd_entry *esp_reconnect_with_tag(struct esp *esp,
if (esp->command_block[0] < SIMPLE_QUEUE_TAG ||
esp->command_block[0] > ORDERED_QUEUE_TAG) {
- printk(KERN_ERR PFX "esp%d: Reconnect, bad tag "
- "type %02x.\n",
- esp->host->unique_id, esp->command_block[0]);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect, bad tag type %02x.\n",
+ esp->command_block[0]);
return NULL;
}
ent = lp->tagged_cmds[esp->command_block[1]];
if (!ent) {
- printk(KERN_ERR PFX "esp%d: Reconnect, no entry for "
- "tag %02x.\n",
- esp->host->unique_id, esp->command_block[1]);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect, no entry for tag %02x.\n",
+ esp->command_block[1]);
return NULL;
}
@@ -1163,9 +1156,9 @@ static int esp_reconnect(struct esp *esp)
tp = &esp->target[target];
dev = __scsi_device_lookup_by_target(tp->starget, lun);
if (!dev) {
- printk(KERN_ERR PFX "esp%d: Reconnect, no lp "
- "tgt[%u] lun[%u]\n",
- esp->host->unique_id, target, lun);
+ shost_printk(KERN_ERR, esp->host,
+ "Reconnect, no lp tgt[%u] lun[%u]\n",
+ target, lun);
goto do_reset;
}
lp = dev->hostdata;
@@ -1291,8 +1284,8 @@ static int esp_finish_select(struct esp *esp)
return 0;
}
- printk("ESP: Unexpected selection completion ireg[%x].\n",
- esp->ireg);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected selection completion ireg[%x]\n", esp->ireg);
esp_schedule_reset(esp);
return 0;
}
@@ -1556,8 +1549,8 @@ static void esp_msgin_extended(struct esp *esp)
return;
}
- printk("ESP: Unexpected extended msg type %x\n",
- esp->msg_in[2]);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected extended msg type %x\n", esp->msg_in[2]);
esp->msg_out[0] = ABORT_TASK_SET;
esp->msg_out_len = 1;
@@ -1574,7 +1567,8 @@ static int esp_msgin_process(struct esp *esp)
if (msg0 & 0x80) {
/* Identify */
- printk("ESP: Unexpected msgin identify\n");
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected msgin identify\n");
return 0;
}
@@ -1673,8 +1667,9 @@ again:
break;
default:
- printk("ESP: Unexpected phase, sreg=%02x\n",
- esp->sreg);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected phase, sreg=%02x\n",
+ esp->sreg);
esp_schedule_reset(esp);
return 0;
}
@@ -1708,18 +1703,17 @@ again:
esp->data_dma_len = dma_len;
if (!dma_len) {
- printk(KERN_ERR PFX "esp%d: DMA length is zero!\n",
- esp->host->unique_id);
- printk(KERN_ERR PFX "esp%d: cur adr[%08llx] len[%08x]\n",
- esp->host->unique_id,
- (unsigned long long)esp_cur_dma_addr(ent, cmd),
- esp_cur_dma_len(ent, cmd));
+ shost_printk(KERN_ERR, esp->host,
+ "DMA length is zero!\n");
+ shost_printk(KERN_ERR, esp->host,
+ "cur adr[%08llx] len[%08x]\n",
+ (unsigned long long)esp_cur_dma_addr(ent, cmd),
+ esp_cur_dma_len(ent, cmd));
esp_schedule_reset(esp);
return 0;
}
- esp_log_datastart("ESP: start data addr[%08llx] len[%u] "
- "write(%d)\n",
+ esp_log_datastart("start data addr[%08llx] len[%u] write(%d)\n",
(unsigned long long)dma_addr, dma_len, write);
esp->ops->send_dma_cmd(esp, dma_addr, dma_len, dma_len,
@@ -1733,7 +1727,8 @@ again:
int bytes_sent;
if (esp->ops->dma_error(esp)) {
- printk("ESP: data done, DMA error, resetting\n");
+ shost_printk(KERN_INFO, esp->host,
+ "data done, DMA error, resetting\n");
esp_schedule_reset(esp);
return 0;
}
@@ -1749,14 +1744,15 @@ again:
/* We should always see exactly a bus-service
* interrupt at the end of a successful transfer.
*/
- printk("ESP: data done, not BSERV, resetting\n");
+ shost_printk(KERN_INFO, esp->host,
+ "data done, not BSERV, resetting\n");
esp_schedule_reset(esp);
return 0;
}
bytes_sent = esp_data_bytes_sent(esp, ent, cmd);
- esp_log_datadone("ESP: data done flgs[%x] sent[%d]\n",
+ esp_log_datadone("data done flgs[%x] sent[%d]\n",
ent->flags, bytes_sent);
if (bytes_sent < 0) {
@@ -1785,8 +1781,9 @@ again:
}
if (ent->message != COMMAND_COMPLETE) {
- printk("ESP: Unexpected message %x in status\n",
- ent->message);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected message %x in status\n",
+ ent->message);
esp_schedule_reset(esp);
return 0;
}
@@ -1804,8 +1801,7 @@ again:
scsi_esp_cmd(esp, ESP_CMD_ESEL);
if (ent->message == COMMAND_COMPLETE) {
- esp_log_cmddone("ESP: Command done status[%x] "
- "message[%x]\n",
+ esp_log_cmddone("Command done status[%x] message[%x]\n",
ent->status, ent->message);
if (ent->status == SAM_STAT_TASK_SET_FULL)
esp_event_queue_full(esp, ent);
@@ -1821,16 +1817,16 @@ again:
DID_OK));
}
} else if (ent->message == DISCONNECT) {
- esp_log_disconnect("ESP: Disconnecting tgt[%d] "
- "tag[%x:%x]\n",
+ esp_log_disconnect("Disconnecting tgt[%d] tag[%x:%x]\n",
cmd->device->id,
ent->tag[0], ent->tag[1]);
esp->active_cmd = NULL;
esp_maybe_execute_command(esp);
} else {
- printk("ESP: Unexpected message %x in freebus\n",
- ent->message);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected message %x in freebus\n",
+ ent->message);
esp_schedule_reset(esp);
return 0;
}
@@ -1917,7 +1913,7 @@ again:
val = esp_read8(ESP_FDATA);
esp->msg_in[esp->msg_in_len++] = val;
- esp_log_msgin("ESP: Got msgin byte %x\n", val);
+ esp_log_msgin("Got msgin byte %x\n", val);
if (!esp_msgin_process(esp))
esp->msg_in_len = 0;
@@ -1930,7 +1926,8 @@ again:
if (esp->event != ESP_EVENT_FREE_BUS)
esp_event(esp, ESP_EVENT_CHECK_PHASE);
} else {
- printk("ESP: MSGIN neither BSERV not FDON, resetting");
+ shost_printk(KERN_INFO, esp->host,
+ "MSGIN neither BSERV not FDON, resetting");
esp_schedule_reset(esp);
return 0;
}
@@ -1961,8 +1958,8 @@ again:
break;
default:
- printk("ESP: Unexpected event %x, resetting\n",
- esp->event);
+ shost_printk(KERN_INFO, esp->host,
+ "Unexpected event %x, resetting\n", esp->event);
esp_schedule_reset(esp);
return 0;
break;
@@ -2085,14 +2082,15 @@ static void __esp_interrupt(struct esp *esp)
}
}
- esp_log_intr("ESP: intr sreg[%02x] seqreg[%02x] "
+ esp_log_intr("intr sreg[%02x] seqreg[%02x] "
"sreg2[%02x] ireg[%02x]\n",
esp->sreg, esp->seqreg, esp->sreg2, esp->ireg);
intr_done = 0;
if (esp->ireg & (ESP_INTR_S | ESP_INTR_SATN | ESP_INTR_IC)) {
- printk("ESP: unexpected IREG %02x\n", esp->ireg);
+ shost_printk(KERN_INFO, esp->host,
+ "unexpected IREG %02x\n", esp->ireg);
if (esp->ireg & ESP_INTR_IC)
esp_dump_cmd_log(esp);
@@ -2334,12 +2332,13 @@ int scsi_esp_register(struct esp *esp, struct device *dev)
esp_bootup_reset(esp);
- printk(KERN_INFO PFX "esp%u, regs[%1p:%1p] irq[%u]\n",
- esp->host->unique_id, esp->regs, esp->dma_regs,
- esp->host->irq);
- printk(KERN_INFO PFX "esp%u is a %s, %u MHz (ccf=%u), SCSI ID %u\n",
- esp->host->unique_id, esp_chip_names[esp->rev],
- esp->cfreq / 1000000, esp->cfact, esp->scsi_id);
+ dev_printk(KERN_INFO, dev, "esp%u: regs[%1p:%1p] irq[%u]\n",
+ esp->host->unique_id, esp->regs, esp->dma_regs,
+ esp->host->irq);
+ dev_printk(KERN_INFO, dev,
+ "esp%u: is a %s, %u MHz (ccf=%u), SCSI ID %u\n",
+ esp->host->unique_id, esp_chip_names[esp->rev],
+ esp->cfreq / 1000000, esp->cfact, esp->scsi_id);
/* Let the SCSI bus reset settle. */
ssleep(esp_bus_reset_settle);
@@ -2437,19 +2436,20 @@ static int esp_eh_abort_handler(struct scsi_cmnd *cmd)
* XXX much for the final driver.
*/
spin_lock_irqsave(esp->host->host_lock, flags);
- printk(KERN_ERR PFX "esp%d: Aborting command [%p:%02x]\n",
- esp->host->unique_id, cmd, cmd->cmnd[0]);
+ shost_printk(KERN_ERR, esp->host, "Aborting command [%p:%02x]\n",
+ cmd, cmd->cmnd[0]);
ent = esp->active_cmd;
if (ent)
- printk(KERN_ERR PFX "esp%d: Current command [%p:%02x]\n",
- esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+ shost_printk(KERN_ERR, esp->host,
+ "Current command [%p:%02x]\n",
+ ent->cmd, ent->cmd->cmnd[0]);
list_for_each_entry(ent, &esp->queued_cmds, list) {
- printk(KERN_ERR PFX "esp%d: Queued command [%p:%02x]\n",
- esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+ shost_printk(KERN_ERR, esp->host, "Queued command [%p:%02x]\n",
+ ent->cmd, ent->cmd->cmnd[0]);
}
list_for_each_entry(ent, &esp->active_cmds, list) {
- printk(KERN_ERR PFX "esp%d: Active command [%p:%02x]\n",
- esp->host->unique_id, ent->cmd, ent->cmd->cmnd[0]);
+ shost_printk(KERN_ERR, esp->host, " Active command [%p:%02x]\n",
+ ent->cmd, ent->cmd->cmnd[0]);
}
esp_dump_cmd_log(esp);
spin_unlock_irqrestore(esp->host->host_lock, flags);
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 04/12] esp_scsi: debug event and command
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
` (2 preceding siblings ...)
2014-11-24 14:37 ` [PATCH 03/12] esp_scsi: convert to dev_printk Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 05/12] esp_scsi: read status registers Hannes Reinecke
` (8 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
Add new debug definitions for event and command logging.
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/esp_scsi.c | 15 +++++++++++++++
1 file changed, 15 insertions(+)
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 10a3d17..3a5d81c 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -49,6 +49,8 @@ static u32 esp_debug;
#define ESP_DEBUG_DATADONE 0x00000100
#define ESP_DEBUG_RECONNECT 0x00000200
#define ESP_DEBUG_AUTOSENSE 0x00000400
+#define ESP_DEBUG_EVENT 0x00000800
+#define ESP_DEBUG_COMMAND 0x00001000
#define esp_log_intr(f, a...) \
do { if (esp_debug & ESP_DEBUG_INTR) \
@@ -100,6 +102,16 @@ do { if (esp_debug & ESP_DEBUG_AUTOSENSE) \
shost_printk(KERN_DEBUG, esp->host, f, ## a); \
} while (0)
+#define esp_log_event(f, a...) \
+do { if (esp_debug & ESP_DEBUG_EVENT) \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
+} while (0)
+
+#define esp_log_command(f, a...) \
+do { if (esp_debug & ESP_DEBUG_COMMAND) \
+ shost_printk(KERN_DEBUG, esp->host, f, ## a); \
+} while (0)
+
#define esp_read8(REG) esp->ops->esp_read8(esp, REG)
#define esp_write8(VAL,REG) esp->ops->esp_write8(esp, VAL, REG)
@@ -126,6 +138,7 @@ void scsi_esp_cmd(struct esp *esp, u8 val)
esp->esp_event_cur = (idx + 1) & (ESP_EVENT_LOG_SZ - 1);
+ esp_log_command("cmd[%02x]\n", val);
esp_write8(val, ESP_CMD);
}
EXPORT_SYMBOL(scsi_esp_cmd);
@@ -1638,6 +1651,8 @@ static int esp_process_event(struct esp *esp)
again:
write = 0;
+ esp_log_event("process event %d phase %x\n",
+ esp->event, esp->sreg & ESP_STAT_PMASK);
switch (esp->event) {
case ESP_EVENT_CHECK_PHASE:
switch (esp->sreg & ESP_STAT_PMASK) {
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 05/12] esp_scsi: read status registers
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
` (3 preceding siblings ...)
2014-11-24 14:37 ` [PATCH 04/12] esp_scsi: debug event and command Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 06/12] esp_scsi: use FIFO for command submission Hannes Reinecke
` (7 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
A read to ESP_INTRPT will clear ESP_STATUS and ESP_SSTEP. So read
all status registers in one go to avoid losing information.
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/esp_scsi.c | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 3a5d81c..0ad0f08 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -982,7 +982,6 @@ static int esp_check_spur_intr(struct esp *esp)
default:
if (!(esp->sreg & ESP_STAT_INTR)) {
- esp->ireg = esp_read8(ESP_INTRPT);
if (esp->ireg & ESP_INTR_SR)
return 1;
@@ -2056,7 +2055,12 @@ static void __esp_interrupt(struct esp *esp)
int finish_reset, intr_done;
u8 phase;
+ /*
+ * Once INTRPT is read STATUS and SSTEP are cleared.
+ */
esp->sreg = esp_read8(ESP_STATUS);
+ esp->seqreg = esp_read8(ESP_SSTEP);
+ esp->ireg = esp_read8(ESP_INTRPT);
if (esp->flags & ESP_FLAG_RESETTING) {
finish_reset = 1;
@@ -2069,8 +2073,6 @@ static void __esp_interrupt(struct esp *esp)
return;
}
- esp->ireg = esp_read8(ESP_INTRPT);
-
if (esp->ireg & ESP_INTR_SR)
finish_reset = 1;
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 06/12] esp_scsi: use FIFO for command submission
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
` (4 preceding siblings ...)
2014-11-24 14:37 ` [PATCH 05/12] esp_scsi: read status registers Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 07/12] scsi: add 'am53c974' driver Hannes Reinecke
` (6 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
Using DMA for command submission has the drawback that it might
generate additional DMA completion interrupts after the command
has been submitted to the device.
Additionally the am53c974 has a design flaw causing it
to generate spurious interrupts even though DMA completion
interrupts are not enabled.
This can be avoided by using the FIFO for command submission.
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/esp_scsi.c | 46 +++++++++++++++++++++++++++++-----------------
drivers/scsi/esp_scsi.h | 1 +
2 files changed, 30 insertions(+), 17 deletions(-)
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 0ad0f08..2a3277d 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -143,6 +143,24 @@ void scsi_esp_cmd(struct esp *esp, u8 val)
}
EXPORT_SYMBOL(scsi_esp_cmd);
+static void esp_send_dma_cmd(struct esp *esp, int len, int max_len, int cmd)
+{
+ if (esp->flags & ESP_FLAG_USE_FIFO) {
+ int i;
+
+ scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+ for (i = 0; i < len; i++)
+ esp_write8(esp->command_block[i], ESP_FDATA);
+ scsi_esp_cmd(esp, cmd);
+ } else {
+ if (esp->rev == FASHME)
+ scsi_esp_cmd(esp, ESP_CMD_FLUSH);
+ cmd |= ESP_CMD_DMA;
+ esp->ops->send_dma_cmd(esp, esp->command_block_dma,
+ len, max_len, 0, cmd);
+ }
+}
+
static void esp_event(struct esp *esp, u8 val)
{
struct esp_event_ent *p;
@@ -650,10 +668,7 @@ static void esp_autosense(struct esp *esp, struct esp_cmd_entry *ent)
val = (p - esp->command_block);
- if (esp->rev == FASHME)
- scsi_esp_cmd(esp, ESP_CMD_FLUSH);
- esp->ops->send_dma_cmd(esp, esp->command_block_dma,
- val, 16, 0, ESP_CMD_DMA | ESP_CMD_SELA);
+ esp_send_dma_cmd(esp, val, 16, ESP_CMD_SELA);
}
static struct esp_cmd_entry *find_and_prep_issuable_command(struct esp *esp)
@@ -789,12 +804,12 @@ build_identify:
}
if (!(esp->flags & ESP_FLAG_DOING_SLOWCMD)) {
- start_cmd = ESP_CMD_DMA | ESP_CMD_SELA;
+ start_cmd = ESP_CMD_SELA;
if (ent->tag[0]) {
*p++ = ent->tag[0];
*p++ = ent->tag[1];
- start_cmd = ESP_CMD_DMA | ESP_CMD_SA3;
+ start_cmd = ESP_CMD_SA3;
}
for (i = 0; i < cmd->cmd_len; i++)
@@ -814,7 +829,7 @@ build_identify:
esp->msg_out_len += 2;
}
- start_cmd = ESP_CMD_DMA | ESP_CMD_SELAS;
+ start_cmd = ESP_CMD_SELAS;
esp->select_state = ESP_SELECT_MSGOUT;
}
val = tgt;
@@ -834,10 +849,7 @@ build_identify:
printk("]\n");
}
- if (esp->rev == FASHME)
- scsi_esp_cmd(esp, ESP_CMD_FLUSH);
- esp->ops->send_dma_cmd(esp, esp->command_block_dma,
- val, 16, 0, start_cmd);
+ esp_send_dma_cmd(esp, val, 16, start_cmd);
}
static struct esp_cmd_entry *esp_get_ent(struct esp *esp)
@@ -1646,7 +1658,7 @@ static int esp_msgin_process(struct esp *esp)
static int esp_process_event(struct esp *esp)
{
- int write;
+ int write, i;
again:
write = 0;
@@ -1872,6 +1884,10 @@ again:
if (esp->msg_out_len == 1) {
esp_write8(esp->msg_out[0], ESP_FDATA);
scsi_esp_cmd(esp, ESP_CMD_TI);
+ } else if (esp->flags & ESP_FLAG_USE_FIFO) {
+ for (i = 0; i < esp->msg_out_len; i++)
+ esp_write8(esp->msg_out[i], ESP_FDATA);
+ scsi_esp_cmd(esp, ESP_CMD_TI);
} else {
/* Use DMA. */
memcpy(esp->command_block,
@@ -1949,11 +1965,7 @@ again:
case ESP_EVENT_CMD_START:
memcpy(esp->command_block, esp->cmd_bytes_ptr,
esp->cmd_bytes_left);
- if (esp->rev == FASHME)
- scsi_esp_cmd(esp, ESP_CMD_FLUSH);
- esp->ops->send_dma_cmd(esp, esp->command_block_dma,
- esp->cmd_bytes_left, 16, 0,
- ESP_CMD_DMA | ESP_CMD_TI);
+ esp_send_dma_cmd(esp, esp->cmd_bytes_left, 16, ESP_CMD_TI);
esp_event(esp, ESP_EVENT_CMD_DONE);
esp->flags |= ESP_FLAG_QUICKIRQ_CHECK;
break;
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index 975d293..27dcaf8 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -478,6 +478,7 @@ struct esp {
#define ESP_FLAG_WIDE_CAPABLE 0x00000008
#define ESP_FLAG_QUICKIRQ_CHECK 0x00000010
#define ESP_FLAG_DISABLE_SYNC 0x00000020
+#define ESP_FLAG_USE_FIFO 0x00000040
u8 select_state;
#define ESP_SELECT_NONE 0x00 /* Not selecting */
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 07/12] scsi: add 'am53c974' driver
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
` (5 preceding siblings ...)
2014-11-24 14:37 ` [PATCH 06/12] esp_scsi: use FIFO for command submission Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 08/12] am53c974: BLAST residual handling Hannes Reinecke
` (5 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
This patch adds a new implementation for the Tekram DC-390T /
AMD AM53c974 SCSI controller, based on the generic
esp_scsi infrastructure.
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/Kconfig | 18 ++
drivers/scsi/Makefile | 1 +
drivers/scsi/am53c974.c | 537 ++++++++++++++++++++++++++++++++++++++++++++++++
3 files changed, 556 insertions(+)
create mode 100644 drivers/scsi/am53c974.c
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 60c67e1..519c3ef 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1357,6 +1357,24 @@ config SCSI_DC390T
To compile this driver as a module, choose M here: the
module will be called tmscsim.
+config SCSI_AM53C974
+ tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
+ depends on PCI && SCSI
+ select SCSI_SPI_ATTRS
+ ---help---
+ This driver supports PCI SCSI host adapters based on the Am53C974A
+ chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
+ PCscsi/PCnet (Am53/79C974) solutions.
+ This is a new implementation base on the generic esp_scsi driver.
+
+ Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
+
+ Note that this driver does NOT support Tekram DC390W/U/F, which are
+ based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
+
+ To compile this driver as a module, choose M here: the
+ module will be called am53c974.
+
config SCSI_T128
tristate "Trantor T128/T128F/T228 SCSI support"
depends on ISA && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 59f1ce6..79a6571 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -101,6 +101,7 @@ obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
obj-$(CONFIG_SCSI_EATA) += eata.o
obj-$(CONFIG_SCSI_DC395x) += dc395x.o
obj-$(CONFIG_SCSI_DC390T) += tmscsim.o
+obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o
obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
obj-$(CONFIG_MEGARAID_SAS) += megaraid/
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
new file mode 100644
index 0000000..a16c9cf
--- /dev/null
+++ b/drivers/scsi/am53c974.c
@@ -0,0 +1,537 @@
+/*
+ * AMD am53c974 driver.
+ * Copyright (c) 2014 Hannes Reinecke, SUSE Linux GmbH
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/delay.h>
+#include <linux/pci.h>
+#include <linux/interrupt.h>
+
+#include <scsi/scsi_host.h>
+
+#include "esp_scsi.h"
+
+#define DRV_MODULE_NAME "am53c974"
+#define DRV_MODULE_VERSION "1.00"
+
+static bool am53c974_debug;
+
+#define esp_dma_log(f, a...) \
+ do { \
+ if (am53c974_debug) \
+ shost_printk(KERN_DEBUG, esp->host, f, ##a); \
+ } while (0)
+
+#define ESP_DMA_CMD 0x10
+#define ESP_DMA_STC 0x11
+#define ESP_DMA_SPA 0x12
+#define ESP_DMA_WBC 0x13
+#define ESP_DMA_WAC 0x14
+#define ESP_DMA_STATUS 0x15
+#define ESP_DMA_SMDLA 0x16
+#define ESP_DMA_WMAC 0x17
+
+#define ESP_DMA_CMD_IDLE 0x00
+#define ESP_DMA_CMD_BLAST 0x01
+#define ESP_DMA_CMD_ABORT 0x02
+#define ESP_DMA_CMD_START 0x03
+#define ESP_DMA_CMD_MASK 0x03
+#define ESP_DMA_CMD_DIAG 0x04
+#define ESP_DMA_CMD_MDL 0x10
+#define ESP_DMA_CMD_INTE_P 0x20
+#define ESP_DMA_CMD_INTE_D 0x40
+#define ESP_DMA_CMD_DIR 0x80
+
+#define ESP_DMA_STAT_PWDN 0x01
+#define ESP_DMA_STAT_ERROR 0x02
+#define ESP_DMA_STAT_ABORT 0x04
+#define ESP_DMA_STAT_DONE 0x08
+#define ESP_DMA_STAT_SCSIINT 0x10
+#define ESP_DMA_STAT_BCMPLT 0x20
+
+/* EEPROM is accessed with 16-bit values */
+#define DC390_EEPROM_READ 0x80
+#define DC390_EEPROM_LEN 0x40
+
+/*
+ * DC390 EEPROM
+ *
+ * 8 * 4 bytes of per-device options
+ * followed by HBA specific options
+ */
+
+/* Per-device options */
+#define DC390_EE_MODE1 0x00
+#define DC390_EE_SPEED 0x01
+
+/* HBA-specific options */
+#define DC390_EE_ADAPT_SCSI_ID 0x40
+#define DC390_EE_MODE2 0x41
+#define DC390_EE_DELAY 0x42
+#define DC390_EE_TAG_CMD_NUM 0x43
+
+#define DC390_EE_MODE1_PARITY_CHK 0x01
+#define DC390_EE_MODE1_SYNC_NEGO 0x02
+#define DC390_EE_MODE1_EN_DISC 0x04
+#define DC390_EE_MODE1_SEND_START 0x08
+#define DC390_EE_MODE1_TCQ 0x10
+
+#define DC390_EE_MODE2_MORE_2DRV 0x01
+#define DC390_EE_MODE2_GREATER_1G 0x02
+#define DC390_EE_MODE2_RST_SCSI_BUS 0x04
+#define DC390_EE_MODE2_ACTIVE_NEGATION 0x08
+#define DC390_EE_MODE2_NO_SEEK 0x10
+#define DC390_EE_MODE2_LUN_CHECK 0x20
+
+struct pci_esp_priv {
+ struct esp *esp;
+ u8 dma_status;
+};
+
+static void pci_esp_dma_drain(struct esp *esp);
+
+static inline struct pci_esp_priv *pci_esp_get_priv(struct esp *esp)
+{
+ struct pci_dev *pdev = esp->dev;
+
+ return pci_get_drvdata(pdev);
+}
+
+static void pci_esp_write8(struct esp *esp, u8 val, unsigned long reg)
+{
+ iowrite8(val, esp->regs + (reg * 4UL));
+}
+
+static u8 pci_esp_read8(struct esp *esp, unsigned long reg)
+{
+ return ioread8(esp->regs + (reg * 4UL));
+}
+
+static void pci_esp_write32(struct esp *esp, u32 val, unsigned long reg)
+{
+ return iowrite32(val, esp->regs + (reg * 4UL));
+}
+
+static dma_addr_t pci_esp_map_single(struct esp *esp, void *buf,
+ size_t sz, int dir)
+{
+ return pci_map_single(esp->dev, buf, sz, dir);
+}
+
+static int pci_esp_map_sg(struct esp *esp, struct scatterlist *sg,
+ int num_sg, int dir)
+{
+ return pci_map_sg(esp->dev, sg, num_sg, dir);
+}
+
+static void pci_esp_unmap_single(struct esp *esp, dma_addr_t addr,
+ size_t sz, int dir)
+{
+ pci_unmap_single(esp->dev, addr, sz, dir);
+}
+
+static void pci_esp_unmap_sg(struct esp *esp, struct scatterlist *sg,
+ int num_sg, int dir)
+{
+ pci_unmap_sg(esp->dev, sg, num_sg, dir);
+}
+
+static int pci_esp_irq_pending(struct esp *esp)
+{
+ struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+ pep->dma_status = pci_esp_read8(esp, ESP_DMA_STATUS);
+ esp_dma_log("dma intr dreg[%02x]\n", pep->dma_status);
+
+ if (pep->dma_status & (ESP_DMA_STAT_ERROR |
+ ESP_DMA_STAT_ABORT |
+ ESP_DMA_STAT_DONE |
+ ESP_DMA_STAT_SCSIINT))
+ return 1;
+
+ return 0;
+}
+
+static void pci_esp_reset_dma(struct esp *esp)
+{
+ /* Nothing to do ? */
+}
+
+static void pci_esp_dma_drain(struct esp *esp)
+{
+ u8 resid;
+ int lim = 1000;
+
+
+ if ((esp->sreg & ESP_STAT_PMASK) == ESP_DOP ||
+ (esp->sreg & ESP_STAT_PMASK) == ESP_DIP)
+ /* Data-In or Data-Out, nothing to be done */
+ return;
+
+ while (--lim > 0) {
+ resid = pci_esp_read8(esp, ESP_FFLAGS) & ESP_FF_FBYTES;
+ if (resid <= 1)
+ break;
+ cpu_relax();
+ }
+ if (resid > 1) {
+ /* FIFO not cleared */
+ shost_printk(KERN_INFO, esp->host,
+ "FIFO not cleared, %d bytes left\n",
+ resid);
+ }
+
+ /*
+ * When there is a residual BCMPLT will never be set
+ * (obviously). But we still have to issue the BLAST
+ * command, otherwise the data will not being transferred.
+ * But we'll never know when the BLAST operation is
+ * finished. So check for some time and give up eventually.
+ */
+ lim = 1000;
+ pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_BLAST, ESP_DMA_CMD);
+ while (pci_esp_read8(esp, ESP_DMA_STATUS) & ESP_DMA_STAT_BCMPLT) {
+ if (--lim == 0)
+ break;
+ cpu_relax();
+ }
+ pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+ esp_dma_log("DMA blast done (%d tries, %d bytes left)\n", lim, resid);
+}
+
+static void pci_esp_dma_invalidate(struct esp *esp)
+{
+ struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+ esp_dma_log("invalidate DMA\n");
+
+ pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+ pep->dma_status = 0;
+}
+
+static int pci_esp_dma_error(struct esp *esp)
+{
+ struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+
+ if (pep->dma_status & ESP_DMA_STAT_ERROR) {
+ u8 dma_cmd = pci_esp_read8(esp, ESP_DMA_CMD);
+
+ if ((dma_cmd & ESP_DMA_CMD_MASK) == ESP_DMA_CMD_START)
+ pci_esp_write8(esp, ESP_DMA_CMD_ABORT, ESP_DMA_CMD);
+
+ return 1;
+ }
+ if (pep->dma_status & ESP_DMA_STAT_ABORT) {
+ pci_esp_write8(esp, ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
+ pep->dma_status = pci_esp_read8(esp, ESP_DMA_CMD);
+ return 1;
+ }
+ return 0;
+}
+
+static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
+ u32 dma_count, int write, u8 cmd)
+{
+ struct pci_esp_priv *pep = pci_esp_get_priv(esp);
+ u32 val = 0;
+
+ BUG_ON(!(cmd & ESP_CMD_DMA));
+
+ pep->dma_status = 0;
+
+ /* Set DMA engine to IDLE */
+ if (write)
+ /* DMA write direction logic is inverted */
+ val |= ESP_DMA_CMD_DIR;
+ pci_esp_write8(esp, ESP_DMA_CMD_IDLE | val, ESP_DMA_CMD);
+
+ pci_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
+ pci_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+
+ pci_esp_write32(esp, esp_count, ESP_DMA_STC);
+ pci_esp_write32(esp, addr, ESP_DMA_SPA);
+
+ esp_dma_log("start dma addr[%x] count[%d:%d]\n",
+ addr, esp_count, dma_count);
+
+ scsi_esp_cmd(esp, cmd);
+ /* Send DMA Start command */
+ pci_esp_write8(esp, ESP_DMA_CMD_START | val, ESP_DMA_CMD);
+}
+
+static const struct esp_driver_ops pci_esp_ops = {
+ .esp_write8 = pci_esp_write8,
+ .esp_read8 = pci_esp_read8,
+ .map_single = pci_esp_map_single,
+ .map_sg = pci_esp_map_sg,
+ .unmap_single = pci_esp_unmap_single,
+ .unmap_sg = pci_esp_unmap_sg,
+ .irq_pending = pci_esp_irq_pending,
+ .reset_dma = pci_esp_reset_dma,
+ .dma_drain = pci_esp_dma_drain,
+ .dma_invalidate = pci_esp_dma_invalidate,
+ .send_dma_cmd = pci_esp_send_dma_cmd,
+ .dma_error = pci_esp_dma_error,
+};
+
+/*
+ * Read DC-390 eeprom
+ */
+static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
+{
+ u8 carry_flag = 1, j = 0x80, bval;
+ int i;
+
+ for (i = 0; i < 9; i++) {
+ if (carry_flag) {
+ pci_write_config_byte(pdev, 0x80, 0x40);
+ bval = 0xc0;
+ } else
+ bval = 0x80;
+
+ udelay(160);
+ pci_write_config_byte(pdev, 0x80, bval);
+ udelay(160);
+ pci_write_config_byte(pdev, 0x80, 0);
+ udelay(160);
+
+ carry_flag = (cmd & j) ? 1 : 0;
+ j >>= 1;
+ }
+}
+
+static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
+{
+ int i;
+ u16 wval = 0;
+ u8 bval;
+
+ for (i = 0; i < 16; i++) {
+ wval <<= 1;
+
+ pci_write_config_byte(pdev, 0x80, 0x80);
+ udelay(160);
+ pci_write_config_byte(pdev, 0x80, 0x40);
+ udelay(160);
+ pci_read_config_byte(pdev, 0x00, &bval);
+
+ if (bval == 0x22)
+ wval |= 1;
+ }
+
+ return wval;
+}
+
+static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
+{
+ u8 cmd = DC390_EEPROM_READ, i;
+
+ for (i = 0; i < DC390_EEPROM_LEN; i++) {
+ pci_write_config_byte(pdev, 0xc0, 0);
+ udelay(160);
+
+ dc390_eeprom_prepare_read(pdev, cmd++);
+ *ptr++ = dc390_eeprom_get_data(pdev);
+
+ pci_write_config_byte(pdev, 0x80, 0);
+ pci_write_config_byte(pdev, 0x80, 0);
+ udelay(160);
+ }
+}
+
+static void dc390_check_eeprom(struct esp *esp)
+{
+ u8 EEbuf[128];
+ u16 *ptr = (u16 *)EEbuf, wval = 0;
+ int i;
+
+ dc390_read_eeprom((struct pci_dev *)esp->dev, ptr);
+
+ for (i = 0; i < DC390_EEPROM_LEN; i++, ptr++)
+ wval += *ptr;
+
+ /* no Tekram EEprom found */
+ if (wval != 0x1234) {
+ struct pci_dev *pdev = esp->dev;
+ dev_printk(KERN_INFO, &pdev->dev,
+ "No valid Tekram EEprom found\n");
+ return;
+ }
+ esp->scsi_id = EEbuf[DC390_EE_ADAPT_SCSI_ID];
+ esp->num_tags = 2 << EEbuf[DC390_EE_TAG_CMD_NUM];
+}
+
+static int pci_esp_probe_one(struct pci_dev *pdev,
+ const struct pci_device_id *id)
+{
+ struct scsi_host_template *hostt = &scsi_esp_template;
+ int err = -ENODEV;
+ struct Scsi_Host *shost;
+ struct esp *esp;
+ struct pci_esp_priv *pep;
+
+ if (pci_enable_device(pdev)) {
+ dev_printk(KERN_INFO, &pdev->dev, "cannot enable device\n");
+ return -ENODEV;
+ }
+
+ if (pci_set_dma_mask(pdev, DMA_BIT_MASK(32))) {
+ dev_printk(KERN_INFO, &pdev->dev,
+ "failed to set 32bit DMA mask\n");
+ goto fail_disable_device;
+ }
+
+ shost = scsi_host_alloc(hostt, sizeof(struct esp));
+ if (!shost) {
+ dev_printk(KERN_INFO, &pdev->dev,
+ "failed to allocate scsi host\n");
+ err = -ENOMEM;
+ goto fail_disable_device;
+ }
+
+ pep = kzalloc(sizeof(struct pci_esp_priv), GFP_KERNEL);
+ if (!pep) {
+ dev_printk(KERN_INFO, &pdev->dev,
+ "failed to allocate esp_priv\n");
+ err = -ENOMEM;
+ goto fail_host_alloc;
+ }
+
+ esp = shost_priv(shost);
+ esp->host = shost;
+ esp->dev = pdev;
+ esp->ops = &pci_esp_ops;
+ /*
+ * The am53c974 HBA has a design flaw of generating
+ * spurious DMA completion interrupts when using
+ * DMA for command submission.
+ */
+ esp->flags |= ESP_FLAG_USE_FIFO;
+ pep->esp = esp;
+
+ if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "pci memory selection failed\n");
+ goto fail_priv_alloc;
+ }
+
+ esp->regs = pci_iomap(pdev, 0, pci_resource_len(pdev, 0));
+ if (!esp->regs) {
+ dev_printk(KERN_ERR, &pdev->dev, "pci I/O map failed\n");
+ err = -EINVAL;
+ goto fail_release_regions;
+ }
+ esp->dma_regs = esp->regs;
+
+ pci_set_master(pdev);
+
+ esp->command_block = pci_alloc_consistent(pdev, 16,
+ &esp->command_block_dma);
+ if (!esp->command_block) {
+ dev_printk(KERN_ERR, &pdev->dev,
+ "failed to allocate command block\n");
+ err = -ENOMEM;
+ goto fail_unmap_regs;
+ }
+
+ err = request_irq(pdev->irq, scsi_esp_intr, IRQF_SHARED,
+ DRV_MODULE_NAME, esp);
+ if (err < 0) {
+ dev_printk(KERN_ERR, &pdev->dev, "failed to register IRQ\n");
+ goto fail_unmap_command_block;
+ }
+
+ esp->scsi_id = 7;
+ dc390_check_eeprom(esp);
+
+ shost->this_id = esp->scsi_id;
+ shost->max_id = 8;
+ shost->irq = pdev->irq;
+ shost->io_port = pci_resource_start(pdev, 0);
+ shost->n_io_port = pci_resource_len(pdev, 0);
+ shost->unique_id = shost->io_port;
+ esp->scsi_id_mask = (1 << esp->scsi_id);
+ /* Assume 40MHz clock */
+ esp->cfreq = 40000000;
+
+ pci_set_drvdata(pdev, pep);
+
+ err = scsi_esp_register(esp, &pdev->dev);
+ if (err)
+ goto fail_free_irq;
+
+ return 0;
+
+fail_free_irq:
+ free_irq(pdev->irq, esp);
+fail_unmap_command_block:
+ pci_free_consistent(pdev, 16, esp->command_block,
+ esp->command_block_dma);
+fail_unmap_regs:
+ pci_iounmap(pdev, esp->regs);
+fail_release_regions:
+ pci_release_regions(pdev);
+fail_priv_alloc:
+ kfree(pep);
+fail_host_alloc:
+ scsi_host_put(shost);
+fail_disable_device:
+ pci_disable_device(pdev);
+
+ return err;
+}
+
+static void pci_esp_remove_one(struct pci_dev *pdev)
+{
+ struct pci_esp_priv *pep = pci_get_drvdata(pdev);
+ struct esp *esp = pep->esp;
+
+ scsi_esp_unregister(esp);
+ free_irq(pdev->irq, esp);
+ pci_free_consistent(pdev, 16, esp->command_block,
+ esp->command_block_dma);
+ pci_iounmap(pdev, esp->regs);
+ pci_release_regions(pdev);
+ pci_disable_device(pdev);
+ kfree(pep);
+
+ scsi_host_put(esp->host);
+}
+
+static struct pci_device_id am53c974_pci_tbl[] = {
+ { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_SCSI,
+ PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
+ { }
+};
+MODULE_DEVICE_TABLE(pci, am53c974_pci_tbl);
+
+static struct pci_driver am53c974_driver = {
+ .name = DRV_MODULE_NAME,
+ .id_table = am53c974_pci_tbl,
+ .probe = pci_esp_probe_one,
+ .remove = pci_esp_remove_one,
+};
+
+static int __init am53c974_module_init(void)
+{
+ return pci_register_driver(&am53c974_driver);
+}
+
+static void __exit am53c974_module_exit(void)
+{
+ pci_unregister_driver(&am53c974_driver);
+}
+
+MODULE_DESCRIPTION("AM53C974 SCSI driver");
+MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
+MODULE_LICENSE("GPL");
+MODULE_VERSION(DRV_MODULE_VERSION);
+
+module_param(am53c974_debug, bool, 0644);
+MODULE_PARM_DESC(am53c974_debug, "Enable debugging");
+
+module_init(am53c974_module_init);
+module_exit(am53c974_module_exit);
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 08/12] am53c974: BLAST residual handling
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
` (6 preceding siblings ...)
2014-11-24 14:37 ` [PATCH 07/12] scsi: add 'am53c974' driver Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 09/12] esp: correctly detect am53c974 Hannes Reinecke
` (4 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
The am53c974 has an design issue where a single byte might be
left in the SCSI FIFO after a DMA transfer.
As the handling code is currently untested add a WARN_ON()
statement here.
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/am53c974.c | 6 ++++++
drivers/scsi/esp_scsi.c | 29 +++++++++++++++++++++++++++++
drivers/scsi/esp_scsi.h | 1 +
3 files changed, 36 insertions(+)
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
index a16c9cf..a42e8db 100644
--- a/drivers/scsi/am53c974.c
+++ b/drivers/scsi/am53c974.c
@@ -200,6 +200,12 @@ static void pci_esp_dma_drain(struct esp *esp)
}
pci_esp_write8(esp, ESP_DMA_CMD_DIR | ESP_DMA_CMD_IDLE, ESP_DMA_CMD);
esp_dma_log("DMA blast done (%d tries, %d bytes left)\n", lim, resid);
+ /* BLAST residual handling is currently untested */
+ if (WARN_ON_ONCE(resid == 1)) {
+ struct esp_cmd_entry *ent = esp->active_cmd;
+
+ ent->flags |= ESP_CMD_FLAG_RESIDUAL;
+ }
}
static void pci_esp_dma_invalidate(struct esp *esp)
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 2a3277d..07b4d93 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -1334,6 +1334,35 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
bytes_sent = esp->data_dma_len;
bytes_sent -= ecount;
+ /*
+ * The am53c974 has a DMA 'pecularity'. The doc states:
+ * In some odd byte conditions, one residual byte will
+ * be left in the SCSI FIFO, and the FIFO Flags will
+ * never count to '0 '. When this happens, the residual
+ * byte should be retrieved via PIO following completion
+ * of the BLAST operation.
+ */
+ if (fifo_cnt == 1 && ent->flags & ESP_CMD_FLAG_RESIDUAL) {
+ size_t count = 1;
+ size_t offset = bytes_sent;
+ u8 bval = esp_read8(ESP_FDATA);
+
+ if (ent->flags & ESP_CMD_FLAG_AUTOSENSE)
+ ent->sense_ptr[bytes_sent] = bval;
+ else {
+ struct esp_cmd_priv *p = ESP_CMD_PRIV(cmd);
+ u8 *ptr;
+
+ ptr = scsi_kmap_atomic_sg(p->cur_sg, p->u.num_sg,
+ &offset, &count);
+ if (likely(ptr)) {
+ *(ptr + offset) = bval;
+ scsi_kunmap_atomic_sg(ptr);
+ }
+ }
+ bytes_sent += fifo_cnt;
+ ent->flags &= ~ESP_CMD_FLAG_RESIDUAL;
+ }
if (!(ent->flags & ESP_CMD_FLAG_WRITE))
bytes_sent -= fifo_cnt;
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index 27dcaf8..5fa456c 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -269,6 +269,7 @@ struct esp_cmd_entry {
#define ESP_CMD_FLAG_WRITE 0x01 /* DMA is a write */
#define ESP_CMD_FLAG_ABORT 0x02 /* being aborted */
#define ESP_CMD_FLAG_AUTOSENSE 0x04 /* Doing automatic REQUEST_SENSE */
+#define ESP_CMD_FLAG_RESIDUAL 0x08 /* AM53c974 BLAST residual */
u8 tag[2];
u8 orig_tag[2];
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 09/12] esp: correctly detect am53c974
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
` (7 preceding siblings ...)
2014-11-24 14:37 ` [PATCH 08/12] am53c974: BLAST residual handling Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 10/12] esp_scsi: let DMA driver provide a config2 value Hannes Reinecke
` (3 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
The am53c974 returns the same ID as the FAS236, but implements
things slightly differently. So detect the am53c974 by checking
for ESP_CONFIG4 register.
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/am53c974.c | 2 ++
drivers/scsi/esp_scsi.c | 17 ++++++++++++++++-
drivers/scsi/esp_scsi.h | 15 +++++++++++++++
3 files changed, 33 insertions(+), 1 deletion(-)
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
index a42e8db..6e88e38 100644
--- a/drivers/scsi/am53c974.c
+++ b/drivers/scsi/am53c974.c
@@ -368,6 +368,8 @@ static void dc390_check_eeprom(struct esp *esp)
}
esp->scsi_id = EEbuf[DC390_EE_ADAPT_SCSI_ID];
esp->num_tags = 2 << EEbuf[DC390_EE_TAG_CMD_NUM];
+ if (EEbuf[DC390_EE_MODE2] & DC390_EE_MODE2_ACTIVE_NEGATION)
+ esp->config4 |= ESP_CONFIG4_RADE | ESP_CONFIG4_RAE;
}
static int pci_esp_probe_one(struct pci_dev *pdev,
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 07b4d93..8a162be 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -268,6 +268,19 @@ static void esp_reset_esp(struct esp *esp)
} else {
esp->min_period = ((5 * esp->ccycle) / 1000);
}
+ if (esp->rev == FAS236) {
+ /*
+ * The AM53c974 chip returns the same ID as FAS236;
+ * try to configure glitch eater.
+ */
+ u8 config4 = ESP_CONFIG4_GE1;
+ esp_write8(config4, ESP_CFG4);
+ config4 = esp_read8(ESP_CFG4);
+ if (config4 & ESP_CONFIG4_GE1) {
+ esp->rev = PCSCSI;
+ esp_write8(esp->config4, ESP_CFG4);
+ }
+ }
esp->max_period = (esp->max_period + 3)>>2;
esp->min_period = (esp->min_period + 3)>>2;
@@ -293,7 +306,8 @@ static void esp_reset_esp(struct esp *esp)
/* fallthrough... */
case FAS236:
- /* Fast 236 or HME */
+ case PCSCSI:
+ /* Fast 236, AM53c974 or HME */
esp_write8(esp->config2, ESP_CFG2);
if (esp->rev == FASHME) {
u8 cfg3 = esp->target[0].esp_config3;
@@ -2364,6 +2378,7 @@ static const char *esp_chip_names[] = {
"FAS100A",
"FAST",
"FASHME",
+ "AM53C974",
};
static struct scsi_transport_template *esp_transport_template;
diff --git a/drivers/scsi/esp_scsi.h b/drivers/scsi/esp_scsi.h
index 5fa456c..84dcbe4 100644
--- a/drivers/scsi/esp_scsi.h
+++ b/drivers/scsi/esp_scsi.h
@@ -25,6 +25,7 @@
#define ESP_CTEST 0x0aUL /* wo Chip test register 0x28 */
#define ESP_CFG2 0x0bUL /* rw Second cfg register 0x2c */
#define ESP_CFG3 0x0cUL /* rw Third cfg register 0x30 */
+#define ESP_CFG4 0x0dUL /* rw Fourth cfg register 0x34 */
#define ESP_TCHI 0x0eUL /* rw High bits transf count 0x38 */
#define ESP_UID ESP_TCHI /* ro Unique ID code 0x38 */
#define FAS_RLO ESP_TCHI /* rw HME extended counter 0x38 */
@@ -76,6 +77,18 @@
#define ESP_CONFIG3_IMS 0x80 /* ID msg chk'ng (esp/fas236) */
#define ESP_CONFIG3_OBPUSH 0x80 /* Push odd-byte to dma (hme) */
+/* ESP config register 4 read-write, found only on am53c974 chips */
+#define ESP_CONFIG4_RADE 0x04 /* Active negation */
+#define ESP_CONFIG4_RAE 0x08 /* Active negation on REQ and ACK */
+#define ESP_CONFIG4_PWD 0x20 /* Reduced power feature */
+#define ESP_CONFIG4_GE0 0x40 /* Glitch eater bit 0 */
+#define ESP_CONFIG4_GE1 0x80 /* Glitch eater bit 1 */
+
+#define ESP_CONFIG_GE_12NS (0)
+#define ESP_CONFIG_GE_25NS (ESP_CONFIG_GE1)
+#define ESP_CONFIG_GE_35NS (ESP_CONFIG_GE0)
+#define ESP_CONFIG_GE_0NS (ESP_CONFIG_GE0 | ESP_CONFIG_GE1)
+
/* ESP command register read-write */
/* Group 1 commands: These may be sent at any point in time to the ESP
* chip. None of them can generate interrupts 'cept
@@ -254,6 +267,7 @@ enum esp_rev {
FAS100A = 0x04,
FAST = 0x05,
FASHME = 0x06,
+ PCSCSI = 0x07, /* AM53c974 */
};
struct esp_cmd_entry {
@@ -466,6 +480,7 @@ struct esp {
u8 bursts;
u8 config1;
u8 config2;
+ u8 config4;
u8 scsi_id;
u32 scsi_id_mask;
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 10/12] esp_scsi: let DMA driver provide a config2 value
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
` (8 preceding siblings ...)
2014-11-24 14:37 ` [PATCH 09/12] esp: correctly detect am53c974 Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974 Hannes Reinecke
` (2 subsequent siblings)
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi
From: Paolo Bonzini <pbonzini@redhat.com>
On PCscsi, the FENAB configuration also enables 24-bit DMA
transfer lengths (and provides the chip id in TCHI after reset).
We want to be able to enable this parameter from the DMA driver.
Check if the caller of scsi_esp_register provided a value for esp->config2.
If this is the case, assume this is not an ESP100, skip the detection
phase and leave esp->config2 untouched. It will be used in esp_reset_esp.
Reviewed-by: Hannes Reinecke <hare@suse.de>
Acked-by: David S. Miller <davem@davemloft.net>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
---
drivers/scsi/esp_scsi.c | 70 ++++++++++++++++++++++++++-----------------------
1 file changed, 37 insertions(+), 33 deletions(-)
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index 8a162be..cfbae52 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -2219,46 +2219,50 @@ static void esp_get_revision(struct esp *esp)
u8 val;
esp->config1 = (ESP_CONFIG1_PENABLE | (esp->scsi_id & 7));
- esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
+ if (esp->config2 == 0) {
+ esp->config2 = (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY);
+ esp_write8(esp->config2, ESP_CFG2);
+
+ val = esp_read8(ESP_CFG2);
+ val &= ~ESP_CONFIG2_MAGIC;
+
+ esp->config2 = 0;
+ if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
+ /*
+ * If what we write to cfg2 does not come back,
+ * cfg2 is not implemented.
+ * Therefore this must be a plain esp100.
+ */
+ esp->rev = ESP100;
+ return;
+ }
+ }
+
+ esp_set_all_config3(esp, 5);
+ esp->prev_cfg3 = 5;
esp_write8(esp->config2, ESP_CFG2);
+ esp_write8(0, ESP_CFG3);
+ esp_write8(esp->prev_cfg3, ESP_CFG3);
- val = esp_read8(ESP_CFG2);
- val &= ~ESP_CONFIG2_MAGIC;
- if (val != (ESP_CONFIG2_SCSI2ENAB | ESP_CONFIG2_REGPARITY)) {
- /* If what we write to cfg2 does not come back, cfg2 is not
- * implemented, therefore this must be a plain esp100.
+ val = esp_read8(ESP_CFG3);
+ if (val != 5) {
+ /* The cfg2 register is implemented, however
+ * cfg3 is not, must be esp100a.
*/
- esp->rev = ESP100;
+ esp->rev = ESP100A;
} else {
- esp->config2 = 0;
- esp_set_all_config3(esp, 5);
- esp->prev_cfg3 = 5;
- esp_write8(esp->config2, ESP_CFG2);
- esp_write8(0, ESP_CFG3);
+ esp_set_all_config3(esp, 0);
+ esp->prev_cfg3 = 0;
esp_write8(esp->prev_cfg3, ESP_CFG3);
- val = esp_read8(ESP_CFG3);
- if (val != 5) {
- /* The cfg2 register is implemented, however
- * cfg3 is not, must be esp100a.
- */
- esp->rev = ESP100A;
+ /* All of cfg{1,2,3} implemented, must be one of
+ * the fas variants, figure out which one.
+ */
+ if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) {
+ esp->rev = FAST;
+ esp->sync_defp = SYNC_DEFP_FAST;
} else {
- esp_set_all_config3(esp, 0);
- esp->prev_cfg3 = 0;
- esp_write8(esp->prev_cfg3, ESP_CFG3);
-
- /* All of cfg{1,2,3} implemented, must be one of
- * the fas variants, figure out which one.
- */
- if (esp->cfact == 0 || esp->cfact > ESP_CCF_F5) {
- esp->rev = FAST;
- esp->sync_defp = SYNC_DEFP_FAST;
- } else {
- esp->rev = ESP236;
- }
- esp->config2 = 0;
- esp_write8(esp->config2, ESP_CFG2);
+ esp->rev = ESP236;
}
}
}
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
` (9 preceding siblings ...)
2014-11-24 14:37 ` [PATCH 10/12] esp_scsi: let DMA driver provide a config2 value Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 14:37 ` [PATCH 12/12] Replace tmscsim by am53c974 Hannes Reinecke
2014-11-24 15:18 ` [PATCHv3 00/12] Re-implement am53c974 driver Christoph Hellwig
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
CONFIG2_FENAB ('feature enable') changed definition between chip
revisions, from 'Latch SCSI Phase' to 'Latch SCSI Phase, display
chip ID upon reset, and enable 24 bit addresses'.
So only enable it for am53c974 where we know what it's doing.
Acked-by: David S. Miller <davem@davemloft.net>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
drivers/scsi/am53c974.c | 40 ++++++++++++++++++++++++++++++++++++++++
drivers/scsi/esp_scsi.c | 2 ++
2 files changed, 42 insertions(+)
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
index 6e88e38..25f0619 100644
--- a/drivers/scsi/am53c974.c
+++ b/drivers/scsi/am53c974.c
@@ -18,6 +18,7 @@
#define DRV_MODULE_VERSION "1.00"
static bool am53c974_debug;
+static bool am53c974_fenab = true;
#define esp_dma_log(f, a...) \
do { \
@@ -256,6 +257,8 @@ static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
pci_esp_write8(esp, (esp_count >> 0) & 0xff, ESP_TCLOW);
pci_esp_write8(esp, (esp_count >> 8) & 0xff, ESP_TCMED);
+ if (esp->config2 & ESP_CONFIG2_FENAB)
+ pci_esp_write8(esp, (esp_count >> 16) & 0xff, ESP_TCHI);
pci_esp_write32(esp, esp_count, ESP_DMA_STC);
pci_esp_write32(esp, addr, ESP_DMA_SPA);
@@ -268,6 +271,33 @@ static void pci_esp_send_dma_cmd(struct esp *esp, u32 addr, u32 esp_count,
pci_esp_write8(esp, ESP_DMA_CMD_START | val, ESP_DMA_CMD);
}
+static u32 pci_esp_dma_length_limit(struct esp *esp, u32 dma_addr, u32 dma_len)
+{
+ int dma_limit = 16;
+ u32 base, end;
+
+ /*
+ * If CONFIG2_FENAB is set we can
+ * handle up to 24 bit addresses
+ */
+ if (esp->config2 & ESP_CONFIG2_FENAB)
+ dma_limit = 24;
+
+ if (dma_len > (1U << dma_limit))
+ dma_len = (1U << dma_limit);
+
+ /*
+ * Prevent crossing a 24-bit address boundary.
+ */
+ base = dma_addr & ((1U << 24) - 1U);
+ end = base + dma_len;
+ if (end > (1U << 24))
+ end = (1U <<24);
+ dma_len = end - base;
+
+ return dma_len;
+}
+
static const struct esp_driver_ops pci_esp_ops = {
.esp_write8 = pci_esp_write8,
.esp_read8 = pci_esp_read8,
@@ -281,6 +311,7 @@ static const struct esp_driver_ops pci_esp_ops = {
.dma_invalidate = pci_esp_dma_invalidate,
.send_dma_cmd = pci_esp_send_dma_cmd,
.dma_error = pci_esp_dma_error,
+ .dma_length_limit = pci_esp_dma_length_limit,
};
/*
@@ -418,6 +449,12 @@ static int pci_esp_probe_one(struct pci_dev *pdev,
* DMA for command submission.
*/
esp->flags |= ESP_FLAG_USE_FIFO;
+ /*
+ * Enable CONFIG2_FENAB to allow for large DMA transfers
+ */
+ if (am53c974_fenab)
+ esp->config2 |= ESP_CONFIG2_FENAB;
+
pep->esp = esp;
if (pci_request_regions(pdev, DRV_MODULE_NAME)) {
@@ -541,5 +578,8 @@ MODULE_VERSION(DRV_MODULE_VERSION);
module_param(am53c974_debug, bool, 0644);
MODULE_PARM_DESC(am53c974_debug, "Enable debugging");
+module_param(am53c974_fenab, bool, 0444);
+MODULE_PARM_DESC(am53c974_fenab, "Enable 24-bit DMA transfer sizes");
+
module_init(am53c974_module_init);
module_exit(am53c974_module_exit);
diff --git a/drivers/scsi/esp_scsi.c b/drivers/scsi/esp_scsi.c
index cfbae52..dc120f9 100644
--- a/drivers/scsi/esp_scsi.c
+++ b/drivers/scsi/esp_scsi.c
@@ -1343,6 +1343,8 @@ static int esp_data_bytes_sent(struct esp *esp, struct esp_cmd_entry *ent,
(((unsigned int)esp_read8(ESP_TCMED)) << 8));
if (esp->rev == FASHME)
ecount |= ((unsigned int)esp_read8(FAS_RLO)) << 16;
+ if (esp->rev == PCSCSI && (esp->config2 & ESP_CONFIG2_FENAB))
+ ecount |= ((unsigned int)esp_read8(ESP_TCHI)) << 16;
}
bytes_sent = esp->data_dma_len;
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* [PATCH 12/12] Replace tmscsim by am53c974
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
` (10 preceding siblings ...)
2014-11-24 14:37 ` [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974 Hannes Reinecke
@ 2014-11-24 14:37 ` Hannes Reinecke
2014-11-24 15:18 ` [PATCHv3 00/12] Re-implement am53c974 driver Christoph Hellwig
12 siblings, 0 replies; 17+ messages in thread
From: Hannes Reinecke @ 2014-11-24 14:37 UTC (permalink / raw)
To: James Bottomley
Cc: Christoph Hellwig, Paolo, "Bonzini <pbonzini",
David S. Miller, linux-scsi, Hannes Reinecke
The am53c974 is a re-implementation of the tmscsim driver,
and provides the same functionality.
So remove the tmscsim driver and make am53c974 an alias to tmscsim.
Acked-by: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
Signed-off-by: Hannes Reinecke <hare@suse.de>
---
MAINTAINERS | 7 +-
drivers/scsi/Kconfig | 16 -
drivers/scsi/Makefile | 1 -
drivers/scsi/am53c974.c | 1 +
drivers/scsi/tmscsim.c | 2626 -----------------------------------------------
drivers/scsi/tmscsim.h | 549 ----------
6 files changed, 4 insertions(+), 3196 deletions(-)
delete mode 100644 drivers/scsi/tmscsim.c
delete mode 100644 drivers/scsi/tmscsim.h
diff --git a/MAINTAINERS b/MAINTAINERS
index d206f37..d780e46 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -2862,11 +2862,10 @@ F: Documentation/networking/dmfe.txt
F: drivers/net/ethernet/dec/tulip/dmfe.c
DC390/AM53C974 SCSI driver
-M: Kurt Garloff <garloff@suse.de>
-W: http://www.garloff.de/kurt/linux/dc390/
-M: Guennadi Liakhovetski <g.liakhovetski@gmx.de>
+M: Hannes Reinecke <hare@suse.de>
+L: linux-scsi@vger.kernel.org
S: Maintained
-F: drivers/scsi/tmscsim.*
+F: drivers/scsi/am53c974.c
DC395x SCSI driver
M: Oliver Neukum <oliver@neukum.org>
diff --git a/drivers/scsi/Kconfig b/drivers/scsi/Kconfig
index 519c3ef..f871a80 100644
--- a/drivers/scsi/Kconfig
+++ b/drivers/scsi/Kconfig
@@ -1341,22 +1341,6 @@ config SCSI_DC395x
To compile this driver as a module, choose M here: the
module will be called dc395x.
-config SCSI_DC390T
- tristate "Tekram DC390(T) and Am53/79C974 SCSI support"
- depends on PCI && SCSI
- ---help---
- This driver supports PCI SCSI host adapters based on the Am53C974A
- chip, e.g. Tekram DC390(T), DawiControl 2974 and some onboard
- PCscsi/PCnet (Am53/79C974) solutions.
-
- Documentation can be found in <file:Documentation/scsi/tmscsim.txt>.
-
- Note that this driver does NOT support Tekram DC390W/U/F, which are
- based on NCR/Symbios chips. Use "NCR53C8XX SCSI support" for those.
-
- To compile this driver as a module, choose M here: the
- module will be called tmscsim.
-
config SCSI_AM53C974
tristate "Tekram DC390(T) and Am53/79C974 SCSI support (new driver)"
depends on PCI && SCSI
diff --git a/drivers/scsi/Makefile b/drivers/scsi/Makefile
index 79a6571..a9f3fa8 100644
--- a/drivers/scsi/Makefile
+++ b/drivers/scsi/Makefile
@@ -100,7 +100,6 @@ obj-$(CONFIG_SCSI_EATA_PIO) += eata_pio.o
obj-$(CONFIG_SCSI_7000FASST) += wd7000.o
obj-$(CONFIG_SCSI_EATA) += eata.o
obj-$(CONFIG_SCSI_DC395x) += dc395x.o
-obj-$(CONFIG_SCSI_DC390T) += tmscsim.o
obj-$(CONFIG_SCSI_AM53C974) += esp_scsi.o am53c974.o
obj-$(CONFIG_MEGARAID_LEGACY) += megaraid.o
obj-$(CONFIG_MEGARAID_NEWGEN) += megaraid/
diff --git a/drivers/scsi/am53c974.c b/drivers/scsi/am53c974.c
index 25f0619..aa3e2c7 100644
--- a/drivers/scsi/am53c974.c
+++ b/drivers/scsi/am53c974.c
@@ -574,6 +574,7 @@ MODULE_DESCRIPTION("AM53C974 SCSI driver");
MODULE_AUTHOR("Hannes Reinecke <hare@suse.de>");
MODULE_LICENSE("GPL");
MODULE_VERSION(DRV_MODULE_VERSION);
+MODULE_ALIAS("tmscsim");
module_param(am53c974_debug, bool, 0644);
MODULE_PARM_DESC(am53c974_debug, "Enable debugging");
diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c
deleted file mode 100644
index 844c9a0..0000000
--- a/drivers/scsi/tmscsim.c
+++ /dev/null
@@ -1,2626 +0,0 @@
-/************************************************************************
- * FILE NAME : TMSCSIM.C *
- * BY : C.L. Huang, ching@tekram.com.tw *
- * Description: Device Driver for Tekram DC-390(T) PCI SCSI *
- * Bus Master Host Adapter *
- * (C)Copyright 1995-1996 Tekram Technology Co., Ltd. *
- ************************************************************************
- * (C) Copyright: put under GNU GPL in 10/96 *
- * (see Documentation/scsi/tmscsim.txt) *
- ************************************************************************
- * $Id: tmscsim.c,v 2.60.2.30 2000/12/20 01:07:12 garloff Exp $ *
- * Enhancements and bugfixes by *
- * Kurt Garloff <kurt@garloff.de> <garloff@suse.de> *
- ************************************************************************
- * HISTORY: *
- * *
- * REV# DATE NAME DESCRIPTION *
- * 1.00 96/04/24 CLH First release *
- * 1.01 96/06/12 CLH Fixed bug of Media Change for Removable *
- * Device, scan all LUN. Support Pre2.0.10 *
- * 1.02 96/06/18 CLH Fixed bug of Command timeout ... *
- * 1.03 96/09/25 KG Added tmscsim_proc_info() *
- * 1.04 96/10/11 CLH Updating for support KV 2.0.x *
- * 1.05 96/10/18 KG Fixed bug in DC390_abort(null ptr deref)*
- * 1.06 96/10/25 KG Fixed module support *
- * 1.07 96/11/09 KG Fixed tmscsim_proc_info() *
- * 1.08 96/11/18 KG Fixed null ptr in DC390_Disconnect() *
- * 1.09 96/11/30 KG Added register the allocated IO space *
- * 1.10 96/12/05 CLH Modified tmscsim_proc_info(), and reset *
- * pending interrupt in DC390_detect() *
- * 1.11 97/02/05 KG/CLH Fixeds problem with partitions greater *
- * than 1GB *
- * 1.12 98/02/15 MJ Rewritten PCI probing *
- * 1.13 98/04/08 KG Support for non DC390, __initfunc decls,*
- * changed max devs from 10 to 16 *
- * 1.14a 98/05/05 KG Dynamic DCB allocation, add-single-dev *
- * for LUNs if LUN_SCAN (BIOS) not set *
- * runtime config using /proc interface *
- * 1.14b 98/05/06 KG eliminated cli (); sti (); spinlocks *
- * 1.14c 98/05/07 KG 2.0.x compatibility *
- * 1.20a 98/05/07 KG changed names of funcs to be consistent *
- * DC390_ (entry points), dc390_ (internal)*
- * reworked locking *
- * 1.20b 98/05/12 KG bugs: version, kfree, _ctmp *
- * debug output *
- * 1.20c 98/05/12 KG bugs: kfree, parsing, EEpromDefaults *
- * 1.20d 98/05/14 KG bugs: list linkage, clear flag after *
- * reset on startup, code cleanup *
- * 1.20e 98/05/15 KG spinlock comments, name space cleanup *
- * pLastDCB now part of ACB structure *
- * added stats, timeout for 2.1, TagQ bug *
- * RESET and INQUIRY interface commands *
- * 1.20f 98/05/18 KG spinlocks fixes, max_lun fix, free DCBs *
- * for missing LUNs, pending int *
- * 1.20g 98/05/19 KG Clean up: Avoid short *
- * 1.20h 98/05/21 KG Remove AdaptSCSIID, max_lun ... *
- * 1.20i 98/05/21 KG Aiiie: Bug with TagQMask *
- * 1.20j 98/05/24 KG Handle STAT_BUSY, handle pACB->pLinkDCB *
- * == 0 in remove_dev and DoingSRB_Done *
- * 1.20k 98/05/25 KG DMA_INT (experimental) *
- * 1.20l 98/05/27 KG remove DMA_INT; DMA_IDLE cmds added; *
- * 1.20m 98/06/10 KG glitch configurable; made some global *
- * vars part of ACB; use DC390_readX *
- * 1.20n 98/06/11 KG startup params *
- * 1.20o 98/06/15 KG added TagMaxNum to boot/module params *
- * Device Nr -> Idx, TagMaxNum power of 2 *
- * 1.20p 98/06/17 KG Docu updates. Reset depends on settings *
- * pci_set_master added; 2.0.xx: pcibios_* *
- * used instead of MechNum things ... *
- * 1.20q 98/06/23 KG Changed defaults. Added debug code for *
- * removable media and fixed it. TagMaxNum *
- * fixed for DC390. Locking: ACB, DRV for *
- * better IRQ sharing. Spelling: Queueing *
- * Parsing and glitch_cfg changes. Display *
- * real SyncSpeed value. Made DisConn *
- * functional (!) *
- * 1.20r 98/06/30 KG Debug macros, allow disabling DsCn, set *
- * BIT4 in CtrlR4, EN_PAGE_INT, 2.0 module *
- * param -1 fixed. *
- * 1.20s 98/08/20 KG Debug info on abort(), try to check PCI,*
- * phys_to_bus instead of phys_to_virt, *
- * fixed sel. process, fixed locking, *
- * added MODULE_XXX infos, changed IRQ *
- * request flags, disable DMA_INT *
- * 1.20t 98/09/07 KG TagQ report fixed; Write Erase DMA Stat;*
- * initfunc -> __init; better abort; *
- * Timeout for XFER_DONE & BLAST_COMPLETE; *
- * Allow up to 33 commands being processed *
- * 2.0a 98/10/14 KG Max Cmnds back to 17. DMA_Stat clearing *
- * all flags. Clear within while() loops *
- * in DataIn_0/Out_0. Null ptr in dumpinfo *
- * for pSRB==0. Better locking during init.*
- * bios_param() now respects part. table. *
- * 2.0b 98/10/24 KG Docu fixes. Timeout Msg in DMA Blast. *
- * Disallow illegal idx in INQUIRY/REMOVE *
- * 2.0c 98/11/19 KG Cleaned up detect/init for SMP boxes, *
- * Write Erase DMA (1.20t) caused problems *
- * 2.0d 98/12/25 KG Christmas release ;-) Message handling *
- * 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 unique_id. Disable RETRY message. *
- * 2.0d2600/01/29 KG Go to new EH. *
- * 2.0d2700/01/31 KG ... but maintain 2.0 compat. *
- * and fix DCB freeing *
- * 2.0d2800/02/14 KG Queue statistics fixed, dump special cmd*
- * Waiting_Timer for failed StartSCSI *
- * New EH: Don't return cmnds to ML on RST *
- * Use old EH (don't have new EH fns yet) *
- * Reset: Unlock, but refuse to queue *
- * 2.3 __setup function *
- * 2.0e 00/05/22 KG Return residual for 2.3 *
- * 2.0e1 00/05/25 KG Compile fixes for 2.3.99 *
- * 2.0e2 00/05/27 KG Jeff Garzik's pci_enable_device() *
- * 2.0e3 00/09/29 KG Some 2.4 changes. Don't try Sync Nego *
- * before INQUIRY has reported ability. *
- * Recognise INQUIRY as scanning command. *
- * 2.0e4 00/10/13 KG Allow compilation into 2.4 kernel *
- * 2.0e5 00/11/17 KG Store Inq.flags in DCB *
- * 2.0e6 00/11/22 KG 2.4 init function (Thx to O.Schumann) *
- * 2.4 PCI device table (Thx to A.Richter) *
- * 2.0e7 00/11/28 KG Allow overriding of BIOS settings *
- * 2.0f 00/12/20 KG Handle failed INQUIRYs during scan *
- * 2.1a 03/11/29 GL, KG Initial fixing for 2.6. Convert to *
- * use the current PCI-mapping API, update *
- * command-queuing. *
- * 2.1b 04/04/13 GL Fix for 64-bit platforms *
- * 2.1b1 04/01/31 GL (applied 05.04) Remove internal *
- * command-queuing. *
- * 2.1b2 04/02/01 CH (applied 05.04) Fix error-handling *
- * 2.1c 04/05/23 GL Update to use the new pci_driver API, *
- * some scsi EH updates, more cleanup. *
- * 2.1d 04/05/27 GL Moved setting of scan_devices to *
- * slave_alloc/_configure/_destroy, as *
- * suggested by CH. *
- ***********************************************************************/
-
-/* DEBUG options */
-//#define DC390_DEBUG0
-//#define DC390_DEBUG1
-//#define DC390_DCBDEBUG
-//#define DC390_PARSEDEBUG
-//#define DC390_REMOVABLEDEBUG
-//#define DC390_LOCKDEBUG
-
-//#define NOP do{}while(0)
-#define C_NOP
-
-/* Debug definitions */
-#ifdef DC390_DEBUG0
-# define DEBUG0(x) x
-#else
-# define DEBUG0(x) C_NOP
-#endif
-#ifdef DC390_DEBUG1
-# define DEBUG1(x) x
-#else
-# define DEBUG1(x) C_NOP
-#endif
-#ifdef DC390_DCBDEBUG
-# define DCBDEBUG(x) x
-#else
-# define DCBDEBUG(x) C_NOP
-#endif
-#ifdef DC390_PARSEDEBUG
-# define PARSEDEBUG(x) x
-#else
-# define PARSEDEBUG(x) C_NOP
-#endif
-#ifdef DC390_REMOVABLEDEBUG
-# define REMOVABLEDEBUG(x) x
-#else
-# define REMOVABLEDEBUG(x) C_NOP
-#endif
-#define DCBDEBUG1(x) C_NOP
-
-#include <linux/module.h>
-#include <linux/delay.h>
-#include <linux/signal.h>
-#include <linux/errno.h>
-#include <linux/kernel.h>
-#include <linux/ioport.h>
-#include <linux/pci.h>
-#include <linux/proc_fs.h>
-#include <linux/string.h>
-#include <linux/mm.h>
-#include <linux/blkdev.h>
-#include <linux/timer.h>
-#include <linux/interrupt.h>
-#include <linux/init.h>
-#include <linux/spinlock.h>
-#include <linux/slab.h>
-#include <asm/io.h>
-
-#include <scsi/scsi.h>
-#include <scsi/scsi_cmnd.h>
-#include <scsi/scsi_device.h>
-#include <scsi/scsi_host.h>
-#include <scsi/scsicam.h>
-#include <scsi/scsi_tcq.h>
-
-#define DC390_BANNER "Tekram DC390/AM53C974"
-#define DC390_VERSION "2.1d 2004-05-27"
-
-#define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI
-
-#include "tmscsim.h"
-
-
-static void dc390_DataOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-static void dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus);
-
-static void dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB );
-static void dc390_Disconnect( struct dc390_acb* pACB );
-static void dc390_Reselect( struct dc390_acb* pACB );
-static void dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB );
-static void dc390_ScsiRstDetect( struct dc390_acb* pACB );
-static void dc390_EnableMsgOut_Abort(struct dc390_acb*, struct dc390_srb*);
-static void dc390_dumpinfo(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB);
-static void dc390_ResetDevParam(struct dc390_acb* pACB);
-
-static u32 dc390_laststatus = 0;
-static u8 dc390_adapterCnt = 0;
-
-static int disable_clustering;
-module_param(disable_clustering, int, S_IRUGO);
-MODULE_PARM_DESC(disable_clustering, "If you experience problems with your devices, try setting to 1");
-
-/* Startup values, to be overriden on the commandline */
-static int tmscsim[] = {-2, -2, -2, -2, -2, -2};
-
-module_param_array(tmscsim, int, NULL, 0);
-MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)");
-MODULE_AUTHOR("C.L. Huang / Kurt Garloff");
-MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");
-MODULE_LICENSE("GPL");
-MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");
-
-static void *dc390_phase0[]={
- dc390_DataOut_0,
- dc390_DataIn_0,
- dc390_Command_0,
- dc390_Status_0,
- dc390_Nop_0,
- dc390_Nop_0,
- dc390_MsgOut_0,
- dc390_MsgIn_0,
- dc390_Nop_1
- };
-
-static void *dc390_phase1[]={
- dc390_DataOutPhase,
- dc390_DataInPhase,
- dc390_CommandPhase,
- dc390_StatusPhase,
- dc390_Nop_0,
- dc390_Nop_0,
- dc390_MsgOutPhase,
- dc390_MsgInPhase,
- dc390_Nop_1
- };
-
-#ifdef DC390_DEBUG1
-static char* dc390_p0_str[] = {
- "dc390_DataOut_0",
- "dc390_DataIn_0",
- "dc390_Command_0",
- "dc390_Status_0",
- "dc390_Nop_0",
- "dc390_Nop_0",
- "dc390_MsgOut_0",
- "dc390_MsgIn_0",
- "dc390_Nop_1"
- };
-
-static char* dc390_p1_str[] = {
- "dc390_DataOutPhase",
- "dc390_DataInPhase",
- "dc390_CommandPhase",
- "dc390_StatusPhase",
- "dc390_Nop_0",
- "dc390_Nop_0",
- "dc390_MsgOutPhase",
- "dc390_MsgInPhase",
- "dc390_Nop_1"
- };
-#endif
-
-static u8 dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];
-static u8 dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};
-static u8 dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};
-
-/***********************************************************************
- * Functions for the management of the internal structures
- * (DCBs, SRBs, Queueing)
- *
- **********************************************************************/
-static void inline dc390_start_segment(struct dc390_srb* pSRB)
-{
- struct scatterlist *psgl = pSRB->pSegmentList;
-
- /* start new sg segment */
- pSRB->SGBusAddr = sg_dma_address(psgl);
- pSRB->SGToBeXferLen = sg_dma_len(psgl);
-}
-
-static unsigned long inline dc390_advance_segment(struct dc390_srb* pSRB, u32 residue)
-{
- unsigned long xfer = pSRB->SGToBeXferLen - residue;
-
- /* xfer more bytes transferred */
- pSRB->SGBusAddr += xfer;
- pSRB->TotalXferredLen += xfer;
- pSRB->SGToBeXferLen = residue;
-
- return xfer;
-}
-
-static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun)
-{
- struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return NULL;
- while (pDCB->TargetID != id || pDCB->TargetLUN != lun)
- {
- pDCB = pDCB->pNextDCB;
- if (pDCB == pACB->pLinkDCB)
- return NULL;
- }
- DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n", \
- pDCB, pDCB->TargetID, pDCB->TargetLUN));
- return pDCB;
-}
-
-/* Insert SRB oin top of free list */
-static __inline__ void dc390_Free_insert (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
- DEBUG0(printk ("DC390: Free SRB %p\n", pSRB));
- pSRB->pNextSRB = pACB->pFreeSRB;
- pACB->pFreeSRB = pSRB;
-}
-
-static __inline__ void dc390_Going_append (struct dc390_dcb* pDCB, struct dc390_srb* 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;
-
- pDCB->pGoingLast = pSRB;
- /* No next one in sent list */
- pSRB->pNextSRB = NULL;
-}
-
-static __inline__ void dc390_Going_remove (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
- DEBUG0(printk("DC390: Remove SRB %p from Going\n", pSRB));
- if (pSRB == pDCB->pGoingSRB)
- pDCB->pGoingSRB = pSRB->pNextSRB;
- else
- {
- struct dc390_srb* 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 struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length)
-{
- sg_init_one(sg, addr, length);
- return sg;
-}
-
-/* Create pci mapping */
-static int dc390_pci_map (struct dc390_srb* pSRB)
-{
- int error = 0;
- struct scsi_cmnd *pcmd = pSRB->pcmd;
- struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
- dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp));
-
- /* Map sense buffer */
- if (pSRB->SRBFlag & AUTO_REQSENSE) {
- pSRB->pSegmentList = dc390_sg_build_single(&pSRB->Segmentx, pcmd->sense_buffer, SCSI_SENSE_BUFFERSIZE);
- pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, 1,
- DMA_FROM_DEVICE);
- cmdp->saved_dma_handle = sg_dma_address(pSRB->pSegmentList);
-
- /* TODO: error handling */
- if (pSRB->SGcount != 1)
- error = 1;
- DEBUG1(printk("%s(): Mapped sense buffer %p at %x\n", __func__, pcmd->sense_buffer, cmdp->saved_dma_handle));
- /* Map SG list */
- } else if (scsi_sg_count(pcmd)) {
- int nseg;
-
- nseg = scsi_dma_map(pcmd);
-
- pSRB->pSegmentList = scsi_sglist(pcmd);
- pSRB->SGcount = nseg;
-
- /* TODO: error handling */
- if (nseg < 0)
- error = 1;
- DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\
- __func__, scsi_sglist(pcmd), nseg, scsi_sg_count(pcmd)));
- /* Map single segment */
- } else
- pSRB->SGcount = 0;
-
- return error;
-}
-
-/* Remove pci mapping */
-static void dc390_pci_unmap (struct dc390_srb* pSRB)
-{
- struct scsi_cmnd *pcmd = pSRB->pcmd;
- struct pci_dev *pdev = pSRB->pSRBDCB->pDCBACB->pdev;
- DEBUG1(dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp)));
-
- if (pSRB->SRBFlag) {
- pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE);
- DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __func__, cmdp->saved_dma_handle));
- } else {
- scsi_dma_unmap(pcmd);
- DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n",
- __func__, scsi_sglist(pcmd), scsi_sg_count(pcmd)));
- }
-}
-
-static void __inline__
-dc390_freetag (struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
- if (pSRB->TagNumber != SCSI_NO_TAG) {
- pDCB->TagMask &= ~(1 << pSRB->TagNumber); /* free tag mask */
- pSRB->TagNumber = SCSI_NO_TAG;
- }
-}
-
-
-static int
-dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
- struct scsi_cmnd *scmd = pSRB->pcmd;
- struct scsi_device *sdev = scmd->device;
- u8 cmd, disc_allowed, try_sync_nego;
-
- pSRB->ScsiPhase = SCSI_NOP0;
-
- 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;
- }
- if (time_before (jiffies, pACB->last_reset))
- {
- DEBUG0(printk ("DC390: We were just reset and don't accept commands yet!\n"));
- return 1;
- }
- /* KG: Moved pci mapping here */
- dc390_pci_map(pSRB);
- /* TODO: error handling */
- DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
- DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
- DC390_write8 (CtrlReg1, pDCB->CtrlR1);
- DC390_write8 (CtrlReg3, pDCB->CtrlR3);
- 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",\
- scmd->cmnd[0], pDCB->SyncMode));
-
- /* 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->SRBFlag & AUTO_REQSENSE))
- disc_allowed = pDCB->DevMode & EN_DISCONNECT_;
- else
- disc_allowed = 0;
-
- if ((pDCB->SyncMode & SYNC_ENABLE) && pDCB->TargetLUN == 0 && sdev->sdtr &&
- (((scmd->cmnd[0] == REQUEST_SENSE || (pSRB->SRBFlag & AUTO_REQSENSE)) &&
- !(pDCB->SyncMode & SYNC_NEGO_DONE)) || scmd->cmnd[0] == INQUIRY))
- try_sync_nego = 1;
- else
- try_sync_nego = 0;
-
- pSRB->MsgCnt = 0;
- cmd = SEL_W_ATN;
- DC390_write8 (ScsiFifo, IDENTIFY(disc_allowed, pDCB->TargetLUN));
- /* Change 99/05/31: Don't use tags when not disconnecting (BUSY) */
- if ((pDCB->SyncMode & EN_TAG_QUEUEING) && disc_allowed && (scmd->flags & SCMD_TAGGED)) {
- DC390_write8(ScsiFifo, MSG_SIMPLE_TAG);
- pDCB->TagMask |= 1 << scmd->request->tag;
- pSRB->TagNumber = scmd->request->tag;
- DC390_write8(ScsiFifo, scmd->request->tag);
- DEBUG1(printk(KERN_INFO "DC390: Select w/DisCn for SRB %p, block tag %02x\n", pSRB, tag[1]));
- cmd = SEL_W_ATN3;
- } else {
- /* No TagQ */
-//no_tag:
- DEBUG1(printk(KERN_INFO "DC390: Select w%s/DisCn for SRB %p, No TagQ\n", disc_allowed ? "" : "o", pSRB));
- }
-
- pSRB->SRBState = SRB_START_;
-
- if (try_sync_nego)
- {
- u8 Sync_Off = pDCB->SyncOffset;
- DEBUG0(printk (KERN_INFO "DC390: NEW Sync Nego code triggered (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN));
- 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 )
- {
- DC390_write8 (ScsiFifo, REQUEST_SENSE);
- DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
- DC390_write8 (ScsiFifo, 0);
- DC390_write8 (ScsiFifo, 0);
- DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
- DC390_write8 (ScsiFifo, 0);
- DEBUG1(printk (KERN_DEBUG "DC390: AutoReqSense !\n"));
- }
- else /* write cmnd to bus */
- {
- u8 *ptr; u8 i;
- ptr = (u8 *)scmd->cmnd;
- for (i = 0; i < scmd->cmd_len; i++)
- DC390_write8 (ScsiFifo, *(ptr++));
- }
- }
- 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 (target %02i-%02i)\n",
- scmd->device->id, (u8)scmd->device->lun));
- pSRB->SRBState = SRB_READY;
- //DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- pACB->SelLost++;
- return 1;
- }
- DC390_write8 (ScsiCmd, cmd);
- pACB->pActiveDCB = pDCB;
- pDCB->pActiveSRB = pSRB;
- pACB->Connected = 1;
- pSRB->ScsiPhase = SCSI_NOP1;
- return 0;
-}
-
-
-static void __inline__
-dc390_InvalidCmd(struct dc390_acb* pACB)
-{
- if (pACB->pActiveDCB->pActiveSRB->SRBState & (SRB_START_ | SRB_MSGOUT))
- DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
-}
-
-
-static irqreturn_t __inline__
-DC390_Interrupt(void *dev_id)
-{
- struct dc390_acb *pACB = dev_id;
- struct dc390_dcb *pDCB;
- struct dc390_srb *pSRB;
- u8 sstatus=0;
- u8 phase;
- void (*stateV)( struct dc390_acb*, struct dc390_srb*, u8 *);
- u8 istate, istatus;
-
- sstatus = DC390_read8 (Scsi_Status);
- if( !(sstatus & INTERRUPT) )
- return IRQ_NONE;
-
- DEBUG1(printk (KERN_DEBUG "sstatus=%02x,", sstatus));
-
- //DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
- //dstatus = DC390_read8 (DMA_Status);
- //DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
- spin_lock_irq(pACB->pScsiHost->host_lock);
-
- istate = DC390_read8 (Intern_State);
- istatus = DC390_read8 (INT_Status); /* This clears Scsi_Status, Intern_State and INT_Status ! */
-
- DEBUG1(printk (KERN_INFO "Istatus(Res,Inv,Dis,Serv,Succ,ReS,SelA,Sel)=%02x,",istatus));
- dc390_laststatus &= ~0x00ffffff;
- dc390_laststatus |= /* dstatus<<24 | */ sstatus<<16 | istate<<8 | istatus;
-
- if (sstatus & ILLEGAL_OP_ERR)
- {
- printk ("DC390: Illegal Operation detected (%08x)!\n", dc390_laststatus);
- dc390_dumpinfo (pACB, pACB->pActiveDCB, pACB->pActiveDCB->pActiveSRB);
- }
-
- 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)
- {
- 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) )
- {
- pDCB = pACB->pActiveDCB;
- if (!pDCB)
- {
- printk (KERN_ERR "DC390: Suc. op/ Serv. req: pActiveDCB = 0!\n");
- goto unlock;
- }
- pSRB = pDCB->pActiveSRB;
- if( pDCB->DCBFlag & ABORT_DEV_ )
- dc390_EnableMsgOut_Abort (pACB, pSRB);
-
- phase = pSRB->ScsiPhase;
- DEBUG1(printk (KERN_INFO "DC390: [%i]%s(0) (%02x)\n", phase, dc390_p0_str[phase], sstatus));
- stateV = (void *) dc390_phase0[phase];
- ( *stateV )( pACB, pSRB, &sstatus );
-
- pSRB->ScsiPhase = sstatus & 7;
- phase = (u8) sstatus & 7;
- DEBUG1(printk (KERN_INFO "DC390: [%i]%s(1) (%02x)\n", phase, dc390_p1_str[phase], sstatus));
- stateV = (void *) dc390_phase1[phase];
- ( *stateV )( pACB, pSRB, &sstatus );
- }
-
- unlock:
- spin_unlock_irq(pACB->pScsiHost->host_lock);
- return IRQ_HANDLED;
-}
-
-static irqreturn_t do_DC390_Interrupt(int irq, void *dev_id)
-{
- irqreturn_t ret;
- DEBUG1(printk (KERN_INFO "DC390: Irq (%i) caught: ", irq));
- /* Locking is done in DC390_Interrupt */
- ret = DC390_Interrupt(dev_id);
- DEBUG1(printk (".. IRQ returned\n"));
- return ret;
-}
-
-static void
-dc390_DataOut_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- u8 sstatus;
- u32 ResidCnt;
- u8 dstate = 0;
-
- sstatus = *psstatus;
-
- if( !(pSRB->SRBState & SRB_XFERPAD) )
- {
- if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR) )
- pSRB->SRBStatus |= PARITY_ERROR;
-
- if( sstatus & COUNT_2_ZERO )
- {
- unsigned long timeout = jiffies + HZ;
-
- /* Function called from the ISR with the host_lock held and interrupts disabled */
- if (pSRB->SGToBeXferLen)
- while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
- spin_unlock_irq(pACB->pScsiHost->host_lock);
- udelay(50);
- spin_lock_irq(pACB->pScsiHost->host_lock);
- }
- if (!time_before(jiffies, timeout))
- printk (KERN_CRIT "DC390: Deadlock in DataOut_0: DMA aborted unfinished: %06x bytes remain!!\n",
- DC390_read32 (DMA_Wk_ByteCntr));
- dc390_laststatus &= ~0xff000000;
- dc390_laststatus |= dstate << 24;
- pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
- pSRB->SGIndex++;
- if( pSRB->SGIndex < pSRB->SGcount )
- {
- pSRB->pSegmentList++;
-
- dc390_start_segment(pSRB);
- }
- else
- pSRB->SGToBeXferLen = 0;
- }
- else
- {
- ResidCnt = ((u32) DC390_read8 (Current_Fifo) & 0x1f) +
- (((u32) DC390_read8 (CtcReg_High) << 16) |
- ((u32) DC390_read8 (CtcReg_Mid) << 8) |
- (u32) DC390_read8 (CtcReg_Low));
-
- dc390_advance_segment(pSRB, ResidCnt);
- }
- }
- if ((*psstatus & 7) != SCSI_DATA_OUT)
- {
- DC390_write8 (DMA_Cmd, WRITE_DIRECTION+DMA_IDLE_CMD);
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- }
-}
-
-static void
-dc390_DataIn_0(struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- u8 sstatus, residual, bval;
- u32 ResidCnt, i;
- unsigned long xferCnt;
-
- sstatus = *psstatus;
-
- if( !(pSRB->SRBState & SRB_XFERPAD) )
- {
- if( sstatus & (PARITY_ERR | ILLEGAL_OP_ERR))
- pSRB->SRBStatus |= PARITY_ERROR;
-
- if( sstatus & COUNT_2_ZERO )
- {
- int dstate = 0;
- unsigned long timeout = jiffies + HZ;
-
- /* Function called from the ISR with the host_lock held and interrupts disabled */
- if (pSRB->SGToBeXferLen)
- while (time_before(jiffies, timeout) && !((dstate = DC390_read8 (DMA_Status)) & DMA_XFER_DONE)) {
- spin_unlock_irq(pACB->pScsiHost->host_lock);
- udelay(50);
- spin_lock_irq(pACB->pScsiHost->host_lock);
- }
- if (!time_before(jiffies, timeout)) {
- printk (KERN_CRIT "DC390: Deadlock in DataIn_0: DMA aborted unfinished: %06x bytes remain!!\n",
- DC390_read32 (DMA_Wk_ByteCntr));
- printk (KERN_CRIT "DC390: DataIn_0: DMA State: %i\n", dstate);
- }
- dc390_laststatus &= ~0xff000000;
- dc390_laststatus |= dstate << 24;
- DEBUG1(ResidCnt = ((unsigned long) DC390_read8 (CtcReg_High) << 16) \
- + ((unsigned long) DC390_read8 (CtcReg_Mid) << 8) \
- + ((unsigned long) DC390_read8 (CtcReg_Low)));
- DEBUG1(printk (KERN_DEBUG "Count_2_Zero (ResidCnt=%u,ToBeXfer=%lu),", ResidCnt, pSRB->SGToBeXferLen));
-
- DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
-
- pSRB->TotalXferredLen += pSRB->SGToBeXferLen;
- pSRB->SGIndex++;
- if( pSRB->SGIndex < pSRB->SGcount )
- {
- pSRB->pSegmentList++;
-
- dc390_start_segment(pSRB);
- }
- else
- pSRB->SGToBeXferLen = 0;
- }
- else /* phase changed */
- {
- residual = 0;
- bval = DC390_read8 (Current_Fifo);
- while( bval & 0x1f )
- {
- DEBUG1(printk (KERN_DEBUG "Check for residuals,"));
- if( (bval & 0x1f) == 1 )
- {
- for(i=0; i < 0x100; i++)
- {
- bval = DC390_read8 (Current_Fifo);
- if( !(bval & 0x1f) )
- goto din_1;
- else if( i == 0x0ff )
- {
- residual = 1; /* ;1 residual byte */
- goto din_1;
- }
- }
- }
- else
- bval = DC390_read8 (Current_Fifo);
- }
-din_1:
- DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_BLAST_CMD);
- for (i = 0xa000; i; i--)
- {
- bval = DC390_read8 (DMA_Status);
- if (bval & BLAST_COMPLETE)
- break;
- }
- /* It seems a DMA Blast abort isn't that bad ... */
- if (!i) printk (KERN_ERR "DC390: DMA Blast aborted unfinished!\n");
- //DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
- dc390_laststatus &= ~0xff000000;
- dc390_laststatus |= bval << 24;
-
- DEBUG1(printk (KERN_DEBUG "Blast: Read %i times DMA_Status %02x", 0xa000-i, bval));
- ResidCnt = (((u32) DC390_read8 (CtcReg_High) << 16) |
- ((u32) DC390_read8 (CtcReg_Mid) << 8)) |
- (u32) DC390_read8 (CtcReg_Low);
-
- xferCnt = dc390_advance_segment(pSRB, ResidCnt);
-
- if (residual) {
- size_t count = 1;
- size_t offset = pSRB->SGBusAddr - sg_dma_address(pSRB->pSegmentList);
- unsigned long flags;
- u8 *ptr;
-
- bval = DC390_read8 (ScsiFifo); /* get one residual byte */
-
- local_irq_save(flags);
- ptr = scsi_kmap_atomic_sg(pSRB->pSegmentList, pSRB->SGcount, &offset, &count);
- if (likely(ptr)) {
- *(ptr + offset) = bval;
- scsi_kunmap_atomic_sg(ptr);
- }
- local_irq_restore(flags);
- WARN_ON(!ptr);
-
- /* 1 more byte read */
- xferCnt += dc390_advance_segment(pSRB, pSRB->SGToBeXferLen - 1);
- }
- DEBUG1(printk (KERN_DEBUG "Xfered: %lu, Total: %lu, Remaining: %lu\n", xferCnt,\
- pSRB->TotalXferredLen, pSRB->SGToBeXferLen));
- }
- }
- if ((*psstatus & 7) != SCSI_DATA_IN)
- {
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- DC390_write8 (DMA_Cmd, READ_DIRECTION+DMA_IDLE_CMD);
- }
-}
-
-static void
-dc390_Command_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-static void
-dc390_Status_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-
- pSRB->TargetStatus = DC390_read8 (ScsiFifo);
- //udelay (1);
- pSRB->EndMessage = DC390_read8 (ScsiFifo); /* get message */
-
- *psstatus = SCSI_NOP0;
- pSRB->SRBState = SRB_COMPLETED;
- DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
-}
-
-static void
-dc390_MsgOut_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- if( pSRB->SRBState & (SRB_UNEXPECT_RESEL+SRB_ABORT_SENT) )
- *psstatus = SCSI_NOP0;
- //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-
-static void __inline__
-dc390_reprog (struct dc390_acb* pACB, struct dc390_dcb* pDCB)
-{
- DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
- DC390_write8 (CtrlReg3, pDCB->CtrlR3);
- DC390_write8 (CtrlReg4, pDCB->CtrlR4);
- dc390_SetXferRate (pACB, pDCB);
-}
-
-
-#ifdef DC390_DEBUG0
-static void
-dc390_printMsg (u8 *MsgBuf, u8 len)
-{
- int i;
- printk (" %02x", MsgBuf[0]);
- for (i = 1; i < len; i++)
- printk (" %02x", MsgBuf[i]);
- printk ("\n");
-}
-#endif
-
-#define DC390_ENABLE_MSGOUT DC390_write8 (ScsiCmd, SET_ATN_CMD)
-
-/* reject_msg */
-static void __inline__
-dc390_MsgIn_reject (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
- pSRB->MsgOutBuf[0] = MESSAGE_REJECT;
- pSRB->MsgCnt = 1;
- DC390_ENABLE_MSGOUT;
- DEBUG0 (printk (KERN_INFO "DC390: Reject message\n"));
-}
-
-/* abort command */
-static void
-dc390_EnableMsgOut_Abort ( struct dc390_acb* pACB, struct dc390_srb* pSRB )
-{
- pSRB->MsgOutBuf[0] = ABORT;
- pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
- pSRB->pSRBDCB->DCBFlag &= ~ABORT_DEV_;
-}
-
-static struct dc390_srb*
-dc390_MsgIn_QTag (struct dc390_acb* pACB, struct dc390_dcb* pDCB, s8 tag)
-{
- struct dc390_srb* pSRB = pDCB->pGoingSRB;
-
- if (pSRB)
- {
- struct scsi_cmnd *scmd = scsi_find_tag(pSRB->pcmd->device, tag);
- pSRB = (struct dc390_srb *)scmd->host_scribble;
-
- if (pDCB->DCBFlag & ABORT_DEV_)
- {
- pSRB->SRBState = SRB_ABORT_SENT;
- dc390_EnableMsgOut_Abort( pACB, pSRB );
- }
-
- if (!(pSRB->SRBState & SRB_DISCONNECT))
- goto mingx0;
-
- pDCB->pActiveSRB = pSRB;
- pSRB->SRBState = SRB_DATA_XFER;
- }
- else
- {
- mingx0:
- pSRB = pACB->pTmpSRB;
- pSRB->SRBState = SRB_UNEXPECT_RESEL;
- pDCB->pActiveSRB = pSRB;
- pSRB->MsgOutBuf[0] = ABORT_TAG;
- pSRB->MsgCnt = 1; DC390_ENABLE_MSGOUT;
- }
- return pSRB;
-}
-
-
-/* set async transfer mode */
-static void
-dc390_MsgIn_set_async (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
- struct dc390_dcb* pDCB = pSRB->pSRBDCB;
- if (!(pSRB->SRBState & DO_SYNC_NEGO))
- printk (KERN_INFO "DC390: Target %i initiates Non-Sync?\n", pDCB->TargetID);
- pSRB->SRBState &= ~DO_SYNC_NEGO;
- pDCB->SyncMode &= ~(SYNC_ENABLE+SYNC_NEGO_DONE);
- pDCB->SyncPeriod = 0;
- pDCB->SyncOffset = 0;
- //pDCB->NegoPeriod = 50; /* 200ns <=> 5 MHz */
- pDCB->CtrlR3 = FAST_CLK; /* fast clock / normal scsi */
- pDCB->CtrlR4 &= 0x3f;
- pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
- dc390_reprog (pACB, pDCB);
-}
-
-/* set sync transfer mode */
-static void
-dc390_MsgIn_set_sync (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
- u8 bval;
- u16 wval, wval1;
- struct dc390_dcb* pDCB = pSRB->pSRBDCB;
- u8 oldsyncperiod = pDCB->SyncPeriod;
- u8 oldsyncoffset = pDCB->SyncOffset;
-
- if (!(pSRB->SRBState & DO_SYNC_NEGO))
- {
- printk (KERN_INFO "DC390: Target %i initiates Sync: %ins %i ... answer ...\n",
- pDCB->TargetID, pSRB->MsgInBuf[3]<<2, pSRB->MsgInBuf[4]);
-
- /* reject */
- //dc390_MsgIn_reject (pACB, pSRB);
- //return dc390_MsgIn_set_async (pACB, pSRB);
-
- /* Reply with corrected SDTR Message */
- if (pSRB->MsgInBuf[4] > 15)
- {
- printk (KERN_INFO "DC390: Lower Sync Offset to 15\n");
- pSRB->MsgInBuf[4] = 15;
- }
- if (pSRB->MsgInBuf[3] < pDCB->NegoPeriod)
- {
- 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);
- pSRB->MsgCnt = 5;
- DC390_ENABLE_MSGOUT;
- }
-
- pSRB->SRBState &= ~DO_SYNC_NEGO;
- pDCB->SyncMode |= SYNC_ENABLE+SYNC_NEGO_DONE;
- pDCB->SyncOffset &= 0x0f0;
- pDCB->SyncOffset |= pSRB->MsgInBuf[4];
- pDCB->NegoPeriod = pSRB->MsgInBuf[3];
-
- wval = (u16) pSRB->MsgInBuf[3];
- wval = wval << 2; wval -= 3; wval1 = wval / 25; /* compute speed */
- if( (wval1 * 25) != wval) wval1++;
- bval = FAST_CLK+FAST_SCSI; /* fast clock / fast scsi */
-
- pDCB->CtrlR4 &= 0x3f; /* Glitch eater: 12ns less than normal */
- if (pACB->glitch_cfg != NS_TO_GLITCH(0))
- pDCB->CtrlR4 |= NS_TO_GLITCH(((GLITCH_TO_NS(pACB->glitch_cfg)) - 1));
- else
- pDCB->CtrlR4 |= NS_TO_GLITCH(0);
- if (wval1 < 4) pDCB->CtrlR4 |= NS_TO_GLITCH(0); /* Ultra */
-
- if (wval1 >= 8)
- {
- wval1--; /* Timing computation differs by 1 from FAST_SCSI */
- bval = FAST_CLK; /* fast clock / normal scsi */
- pDCB->CtrlR4 |= pACB->glitch_cfg; /* glitch eater */
- }
-
- pDCB->CtrlR3 = bval;
- pDCB->SyncPeriod = (u8)wval1;
-
- if ((oldsyncperiod != wval1 || oldsyncoffset != pDCB->SyncOffset) && pDCB->TargetLUN == 0)
- {
- if (! (bval & FAST_SCSI)) wval1++;
- printk (KERN_INFO "DC390: Target %i: Sync transfer %i.%1i MHz, Offset %i\n", pDCB->TargetID,
- 40/wval1, ((40%wval1)*10+wval1/2)/wval1, pDCB->SyncOffset & 0x0f);
- }
-
- dc390_reprog (pACB, pDCB);
-}
-
-
-/* handle RESTORE_PTR */
-/* This doesn't look very healthy... to-be-fixed */
-static void
-dc390_restore_ptr (struct dc390_acb* pACB, struct dc390_srb* pSRB)
-{
- struct scsi_cmnd *pcmd = pSRB->pcmd;
- struct scatterlist *psgl;
- pSRB->TotalXferredLen = 0;
- pSRB->SGIndex = 0;
- if (scsi_sg_count(pcmd)) {
- size_t saved;
- pSRB->pSegmentList = scsi_sglist(pcmd);
- psgl = pSRB->pSegmentList;
- //dc390_pci_sync(pSRB);
-
- while (pSRB->TotalXferredLen + (unsigned long) sg_dma_len(psgl) < pSRB->Saved_Ptr)
- {
- pSRB->TotalXferredLen += (unsigned long) sg_dma_len(psgl);
- pSRB->SGIndex++;
- if( pSRB->SGIndex < pSRB->SGcount )
- {
- pSRB->pSegmentList++;
-
- dc390_start_segment(pSRB);
- }
- else
- pSRB->SGToBeXferLen = 0;
- }
-
- saved = pSRB->Saved_Ptr - pSRB->TotalXferredLen;
- pSRB->SGToBeXferLen -= saved;
- pSRB->SGBusAddr += saved;
- printk (KERN_INFO "DC390: Pointer restored. Segment %i, Total %li, Bus %08lx\n",
- pSRB->SGIndex, pSRB->Saved_Ptr, pSRB->SGBusAddr);
-
- } 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 Successful Operation IRQ before asserting ACK for
- * the last byte (how does it know whether it's the last ?) */
-/* The old code handled it in another way, indicating, that on
- * every message byte an IRQ is generated and every byte has to
- * be manually ACKed. Hmmm ? (KG, 98/11/28) */
-/* The old implementation was correct. Sigh! */
-
-/* Check if the message is complete */
-static u8 __inline__
-dc390_MsgIn_complete (u8 *msgbuf, u32 len)
-{
- 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;
- return 1;
-}
-
-
-
-/* read and eval received messages */
-static void
-dc390_MsgIn_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- struct dc390_dcb* pDCB = pACB->pActiveDCB;
-
- /* Read the msg */
-
- pSRB->MsgInBuf[pACB->MsgLen++] = DC390_read8 (ScsiFifo);
- //pSRB->SRBState = 0;
-
- /* Msg complete ? */
- if (dc390_MsgIn_complete (pSRB->MsgInBuf, pACB->MsgLen))
- {
- DEBUG0 (printk (KERN_INFO "DC390: MsgIn:"); dc390_printMsg (pSRB->MsgInBuf, pACB->MsgLen));
- /* Now eval the msg */
- switch (pSRB->MsgInBuf[0])
- {
- case DISCONNECT:
- pSRB->SRBState = SRB_DISCONNECT; break;
-
- case SIMPLE_QUEUE_TAG:
- case HEAD_OF_QUEUE_TAG:
- case ORDERED_QUEUE_TAG:
- pSRB = dc390_MsgIn_QTag (pACB, pDCB, pSRB->MsgInBuf[1]);
- break;
-
- 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 EXTENDED_MESSAGE:
- /* reject every extended msg but SDTR */
- if (pSRB->MsgInBuf[1] != 3 || pSRB->MsgInBuf[2] != EXTENDED_SDTR)
- dc390_MsgIn_reject (pACB, pSRB);
- else
- {
- if (pSRB->MsgInBuf[3] == 0 || pSRB->MsgInBuf[4] == 0)
- dc390_MsgIn_set_async (pACB, pSRB);
- else
- dc390_MsgIn_set_sync (pACB, pSRB);
- }
-
- // nothing has to be done
- case COMMAND_COMPLETE: break;
-
- // SAVE POINTER may be ignored as we have the struct dc390_srb* associated with the
- // scsi command. Thanks, Gerard, for pointing it out.
- case SAVE_POINTERS:
- pSRB->Saved_Ptr = pSRB->TotalXferredLen;
- break;
- // The device might want to restart transfer with a RESTORE
- 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);
- }
-
- /* Clear counter and MsgIn state */
- pSRB->SRBState &= ~SRB_MSGIN;
- pACB->MsgLen = 0;
- }
-
- *psstatus = SCSI_NOP0;
- DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD);
- //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-
-static void
-dc390_DataIO_Comm( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 ioDir)
-{
- unsigned long lval;
- struct dc390_dcb* pDCB = pACB->pActiveDCB;
-
- if (pSRB == pACB->pTmpSRB)
- {
- if (pDCB)
- printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (%02i-%i)\n", pDCB->TargetID, pDCB->TargetLUN);
- else
- printk(KERN_ERR "DC390: pSRB == pTmpSRB! (TagQ Error?) (DCB 0!)\n");
-
- /* Try to recover - some broken disks react badly to tagged INQUIRY */
- if (pDCB && pACB->scan_devices && pDCB->GoingSRBCnt == 1) {
- pSRB = pDCB->pGoingSRB;
- pDCB->pActiveSRB = pSRB;
- } else {
- pSRB->pSRBDCB = pDCB;
- dc390_EnableMsgOut_Abort(pACB, pSRB);
- if (pDCB)
- pDCB->DCBFlag |= ABORT_DEV;
- return;
- }
- }
-
- if( pSRB->SGIndex < pSRB->SGcount )
- {
- DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
- if( !pSRB->SGToBeXferLen )
- {
- dc390_start_segment(pSRB);
-
- DEBUG1(printk (KERN_DEBUG " DC390: Next SG segment."));
- }
- lval = pSRB->SGToBeXferLen;
- DEBUG1(printk (KERN_DEBUG " DC390: Start transfer: %li bytes (address %08lx)\n", lval, pSRB->SGBusAddr));
- DC390_write8 (CtcReg_Low, (u8) lval);
- lval >>= 8;
- DC390_write8 (CtcReg_Mid, (u8) lval);
- lval >>= 8;
- DC390_write8 (CtcReg_High, (u8) lval);
-
- DC390_write32 (DMA_XferCnt, pSRB->SGToBeXferLen);
- DC390_write32 (DMA_XferAddr, pSRB->SGBusAddr);
-
- //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
- pSRB->SRBState = SRB_DATA_XFER;
-
- DC390_write8 (ScsiCmd, DMA_COMMAND+INFO_XFER_CMD);
-
- DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
- //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT));
- //DEBUG1(printk (KERN_DEBUG "DC390: DMA_Status: %02x\n", DC390_read8 (DMA_Status)));
- //DEBUG1(DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT));
- }
- else /* xfer pad */
- {
- if( pSRB->SGcount )
- {
- pSRB->AdaptStatus = H_OVER_UNDER_RUN;
- pSRB->SRBStatus |= OVER_RUN;
- DEBUG0(printk (KERN_WARNING " DC390: Overrun -"));
- }
- DEBUG0(printk (KERN_WARNING " Clear transfer pad \n"));
- DC390_write8 (CtcReg_Low, 0);
- DC390_write8 (CtcReg_Mid, 0);
- DC390_write8 (CtcReg_High, 0);
-
- pSRB->SRBState |= SRB_XFERPAD;
- DC390_write8 (ScsiCmd, DMA_COMMAND+XFER_PAD_BYTE);
-/*
- DC390_write8 (DMA_Cmd, DMA_IDLE_CMD | ioDir);
- DC390_write8 (DMA_Cmd, DMA_START_CMD | ioDir);
-*/
- }
-}
-
-
-static void
-dc390_DataOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- dc390_DataIO_Comm (pACB, pSRB, WRITE_DIRECTION);
-}
-
-static void
-dc390_DataInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- dc390_DataIO_Comm (pACB, pSRB, READ_DIRECTION);
-}
-
-static void
-dc390_CommandPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- struct dc390_dcb* pDCB;
- u8 i, cnt;
- u8 *ptr;
-
- DC390_write8 (ScsiCmd, RESET_ATN_CMD);
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- if( !(pSRB->SRBFlag & AUTO_REQSENSE) )
- {
- cnt = (u8) pSRB->pcmd->cmd_len;
- ptr = (u8 *) pSRB->pcmd->cmnd;
- for(i=0; i < cnt; i++)
- DC390_write8 (ScsiFifo, *(ptr++));
- }
- else
- {
- DC390_write8 (ScsiFifo, REQUEST_SENSE);
- pDCB = pACB->pActiveDCB;
- DC390_write8 (ScsiFifo, pDCB->TargetLUN << 5);
- DC390_write8 (ScsiFifo, 0);
- DC390_write8 (ScsiFifo, 0);
- DC390_write8 (ScsiFifo, SCSI_SENSE_BUFFERSIZE);
- DC390_write8 (ScsiFifo, 0);
- DEBUG0(printk(KERN_DEBUG "DC390: AutoReqSense (CmndPhase)!\n"));
- }
- pSRB->SRBState = SRB_COMMAND;
- DC390_write8 (ScsiCmd, INFO_XFER_CMD);
-}
-
-static void
-dc390_StatusPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- pSRB->SRBState = SRB_STATUS;
- DC390_write8 (ScsiCmd, INITIATOR_CMD_CMPLTE);
- //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-static void
-dc390_MsgOutPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- u8 bval, i, cnt;
- u8 *ptr;
- struct dc390_dcb* pDCB;
-
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- pDCB = pACB->pActiveDCB;
- if( !(pSRB->SRBState & SRB_MSGOUT) )
- {
- cnt = pSRB->MsgCnt;
- if( cnt )
- {
- ptr = (u8 *) pSRB->MsgOutBuf;
- for(i=0; i < cnt; i++)
- DC390_write8 (ScsiFifo, *(ptr++));
- pSRB->MsgCnt = 0;
- if( (pDCB->DCBFlag & ABORT_DEV_) &&
- (pSRB->MsgOutBuf[0] == ABORT) )
- pSRB->SRBState = SRB_ABORT_SENT;
- }
- else
- {
- 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 )
- goto mop1;
- }
- DC390_write8 (ScsiFifo, bval);
- }
- DC390_write8 (ScsiCmd, INFO_XFER_CMD);
- }
- else
- {
-mop1:
- printk (KERN_ERR "DC390: OLD Sync Nego code triggered! (%i %i)\n", pDCB->TargetID, pDCB->TargetLUN);
- 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);
- if (pDCB->SyncOffset & 0x0f)
- DC390_write8 (ScsiFifo, pDCB->SyncOffset);
- else
- DC390_write8 (ScsiFifo, SYNC_NEGO_OFFSET);
- pSRB->SRBState |= DO_SYNC_NEGO;
- DC390_write8 (ScsiCmd, INFO_XFER_CMD);
- }
-}
-
-static void
-dc390_MsgInPhase( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- if( !(pSRB->SRBState & SRB_MSGIN) )
- {
- pSRB->SRBState &= ~SRB_DISCONNECT;
- pSRB->SRBState |= SRB_MSGIN;
- }
- DC390_write8 (ScsiCmd, INFO_XFER_CMD);
- //DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
-}
-
-static void
-dc390_Nop_0( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-static void
-dc390_Nop_1( struct dc390_acb* pACB, struct dc390_srb* pSRB, u8 *psstatus)
-{
-}
-
-
-static void
-dc390_SetXferRate( struct dc390_acb* pACB, struct dc390_dcb* pDCB )
-{
- u8 bval, i, cnt;
- struct dc390_dcb* ptr;
-
- if( !(pDCB->TargetLUN) )
- {
- if( !pACB->scan_devices )
- {
- ptr = pACB->pLinkDCB;
- cnt = pACB->DCBCnt;
- bval = pDCB->TargetID;
- for(i=0; i<cnt; i++)
- {
- if( ptr->TargetID == bval )
- {
- ptr->SyncPeriod = pDCB->SyncPeriod;
- ptr->SyncOffset = pDCB->SyncOffset;
- ptr->CtrlR3 = pDCB->CtrlR3;
- ptr->CtrlR4 = pDCB->CtrlR4;
- ptr->SyncMode = pDCB->SyncMode;
- }
- ptr = ptr->pNextDCB;
- }
- }
- }
- return;
-}
-
-
-static void
-dc390_Disconnect( struct dc390_acb* pACB )
-{
- struct dc390_dcb *pDCB;
- struct dc390_srb *pSRB, *psrb;
- u8 i, cnt;
-
- 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)
- {
- DEBUG0(printk(KERN_ERR "ACB:%p->ActiveDCB:%p IOPort:%04x IRQ:%02x !\n",\
- pACB, pDCB, pACB->IOPortBase, pACB->IRQLevel));
- mdelay(400);
- 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 = NULL;
- pSRB->ScsiPhase = SCSI_NOP0;
- if( pSRB->SRBState & SRB_UNEXPECT_RESEL )
- pSRB->SRBState = 0;
- else if( pSRB->SRBState & SRB_ABORT_SENT )
- {
- pDCB->TagMask = 0;
- pDCB->DCBFlag = 0;
- cnt = pDCB->GoingSRBCnt;
- pDCB->GoingSRBCnt = 0;
- pSRB = pDCB->pGoingSRB;
- for( i=0; i < cnt; i++)
- {
- psrb = pSRB->pNextSRB;
- dc390_Free_insert (pACB, pSRB);
- pSRB = psrb;
- }
- pDCB->pGoingSRB = NULL;
- }
- else
- {
- if( (pSRB->SRBState & (SRB_START_+SRB_MSGOUT)) ||
- !(pSRB->SRBState & (SRB_DISCONNECT+SRB_COMPLETED)) )
- { /* Selection time out */
- pSRB->AdaptStatus = H_SEL_TIMEOUT;
- pSRB->TargetStatus = 0;
- goto disc1;
- }
- else if (!(pSRB->SRBState & SRB_DISCONNECT) && (pSRB->SRBState & SRB_COMPLETED))
- {
-disc1:
- dc390_freetag (pDCB, pSRB);
- pDCB->pActiveSRB = NULL;
- pSRB->SRBState = SRB_FREE;
- dc390_SRBdone( pACB, pDCB, pSRB);
- }
- }
- pACB->MsgLen = 0;
-}
-
-
-static void
-dc390_Reselect( struct dc390_acb* pACB )
-{
- struct dc390_dcb* pDCB;
- struct dc390_srb* pSRB;
- u8 id, lun;
-
- DEBUG0(printk(KERN_INFO "RSEL,"));
- pACB->Connected = 1;
- pDCB = pACB->pActiveDCB;
- if( pDCB )
- { /* Arbitration lost but Reselection won */
- DEBUG0(printk ("DC390: (ActiveDCB != 0: Arb. lost but resel. won)!\n"));
- pSRB = pDCB->pActiveSRB;
- if( !( pACB->scan_devices ) )
- {
- struct scsi_cmnd *pcmd = pSRB->pcmd;
- scsi_set_resid(pcmd, scsi_bufflen(pcmd));
- SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
- dc390_Going_remove(pDCB, pSRB);
- dc390_Free_insert(pACB, pSRB);
- pcmd->scsi_done (pcmd);
- DEBUG0(printk(KERN_DEBUG"DC390: Return SRB %p to free\n", pSRB));
- }
- }
- /* Get ID */
- lun = DC390_read8 (ScsiFifo);
- DEBUG0(printk ("Dev %02x,", lun));
- if (!(lun & (1 << pACB->pScsiHost->this_id)))
- printk (KERN_ERR "DC390: Reselection must select host adapter: %02x!\n", lun);
- else
- lun ^= 1 << pACB->pScsiHost->this_id; /* Mask AdapterID */
- id = 0; while (lun >>= 1) id++;
- /* Get LUN */
- lun = DC390_read8 (ScsiFifo);
- if (!(lun & IDENTIFY_BASE)) printk (KERN_ERR "DC390: Resel: Expect identify message!\n");
- lun &= 7;
- DEBUG0(printk ("(%02i-%i),", id, lun));
- pDCB = dc390_findDCB (pACB, id, lun);
- if (!pDCB)
- {
- printk (KERN_ERR "DC390: Reselect from non existing device (%02i-%i)\n",
- id, lun);
- return;
- }
- pACB->pActiveDCB = pDCB;
- /* TagQ: We expect a message soon, so never mind the exact SRB */
- if( pDCB->SyncMode & EN_TAG_QUEUEING )
- {
- pSRB = pACB->pTmpSRB;
- pDCB->pActiveSRB = pSRB;
- }
- else
- {
- pSRB = pDCB->pActiveSRB;
- if( !pSRB || !(pSRB->SRBState & SRB_DISCONNECT) )
- {
- pSRB= pACB->pTmpSRB;
- pSRB->SRBState = SRB_UNEXPECT_RESEL;
- printk (KERN_ERR "DC390: Reselect without outstanding cmnd (%02i-%i)\n",
- id, lun);
- pDCB->pActiveSRB = pSRB;
- dc390_EnableMsgOut_Abort ( pACB, pSRB );
- }
- else
- {
- if( pDCB->DCBFlag & ABORT_DEV_ )
- {
- pSRB->SRBState = SRB_ABORT_SENT;
- printk (KERN_INFO "DC390: Reselect: Abort (%02i-%i)\n",
- id, lun);
- dc390_EnableMsgOut_Abort( pACB, pSRB );
- }
- else
- pSRB->SRBState = SRB_DATA_XFER;
- }
- }
-
- DEBUG1(printk (KERN_DEBUG "Resel SRB(%p): TagNum (%02x)\n", pSRB, pSRB->TagNumber));
- pSRB->ScsiPhase = SCSI_NOP0;
- DC390_write8 (Scsi_Dest_ID, pDCB->TargetID);
- DC390_write8 (Sync_Period, pDCB->SyncPeriod);
- DC390_write8 (Sync_Offset, pDCB->SyncOffset);
- DC390_write8 (CtrlReg1, pDCB->CtrlR1);
- DC390_write8 (CtrlReg3, pDCB->CtrlR3);
- DC390_write8 (CtrlReg4, pDCB->CtrlR4); /* ; Glitch eater */
- DC390_write8 (ScsiCmd, MSG_ACCEPTED_CMD); /* ;to release the /ACK signal */
-}
-
-static int __inline__
-dc390_RequestSense(struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
- struct scsi_cmnd *pcmd;
-
- pcmd = pSRB->pcmd;
-
- REMOVABLEDEBUG(printk(KERN_INFO "DC390: RequestSense(Cmd %02x, Id %02x, LUN %02x)\n",\
- pcmd->cmnd[0], pDCB->TargetID, pDCB->TargetLUN));
-
- pSRB->SRBFlag |= AUTO_REQSENSE;
- pSRB->SavedTotXLen = pSRB->TotalXferredLen;
- pSRB->AdaptStatus = 0;
- pSRB->TargetStatus = 0; /* CHECK_CONDITION<<1; */
-
- /* We are called from SRBdone, original PCI mapping has been removed
- * already, new one is set up from StartSCSI */
- pSRB->SGIndex = 0;
-
- pSRB->TotalXferredLen = 0;
- pSRB->SGToBeXferLen = 0;
- return dc390_StartSCSI(pACB, pDCB, pSRB);
-}
-
-
-static void
-dc390_SRBdone( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB )
-{
- u8 status;
- struct scsi_cmnd *pcmd;
-
- pcmd = pSRB->pcmd;
- /* KG: Moved pci_unmap here */
- dc390_pci_unmap(pSRB);
-
- status = pSRB->TargetStatus;
-
- DEBUG0(printk (" SRBdone (%02x,%08x), SRB %p\n", status, pcmd->result, pSRB));
- if(pSRB->SRBFlag & AUTO_REQSENSE)
- { /* Last command was a Request Sense */
- pSRB->SRBFlag &= ~AUTO_REQSENSE;
- pSRB->AdaptStatus = 0;
- pSRB->TargetStatus = SAM_STAT_CHECK_CONDITION;
-
- //pcmd->result = MK_RES(DRIVER_SENSE,DID_OK,0,status);
- if (status == SAM_STAT_CHECK_CONDITION)
- pcmd->result = MK_RES_LNX(0, DID_BAD_TARGET, 0, /*CHECK_CONDITION*/0);
- else /* Retry */
- {
- if( pSRB->pcmd->cmnd[0] == TEST_UNIT_READY /* || pSRB->pcmd->cmnd[0] == START_STOP */)
- {
- /* Don't retry on TEST_UNIT_READY */
- pcmd->result = MK_RES_LNX(DRIVER_SENSE, DID_OK, 0, SAM_STAT_CHECK_CONDITION);
- REMOVABLEDEBUG(printk(KERN_INFO "Cmd=%02x, Result=%08x, XferL=%08x\n",pSRB->pcmd->cmnd[0],\
- (u32) pcmd->result, (u32) pSRB->TotalXferredLen));
- } else {
- SET_RES_DRV(pcmd->result, DRIVER_SENSE);
- //pSRB->ScsiCmdLen = (u8) (pSRB->Segment1[0] >> 8);
- DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
- pSRB->TotalXferredLen = 0;
- SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
- }
- }
- goto cmd_done;
- }
- if( status )
- {
- if (status == SAM_STAT_CHECK_CONDITION)
- {
- if (dc390_RequestSense(pACB, pDCB, pSRB)) {
- SET_RES_DID(pcmd->result, DID_ERROR);
- goto cmd_done;
- }
- return;
- }
- else if (status == SAM_STAT_TASK_SET_FULL)
- {
- scsi_track_queue_full(pcmd->device, pDCB->GoingSRBCnt - 1);
- DEBUG0 (printk ("DC390: RETRY (%02x), target %02i-%02i\n", pcmd->cmnd[0], pcmd->device->id, (u8)pcmd->device->lun));
- pSRB->TotalXferredLen = 0;
- SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
- }
- else if (status == SAM_STAT_BUSY &&
- (pcmd->cmnd[0] == TEST_UNIT_READY || pcmd->cmnd[0] == INQUIRY) &&
- pACB->scan_devices)
- {
- pSRB->AdaptStatus = 0;
- pSRB->TargetStatus = status;
- pcmd->result = MK_RES(0,0,pSRB->EndMessage,/*status*/0);
- }
- else
- { /* Another error */
- pSRB->TotalXferredLen = 0;
- SET_RES_DID(pcmd->result, DID_SOFT_ERROR);
- goto cmd_done;
- }
- }
- else
- { /* Target status == 0 */
- status = pSRB->AdaptStatus;
- if (status == H_OVER_UNDER_RUN)
- {
- pSRB->TargetStatus = 0;
- SET_RES_DID(pcmd->result,DID_OK);
- SET_RES_MSG(pcmd->result,pSRB->EndMessage);
- }
- else if (status == H_SEL_TIMEOUT)
- {
- pcmd->result = MK_RES(0, DID_NO_CONNECT, 0, 0);
- /* Devices are removed below ... */
- }
- else if( pSRB->SRBStatus & PARITY_ERROR)
- {
- //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;
- SET_RES_DID(pcmd->result,DID_OK);
- }
- }
-
-cmd_done:
- scsi_set_resid(pcmd, scsi_bufflen(pcmd) - pSRB->TotalXferredLen);
-
- dc390_Going_remove (pDCB, pSRB);
- /* Add to free list */
- dc390_Free_insert (pACB, pSRB);
-
- DEBUG0(printk (KERN_DEBUG "DC390: SRBdone: done\n"));
- pcmd->scsi_done (pcmd);
-
- return;
-}
-
-
-/* Remove all SRBs from Going list and inform midlevel */
-static void
-dc390_DoingSRB_Done(struct dc390_acb* pACB, struct scsi_cmnd *cmd)
-{
- struct dc390_dcb *pDCB, *pdcb;
- struct dc390_srb *psrb, *psrb2;
- int i;
- struct scsi_cmnd *pcmd;
-
- pDCB = pACB->pLinkDCB;
- pdcb = pDCB;
- if (! pdcb) return;
- do
- {
- psrb = pdcb->pGoingSRB;
- for (i = 0; i < pdcb->GoingSRBCnt; i++)
- {
- psrb2 = psrb->pNextSRB;
- pcmd = psrb->pcmd;
- dc390_Free_insert (pACB, psrb);
- psrb = psrb2;
- }
- pdcb->GoingSRBCnt = 0;
- pdcb->pGoingSRB = NULL;
- pdcb->TagMask = 0;
- pdcb = pdcb->pNextDCB;
- } while( pdcb != pDCB );
-}
-
-
-static void
-dc390_ResetSCSIBus( struct dc390_acb* pACB )
-{
- //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;
-}
-
-static void
-dc390_ScsiRstDetect( struct dc390_acb* pACB )
-{
- printk ("DC390: Rst_Detect: laststat = %08x\n", dc390_laststatus);
- //DEBUG0(printk(KERN_INFO "RST_DETECT,"));
-
- DC390_write8 (DMA_Cmd, DMA_IDLE_CMD);
- /* Unlock before ? */
- /* delay half a second */
- udelay (1000);
- DC390_write8 (ScsiCmd, CLEAR_FIFO_CMD);
- pACB->last_reset = jiffies + 5*HZ/2
- + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
- 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, NULL);
- //dc390_RecoverSRB( pACB );
- pACB->pActiveDCB = NULL;
- pACB->ACBFlag = 0;
- }
- return;
-}
-
-static int DC390_queuecommand_lck(struct scsi_cmnd *cmd,
- void (*done)(struct scsi_cmnd *))
-{
- struct scsi_device *sdev = cmd->device;
- struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
- struct dc390_dcb *dcb = sdev->hostdata;
- struct dc390_srb *srb;
-
- if (sdev->queue_depth <= dcb->GoingSRBCnt)
- goto device_busy;
- if (acb->pActiveDCB)
- goto host_busy;
- if (acb->ACBFlag & (RESET_DETECT|RESET_DONE|RESET_DEV))
- goto host_busy;
-
- srb = acb->pFreeSRB;
- if (unlikely(srb == NULL))
- goto host_busy;
-
- cmd->scsi_done = done;
- cmd->result = 0;
- acb->Cmds++;
-
- acb->pFreeSRB = srb->pNextSRB;
- srb->pNextSRB = NULL;
-
- srb->pSRBDCB = dcb;
- srb->pcmd = cmd;
- cmd->host_scribble = (char *)srb;
-
- srb->SGIndex = 0;
- srb->AdaptStatus = 0;
- srb->TargetStatus = 0;
- srb->MsgCnt = 0;
-
- srb->SRBStatus = 0;
- srb->SRBFlag = 0;
- srb->SRBState = 0;
- srb->TotalXferredLen = 0;
- srb->SGBusAddr = 0;
- srb->SGToBeXferLen = 0;
- srb->ScsiPhase = 0;
- srb->EndMessage = 0;
- srb->TagNumber = SCSI_NO_TAG;
-
- if (dc390_StartSCSI(acb, dcb, srb)) {
- dc390_Free_insert(acb, srb);
- goto host_busy;
- }
-
- dc390_Going_append(dcb, srb);
-
- return 0;
-
- host_busy:
- return SCSI_MLQUEUE_HOST_BUSY;
-
- device_busy:
- return SCSI_MLQUEUE_DEVICE_BUSY;
-}
-
-static DEF_SCSI_QCMD(DC390_queuecommand)
-
-static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB)
-{
- struct pci_dev *pdev;
- u16 pstat;
-
- if (!pDCB) pDCB = pACB->pActiveDCB;
- if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB;
-
- if (pSRB)
- {
- 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): %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",
- DC390_read8(CtcReg_Low) + (DC390_read8(CtcReg_Mid) << 8) + (DC390_read8(CtcReg_High) << 16),
- DC390_read8(ScsiCmd), DC390_read8(Scsi_Status), DC390_read8(Intern_State));
- printk (" %02x %02x %02x %02x %02x %02x\n",
- DC390_read8(INT_Status), DC390_read8(Current_Fifo), DC390_read8(CtrlReg1),
- DC390_read8(CtrlReg2), DC390_read8(CtrlReg3), DC390_read8(CtrlReg4));
- DC390_write32 (DMA_ScsiBusCtrl, WRT_ERASE_DMA_STAT | EN_INT_ON_PCI_ABORT);
- 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",
- DC390_read8(DMA_Cmd), DC390_read32(DMA_XferCnt), DC390_read32(DMA_XferAddr),
- DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr),
- DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl));
- DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
- pdev = pACB->pdev;
- pci_read_config_word(pdev, PCI_STATUS, &pstat);
- printk ("DC390: Register dump: PCI Status: %04x\n", pstat);
- printk ("DC390: In case of driver trouble read Documentation/scsi/tmscsim.txt\n");
-}
-
-
-static int DC390_abort(struct scsi_cmnd *cmd)
-{
- struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata;
- struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata;
-
- scmd_printk(KERN_WARNING, cmd, "DC390: Abort command\n");
-
- /* 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, NULL);
-
- pDCB->DCBFlag |= ABORT_DEV_;
- printk(KERN_INFO "DC390: Aborted.\n");
-
- return FAILED;
-}
-
-
-static void dc390_ResetDevParam( struct dc390_acb* pACB )
-{
- struct dc390_dcb *pDCB, *pdcb;
-
- pDCB = pACB->pLinkDCB;
- if (! pDCB) return;
- pdcb = pDCB;
- do
- {
- 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);
-
-}
-
-static int DC390_bus_reset (struct scsi_cmnd *cmd)
-{
- struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata;
- u8 bval;
-
- spin_lock_irq(cmd->device->host->host_lock);
-
- bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
- DC390_write8(CtrlReg1, bval); /* disable IRQ on bus reset */
-
- pACB->ACBFlag |= RESET_DEV;
- dc390_ResetSCSIBus(pACB);
-
- dc390_ResetDevParam(pACB);
- mdelay(1);
- pACB->last_reset = jiffies + 3*HZ/2
- + HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
-
- DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
- DC390_read8(INT_Status); /* Reset Pending INT */
-
- dc390_DoingSRB_Done(pACB, cmd);
-
- pACB->pActiveDCB = NULL;
- pACB->ACBFlag = 0;
-
- bval = DC390_read8(CtrlReg1) & ~DIS_INT_ON_SCSI_RST;
- DC390_write8(CtrlReg1, bval); /* re-enable interrupt */
-
- spin_unlock_irq(cmd->device->host->host_lock);
-
- return SUCCESS;
-}
-
-/**
- * dc390_slave_alloc - Called by the scsi mid layer to tell us about a new
- * scsi device that we need to deal with.
- *
- * @scsi_device: The new scsi device that we need to handle.
- */
-static int dc390_slave_alloc(struct scsi_device *scsi_device)
-{
- struct dc390_acb *pACB = (struct dc390_acb*) scsi_device->host->hostdata;
- struct dc390_dcb *pDCB, *pDCB2 = NULL;
- uint id = scsi_device->id;
- uint lun = scsi_device->lun;
-
- pDCB = kzalloc(sizeof(struct dc390_dcb), GFP_KERNEL);
- if (!pDCB)
- return -ENOMEM;
-
- if (!pACB->DCBCnt++) {
- pACB->pLinkDCB = pDCB;
- pACB->pDCBRunRobin = pDCB;
- } else {
- pACB->pLastDCB->pNextDCB = pDCB;
- }
-
- pDCB->pNextDCB = pACB->pLinkDCB;
- pACB->pLastDCB = pDCB;
-
- pDCB->pDCBACB = pACB;
- pDCB->TargetID = id;
- pDCB->TargetLUN = lun;
-
- /*
- * Some values are for all LUNs: Copy them
- * In a clean way: We would have an own structure for a SCSI-ID
- */
- if (lun && (pDCB2 = dc390_findDCB(pACB, id, 0))) {
- pDCB->DevMode = pDCB2->DevMode;
- pDCB->SyncMode = pDCB2->SyncMode & SYNC_NEGO_DONE;
- pDCB->SyncPeriod = pDCB2->SyncPeriod;
- pDCB->SyncOffset = pDCB2->SyncOffset;
- pDCB->NegoPeriod = pDCB2->NegoPeriod;
-
- pDCB->CtrlR3 = pDCB2->CtrlR3;
- pDCB->CtrlR4 = pDCB2->CtrlR4;
- } else {
- u8 index = pACB->AdapterIndex;
- PEEprom prom = (PEEprom) &dc390_eepromBuf[index][id << 2];
-
- pDCB->DevMode = prom->EE_MODE1;
- 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;
- }
-
- if (pDCB->DevMode & SYNC_NEGO_)
- pDCB->SyncMode |= SYNC_ENABLE;
- else {
- pDCB->SyncMode = 0;
- pDCB->SyncOffset &= ~0x0f;
- }
-
- pDCB->CtrlR1 = pACB->pScsiHost->this_id;
- if (pDCB->DevMode & PARITY_CHK_)
- pDCB->CtrlR1 |= PARITY_ERR_REPO;
-
- pACB->scan_devices = 1;
- scsi_device->hostdata = pDCB;
- return 0;
-}
-
-/**
- * dc390_slave_destroy - Called by the scsi mid layer to tell us about a
- * device that is going away.
- *
- * @scsi_device: The scsi device that we need to remove.
- */
-static void dc390_slave_destroy(struct scsi_device *scsi_device)
-{
- struct dc390_acb* pACB = (struct dc390_acb*) scsi_device->host->hostdata;
- struct dc390_dcb* pDCB = (struct dc390_dcb*) scsi_device->hostdata;
- struct dc390_dcb* pPrevDCB = pACB->pLinkDCB;
-
- pACB->scan_devices = 0;
-
- BUG_ON(pDCB->GoingSRBCnt > 1);
-
- if (pDCB == pACB->pLinkDCB) {
- if (pACB->pLastDCB == pDCB) {
- pDCB->pNextDCB = NULL;
- pACB->pLastDCB = NULL;
- }
- pACB->pLinkDCB = pDCB->pNextDCB;
- } else {
- while (pPrevDCB->pNextDCB != pDCB)
- pPrevDCB = pPrevDCB->pNextDCB;
- pPrevDCB->pNextDCB = pDCB->pNextDCB;
- if (pDCB == pACB->pLastDCB)
- pACB->pLastDCB = pPrevDCB;
- }
-
- if (pDCB == pACB->pActiveDCB)
- pACB->pActiveDCB = NULL;
- if (pDCB == pACB->pLinkDCB)
- pACB->pLinkDCB = pDCB->pNextDCB;
- if (pDCB == pACB->pDCBRunRobin)
- pACB->pDCBRunRobin = pDCB->pNextDCB;
- kfree(pDCB);
-
- pACB->DCBCnt--;
-}
-
-static int dc390_slave_configure(struct scsi_device *sdev)
-{
- struct dc390_acb *acb = (struct dc390_acb *)sdev->host->hostdata;
- struct dc390_dcb *dcb = (struct dc390_dcb *)sdev->hostdata;
-
- acb->scan_devices = 0;
-
- /*
- * XXX: Note that while this driver used to called scsi_activate_tcq,
- * it never actually set a tag type, so emulate the old behavior.
- */
- scsi_set_tag_type(sdev, 0);
-
- if (sdev->tagged_supported && (dcb->DevMode & TAG_QUEUEING_)) {
- dcb->SyncMode |= EN_TAG_QUEUEING;
- scsi_adjust_queue_depth(sdev, acb->TagMaxNum);
- }
-
- return 0;
-}
-
-static struct scsi_host_template driver_template = {
- .module = THIS_MODULE,
- .proc_name = "tmscsim",
- .name = DC390_BANNER " V" DC390_VERSION,
- .slave_alloc = dc390_slave_alloc,
- .slave_configure = dc390_slave_configure,
- .slave_destroy = dc390_slave_destroy,
- .queuecommand = DC390_queuecommand,
- .eh_abort_handler = DC390_abort,
- .eh_bus_reset_handler = DC390_bus_reset,
- .can_queue = 1,
- .this_id = 7,
- .sg_tablesize = SG_ALL,
- .cmd_per_lun = 1,
- .use_clustering = ENABLE_CLUSTERING,
- .max_sectors = 0x4000, /* 8MiB = 16 * 1024 * 512 */
- .use_blk_tags = 1,
-};
-
-/***********************************************************************
- * Functions for access to DC390 EEPROM
- * and some to emulate it
- *
- **********************************************************************/
-
-static void dc390_eeprom_prepare_read(struct pci_dev *pdev, u8 cmd)
-{
- u8 carryFlag = 1, j = 0x80, bval;
- int i;
-
- for (i = 0; i < 9; i++) {
- if (carryFlag) {
- pci_write_config_byte(pdev, 0x80, 0x40);
- bval = 0xc0;
- } else
- bval = 0x80;
-
- udelay(160);
- pci_write_config_byte(pdev, 0x80, bval);
- udelay(160);
- pci_write_config_byte(pdev, 0x80, 0);
- udelay(160);
-
- carryFlag = (cmd & j) ? 1 : 0;
- j >>= 1;
- }
-}
-
-static u16 dc390_eeprom_get_data(struct pci_dev *pdev)
-{
- int i;
- u16 wval = 0;
- u8 bval;
-
- for (i = 0; i < 16; i++) {
- wval <<= 1;
-
- pci_write_config_byte(pdev, 0x80, 0x80);
- udelay(160);
- pci_write_config_byte(pdev, 0x80, 0x40);
- udelay(160);
- pci_read_config_byte(pdev, 0x00, &bval);
-
- if (bval == 0x22)
- wval |= 1;
- }
-
- return wval;
-}
-
-static void dc390_read_eeprom(struct pci_dev *pdev, u16 *ptr)
-{
- u8 cmd = EEPROM_READ, i;
-
- for (i = 0; i < 0x40; i++) {
- pci_write_config_byte(pdev, 0xc0, 0);
- udelay(160);
-
- dc390_eeprom_prepare_read(pdev, cmd++);
- *ptr++ = dc390_eeprom_get_data(pdev);
-
- pci_write_config_byte(pdev, 0x80, 0);
- pci_write_config_byte(pdev, 0x80, 0);
- udelay(160);
- }
-}
-
-/* Override EEprom values with explicitly set values */
-static void dc390_eeprom_override(u8 index)
-{
- u8 *ptr = (u8 *) dc390_eepromBuf[index], id;
-
- /* Adapter Settings */
- if (tmscsim[0] != -2)
- ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0]; /* Adapter ID */
- if (tmscsim[3] != -2)
- ptr[EE_MODE2] = (u8)tmscsim[3];
- if (tmscsim[5] != -2)
- ptr[EE_DELAY] = tmscsim[5]; /* Reset delay */
- if (tmscsim[4] != -2)
- ptr[EE_TAG_CMD_NUM] = (u8)tmscsim[4]; /* Tagged Cmds */
-
- /* Device Settings */
- for (id = 0; id < MAX_SCSI_ID; id++) {
- if (tmscsim[2] != -2)
- ptr[id << 2] = (u8)tmscsim[2]; /* EE_MODE1 */
- if (tmscsim[1] != -2)
- ptr[(id << 2) + 1] = (u8)tmscsim[1]; /* EE_Speed */
- }
-}
-
-static int tmscsim_def[] = {
- 7,
- 0 /* 10MHz */,
- PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_,
- MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION | LUN_CHECK,
- 3 /* 16 Tags per LUN */,
- 1 /* s delay after Reset */,
-};
-
-/* Copy defaults over set values where missing */
-static void dc390_fill_with_defaults (void)
-{
- int i;
-
- for (i = 0; i < 6; i++) {
- if (tmscsim[i] < 0 || tmscsim[i] > 255)
- tmscsim[i] = tmscsim_def[i];
- }
-
- /* Sanity checks */
- if (tmscsim[0] > 7)
- tmscsim[0] = 7;
- if (tmscsim[1] > 7)
- tmscsim[1] = 4;
- if (tmscsim[4] > 5)
- tmscsim[4] = 4;
- if (tmscsim[5] > 180)
- tmscsim[5] = 180;
-}
-
-static void dc390_check_eeprom(struct pci_dev *pdev, u8 index)
-{
- u8 interpd[] = {1, 3, 5, 10, 16, 30, 60, 120};
- u8 EEbuf[128];
- u16 *ptr = (u16 *)EEbuf, wval = 0;
- int i;
-
- dc390_read_eeprom(pdev, ptr);
- memcpy(dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID);
- memcpy(&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID],
- &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID);
-
- dc390_eepromBuf[index][EE_DELAY] = interpd[dc390_eepromBuf[index][EE_DELAY]];
-
- for (i = 0; i < 0x40; i++, ptr++)
- wval += *ptr;
-
- /* no Tekram EEprom found */
- if (wval != 0x1234) {
- int speed;
-
- printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n");
-
- /*
- * XXX(hch): bogus, because we might have tekram and
- * non-tekram hbas in a single machine.
- */
- dc390_fill_with_defaults();
-
- speed = dc390_clock_speed[tmscsim[1]];
- printk(KERN_INFO "DC390: Used defaults: AdaptID=%i, SpeedIdx=%i (%i.%i MHz), "
- "DevMode=0x%02x, AdaptMode=0x%02x, TaggedCmnds=%i (%i), DelayReset=%is\n",
- tmscsim[0], tmscsim[1], speed / 10, speed % 10,
- (u8)tmscsim[2], (u8)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]);
- }
-}
-
-static void dc390_init_hw(struct dc390_acb *pACB, u8 index)
-{
- struct Scsi_Host *shost = pACB->pScsiHost;
- u8 dstate;
-
- /* Disable SCSI bus reset interrupt */
- DC390_write8(CtrlReg1, DIS_INT_ON_SCSI_RST | shost->this_id);
-
- if (pACB->Gmode2 & RST_SCSI_BUS) {
- dc390_ResetSCSIBus(pACB);
- udelay(1000);
- pACB->last_reset = jiffies + HZ/2 +
- HZ * dc390_eepromBuf[pACB->AdapterIndex][EE_DELAY];
- }
-
- pACB->ACBFlag = 0;
-
- /* Reset Pending INT */
- DC390_read8(INT_Status);
-
- /* 250ms selection timeout */
- DC390_write8(Scsi_TimeOut, SEL_TIMEOUT);
-
- /* Conversion factor = 0 , 40MHz clock */
- DC390_write8(Clk_Factor, CLK_FREQ_40MHZ);
-
- /* NOP cmd - clear command register */
- DC390_write8(ScsiCmd, NOP_CMD);
-
- /* Enable Feature and SCSI-2 */
- DC390_write8(CtrlReg2, EN_FEATURE+EN_SCSI2_CMD);
-
- /* Fast clock */
- DC390_write8(CtrlReg3, FAST_CLK);
-
- /* Negation */
- DC390_write8(CtrlReg4, pACB->glitch_cfg | /* glitch eater */
- (dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) ?
- NEGATE_REQACKDATA : 0);
-
- /* Clear Transfer Count High: ID */
- DC390_write8(CtcReg_High, 0);
- DC390_write8(DMA_Cmd, DMA_IDLE_CMD);
- DC390_write8(ScsiCmd, CLEAR_FIFO_CMD);
- DC390_write32(DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT);
-
- dstate = DC390_read8(DMA_Status);
- DC390_write8(DMA_Status, dstate);
-}
-
-static int dc390_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
-{
- struct dc390_acb *pACB;
- struct Scsi_Host *shost;
- unsigned long io_port;
- int error = -ENODEV, i;
-
- if (pci_enable_device(pdev))
- goto out;
-
- pci_set_master(pdev);
-
- error = -ENOMEM;
- if (disable_clustering)
- driver_template.use_clustering = DISABLE_CLUSTERING;
- shost = scsi_host_alloc(&driver_template, sizeof(struct dc390_acb));
- if (!shost)
- goto out_disable_device;
-
- pACB = (struct dc390_acb *)shost->hostdata;
- memset(pACB, 0, sizeof(struct dc390_acb));
-
- dc390_check_eeprom(pdev, dc390_adapterCnt);
- dc390_eeprom_override(dc390_adapterCnt);
-
- io_port = pci_resource_start(pdev, 0);
-
- shost->this_id = dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID];
- shost->io_port = io_port;
- shost->n_io_port = 0x80;
- shost->irq = pdev->irq;
- shost->base = io_port;
- shost->unique_id = io_port;
-
- pACB->last_reset = jiffies;
- pACB->pScsiHost = shost;
- pACB->IOPortBase = (u16) io_port;
- pACB->IRQLevel = pdev->irq;
-
- shost->max_id = 8;
-
- if (shost->max_id - 1 ==
- dc390_eepromBuf[dc390_adapterCnt][EE_ADAPT_SCSI_ID])
- shost->max_id--;
-
- if (dc390_eepromBuf[dc390_adapterCnt][EE_MODE2] & LUN_CHECK)
- shost->max_lun = 8;
- else
- shost->max_lun = 1;
-
- pACB->pFreeSRB = pACB->SRB_array;
- pACB->SRBCount = MAX_SRB_CNT;
- pACB->AdapterIndex = dc390_adapterCnt;
- pACB->TagMaxNum =
- 2 << dc390_eepromBuf[dc390_adapterCnt][EE_TAG_CMD_NUM];
- pACB->Gmode2 = dc390_eepromBuf[dc390_adapterCnt][EE_MODE2];
-
- for (i = 0; i < pACB->SRBCount-1; i++)
- pACB->SRB_array[i].pNextSRB = &pACB->SRB_array[i+1];
- pACB->SRB_array[pACB->SRBCount-1].pNextSRB = NULL;
- pACB->pTmpSRB = &pACB->TmpSRB;
-
- pACB->sel_timeout = SEL_TIMEOUT;
- pACB->glitch_cfg = EATER_25NS;
- pACB->pdev = pdev;
-
- if (!request_region(io_port, shost->n_io_port, "tmscsim")) {
- printk(KERN_ERR "DC390: register IO ports error!\n");
- goto out_host_put;
- }
-
- /* Reset Pending INT */
- DC390_read8_(INT_Status, io_port);
-
- if (request_irq(pdev->irq, do_DC390_Interrupt, IRQF_SHARED,
- "tmscsim", pACB)) {
- printk(KERN_ERR "DC390: register IRQ error!\n");
- goto out_release_region;
- }
-
- dc390_init_hw(pACB, dc390_adapterCnt);
-
- dc390_adapterCnt++;
-
- pci_set_drvdata(pdev, shost);
-
- error = scsi_add_host(shost, &pdev->dev);
- if (error)
- goto out_free_irq;
- scsi_scan_host(shost);
- return 0;
-
- out_free_irq:
- free_irq(pdev->irq, pACB);
- out_release_region:
- release_region(io_port, shost->n_io_port);
- out_host_put:
- scsi_host_put(shost);
- out_disable_device:
- pci_disable_device(pdev);
- out:
- return error;
-}
-
-/**
- * dc390_remove_one - Called to remove a single instance of the adapter.
- *
- * @dev: The PCI device to remove.
- */
-static void dc390_remove_one(struct pci_dev *dev)
-{
- struct Scsi_Host *scsi_host = pci_get_drvdata(dev);
- unsigned long iflags;
- struct dc390_acb* pACB = (struct dc390_acb*) scsi_host->hostdata;
- u8 bval;
-
- scsi_remove_host(scsi_host);
-
- spin_lock_irqsave(scsi_host->host_lock, iflags);
- pACB->ACBFlag = RESET_DEV;
- bval = DC390_read8(CtrlReg1) | DIS_INT_ON_SCSI_RST;
- DC390_write8 (CtrlReg1, bval); /* disable interrupt */
- if (pACB->Gmode2 & RST_SCSI_BUS)
- dc390_ResetSCSIBus(pACB);
- spin_unlock_irqrestore(scsi_host->host_lock, iflags);
-
- free_irq(scsi_host->irq, pACB);
- release_region(scsi_host->io_port, scsi_host->n_io_port);
-
- pci_disable_device(dev);
- scsi_host_put(scsi_host);
-}
-
-static struct pci_device_id tmscsim_pci_tbl[] = {
- { PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974,
- PCI_ANY_ID, PCI_ANY_ID, 0, 0, 0 },
- { }
-};
-MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);
-
-static struct pci_driver dc390_driver = {
- .name = "tmscsim",
- .id_table = tmscsim_pci_tbl,
- .probe = dc390_probe_one,
- .remove = dc390_remove_one,
-};
-
-static int __init dc390_module_init(void)
-{
- if (!disable_clustering) {
- printk(KERN_INFO "DC390: clustering now enabled by default. If you get problems load\n");
- printk(KERN_INFO " with \"disable_clustering=1\" and report to maintainers\n");
- }
-
- if (tmscsim[0] == -1 || tmscsim[0] > 15) {
- tmscsim[0] = 7;
- tmscsim[1] = 4;
- tmscsim[2] = PARITY_CHK_ | TAG_QUEUEING_;
- tmscsim[3] = MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION;
- tmscsim[4] = 2;
- tmscsim[5] = 10;
- printk (KERN_INFO "DC390: Using safe settings.\n");
- }
-
- return pci_register_driver(&dc390_driver);
-}
-
-static void __exit dc390_module_exit(void)
-{
- pci_unregister_driver(&dc390_driver);
-}
-
-module_init(dc390_module_init);
-module_exit(dc390_module_exit);
-
-#ifndef MODULE
-static int __init dc390_setup (char *str)
-{
- int ints[8],i, im;
-
- get_options(str, ARRAY_SIZE(ints), ints);
- 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 (); */
- return 1;
-}
-
-__setup("tmscsim=", dc390_setup);
-#endif
diff --git a/drivers/scsi/tmscsim.h b/drivers/scsi/tmscsim.h
deleted file mode 100644
index c9ad4bb..0000000
--- a/drivers/scsi/tmscsim.h
+++ /dev/null
@@ -1,549 +0,0 @@
-/***********************************************************************
-;* File Name : TMSCSIM.H *
-;* TEKRAM DC-390(T) PCI SCSI Bus Master Host Adapter *
-;* Device Driver *
-;***********************************************************************/
-/* $Id: tmscsim.h,v 2.15.2.3 2000/11/17 20:52:27 garloff Exp $ */
-
-#ifndef _TMSCSIM_H
-#define _TMSCSIM_H
-
-#include <linux/types.h>
-
-#define MAX_ADAPTER_NUM 4
-#define MAX_SG_LIST_BUF 16 /* Not used */
-#define MAX_SCSI_ID 8
-#define MAX_SRB_CNT 50 /* Max number of started commands */
-
-#define SEL_TIMEOUT 153 /* 250 ms selection timeout (@ 40 MHz) */
-
-/*
-;-----------------------------------------------------------------------
-; SCSI Request Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_srb
-{
-//u8 CmdBlock[12];
-
-struct dc390_srb *pNextSRB;
-struct dc390_dcb *pSRBDCB;
-struct scsi_cmnd *pcmd;
-struct scatterlist *pSegmentList;
-
-struct scatterlist Segmentx; /* make a one entry of S/G list table */
-
-unsigned long SGBusAddr; /*;a segment starting address as seen by AM53C974A
- in CPU endianness. We're only getting 32-bit bus
- addresses by default */
-unsigned long SGToBeXferLen; /*; to be xfer length */
-unsigned long TotalXferredLen;
-unsigned long SavedTotXLen;
-unsigned long Saved_Ptr;
-u32 SRBState;
-
-u8 SRBStatus;
-u8 SRBFlag; /*; b0-AutoReqSense,b6-Read,b7-write */
- /*; b4-settimeout,b5-Residual valid */
-u8 AdaptStatus;
-u8 TargetStatus;
-
-u8 ScsiPhase;
-s8 TagNumber;
-u8 SGIndex;
-u8 SGcount;
-
-u8 MsgCnt;
-u8 EndMessage;
-
-u8 MsgInBuf[6];
-u8 MsgOutBuf[6];
-
-//u8 IORBFlag; /*;81h-Reset, 2-retry */
-};
-
-
-/*
-;-----------------------------------------------------------------------
-; Device Control Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_dcb
-{
-struct dc390_dcb *pNextDCB;
-struct dc390_acb *pDCBACB;
-
-/* Queued SRBs */
-struct dc390_srb *pGoingSRB;
-struct dc390_srb *pGoingLast;
-struct dc390_srb *pActiveSRB;
-u8 GoingSRBCnt;
-
-u32 TagMask;
-
-u8 TargetID; /*; SCSI Target ID (SCSI Only) */
-u8 TargetLUN; /*; SCSI Log. Unit (SCSI Only) */
-u8 DevMode;
-u8 DCBFlag;
-
-u8 CtrlR1;
-u8 CtrlR3;
-u8 CtrlR4;
-
-u8 SyncMode; /*; 0:async mode */
-u8 NegoPeriod; /*;for nego. */
-u8 SyncPeriod; /*;for reg. */
-u8 SyncOffset; /*;for reg. and nego.(low nibble) */
-};
-
-
-/*
-;-----------------------------------------------------------------------
-; Adapter Control Block
-;-----------------------------------------------------------------------
-*/
-struct dc390_acb
-{
-struct Scsi_Host *pScsiHost;
-u16 IOPortBase;
-u8 IRQLevel;
-u8 status;
-
-u8 SRBCount;
-u8 AdapterIndex; /*; nth Adapter this driver */
-u8 DCBCnt;
-
-u8 TagMaxNum;
-u8 ACBFlag;
-u8 Gmode2;
-u8 scan_devices;
-
-struct dc390_dcb *pLinkDCB;
-struct dc390_dcb *pLastDCB;
-struct dc390_dcb *pDCBRunRobin;
-
-struct dc390_dcb *pActiveDCB;
-struct dc390_srb *pFreeSRB;
-struct dc390_srb *pTmpSRB;
-
-u8 msgin123[4];
-u8 Connected;
-u8 pad;
-
-#if defined(USE_SPINLOCKS) && USE_SPINLOCKS > 1 && (defined(CONFIG_SMP) || DEBUG_SPINLOCKS > 0)
-spinlock_t lock;
-#endif
-u8 sel_timeout;
-u8 glitch_cfg;
-
-u8 MsgLen;
-u8 Ignore_IRQ; /* Not used */
-
-struct pci_dev *pdev;
-
-unsigned long last_reset;
-unsigned long Cmds;
-u32 SelLost;
-u32 SelConn;
-u32 CmdInQ;
-u32 CmdOutOfSRB;
-
-struct dc390_srb TmpSRB;
-struct dc390_srb SRB_array[MAX_SRB_CNT]; /* 50 SRBs */
-};
-
-
-/*;-----------------------------------------------------------------------*/
-
-
-#define BIT31 0x80000000
-#define BIT30 0x40000000
-#define BIT29 0x20000000
-#define BIT28 0x10000000
-#define BIT27 0x08000000
-#define BIT26 0x04000000
-#define BIT25 0x02000000
-#define BIT24 0x01000000
-#define BIT23 0x00800000
-#define BIT22 0x00400000
-#define BIT21 0x00200000
-#define BIT20 0x00100000
-#define BIT19 0x00080000
-#define BIT18 0x00040000
-#define BIT17 0x00020000
-#define BIT16 0x00010000
-#define BIT15 0x00008000
-#define BIT14 0x00004000
-#define BIT13 0x00002000
-#define BIT12 0x00001000
-#define BIT11 0x00000800
-#define BIT10 0x00000400
-#define BIT9 0x00000200
-#define BIT8 0x00000100
-#define BIT7 0x00000080
-#define BIT6 0x00000040
-#define BIT5 0x00000020
-#define BIT4 0x00000010
-#define BIT3 0x00000008
-#define BIT2 0x00000004
-#define BIT1 0x00000002
-#define BIT0 0x00000001
-
-/*;---UnitCtrlFlag */
-#define UNIT_ALLOCATED BIT0
-#define UNIT_INFO_CHANGED BIT1
-#define FORMATING_MEDIA BIT2
-#define UNIT_RETRY BIT3
-
-/*;---UnitFlags */
-#define DASD_SUPPORT BIT0
-#define SCSI_SUPPORT BIT1
-#define ASPI_SUPPORT BIT2
-
-/*;----SRBState machine definition */
-#define SRB_FREE 0
-#define SRB_WAIT BIT0
-#define SRB_READY BIT1
-#define SRB_MSGOUT BIT2 /*;arbitration+msg_out 1st byte*/
-#define SRB_MSGIN BIT3
-#define SRB_MSGIN_MULTI BIT4
-#define SRB_COMMAND BIT5
-#define SRB_START_ BIT6 /*;arbitration+msg_out+command_out*/
-#define SRB_DISCONNECT BIT7
-#define SRB_DATA_XFER BIT8
-#define SRB_XFERPAD BIT9
-#define SRB_STATUS BIT10
-#define SRB_COMPLETED BIT11
-#define SRB_ABORT_SENT BIT12
-#define DO_SYNC_NEGO BIT13
-#define SRB_UNEXPECT_RESEL BIT14
-
-/*;---SRBstatus */
-#define SRB_OK BIT0
-#define ABORTION BIT1
-#define OVER_RUN BIT2
-#define UNDER_RUN BIT3
-#define PARITY_ERROR BIT4
-#define SRB_ERROR BIT5
-
-/*;---ACBFlag */
-#define RESET_DEV BIT0
-#define RESET_DETECT BIT1
-#define RESET_DONE BIT2
-
-/*;---DCBFlag */
-#define ABORT_DEV_ BIT0
-
-/*;---SRBFlag */
-#define DATAOUT BIT7
-#define DATAIN BIT6
-#define RESIDUAL_VALID BIT5
-#define ENABLE_TIMER BIT4
-#define RESET_DEV0 BIT2
-#define ABORT_DEV BIT1
-#define AUTO_REQSENSE BIT0
-
-/*;---Adapter status */
-#define H_STATUS_GOOD 0
-#define H_SEL_TIMEOUT 0x11
-#define H_OVER_UNDER_RUN 0x12
-#define H_UNEXP_BUS_FREE 0x13
-#define H_TARGET_PHASE_F 0x14
-#define H_INVALID_CCB_OP 0x16
-#define H_LINK_CCB_BAD 0x17
-#define H_BAD_TARGET_DIR 0x18
-#define H_DUPLICATE_CCB 0x19
-#define H_BAD_CCB_OR_SG 0x1A
-#define H_ABORT 0x0FF
-
-/* 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))
-
-#define SET_RES_TARGET(who, tgt) do { who &= ~RES_TARGET; who |= (int)(tgt); } while (0)
-#define SET_RES_TARGET_LNX(who, tgt) do { who &= ~RES_TARGET_LNX; who |= (int)(tgt) << 1; } while (0)
-#define SET_RES_MSG(who, msg) do { who &= ~RES_ENDMSG; who |= (int)(msg) << 8; } while (0)
-#define SET_RES_DID(who, did) do { who &= ~RES_DID; who |= (int)(did) << 16; } while (0)
-#define SET_RES_DRV(who, drv) do { who &= ~RES_DRV; who |= (int)(drv) << 24; } while (0)
-
-/*;---Sync_Mode */
-#define SYNC_DISABLE 0
-#define SYNC_ENABLE BIT0
-#define SYNC_NEGO_DONE BIT1
-#define WIDE_ENABLE BIT2 /* Not used ;-) */
-#define WIDE_NEGO_DONE BIT3 /* Not used ;-) */
-#define EN_TAG_QUEUEING BIT4
-#define EN_ATN_STOP BIT5
-
-#define SYNC_NEGO_OFFSET 15
-
-/*;---SCSI bus phase*/
-#define SCSI_DATA_OUT 0
-#define SCSI_DATA_IN 1
-#define SCSI_COMMAND 2
-#define SCSI_STATUS_ 3
-#define SCSI_NOP0 4
-#define SCSI_NOP1 5
-#define SCSI_MSG_OUT 6
-#define SCSI_MSG_IN 7
-
-/*;----SCSI MSG BYTE*/ /* see scsi/scsi.h */ /* One is missing ! */
-#define ABORT_TAG 0x0d
-
-/*
- * SISC query queue
- */
-typedef struct {
- dma_addr_t saved_dma_handle;
-} dc390_cmd_scp_t;
-
-/*
-;==========================================================
-; EEPROM byte offset
-;==========================================================
-*/
-typedef struct _EEprom
-{
-u8 EE_MODE1;
-u8 EE_SPEED;
-u8 xx1;
-u8 xx2;
-} EEprom, *PEEprom;
-
-#define REAL_EE_ADAPT_SCSI_ID 64
-#define REAL_EE_MODE2 65
-#define REAL_EE_DELAY 66
-#define REAL_EE_TAG_CMD_NUM 67
-
-#define EE_ADAPT_SCSI_ID 32
-#define EE_MODE2 33
-#define EE_DELAY 34
-#define EE_TAG_CMD_NUM 35
-
-#define EE_LEN 40
-
-/*; EE_MODE1 bits definition*/
-#define PARITY_CHK_ BIT0
-#define SYNC_NEGO_ BIT1
-#define EN_DISCONNECT_ BIT2
-#define SEND_START_ BIT3
-#define TAG_QUEUEING_ BIT4
-
-/*; EE_MODE2 bits definition*/
-#define MORE2_DRV BIT0
-#define GREATER_1G BIT1
-#define RST_SCSI_BUS BIT2
-#define ACTIVE_NEGATION BIT3
-#define NO_SEEK BIT4
-#define LUN_CHECK BIT5
-
-#define ENABLE_CE 1
-#define DISABLE_CE 0
-#define EEPROM_READ 0x80
-
-/*
-;==========================================================
-; AMD 53C974 Registers bit Definition
-;==========================================================
-*/
-/*
-;====================
-; SCSI Register
-;====================
-*/
-
-/*; Command Reg.(+0CH) (rw) */
-#define DMA_COMMAND BIT7
-#define NOP_CMD 0
-#define CLEAR_FIFO_CMD 1
-#define RST_DEVICE_CMD 2
-#define RST_SCSI_BUS_CMD 3
-
-#define INFO_XFER_CMD 0x10
-#define INITIATOR_CMD_CMPLTE 0x11
-#define MSG_ACCEPTED_CMD 0x12
-#define XFER_PAD_BYTE 0x18
-#define SET_ATN_CMD 0x1A
-#define RESET_ATN_CMD 0x1B
-
-#define SEL_WO_ATN 0x41 /* currently not used */
-#define SEL_W_ATN 0x42
-#define SEL_W_ATN_STOP 0x43
-#define SEL_W_ATN3 0x46
-#define EN_SEL_RESEL 0x44
-#define DIS_SEL_RESEL 0x45 /* currently not used */
-#define RESEL 0x40 /* " */
-#define RESEL_ATN3 0x47 /* " */
-
-#define DATA_XFER_CMD INFO_XFER_CMD
-
-
-/*; SCSI Status Reg.(+10H) (r) */
-#define INTERRUPT BIT7
-#define ILLEGAL_OP_ERR BIT6
-#define PARITY_ERR BIT5
-#define COUNT_2_ZERO BIT4
-#define GROUP_CODE_VALID BIT3
-#define SCSI_PHASE_MASK (BIT2+BIT1+BIT0)
-/* BIT2: MSG phase; BIT1: C/D physe; BIT0: I/O phase */
-
-/*; Interrupt Status Reg.(+14H) (r) */
-#define SCSI_RESET BIT7
-#define INVALID_CMD BIT6
-#define DISCONNECTED BIT5
-#define SERVICE_REQUEST BIT4
-#define SUCCESSFUL_OP BIT3
-#define RESELECTED BIT2
-#define SEL_ATTENTION BIT1
-#define SELECTED BIT0
-
-/*; Internal State Reg.(+18H) (r) */
-#define SYNC_OFFSET_FLAG BIT3
-#define INTRN_STATE_MASK (BIT2+BIT1+BIT0)
-/* 0x04: Sel. successful (w/o stop), 0x01: Sel. successful (w/ stop) */
-
-/*; Clock Factor Reg.(+24H) (w) */
-#define CLK_FREQ_40MHZ 0
-#define CLK_FREQ_35MHZ (BIT2+BIT1+BIT0)
-#define CLK_FREQ_30MHZ (BIT2+BIT1)
-#define CLK_FREQ_25MHZ (BIT2+BIT0)
-#define CLK_FREQ_20MHZ BIT2
-#define CLK_FREQ_15MHZ (BIT1+BIT0)
-#define CLK_FREQ_10MHZ BIT1
-
-/*; Control Reg. 1(+20H) (rw) */
-#define EXTENDED_TIMING BIT7
-#define DIS_INT_ON_SCSI_RST BIT6
-#define PARITY_ERR_REPO BIT4
-#define SCSI_ID_ON_BUS (BIT2+BIT1+BIT0) /* host adapter ID */
-
-/*; Control Reg. 2(+2CH) (rw) */
-#define EN_FEATURE BIT6
-#define EN_SCSI2_CMD BIT3
-
-/*; Control Reg. 3(+30H) (rw) */
-#define ID_MSG_CHECK BIT7
-#define EN_QTAG_MSG BIT6
-#define EN_GRP2_CMD BIT5
-#define FAST_SCSI BIT4 /* ;10MB/SEC */
-#define FAST_CLK BIT3 /* ;25 - 40 MHZ */
-
-/*; Control Reg. 4(+34H) (rw) */
-#define EATER_12NS 0
-#define EATER_25NS BIT7
-#define EATER_35NS BIT6
-#define EATER_0NS (BIT7+BIT6)
-#define REDUCED_POWER BIT5
-#define CTRL4_RESERVED BIT4 /* must be 1 acc. to AM53C974.c */
-#define NEGATE_REQACKDATA BIT2
-#define NEGATE_REQACK BIT3
-
-#define GLITCH_TO_NS(x) (((~x>>6 & 2) >> 1) | ((x>>6 & 1) << 1 ^ (x>>6 & 2)))
-#define NS_TO_GLITCH(y) (((~y<<7) | ~((y<<6) ^ ((y<<5 & 1<<6) | ~0x40))) & 0xc0)
-
-/*
-;====================
-; DMA Register
-;====================
-*/
-/*; DMA Command Reg.(+40H) (rw) */
-#define READ_DIRECTION BIT7
-#define WRITE_DIRECTION 0
-#define EN_DMA_INT BIT6
-#define EN_PAGE_INT BIT5 /* page transfer interrupt enable */
-#define MAP_TO_MDL BIT4
-#define DIAGNOSTIC BIT2
-#define DMA_IDLE_CMD 0
-#define DMA_BLAST_CMD BIT0
-#define DMA_ABORT_CMD BIT1
-#define DMA_START_CMD (BIT1+BIT0)
-
-/*; DMA Status Reg.(+54H) (r) */
-#define PCI_MS_ABORT BIT6
-#define BLAST_COMPLETE BIT5
-#define SCSI_INTERRUPT BIT4
-#define DMA_XFER_DONE BIT3
-#define DMA_XFER_ABORT BIT2
-#define DMA_XFER_ERROR BIT1
-#define POWER_DOWN BIT0
-
-/*; DMA SCSI Bus and Ctrl.(+70H) */
-#define EN_INT_ON_PCI_ABORT BIT25
-#define WRT_ERASE_DMA_STAT BIT24
-#define PW_DOWN_CTRL BIT21
-#define SCSI_BUSY BIT20
-#define SCLK BIT19
-#define SCAM BIT18
-#define SCSI_LINES 0x0003ffff
-
-/*
-;==========================================================
-; SCSI Chip register address offset
-;==========================================================
-;Registers are rw unless declared otherwise
-*/
-#define CtcReg_Low 0x00 /* r curr. transfer count */
-#define CtcReg_Mid 0x04 /* r */
-#define CtcReg_High 0x38 /* r */
-#define ScsiFifo 0x08
-#define ScsiCmd 0x0C
-#define Scsi_Status 0x10 /* r */
-#define INT_Status 0x14 /* r */
-#define Sync_Period 0x18 /* w */
-#define Sync_Offset 0x1C /* w */
-#define Clk_Factor 0x24 /* w */
-#define CtrlReg1 0x20
-#define CtrlReg2 0x2C
-#define CtrlReg3 0x30
-#define CtrlReg4 0x34
-#define DMA_Cmd 0x40
-#define DMA_XferCnt 0x44 /* rw starting transfer count (32 bit) */
-#define DMA_XferAddr 0x48 /* rw starting physical address (32 bit) */
-#define DMA_Wk_ByteCntr 0x4C /* r working byte counter */
-#define DMA_Wk_AddrCntr 0x50 /* r working address counter */
-#define DMA_Status 0x54 /* r */
-#define DMA_MDL_Addr 0x58 /* rw starting MDL address */
-#define DMA_Wk_MDL_Cntr 0x5C /* r working MDL counter */
-#define DMA_ScsiBusCtrl 0x70 /* rw SCSI Bus, PCI/DMA Ctrl */
-
-#define StcReg_Low CtcReg_Low /* w start transfer count */
-#define StcReg_Mid CtcReg_Mid /* w */
-#define StcReg_High CtcReg_High /* w */
-#define Scsi_Dest_ID Scsi_Status /* w */
-#define Scsi_TimeOut INT_Status /* w */
-#define Intern_State Sync_Period /* r */
-#define Current_Fifo Sync_Offset /* r Curr. FIFO / int. state */
-
-
-#define DC390_read8(address) \
- (inb (pACB->IOPortBase + (address)))
-
-#define DC390_read8_(address, base) \
- (inb ((u16)(base) + (address)))
-
-#define DC390_read16(address) \
- (inw (pACB->IOPortBase + (address)))
-
-#define DC390_read32(address) \
- (inl (pACB->IOPortBase + (address)))
-
-#define DC390_write8(address,value) \
- outb ((value), pACB->IOPortBase + (address))
-
-#define DC390_write8_(address,value,base) \
- outb ((value), (u16)(base) + (address))
-
-#define DC390_write16(address,value) \
- outw ((value), pACB->IOPortBase + (address))
-
-#define DC390_write32(address,value) \
- outl ((value), pACB->IOPortBase + (address))
-
-
-#endif /* _TMSCSIM_H */
--
1.8.5.2
^ permalink raw reply related [flat|nested] 17+ messages in thread
* Re: [PATCHv3 00/12] Re-implement am53c974 driver
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
` (11 preceding siblings ...)
2014-11-24 14:37 ` [PATCH 12/12] Replace tmscsim by am53c974 Hannes Reinecke
@ 2014-11-24 15:18 ` Christoph Hellwig
12 siblings, 0 replies; 17+ messages in thread
From: Christoph Hellwig @ 2014-11-24 15:18 UTC (permalink / raw)
To: Hannes Reinecke
Cc: James Bottomley, Paolo Bonzini, David S. Miller, linux-scsi
Thanks,
applied to drivers-for-3.19.
^ permalink raw reply [flat|nested] 17+ messages in thread
end of thread, other threads:[~2014-11-24 15:18 UTC | newest]
Thread overview: 17+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-24 14:37 [PATCHv3 00/12] Re-implement am53c974 driver Hannes Reinecke
2014-11-24 14:37 ` [PATCH 01/12] esp_scsi: spellcheck 'driver' Hannes Reinecke
2014-11-24 14:37 ` [PATCH 02/12] esp_scsi: make number of tags configurable Hannes Reinecke
2014-11-24 14:37 ` [PATCH 03/12] esp_scsi: convert to dev_printk Hannes Reinecke
2014-11-24 14:37 ` [PATCH 04/12] esp_scsi: debug event and command Hannes Reinecke
2014-11-24 14:37 ` [PATCH 05/12] esp_scsi: read status registers Hannes Reinecke
2014-11-24 14:37 ` [PATCH 06/12] esp_scsi: use FIFO for command submission Hannes Reinecke
2014-11-24 14:37 ` [PATCH 07/12] scsi: add 'am53c974' driver Hannes Reinecke
2014-11-24 14:37 ` [PATCH 08/12] am53c974: BLAST residual handling Hannes Reinecke
2014-11-24 14:37 ` [PATCH 09/12] esp: correctly detect am53c974 Hannes Reinecke
2014-11-24 14:37 ` [PATCH 10/12] esp_scsi: let DMA driver provide a config2 value Hannes Reinecke
2014-11-24 14:37 ` [PATCH 11/12] esp: enable CONFIG2_FENAB for am53c974 Hannes Reinecke
2014-11-24 14:37 ` [PATCH 12/12] Replace tmscsim by am53c974 Hannes Reinecke
2014-11-24 15:18 ` [PATCHv3 00/12] Re-implement am53c974 driver Christoph Hellwig
-- strict thread matches above, loose matches on Subject: below --
2014-11-21 12:41 [PATCHv2 " Hannes Reinecke
2014-11-21 12:41 ` [PATCH 12/12] Replace tmscsim by am53c974 Hannes Reinecke
2014-11-23 13:22 ` Guennadi Liakhovetski
2014-11-23 18:45 ` David Miller
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).