📄 tmscsim.c
字号:
/*********************************************************************** * 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 README.tmscsim) **************************************************************************//* $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 * ***********************************************************************//* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */#define DC390_IRQ SA_SHIRQ /* | SA_INTERRUPT *//* DEBUG options *///#define DC390_DEBUG0//#define DC390_DEBUG1//#define DC390_DCBDEBUG//#define DC390_PARSEDEBUG//#define DC390_REMOVABLEDEBUG//#define DC390_LOCKDEBUG/* Debug definitions */#ifdef DC390_DEBUG0# define DEBUG0(x) x;#else# define DEBUG0(x)#endif#ifdef DC390_DEBUG1# define DEBUG1(x) x;#else# define DEBUG1(x)#endif#ifdef DC390_DCBDEBUG# define DCBDEBUG(x) x;#else# define DCBDEBUG(x)#endif#ifdef DC390_PARSEDEBUG# define PARSEDEBUG(x) x;#else# define PARSEDEBUG(x)#endif#ifdef DC390_REMOVABLEDEBUG# define REMOVABLEDEBUG(x) x;#else# define REMOVABLEDEBUG(x)#endif#define DCBDEBUG1(x)/* Includes */#ifdef MODULE# include <linux/module.h>#endif#include <asm/dma.h>#include <asm/io.h>#include <asm/system.h>#include <linux/delay.h>#include <linux/signal.h>#include <linux/sched.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/ctype.h>#include <linux/mm.h>#include <linux/config.h>#include <linux/version.h>#include <linux/blk.h>#include <linux/timer.h>#include "scsi.h"#include "hosts.h"#include "constants.h"#include "sd.h"#include <linux/stat.h>#include <scsi/scsicam.h>#include "dc390.h"#define PCI_DEVICE_ID_AMD53C974 PCI_DEVICE_ID_AMD_SCSI/* Locking *//* Note: Starting from 2.1.9x, the mid-level scsi code issues a * spinlock_irqsave (&io_request_lock) before calling the driver's * routines, so we don't need to lock, except in the IRQ handler. * The policy 3, let the midlevel scsi code do the io_request_locks * and us locking on a driver specific lock, shouldn't hurt anybody; it * just causes a minor performance degradation for setting the locks. *//* spinlock things * level 3: lock on both adapter specific locks and (global) io_request_lock * level 2: lock on adapter specific locks only * level 1: rely on the locking of the mid level code (io_request_lock) * undef : traditional save_flags; cli; restore_flags; *///#define DEBUG_SPINLOCKS 2 /* Set to 0, 1 or 2 in include/linux/spinlock.h */#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)# include <linux/init.h>#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,30)# include <linux/spinlock.h>#else# include <asm/spinlock.h>#endif#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,93) # define USE_SPINLOCKS 1# define NEW_PCI 1#else# undef NEW_PCI# if LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)# define USE_SPINLOCKS 2# endif#endif#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,99)static struct pci_device_id tmscsim_pci_tbl[] __initdata = { { vendor: PCI_VENDOR_ID_AMD, device: PCI_DEVICE_ID_AMD53C974, subvendor: PCI_ANY_ID, subdevice: PCI_ANY_ID, }, { } /* Terminating entry */};MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl);#endif #ifdef USE_SPINLOCKS# if USE_SPINLOCKS == 3 /* both */# if defined (CONFIG_SMP) || DEBUG_SPINLOCKS > 0# define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };# else# define DC390_LOCKA_INIT# endif spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;# define DC390_AFLAGS unsigned long aflags;# define DC390_IFLAGS unsigned long iflags;# define DC390_DFLAGS unsigned long dflags; # define DC390_LOCK_IO spin_lock_irqsave (&io_request_lock, iflags)# define DC390_UNLOCK_IO spin_unlock_irqrestore (&io_request_lock, iflags)# define DC390_LOCK_DRV spin_lock_irqsave (&dc390_drvlock, dflags)# define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags)# define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock)# define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock)# define DC390_LOCK_ACB spin_lock_irqsave (&(pACB->lock), aflags)# define DC390_UNLOCK_ACB spin_unlock_irqrestore (&(pACB->lock), aflags)# define DC390_LOCK_ACB_NI spin_lock (&(pACB->lock))# define DC390_UNLOCK_ACB_NI spin_unlock (&(pACB->lock))//# define DC390_LOCKA_INIT spin_lock_init (&(pACB->lock))# else# if USE_SPINLOCKS == 2 /* adapter specific locks */# if defined (CONFIG_SMP) || DEBUG_SPINLOCKS > 0# define DC390_LOCKA_INIT { spinlock_t __unlocked = SPIN_LOCK_UNLOCKED; pACB->lock = __unlocked; };# else# define DC390_LOCKA_INIT# endif spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;# define DC390_AFLAGS unsigned long aflags;# define DC390_IFLAGS # define DC390_DFLAGS unsigned long dflags; # define DC390_LOCK_IO /* spin_lock_irqsave (&io_request_lock, iflags) */# define DC390_UNLOCK_IO /* spin_unlock_irqrestore (&io_request_lock, iflags) */# define DC390_LOCK_DRV spin_lock_irqsave (&dc390_drvlock, dflags)# define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags)# define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock)# define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock)# define DC390_LOCK_ACB spin_lock_irqsave (&(pACB->lock), aflags)# define DC390_UNLOCK_ACB spin_unlock_irqrestore (&(pACB->lock), aflags)# define DC390_LOCK_ACB_NI spin_lock (&(pACB->lock))# define DC390_UNLOCK_ACB_NI spin_unlock (&(pACB->lock))//# define DC390_LOCKA_INIT spin_lock_init (&(pACB->lock))# else /* USE_SPINLOCKS == 1: global lock io_request_lock */# define DC390_AFLAGS # define DC390_IFLAGS unsigned long iflags;# define DC390_DFLAGS unsigned long dflags; spinlock_t dc390_drvlock = SPIN_LOCK_UNLOCKED;# define DC390_LOCK_IO spin_lock_irqsave (&io_request_lock, iflags)# define DC390_UNLOCK_IO spin_unlock_irqrestore (&io_request_lock, iflags)# define DC390_LOCK_DRV spin_lock_irqsave (&dc390_drvlock, dflags)# define DC390_UNLOCK_DRV spin_unlock_irqrestore (&dc390_drvlock, dflags)# define DC390_LOCK_DRV_NI spin_lock (&dc390_drvlock)# define DC390_UNLOCK_DRV_NI spin_unlock (&dc390_drvlock)# define DC390_LOCK_ACB /* DC390_LOCK_IO */# define DC390_UNLOCK_ACB /* DC390_UNLOCK_IO */# define DC390_LOCK_ACB_NI /* spin_lock (&(pACB->lock)) */# define DC390_UNLOCK_ACB_NI /* spin_unlock (&(pACB->lock)) */# define DC390_LOCKA_INIT /* DC390_LOCKA_INIT */# endif /* 2 */# endif /* 3 */#else /* USE_SPINLOCKS undefined */# define DC390_AFLAGS unsigned long aflags;# define DC390_IFLAGS unsigned long iflags;# define DC390_DFLAGS unsigned long dflags; # define DC390_LOCK_IO save_flags (iflags); cli ()# define DC390_UNLOCK_IO restore_flags (iflags)# define DC390_LOCK_DRV save_flags (dflags); cli ()# define DC390_UNLOCK_DRV restore_flags (dflags)# define DC390_LOCK_DRV_NI# define DC390_UNLOCK_DRV_NI# define DC390_LOCK_ACB save_flags (aflags); cli ()# define DC390_UNLOCK_ACB restore_flags (aflags)# define DC390_LOCK_ACB_NI# define DC390_UNLOCK_ACB_NI# define DC390_LOCKA_INIT#endif /* def *//* These macros are used for uniform access to 2.0.x and 2.1.x PCI config space*/#ifdef NEW_PCI# define PDEV pdev# define PDEVDECL struct pci_dev *pdev# define PDEVDECL0 struct pci_dev *pdev = NULL# define PDEVDECL1 struct pci_dev *pdev# define PDEVSET pACB->pdev=pdev# define PDEVSET1 pdev=pACB->pdev# define PCI_WRITE_CONFIG_BYTE(pd, rv, bv) pci_write_config_byte (pd, rv, bv)# define PCI_READ_CONFIG_BYTE(pd, rv, bv) pci_read_config_byte (pd, rv, bv)# define PCI_WRITE_CONFIG_WORD(pd, rv, bv) pci_write_config_word (pd, rv, bv)# define PCI_READ_CONFIG_WORD(pd, rv, bv) pci_read_config_word (pd, rv, bv)# define PCI_BUS_DEV pdev->bus->number, pdev->devfn# define PCI_PRESENT pci_present ()# define PCI_SET_MASTER pci_set_master (pdev)# define PCI_FIND_DEVICE(vend, id) (pdev = pci_find_device (vend, id, pdev))#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,10)# define PCI_GET_IO_AND_IRQ io_port = pci_resource_start (pdev, 0); irq = pdev->irq#else# define PCI_GET_IO_AND_IRQ io_port = pdev->base_address[0] & PCI_BASE_ADDRESS_IO_MASK; irq = pdev->irq#endif#else# include <linux/bios32.h># define PDEV pbus, pdevfn# define PDEVDECL UCHAR pbus, UCHAR pdevfn# define PDEVDECL0 UCHAR pbus = 0; UCHAR pdevfn = 0; USHORT pci_index = 0; int error# define PDEVDECL1 UCHAR pbus; UCHAR pdevfn /*; USHORT pci_index */# define PDEVSET pACB->pbus=pbus; pACB->pdevfn=pdevfn /*; pACB->pci_index=pci_index */# define PDEVSET1 pbus=pACB->pbus; pdevfn=pACB->pdevfn /*; pci_index=pACB->pci_index */# define PCI_WRITE_CONFIG_BYTE(pd, rv, bv) pcibios_write_config_byte (pd, rv, bv)# define PCI_READ_CONFIG_BYTE(pd, rv, bv) pcibios_read_config_byte (pd, rv, bv)# define PCI_WRITE_CONFIG_WORD(pd, rv, bv) pcibios_write_config_word (pd, rv, bv)# define PCI_READ_CONFIG_WORD(pd, rv, bv) pcibios_read_config_word (pd, rv, bv)# define PCI_BUS_DEV pbus, pdevfn# define PCI_PRESENT pcibios_present ()# define PCI_SET_MASTER dc390_set_master (pbus, pdevfn)# define PCI_FIND_DEVICE(vend, id) (!pcibios_find_device (vend, id, pci_index++, &pbus, &pdevfn))# define PCI_GET_IO_AND_IRQ error = pcibios_read_config_dword (pbus, pdevfn, PCI_BASE_ADDRESS_0, &io_port); \ error |= pcibios_read_config_byte (pbus, pdevfn, PCI_INTERRUPT_LINE, &irq); \ io_port &= 0xfffe; \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -