X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=drivers%2Fscsi%2Ftmscsim.c;h=1b324b8002e94140c618a94659bdc423aa290b9f;hb=9bf4aaab3e101692164d49b7ca357651eb691cb6;hp=c9c6cbc268eaea57524060afaada2a7b0a0877c8;hpb=db216c3d5e4c040e557a50f8f5d35d5c415e8c1c;p=linux-2.6.git diff --git a/drivers/scsi/tmscsim.c b/drivers/scsi/tmscsim.c index c9c6cbc26..1b324b800 100644 --- a/drivers/scsi/tmscsim.c +++ b/drivers/scsi/tmscsim.c @@ -172,6 +172,11 @@ * 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. * ***********************************************************************/ /* Uncomment SA_INTERRUPT, if the driver refuses to share its IRQ with other devices */ @@ -216,11 +221,8 @@ #endif #define DCBDEBUG1(x) C_NOP -/* Includes */ +#include #include -#include -#include -#include #include #include #include @@ -230,45 +232,30 @@ #include #include #include -#include #include -#include -#include #include #include #include +#include +#include +#include +#if 0 +#include +#include +#include +#else #include "scsi.h" -#include "hosts.h" -#include +#endif +#include #include #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; - */ - -#include -#include -#if defined(MODULE) -static struct pci_device_id tmscsim_pci_tbl[] = { + static struct pci_device_id tmscsim_pci_tbl[] = { { .vendor = PCI_VENDOR_ID_AMD, .device = PCI_DEVICE_ID_AMD53C974, @@ -278,91 +265,61 @@ static struct pci_device_id tmscsim_pci_tbl[] = { { } /* Terminating entry */ }; MODULE_DEVICE_TABLE(pci, tmscsim_pci_tbl); -#endif - -#define USE_SPINLOCKS 1 - -#define DC390_IFLAGS unsigned long iflags -#define DC390_LOCK_IO(dev) spin_lock_irqsave (((struct Scsi_Host *)dev)->host_lock, iflags) -#define DC390_UNLOCK_IO(dev) spin_unlock_irqrestore (((struct Scsi_Host *)dev)->host_lock, iflags) - -/* These macros are used for uniform access to 2.0.x and 2.1.x PCI config space*/ - -#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_PRESENT (1) -#define PCI_GET_IO_AND_IRQ do{io_port = pci_resource_start (pdev, 0); irq = pdev->irq;} while(0) #include "tmscsim.h" -#ifndef __init -# define __init -#endif - -static UCHAR dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB ); -static void dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_DataIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_Command_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_Status_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_MsgOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_MsgIn_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_DataOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_DataInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_MsgOutPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_MsgInPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_Nop_0( PACB pACB, PSRB pSRB, PUCHAR psstatus); -static void dc390_Nop_1( PACB pACB, PSRB pSRB, PUCHAR psstatus); - -static void dc390_SetXferRate( PACB pACB, PDCB pDCB ); -static void dc390_Disconnect( PACB pACB ); -static void dc390_Reselect( PACB pACB ); -static void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB ); -static void dc390_DoingSRB_Done( PACB pACB, PSCSICMD cmd ); -static void dc390_ScsiRstDetect( PACB pACB ); -static void dc390_ResetSCSIBus( PACB pACB ); -static void __inline__ dc390_RequestSense( PACB pACB, PDCB pDCB, PSRB pSRB ); -static void __inline__ dc390_InvalidCmd( PACB pACB ); -static void __inline__ dc390_EnableMsgOut_Abort (PACB, PSRB); -static void dc390_remove_dev (PACB pACB, PDCB pDCB); +static u8 dc390_StartSCSI( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB ); +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_DoingSRB_Done( struct dc390_acb* pACB, struct scsi_cmnd * cmd); +static void dc390_ScsiRstDetect( struct dc390_acb* pACB ); +static void dc390_ResetSCSIBus( struct dc390_acb* pACB ); +static void __inline__ dc390_RequestSense( struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB ); +static void __inline__ dc390_InvalidCmd( struct dc390_acb* pACB ); +static void __inline__ dc390_EnableMsgOut_Abort (struct dc390_acb*, struct dc390_srb*); static irqreturn_t do_DC390_Interrupt( int, void *, struct pt_regs *); -static int dc390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, UCHAR index ); -static void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun); -static void dc390_updateDCB (PACB pACB, PDCB pDCB); +static int dc390_initAdapter(struct Scsi_Host *psh, unsigned long io_port, u8 Irq, u8 index ); +static void dc390_updateDCB (struct dc390_acb* pACB, struct dc390_dcb* pDCB); -static int DC390_release(struct Scsi_Host *host); -static int dc390_shutdown (struct Scsi_Host *host); +static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start, + off_t offset, int length, int inout); -static PACB dc390_pACB_start= NULL; -static PACB dc390_pACB_current = NULL; -static ULONG dc390_lastabortedpid = 0; -static UINT dc390_laststatus = 0; -static UCHAR dc390_adapterCnt = 0; +static struct dc390_acb* dc390_pACB_start= NULL; +static struct dc390_acb* dc390_pACB_current = NULL; +static unsigned long dc390_lastabortedpid = 0; +static u32 dc390_laststatus = 0; +static u8 dc390_adapterCnt = 0; /* Startup values, to be overriden on the commandline */ static int tmscsim[] = {-2, -2, -2, -2, -2, -2}; +static int tmscsim_paramnum = ARRAY_SIZE(tmscsim); -#if defined(MODULE) -MODULE_PARM(tmscsim, "1-6i"); +module_param_array(tmscsim, int, tmscsim_paramnum, 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"); -#endif -static PVOID dc390_phase0[]={ +static void *dc390_phase0[]={ dc390_DataOut_0, dc390_DataIn_0, dc390_Command_0, @@ -374,7 +331,7 @@ static PVOID dc390_phase0[]={ dc390_Nop_1 }; -static PVOID dc390_phase1[]={ +static void *dc390_phase1[]={ dc390_DataOutPhase, dc390_DataInPhase, dc390_CommandPhase, @@ -413,15 +370,15 @@ static char* dc390_p1_str[] = { #endif /* Devices erroneously pretending to be able to do TagQ */ -static UCHAR dc390_baddevname1[2][28] ={ +static u8 dc390_baddevname1[2][28] ={ "SEAGATE ST3390N 9546", "HP C3323-300 4269"}; #define BADDEVCNT 2 static char* dc390_adapname = "DC390"; -static UCHAR dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN]; -static UCHAR dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20}; -static UCHAR dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20}; +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 access to DC390 EEPROM @@ -430,51 +387,50 @@ static UCHAR dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20}; **********************************************************************/ -static void __init dc390_EnDisableCE( UCHAR mode, PDEVDECL, PUCHAR regval ) +static void __devinit dc390_EnDisableCE(u8 mode, struct pci_dev *pdev, u8 *regval) { - UCHAR bval; + u8 bval; bval = 0; if(mode == ENABLE_CE) *regval = 0xc0; else *regval = 0x80; - PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); + pci_write_config_byte(pdev, *regval, bval); if(mode == DISABLE_CE) - PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); + pci_write_config_byte(pdev, *regval, bval); udelay(160); } /* Override EEprom values with explicitly set values */ -static void __init dc390_EEprom_Override (UCHAR index) +static void __devinit dc390_EEprom_Override (u8 index) { - PUCHAR ptr; - UCHAR id; - ptr = (PUCHAR) dc390_eepromBuf[index]; + u8 *ptr = (u8 *) dc390_eepromBuf[index]; + u8 id; /* Adapter Settings */ if (tmscsim[0] != -2) - ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0]; /* Adapter ID */ + ptr[EE_ADAPT_SCSI_ID] = (u8)tmscsim[0]; /* Adapter ID */ if (tmscsim[3] != -2) - ptr[EE_MODE2] = (UCHAR)tmscsim[3]; + 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] = (UCHAR)tmscsim[4]; /* Tagged Cmds */ + 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] = (UCHAR)tmscsim[2]; /* EE_MODE1 */ + ptr[id<<2] = (u8)tmscsim[2]; /* EE_MODE1 */ if (tmscsim[1] != -2) - ptr[(id<<2) + 1] = (UCHAR)tmscsim[1]; /* EE_Speed */ + ptr[(id<<2) + 1] = (u8)tmscsim[1]; /* EE_Speed */ } } /* Handle "-1" case */ -static void __init dc390_check_for_safe_settings (void) +static void __devinit dc390_check_for_safe_settings (void) { if (tmscsim[0] == -1 || tmscsim[0] > 15) /* modules-2.0.0 passes -1 as string */ { @@ -497,7 +453,7 @@ static int __initdata tmscsim_def[] = {7, 0 /* 10MHz */, , 3 /* 16 Tags per LUN */, 1 /* s delay after Reset */ }; /* Copy defaults over set values where missing */ -static void __init dc390_fill_with_defaults (void) +static void __devinit dc390_fill_with_defaults (void) { int i; PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x %08x\n", tmscsim[0],\ @@ -514,6 +470,7 @@ static void __init dc390_fill_with_defaults (void) if (tmscsim[5] > 180) tmscsim[5] = 180; } +#ifndef MODULE /* Override defaults on cmdline: * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped) */ @@ -533,40 +490,40 @@ static int __init dc390_setup (char *str) /* dc390_checkparams (); */ return 1; } -#ifndef MODULE + __setup("tmscsim=", dc390_setup); #endif -static void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry ) +static void __devinit dc390_EEpromOutDI(struct pci_dev *pdev, u8 *regval, u8 Carry) { - UCHAR bval; + u8 bval; bval = 0; if(Carry) { bval = 0x40; *regval = 0x80; - PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); + pci_write_config_byte(pdev, *regval, bval); } udelay(160); bval |= 0x80; - PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); + pci_write_config_byte(pdev, *regval, bval); udelay(160); bval = 0; - PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); + pci_write_config_byte(pdev, *regval, bval); udelay(160); } -static UCHAR __init dc390_EEpromInDO( PDEVDECL ) +static u8 __devinit dc390_EEpromInDO(struct pci_dev *pdev) { - UCHAR bval; + u8 bval; - PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x80); + pci_write_config_byte(pdev, 0x80, 0x80); udelay(160); - PCI_WRITE_CONFIG_BYTE(PDEV, 0x80, 0x40); + pci_write_config_byte(pdev, 0x80, 0x40); udelay(160); - PCI_READ_CONFIG_BYTE(PDEV, 0x00, &bval); + pci_read_config_byte(pdev, 0x00, &bval); if(bval == 0x22) return(1); else @@ -574,68 +531,68 @@ static UCHAR __init dc390_EEpromInDO( PDEVDECL ) } -static USHORT __init dc390_EEpromGetData1( PDEVDECL ) +static u16 __devinit dc390_EEpromGetData1(struct pci_dev *pdev) { - UCHAR i; - UCHAR carryFlag; - USHORT wval; + u8 i; + u8 carryFlag; + u16 wval; wval = 0; for(i=0; i<16; i++) { wval <<= 1; - carryFlag = dc390_EEpromInDO(PDEV); + carryFlag = dc390_EEpromInDO(pdev); wval |= carryFlag; } return(wval); } -static void __init dc390_Prepare( PDEVDECL, PUCHAR regval, UCHAR EEpromCmd ) +static void __devinit dc390_Prepare(struct pci_dev *pdev, u8 *regval, u8 EEpromCmd) { - UCHAR i,j; - UCHAR carryFlag; + u8 i,j; + u8 carryFlag; carryFlag = 1; j = 0x80; for(i=0; i<9; i++) { - dc390_EEpromOutDI(PDEV,regval,carryFlag); + dc390_EEpromOutDI(pdev, regval, carryFlag); carryFlag = (EEpromCmd & j) ? 1 : 0; j >>= 1; } } -static void __init dc390_ReadEEprom( PDEVDECL, PUSHORT ptr) +static void __devinit dc390_ReadEEprom(struct pci_dev *pdev, u16 *ptr) { - UCHAR regval,cmd; - UCHAR i; + u8 regval,cmd; + u8 i; cmd = EEPROM_READ; for(i=0; i<0x40; i++) { - dc390_EnDisableCE(ENABLE_CE, PDEV, ®val); - dc390_Prepare(PDEV, ®val, cmd++); - *ptr++ = dc390_EEpromGetData1(PDEV); - dc390_EnDisableCE(DISABLE_CE, PDEV, ®val); + dc390_EnDisableCE(ENABLE_CE, pdev, ®val); + dc390_Prepare(pdev, ®val, cmd++); + *ptr++ = dc390_EEpromGetData1(pdev); + dc390_EnDisableCE(DISABLE_CE, pdev, ®val); } } -static void __init dc390_interpret_delay (UCHAR index) +static void __devinit dc390_interpret_delay (u8 index) { char interpd [] = {1,3,5,10,16,30,60,120}; dc390_eepromBuf[index][EE_DELAY] = interpd [dc390_eepromBuf[index][EE_DELAY]]; } -static UCHAR __init dc390_CheckEEpromCheckSum( PDEVDECL, UCHAR index ) +static u8 __devinit dc390_CheckEEpromCheckSum(struct pci_dev *pdev, u8 index) { - UCHAR i; + u8 i; char EEbuf[128]; - USHORT wval, *ptr = (PUSHORT)EEbuf; + u16 wval, *ptr = (u16 *)EEbuf; - dc390_ReadEEprom( PDEV, ptr ); + dc390_ReadEEprom(pdev, ptr); memcpy (dc390_eepromBuf[index], EEbuf, EE_ADAPT_SCSI_ID); memcpy (&dc390_eepromBuf[index][EE_ADAPT_SCSI_ID], &EEbuf[REAL_EE_ADAPT_SCSI_ID], EE_LEN - EE_ADAPT_SCSI_ID); @@ -653,9 +610,9 @@ static UCHAR __init dc390_CheckEEpromCheckSum( PDEVDECL, UCHAR index ) * (DCBs, SRBs, Queueing) * **********************************************************************/ -static PDCB __inline__ dc390_findDCB ( PACB pACB, UCHAR id, UCHAR lun) +static struct dc390_dcb __inline__ *dc390_findDCB ( struct dc390_acb* pACB, u8 id, u8 lun) { - PDCB pDCB = pACB->pLinkDCB; if (!pDCB) return 0; + struct dc390_dcb* pDCB = pACB->pLinkDCB; if (!pDCB) return 0; while (pDCB->TargetID != id || pDCB->TargetLUN != lun) { pDCB = pDCB->pNextDCB; @@ -685,26 +642,10 @@ static PDCB __inline__ dc390_findDCB ( PACB pACB, UCHAR id, UCHAR lun) * Lists are managed using two pointers and eventually a counter */ - -#if 0 -/* Look for a SCSI cmd in a SRB queue */ -static PSRB dc390_find_cmd_in_SRBq (PSCSICMD cmd, PSRB queue) -{ - PSRB q = queue; - while (q) - { - if (q->pcmd == cmd) return q; - q = q->pNextSRB; - if (q == queue) return 0; - } - return q; -} -#endif - /* Return next free SRB */ -static __inline__ PSRB dc390_Free_get ( PACB pACB ) +static __inline__ struct dc390_srb* dc390_Free_get ( struct dc390_acb* pACB ) { - PSRB pSRB; + struct dc390_srb* pSRB; pSRB = pACB->pFreeSRB; DEBUG0(printk ("DC390: Get Free SRB %p\n", pSRB)); @@ -718,7 +659,7 @@ static __inline__ PSRB dc390_Free_get ( PACB pACB ) } /* Insert SRB oin top of free list */ -static __inline__ void dc390_Free_insert (PACB pACB, PSRB pSRB) +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; @@ -727,7 +668,7 @@ static __inline__ void dc390_Free_insert (PACB pACB, PSRB pSRB) /* Inserts a SRB to the top of the Waiting list */ -static __inline__ void dc390_Waiting_insert ( PDCB pDCB, PSRB pSRB ) +static __inline__ void dc390_Waiting_insert ( struct dc390_dcb* pDCB, struct dc390_srb* pSRB ) { DEBUG0(printk ("DC390: Insert pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid)); pSRB->pNextSRB = pDCB->pWaitingSRB; @@ -739,7 +680,7 @@ static __inline__ void dc390_Waiting_insert ( PDCB pDCB, PSRB pSRB ) /* Queue SRB to waiting list */ -static __inline__ void dc390_Waiting_append ( PDCB pDCB, PSRB pSRB) +static __inline__ void dc390_Waiting_append ( struct dc390_dcb* pDCB, struct dc390_srb* pSRB) { DEBUG0(printk ("DC390: Append pSRB %p cmd %li to Waiting\n", pSRB, pSRB->pcmd->pid)); if( pDCB->pWaitingSRB ) @@ -753,7 +694,7 @@ static __inline__ void dc390_Waiting_append ( PDCB pDCB, PSRB pSRB) pDCB->pDCBACB->CmdInQ++; } -static __inline__ void dc390_Going_append (PDCB pDCB, PSRB 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)); @@ -768,14 +709,14 @@ static __inline__ void dc390_Going_append (PDCB pDCB, PSRB pSRB) pSRB->pNextSRB = NULL; } -static __inline__ void dc390_Going_remove (PDCB pDCB, PSRB pSRB) +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 { - PSRB psrb = pDCB->pGoingSRB; + struct dc390_srb* psrb = pDCB->pGoingSRB; while (psrb && psrb->pNextSRB != pSRB) psrb = psrb->pNextSRB; if (!psrb) @@ -788,7 +729,7 @@ static __inline__ void dc390_Going_remove (PDCB pDCB, PSRB pSRB) } /* Moves SRB from Going list to the top of Waiting list */ -static void dc390_Going_to_Waiting ( PDCB pDCB, PSRB pSRB ) +static void dc390_Going_to_Waiting ( struct dc390_dcb* pDCB, struct dc390_srb* pSRB ) { DEBUG0(printk(KERN_INFO "DC390: Going_to_Waiting (SRB %p) pid = %li\n", pSRB, pSRB->pcmd->pid)); /* Remove SRB from Going */ @@ -799,7 +740,7 @@ static void dc390_Going_to_Waiting ( PDCB pDCB, PSRB pSRB ) } /* Moves first SRB from Waiting list to Going list */ -static __inline__ void dc390_Waiting_to_Going ( PDCB pDCB, PSRB pSRB ) +static __inline__ void dc390_Waiting_to_Going ( struct dc390_dcb* pDCB, struct dc390_srb* pSRB ) { /* Remove from waiting list */ DEBUG0(printk("DC390: Remove SRB %p from head of Waiting\n", pSRB)); @@ -811,7 +752,7 @@ static __inline__ void dc390_Waiting_to_Going ( PDCB pDCB, PSRB pSRB ) static void DC390_waiting_timed_out (unsigned long ptr); /* Sets the timer to wake us up */ -static void dc390_waiting_timer (PACB pACB, unsigned long to) +static void dc390_waiting_timer (struct dc390_acb* pACB, unsigned long to) { if (timer_pending (&pACB->Waiting_Timer)) return; init_timer (&pACB->Waiting_Timer); @@ -826,10 +767,10 @@ static void dc390_waiting_timer (PACB pACB, unsigned long to) /* Send the next command from the waiting list to the bus */ -static void dc390_Waiting_process ( PACB pACB ) +static void dc390_Waiting_process ( struct dc390_acb* pACB ) { - PDCB ptr, ptr1; - PSRB pSRB; + struct dc390_dcb *ptr, *ptr1; + struct dc390_srb *pSRB; if( (pACB->pActiveDCB) || (pACB->ACBFlag & (RESET_DETECT+RESET_DONE+RESET_DEV) ) ) return; @@ -864,24 +805,24 @@ static void dc390_Waiting_process ( PACB pACB ) /* Wake up waiting queue */ static void DC390_waiting_timed_out (unsigned long ptr) { - PACB pACB = (PACB)ptr; - DC390_IFLAGS; + struct dc390_acb* pACB = (struct dc390_acb*)ptr; + unsigned long iflags; DEBUG0(printk ("DC390: Debug: Waiting queue woken up by timer!\n")); - DC390_LOCK_IO(pACB->pScsiHost); + spin_lock_irqsave(pACB->pScsiHost->host_lock, iflags); dc390_Waiting_process (pACB); - DC390_UNLOCK_IO(pACB->pScsiHost); + spin_unlock_irqrestore(pACB->pScsiHost->host_lock, iflags); } /*********************************************************************** - * Function: static void dc390_SendSRB (PACB pACB, PSRB pSRB) + * Function: static void dc390_SendSRB (struct dc390_acb* pACB, struct dc390_srb* pSRB) * * Purpose: Send SCSI Request Block (pSRB) to adapter (pACB) * ***********************************************************************/ -static void dc390_SendSRB( PACB pACB, PSRB pSRB ) +static void dc390_SendSRB( struct dc390_acb* pACB, struct dc390_srb* pSRB ) { - PDCB pDCB; + struct dc390_dcb* pDCB; pDCB = pSRB->pSRBDCB; if( (pDCB->MaxCommand <= pDCB->GoingSRBCnt) || (pACB->pActiveDCB) || @@ -913,85 +854,91 @@ static void dc390_SendSRB( PACB pACB, PSRB pSRB ) } } +static struct scatterlist* dc390_sg_build_single(struct scatterlist *sg, void *addr, unsigned int length) +{ + memset(sg, 0, sizeof(struct scatterlist)); + sg->page = virt_to_page(addr); + sg->length = length; + sg->offset = (unsigned long)addr & ~PAGE_MASK; + return sg; +} /* Create pci mapping */ -static int dc390_pci_map (PSRB pSRB) +static int dc390_pci_map (struct dc390_srb* pSRB) { int error = 0; - Scsi_Cmnd *pcmd = pSRB->pcmd; + 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) { - sg_dma_address(&pSRB->Segmentx) = cmdp->saved_dma_handle = - pci_map_page(pdev, virt_to_page(pcmd->sense_buffer), - (unsigned long)pcmd->sense_buffer & ~PAGE_MASK, sizeof(pcmd->sense_buffer), - DMA_FROM_DEVICE); - sg_dma_len(&pSRB->Segmentx) = sizeof(pcmd->sense_buffer); - pSRB->SGcount = 1; - pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + pSRB->pSegmentList = dc390_sg_build_single(&pSRB->Segmentx, pcmd->sense_buffer, sizeof(pcmd->sense_buffer)); + 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", __FUNCTION__, pcmd->sense_buffer, cmdp->saved_dma_handle)); - /* Make SG list */ + /* Map SG list */ } else if (pcmd->use_sg) { - pSRB->pSegmentList = (PSGL) pcmd->request_buffer; - pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, - pcmd->use_sg, - scsi_to_pci_dma_dir(pcmd->sc_data_direction)); + pSRB->pSegmentList = (struct scatterlist *) pcmd->request_buffer; + pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, pcmd->use_sg, + pcmd->sc_data_direction); /* TODO: error handling */ if (!pSRB->SGcount) error = 1; - DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n", __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg)); + DEBUG1(printk("%s(): Mapped SG %p with %d (%d) elements\n",\ + __FUNCTION__, pcmd->request_buffer, pSRB->SGcount, pcmd->use_sg)); /* Map single segment */ } else if (pcmd->request_buffer && pcmd->request_bufflen) { - sg_dma_address(&pSRB->Segmentx) = cmdp->saved_dma_handle = - pci_map_page(pdev, virt_to_page(pcmd->request_buffer), - (unsigned long)pcmd->request_buffer & ~PAGE_MASK, - pcmd->request_bufflen, scsi_to_pci_dma_dir(pcmd->sc_data_direction)); + pSRB->pSegmentList = dc390_sg_build_single(&pSRB->Segmentx, pcmd->request_buffer, pcmd->request_bufflen); + pSRB->SGcount = pci_map_sg(pdev, pSRB->pSegmentList, 1, + pcmd->sc_data_direction); + cmdp->saved_dma_handle = sg_dma_address(pSRB->pSegmentList); + /* TODO: error handling */ - sg_dma_len(&pSRB->Segmentx) = pcmd->request_bufflen; - pSRB->SGcount = 1; - pSRB->pSegmentList = (PSGL) &pSRB->Segmentx; + if (pSRB->SGcount != 1) + error = 1; DEBUG1(printk("%s(): Mapped request buffer %p at %x\n", __FUNCTION__, pcmd->request_buffer, cmdp->saved_dma_handle)); /* No mapping !? */ } else pSRB->SGcount = 0; + return error; } /* Remove pci mapping */ -static void dc390_pci_unmap (PSRB pSRB) +static void dc390_pci_unmap (struct dc390_srb* pSRB) { - Scsi_Cmnd* pcmd = pSRB->pcmd; + 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)); + DEBUG1(dc390_cmd_scp_t* cmdp = ((dc390_cmd_scp_t*)(&pcmd->SCp))); if (pSRB->SRBFlag) { - pci_unmap_page(pdev, cmdp->saved_dma_handle, - sizeof(pcmd->sense_buffer), DMA_FROM_DEVICE); + pci_unmap_sg(pdev, &pSRB->Segmentx, 1, DMA_FROM_DEVICE); DEBUG1(printk("%s(): Unmapped sense buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle)); } else if (pcmd->use_sg) { - pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg, - scsi_to_pci_dma_dir(pcmd->sc_data_direction)); + pci_unmap_sg(pdev, pcmd->request_buffer, pcmd->use_sg, pcmd->sc_data_direction); DEBUG1(printk("%s(): Unmapped SG at %p with %d elements\n", __FUNCTION__, pcmd->request_buffer, pcmd->use_sg)); } else if (pcmd->request_buffer && pcmd->request_bufflen) { - pci_unmap_page(pdev, - cmdp->saved_dma_handle, - pcmd->request_bufflen, - scsi_to_pci_dma_dir(pcmd->sc_data_direction)); + pci_unmap_sg(pdev, &pSRB->Segmentx, 1, pcmd->sc_data_direction); DEBUG1(printk("%s(): Unmapped request buffer at %x\n", __FUNCTION__, cmdp->saved_dma_handle)); } } /*********************************************************************** - * Function: static void dc390_BuildSRB (Scsi_Cmd *pcmd, PDCB pDCB, - * PSRB pSRB) + * Function: static void dc390_BuildSRB (Scsi_Cmd *pcmd, struct dc390_dcb* pDCB, + * struct dc390_srb* pSRB) * * Purpose: Prepare SRB for being sent to Device DCB w/ command *pcmd * ***********************************************************************/ -static void dc390_BuildSRB (Scsi_Cmnd* pcmd, PDCB pDCB, PSRB pSRB) +static void dc390_BuildSRB (struct scsi_cmnd *pcmd, struct dc390_dcb* pDCB, struct dc390_srb* pSRB) { pSRB->pSRBDCB = pDCB; pSRB->pcmd = pcmd; @@ -1019,8 +966,8 @@ static void dc390_BuildSRB (Scsi_Cmnd* pcmd, PDCB pDCB, PSRB pSRB) } /*********************************************************************** - * Function : static int DC390_queue_command (Scsi_Cmnd *cmd, - * void (*done)(Scsi_Cmnd *)) + * Function : static int DC390_queue_command (struct scsi_cmnd *cmd, + * void (*done)(struct scsi_cmnd *)) * * Purpose : enqueues a SCSI command * @@ -1031,17 +978,18 @@ static void dc390_BuildSRB (Scsi_Cmnd* pcmd, PDCB pDCB, PSRB pSRB) * 2.0.x: always return 0 * 2.1.x: old model: (use_new_eh_code == 0): like 2.0.x * TO BE DONE: - * new model: return 0 if successful - * return 1 if command cannot be queued (queue full) + * new model: return 0 if successful, or must not be re-queued + * return 1 if command cannot be queued (queue full) * command will be inserted in midlevel queue then ... * ***********************************************************************/ -static int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) +static int DC390_queue_command(struct scsi_cmnd *cmd, + void (* done)(struct scsi_cmnd *)) { - PDCB pDCB; - PSRB pSRB; - PACB pACB = (PACB) cmd->device->host->hostdata; + struct dc390_dcb* pDCB = (struct dc390_dcb*) cmd->device->hostdata; + struct dc390_srb* pSRB; + struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata; DEBUG0(/* if(pACB->scan_devices) */ \ printk(KERN_INFO "DC390: Queue Cmd=%02x,Tgt=%d,LUN=%d (pid=%li), buffer=%p\n",\ @@ -1050,42 +998,19 @@ static int DC390_queue_command (Scsi_Cmnd *cmd, void (* done)(Scsi_Cmnd *)) /* TODO: Change the policy: Always accept TEST_UNIT_READY or INQUIRY * commands and alloc a DCB for the device if not yet there. DCB will * be removed in dc390_SRBdone if SEL_TIMEOUT */ - - if( (pACB->scan_devices == END_SCAN) && (cmd->cmnd[0] != INQUIRY) ) - pACB->scan_devices = 0; - - else if( (pACB->scan_devices) && (cmd->cmnd[0] == READ_6) ) - pACB->scan_devices = 0; - - if( (pACB->scan_devices || cmd->cmnd[0] == TEST_UNIT_READY || cmd->cmnd[0] == INQUIRY) && - !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun)) ) - { - pACB->scan_devices = 1; - - dc390_initDCB( pACB, &pDCB, cmd->device->id, cmd->device->lun ); - if (!pDCB) - { - printk (KERN_ERR "DC390: kmalloc for DCB failed, target %02x lun %02x\n", - cmd->device->id, cmd->device->lun); - goto fail; - } - - } - else if( !(pACB->scan_devices) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun)) ) - { + if (!(pACB->scan_devices) && !(pACB->DCBmap[cmd->device->id] & (1 << cmd->device->lun))) { printk(KERN_INFO "DC390: Ignore target %02x lun %02x\n", cmd->device->id, cmd->device->lun); goto fail; } - else - { - pDCB = dc390_findDCB (pACB, cmd->device->id, cmd->device->lun); - if (!pDCB) - { /* should never happen */ - printk (KERN_ERR "DC390: no DCB failed, target %02x lun %02x\n", - cmd->device->id, cmd->device->lun); - goto fail; - } + + /* Should it be: BUG_ON(!pDCB); ? */ + + if (!pDCB) + { /* should never happen */ + printk (KERN_ERR "DC390: no DCB found, target %02x lun %02x\n", + cmd->device->id, cmd->device->lun); + goto fail; } pACB->Cmds++; @@ -1208,7 +1133,7 @@ static int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev sector_t capacity, int geom[]) { int heads, sectors, cylinders; - PACB pACB = (PACB) sdev->host->hostdata; + struct dc390_acb* pACB = (struct dc390_acb*) sdev->host->hostdata; int ret_code = -1; int size = capacity; unsigned char *buf; @@ -1248,9 +1173,11 @@ static int DC390_bios_param (struct scsi_device *sdev, struct block_device *bdev } #endif -static void dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB) +static void dc390_dumpinfo (struct dc390_acb* pACB, struct dc390_dcb* pDCB, struct dc390_srb* pSRB) { - USHORT pstat; PDEVDECL1; + struct pci_dev *pdev; + u16 pstat; + if (!pDCB) pDCB = pACB->pActiveDCB; if (!pSRB && pDCB) pSRB = pDCB->pActiveSRB; @@ -1284,14 +1211,16 @@ static void dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB) DC390_read32(DMA_Wk_ByteCntr), DC390_read32(DMA_Wk_AddrCntr), DC390_read8(DMA_Status), DC390_read32(DMA_ScsiBusCtrl)); DC390_write32 (DMA_ScsiBusCtrl, EN_INT_ON_PCI_ABORT); - PDEVSET1; PCI_READ_CONFIG_WORD(PDEV, PCI_STATUS, &pstat); + + 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 linux/Documentation/scsi/tmscsim.txt\n"); + printk ("DC390: In case of driver trouble read Documentation/scsi/tmscsim.txt\n"); } /*********************************************************************** - * Function : int DC390_abort (Scsi_Cmnd *cmd) + * Function : int DC390_abort (struct scsi_cmnd *cmd) * * Purpose : Abort an errant SCSI command * @@ -1302,19 +1231,18 @@ static void dc390_dumpinfo (PACB pACB, PDCB pDCB, PSRB pSRB) * Status: Buggy ! ***********************************************************************/ -static int DC390_abort (Scsi_Cmnd *cmd) +static int DC390_abort (struct scsi_cmnd *cmd) { - PDCB pDCB; - PSRB pSRB, psrb; - UINT count, i; + struct dc390_dcb *pDCB = (struct dc390_dcb*) cmd->device->hostdata; + struct dc390_srb *pSRB, *psrb; + u32 count, i; int status; - //ULONG sbac; - PACB pACB = (PACB) cmd->device->host->hostdata; + //unsigned long sbac; + struct dc390_acb *pACB = (struct dc390_acb*) cmd->device->host->hostdata; printk ("DC390: Abort command (pid %li, Device %02i-%02i)\n", cmd->pid, cmd->device->id, cmd->device->lun); - pDCB = dc390_findDCB (pACB, cmd->device->id, cmd->device->lun); if( !pDCB ) goto NOT_RUN; /* Added 98/07/02 KG */ @@ -1434,9 +1362,9 @@ ABO_X: } -static void dc390_ResetDevParam( PACB pACB ) +static void dc390_ResetDevParam( struct dc390_acb* pACB ) { - PDCB pDCB, pdcb; + struct dc390_dcb *pDCB, *pdcb; pDCB = pACB->pLinkDCB; if (! pDCB) return; @@ -1459,11 +1387,11 @@ static void dc390_ResetDevParam( PACB pACB ) #if 0 /* Moves all SRBs from Going to Waiting for all DCBs */ -static void dc390_RecoverSRB( PACB pACB ) +static void dc390_RecoverSRB( struct dc390_acb* pACB ) { - PDCB pDCB, pdcb; - PSRB psrb, psrb2; - UINT cnt, i; + struct dc390_dcb *pDCB, *pdcb; + struct dc390_srb *psrb, *psrb2; + u32 cnt, i; pDCB = pACB->pLinkDCB; if( !pDCB ) return; @@ -1498,7 +1426,7 @@ static void dc390_RecoverSRB( PACB pACB ) #endif /*********************************************************************** - * Function : int DC390_reset (Scsi_Cmnd *cmd, ...) + * Function : int DC390_reset (struct scsi_cmnd *cmd, ...) * * Purpose : perform a hard reset on the SCSI bus * @@ -1508,10 +1436,10 @@ static void dc390_RecoverSRB( PACB pACB ) * Returns : 0 on success. ***********************************************************************/ -static int DC390_reset (Scsi_Cmnd *cmd) +static int DC390_reset (struct scsi_cmnd *cmd) { - UCHAR bval; - PACB pACB = (PACB) cmd->device->host->hostdata; + u8 bval; + struct dc390_acb* pACB = (struct dc390_acb*) cmd->device->host->hostdata; printk(KERN_INFO "DC390: RESET ... "); @@ -1548,101 +1476,13 @@ static int DC390_reset (Scsi_Cmnd *cmd) #include "scsiiom.c" - -/*********************************************************************** - * Function : static void dc390_initDCB() - * - * Purpose : initialize the internal structures for a DCB (to be malloced) - * - * Inputs : SCSI id and lun - ***********************************************************************/ - -static void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun ) -{ - PEEprom prom; - UCHAR index; - PDCB pDCB, pDCB2; - - pDCB = kmalloc (sizeof(DC390_DCB), GFP_ATOMIC); - DCBDEBUG(printk (KERN_INFO "DC390: alloc mem for DCB (ID %i, LUN %i): %p\n", \ - id, lun, pDCB)); - - *ppDCB = pDCB; - if (!pDCB) return; - pDCB2 = 0; - if( pACB->DCBCnt == 0 ) - { - pACB->pLinkDCB = pDCB; - pACB->pDCBRunRobin = pDCB; - } - else - { - pACB->pLastDCB->pNextDCB = pDCB; - } - - pACB->DCBCnt++; - - pDCB->pNextDCB = pACB->pLinkDCB; - pACB->pLastDCB = pDCB; - - pDCB->pDCBACB = pACB; - pDCB->TargetID = id; - pDCB->TargetLUN = lun; - pDCB->pWaitingSRB = NULL; - pDCB->pGoingSRB = NULL; - pDCB->GoingSRBCnt = 0; - pDCB->WaitSRBCnt = 0; - pDCB->pActiveSRB = NULL; - pDCB->TagMask = 0; - pDCB->MaxCommand = 1; - index = pACB->AdapterIndex; - pDCB->DCBFlag = 0; - - /* Is there a corresp. LUN==0 device ? */ - if (lun != 0) - pDCB2 = dc390_findDCB (pACB, id, 0); - prom = (PEEprom) &dc390_eepromBuf[index][id << 2]; - /* Some values are for all LUNs: Copy them */ - /* In a clean way: We would have an own structure for a SCSI-ID */ - if (pDCB2) - { - pDCB->DevMode = pDCB2->DevMode; - pDCB->SyncMode = pDCB2->SyncMode; - pDCB->SyncPeriod = pDCB2->SyncPeriod; - pDCB->SyncOffset = pDCB2->SyncOffset; - pDCB->NegoPeriod = pDCB2->NegoPeriod; - - pDCB->CtrlR3 = pDCB2->CtrlR3; - pDCB->CtrlR4 = pDCB2->CtrlR4; - pDCB->Inquiry7 = pDCB2->Inquiry7; - } - else - { - pDCB->DevMode = prom->EE_MODE1; - pDCB->SyncMode = 0; - pDCB->SyncPeriod = 0; - pDCB->SyncOffset = 0; - pDCB->NegoPeriod = (dc390_clock_period1[prom->EE_SPEED] * 25) >> 2; - - pDCB->CtrlR3 = FAST_CLK; - - pDCB->CtrlR4 = pACB->glitch_cfg | CTRL4_RESERVED; - if( dc390_eepromBuf[index][EE_MODE2] & ACTIVE_NEGATION) - pDCB->CtrlR4 |= NEGATE_REQACKDATA | NEGATE_REQACK; - pDCB->Inquiry7 = 0; - } - - pACB->DCBmap[id] |= (1 << lun); - dc390_updateDCB(pACB, pDCB); -} - /*********************************************************************** * Function : static void dc390_updateDCB() * * Purpose : Set the configuration dependent DCB parameters ***********************************************************************/ -static void dc390_updateDCB (PACB pACB, PDCB pDCB) +static void dc390_updateDCB (struct dc390_acb* pACB, struct dc390_dcb* pDCB) { pDCB->SyncMode &= EN_TAG_QUEUEING | SYNC_NEGO_DONE /*| EN_ATN_STOP*/; if (pDCB->DevMode & TAG_QUEUEING_) { @@ -1674,15 +1514,15 @@ static void dc390_updateDCB (PACB pACB, PDCB pDCB) * Inputs : psrb - pointer to this scsi request block structure ***********************************************************************/ -static void __inline__ dc390_initSRB( PSRB psrb ) +static void __inline__ dc390_initSRB( struct dc390_srb* psrb ) { /* psrb->PhysSRB = virt_to_phys( psrb ); */ } -static void dc390_linkSRB( PACB pACB ) +static void dc390_linkSRB( struct dc390_acb* pACB ) { - UINT count, i; + u32 count, i; count = pACB->SRBCount; for( i=0; ican_queue = MAX_CMD_QUEUE; psh->cmd_per_lun = MAX_CMD_PER_LUN; @@ -1721,10 +1561,10 @@ static void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index psh->dma_channel = -1; psh->last_reset = jiffies; - pACB = (PACB) psh->hostdata; + pACB = (struct dc390_acb*) psh->hostdata; pACB->pScsiHost = psh; - pACB->IOPortBase = (USHORT) io_port; + pACB->IOPortBase = (u16) io_port; pACB->IRQLevel = Irq; DEBUG0(printk (KERN_INFO "DC390: Adapter index %i, ID %i, IO 0x%08x, IRQ 0x%02x\n", \ @@ -1745,8 +1585,6 @@ static void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index pACB->SRBCount = MAX_SRB_CNT; pACB->AdapterIndex = index; pACB->status = 0; - psh->this_id = dc390_eepromBuf[index][EE_ADAPT_SCSI_ID]; - pACB->DeviceCnt = 0; pACB->DCBCnt = 0; pACB->TagMaxNum = 2 << dc390_eepromBuf[index][EE_TAG_CMD_NUM]; pACB->ACBFlag = 0; @@ -1778,13 +1616,13 @@ static void __init dc390_initACB (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index * Outputs: 0 on success, -1 on error ***********************************************************************/ -static int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR index) +static int __devinit dc390_initAdapter (struct Scsi_Host *psh, unsigned long io_port, u8 Irq, u8 index) { - PACB pACB, pACB2; - UCHAR dstate; + struct dc390_acb *pACB, *pACB2; + u8 dstate; int i; - pACB = (PACB) psh->hostdata; + pACB = (struct dc390_acb*) psh->hostdata; if (request_region (io_port, psh->n_io_port, "tmscsim") == NULL) { printk(KERN_ERR "DC390: register IO ports error!\n"); @@ -1849,120 +1687,256 @@ static int __init dc390_initAdapter (PSH psh, ULONG io_port, UCHAR Irq, UCHAR in } -/*********************************************************************** - * Function : static int DC390_init (struct Scsi_Host *host, ...) - * - * Purpose : initialize the internal structures for a given SCSI host - * - * Inputs : host - pointer to this host adapter's structure - * io_port - IO ports mapped to this adapter - * Irq - IRQ assigned to this adpater - * struct pci_dev - PCI access handle - * index - Adapter index - * - * Outputs: 0 on success, -1 on error - * - * Note: written in capitals, because the locking is only done here, - * not in DC390_detect, called from outside - ***********************************************************************/ +static void __devinit dc390_set_pci_cfg (struct pci_dev *pdev) +{ + u16 cmd; + + pci_read_config_word(pdev, PCI_COMMAND, &cmd); + cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO; + pci_write_config_word(pdev, PCI_COMMAND, cmd); + pci_write_config_word(pdev, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)); +} -static int __init DC390_init (PSHT psht, ULONG io_port, UCHAR Irq, struct pci_dev *pdev, UCHAR index) +/** + * 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) { - PSH psh; - PACB pACB; + struct dc390_acb *pACB = (struct dc390_acb*) scsi_device->host->hostdata; + struct dc390_dcb *pDCB, *pDCB2 = 0; + uint id = scsi_device->id; + uint lun = scsi_device->lun; - if (dc390_CheckEEpromCheckSum (PDEV, index)) - { - int speed; - dc390_adapname = "AM53C974"; - printk (KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n"); - dc390_check_for_safe_settings (); - dc390_fill_with_defaults (); - dc390_EEprom_Override (index); - 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, - (UCHAR)tmscsim[2], (UCHAR)tmscsim[3], tmscsim[4], 2 << (tmscsim[4]), tmscsim[5]); - } - else - { - dc390_check_for_safe_settings (); - dc390_EEprom_Override (index); - } + pDCB = kmalloc(sizeof(struct dc390_dcb), GFP_KERNEL); + if (!pDCB) + return -ENOMEM; + memset(pDCB, 0, sizeof(struct dc390_dcb)); + + if (!pACB->DCBCnt++) { + pACB->pLinkDCB = pDCB; + pACB->pDCBRunRobin = pDCB; + } else { + pACB->pLastDCB->pNextDCB = pDCB; + } - psh = scsi_register( psht, sizeof(DC390_ACB) ); - if( !psh ) return( -1 ); - - scsi_set_device(psh, &pdev->dev); - pACB = (PACB) psh->hostdata; + pDCB->pNextDCB = pACB->pLinkDCB; + pACB->pLastDCB = pDCB; - DEBUG0(printk(KERN_INFO "DC390: pSH = %8x, Index %02i\n", (UINT) psh, index)); + pDCB->pDCBACB = pACB; + pDCB->TargetID = id; + pDCB->TargetLUN = lun; + pDCB->MaxCommand = 1; - dc390_initACB( psh, io_port, Irq, index ); - - PDEVSET; + /* + * 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; + pDCB->SyncPeriod = pDCB2->SyncPeriod; + pDCB->SyncOffset = pDCB2->SyncOffset; + pDCB->NegoPeriod = pDCB2->NegoPeriod; + + pDCB->CtrlR3 = pDCB2->CtrlR3; + pDCB->CtrlR4 = pDCB2->CtrlR4; + pDCB->Inquiry7 = pDCB2->Inquiry7; + } 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( !dc390_initAdapter( psh, io_port, Irq, index ) ) - { - DEBUG0(printk("DC390: pACB = %8x, pDCBmap = %8x, pSRB_array = %8x\n",\ - (UINT) pACB, (UINT) pACB->DCBmap, (UINT) pACB->SRB_array)); - DEBUG0(printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n",\ - sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) )); - return (0); - } - else - { - scsi_unregister( psh ); - return( -1 ); - } + pACB->DCBmap[id] |= (1 << lun); + dc390_updateDCB(pACB, pDCB); + + pACB->scan_devices = 1; + scsi_device->hostdata = pDCB; + return 0; } -static void __init dc390_set_pci_cfg (PDEVDECL) +/** + * 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) { - USHORT cmd; - PCI_READ_CONFIG_WORD (PDEV, PCI_COMMAND, &cmd); - cmd |= PCI_COMMAND_SERR | PCI_COMMAND_PARITY | PCI_COMMAND_IO; - PCI_WRITE_CONFIG_WORD (PDEV, PCI_COMMAND, cmd); - PCI_WRITE_CONFIG_WORD (PDEV, PCI_STATUS, (PCI_STATUS_SIG_SYSTEM_ERROR | PCI_STATUS_DETECTED_PARITY)); + 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); + + pACB->DCBmap[pDCB->TargetID] &= ~(1 << pDCB->TargetLUN); + + 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--; } -int __init DC390_detect (Scsi_Host_Template *psht) +static int dc390_slave_configure(struct scsi_device *scsi_device) { - struct pci_dev *pdev = NULL; - UCHAR irq; - ULONG io_port; + struct dc390_acb* pACB = (struct dc390_acb*) scsi_device->host->hostdata; + pACB->scan_devices = 0; + return 0; +} - dc390_pACB_start = NULL; +static struct scsi_host_template driver_template = { + .module = THIS_MODULE, + .proc_name = "tmscsim", + .proc_info = DC390_proc_info, + .name = DC390_BANNER " V" DC390_VERSION, + .slave_alloc = dc390_slave_alloc, + .slave_configure = dc390_slave_configure, + .slave_destroy = dc390_slave_destroy, + .queuecommand = DC390_queue_command, + .eh_abort_handler = DC390_abort, + .eh_bus_reset_handler = DC390_reset, + .bios_param = DC390_bios_param, + .can_queue = 42, + .this_id = 7, + .sg_tablesize = SG_ALL, + .cmd_per_lun = 16, + .use_clustering = DISABLE_CLUSTERING, +}; - if ( PCI_PRESENT ) - while ((pdev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974, pdev))) - { - if (pci_enable_device (pdev)) - continue; +static int __devinit dc390_init_one(struct pci_dev *dev, + const struct pci_device_id *id) +{ + struct Scsi_Host *scsi_host; + unsigned long io_port; + u8 irq; + struct dc390_acb* pACB; + int ret = -ENOMEM; + + if (pci_enable_device(dev)) + return -ENODEV; + + io_port = pci_resource_start(dev, 0); + irq = dev->irq; + + /* allocate scsi host information (includes out adapter) */ + scsi_host = scsi_host_alloc(&driver_template, sizeof(struct dc390_acb)); + if (!scsi_host) + goto nomem; + + pACB = (struct dc390_acb*) scsi_host->hostdata; + + if (dc390_CheckEEpromCheckSum (dev, dc390_adapterCnt)) { + int speed; + dc390_adapname = "AM53C974"; + printk(KERN_INFO "DC390_init: No EEPROM found! Trying default settings ...\n"); + dc390_check_for_safe_settings(); + dc390_fill_with_defaults(); + dc390_EEprom_Override(dc390_adapterCnt); + 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]); + } else { + dc390_check_for_safe_settings(); + dc390_EEprom_Override(dc390_adapterCnt); + } - if (pci_set_dma_mask(pdev, 0xffffffff)) { - printk(KERN_ERR "DC390(%i): No suitable DMA available.\n", dc390_adapterCnt); - continue; - } - PCI_GET_IO_AND_IRQ; - DEBUG0(printk(KERN_INFO "DC390(%i): IO_PORT=%04x,IRQ=%x\n", dc390_adapterCnt, (UINT) io_port, irq)); + DEBUG0(printk(KERN_INFO "DC390: pSH = %8x, Index %02i\n", (u32) scsi_host, dc390_adapterCnt)); - if( !DC390_init(psht, io_port, irq, PDEV, dc390_adapterCnt)) - { - pci_set_master(pdev); - dc390_set_pci_cfg (PDEV); - dc390_adapterCnt++; - } + dc390_initACB(scsi_host, io_port, irq, dc390_adapterCnt); + + pACB->pdev = dev; + + if (dc390_initAdapter(scsi_host, io_port, irq, dc390_adapterCnt)) { + scsi_unregister(scsi_host); + ret = -EBUSY; + goto busy; } - else - printk (KERN_ERR "DC390: No PCI BIOS found!\n"); - - if (dc390_adapterCnt) - psht->proc_name = "tmscsim"; - printk(KERN_INFO "DC390: %i adapters found\n", dc390_adapterCnt); - return( dc390_adapterCnt ); + pci_set_master(dev); + dc390_set_pci_cfg(dev); + dc390_adapterCnt++; + + /* get the scsi mid level to scan for new devices on the bus */ + if (scsi_add_host(scsi_host, &dev->dev)) { + ret = -ENODEV; + goto nodev; + } + pci_set_drvdata(dev, scsi_host); + scsi_scan_host(scsi_host); + + return 0; + +nodev: +busy: + scsi_host_put(scsi_host); +nomem: + pci_disable_device(dev); + return ret; +} + +/** + * dc390_remove_one - Called to remove a single instance of the adapter. + * + * @dev: The PCI device to remove. + */ +static void __devexit 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); + + del_timer_sync(&pACB->Waiting_Timer); + + 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); + pci_set_drvdata(dev, NULL); } /******************************************************************** @@ -1997,19 +1971,19 @@ static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start, { int dev, spd, spd1; char *pos = buffer; - PACB pACB; - PDCB pDCB; + struct dc390_acb* pACB; + struct dc390_dcb* pDCB; pACB = dc390_pACB_start; - while(pACB != (PACB)-1) + while(pACB != (struct dc390_acb*)-1) { if (shpnt == pACB->pScsiHost) break; pACB = pACB->pNextACB; } - if (pACB == (PACB)-1) return(-ESRCH); + if (pACB == (struct dc390_acb*)-1) return(-ESRCH); if(inout) /* Has data been written to the file ? */ return -ENOSYS; @@ -2035,7 +2009,7 @@ static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start, SPRINTF(" Lost arbitrations %i, Sel. connected %i, Connected: %s\n", pACB->SelLost, pACB->SelConn, pACB->Connected? "Yes": "No"); - SPRINTF("Nr of attached devices: %i, Nr of DCBs: %i\n", pACB->DeviceCnt, pACB->DCBCnt); + SPRINTF("Nr of DCBs: %i\n", pACB->DCBCnt); SPRINTF("Map of attached LUNs: %02x %02x %02x %02x %02x %02x %02x %02x\n", pACB->DCBmap[0], pACB->DCBmap[1], pACB->DCBmap[2], pACB->DCBmap[3], pACB->DCBmap[4], pACB->DCBmap[5], pACB->DCBmap[6], pACB->DCBmap[7]); @@ -2070,7 +2044,7 @@ static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start, for (dev = 0; dev < pACB->DCBCnt; dev++) { - PSRB pSRB; + struct dc390_srb* pSRB; if (pDCB->WaitSRBCnt) SPRINTF ("DCB (%02i-%i): Waiting: %i:", pDCB->TargetID, pDCB->TargetLUN, pDCB->WaitSRBCnt); @@ -2111,90 +2085,22 @@ static int DC390_proc_info (struct Scsi_Host *shpnt, char *buffer, char **start, #undef YESNO #undef SPRINTF -/*********************************************************************** - * Function : static int dc390_shutdown (struct Scsi_Host *host) - * - * Purpose : does a clean (we hope) shutdown of the SCSI chip. - * Use prior to dumping core, unloading the driver, etc. - * - * Returns : 0 on success - ***********************************************************************/ -static int dc390_shutdown (struct Scsi_Host *host) -{ - UCHAR bval; - PACB pACB = (PACB)(host->hostdata); - -/* pACB->soft_reset(host); */ - - printk(KERN_INFO "DC390: shutdown\n"); - - pACB->ACBFlag = RESET_DEV; - bval = DC390_read8 (CtrlReg1); - bval |= DIS_INT_ON_SCSI_RST; - DC390_write8 (CtrlReg1, bval); /* disable interrupt */ - if (pACB->Gmode2 & RST_SCSI_BUS) - dc390_ResetSCSIBus (pACB); - - if (timer_pending (&pACB->Waiting_Timer)) del_timer (&pACB->Waiting_Timer); - return( 0 ); -} +static struct pci_driver dc390_driver = { + .name = "tmscsim", + .id_table = tmscsim_pci_tbl, + .probe = dc390_init_one, + .remove = __devexit_p(dc390_remove_one), +}; -static void dc390_freeDCBs (struct Scsi_Host *host) +static int __init dc390_module_init(void) { - PDCB pDCB, nDCB; - PACB pACB = (PACB)(host->hostdata); - - pDCB = pACB->pLinkDCB; - if (!pDCB) return; - do - { - nDCB = pDCB->pNextDCB; - DCBDEBUG(printk (KERN_INFO "DC390: Free DCB (ID %i, LUN %i): %p\n",\ - pDCB->TargetID, pDCB->TargetLUN, pDCB)); - //kfree (pDCB); - dc390_remove_dev (pACB, pDCB); - pDCB = nDCB; - } while (pDCB && pACB->pLinkDCB); - + return pci_module_init(&dc390_driver); } -static int DC390_release (struct Scsi_Host *host) +static void __exit dc390_module_exit(void) { - DC390_IFLAGS; - PACB pACB = (PACB)(host->hostdata); - - DC390_LOCK_IO(host); - - /* TO DO: We should check for outstanding commands first. */ - dc390_shutdown (host); - - if (host->irq != SCSI_IRQ_NONE) - { - DEBUG0(printk(KERN_INFO "DC390: Free IRQ %i\n",host->irq)); - free_irq (host->irq, pACB); - } - - release_region(host->io_port,host->n_io_port); - dc390_freeDCBs (host); - DC390_UNLOCK_IO(host); - scsi_unregister(host); - return( 1 ); + pci_unregister_driver(&dc390_driver); } -static Scsi_Host_Template driver_template = { - .proc_name = "tmscsim", - .proc_info = DC390_proc_info, - .name = DC390_BANNER " V" DC390_VERSION, - .detect = DC390_detect, - .release = DC390_release, - .queuecommand = DC390_queue_command, - .eh_abort_handler = DC390_abort, - .eh_bus_reset_handler = DC390_reset, - .bios_param = DC390_bios_param, - .can_queue = 42, - .this_id = 7, - .sg_tablesize = SG_ALL, - .cmd_per_lun = 16, - .use_clustering = DISABLE_CLUSTERING, -}; -#include "scsi_module.c" +module_init(dc390_module_init); +module_exit(dc390_module_exit);