📄 tmscsim.c
字号:
if (error) { printk (KERN_ERR "DC390_detect: Error reading PCI config registers!\n"); continue; }#endif #include "tmscsim.h"#ifndef __init# define __init#endifUCHAR dc390_StartSCSI( PACB pACB, PDCB pDCB, PSRB pSRB );void dc390_DataOut_0( PACB pACB, PSRB pSRB, PUCHAR psstatus);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);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);void dc390_CommandPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);static void dc390_StatusPhase( PACB pACB, PSRB pSRB, PUCHAR psstatus);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 );void dc390_Disconnect( PACB pACB );void dc390_Reselect( PACB pACB );void dc390_SRBdone( PACB pACB, PDCB pDCB, PSRB pSRB );void dc390_DoingSRB_Done( PACB pACB, 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);void do_DC390_Interrupt( int, void *, struct pt_regs *);int dc390_initAdapter( PSH psh, ULONG io_port, UCHAR Irq, UCHAR index );void dc390_initDCB( PACB pACB, PDCB *ppDCB, UCHAR id, UCHAR lun);void dc390_updateDCB (PACB pACB, PDCB pDCB);#ifdef MODULE static int DC390_release(struct Scsi_Host *host); static int dc390_shutdown (struct Scsi_Host *host);#endif//static PSHT dc390_pSHT_start = NULL;//static PSH dc390_pSH_start = NULL;//static PSH dc390_pSH_current = NULL;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;/* Startup values, to be overriden on the commandline */int tmscsim[] = {-2, -2, -2, -2, -2, -2};# if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)MODULE_PARM(tmscsim, "1-6i");MODULE_PARM_DESC(tmscsim, "Host SCSI ID, Speed (0=10MHz), Device Flags, Adapter Flags, Max Tags (log2(tags)-1), DelayReset (s)");# endif#if defined(MODULE) && LINUX_VERSION_CODE >= KERNEL_VERSION(2,1,30)MODULE_AUTHOR("C.L. Huang / Kurt Garloff");MODULE_DESCRIPTION("SCSI host adapter driver for Tekram DC390 and other AMD53C974A based PCI SCSI adapters");MODULE_SUPPORTED_DEVICE("sd,sr,sg,st");#endifstatic PVOID 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 PVOID 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_DEBUG1static 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 /* Devices erroneously pretending to be able to do TagQ */UCHAR dc390_baddevname1[2][28] ={ "SEAGATE ST3390N 9546", "HP C3323-300 4269"};#define BADDEVCNT 2static char* dc390_adapname = "DC390";UCHAR dc390_eepromBuf[MAX_ADAPTER_NUM][EE_LEN];UCHAR dc390_clock_period1[] = {4, 5, 6, 7, 8, 10, 13, 20};UCHAR dc390_clock_speed[] = {100,80,67,57,50, 40, 31, 20};#if LINUX_VERSION_CODE < KERNEL_VERSION(2,3,30)struct proc_dir_entry DC390_proc_scsi_tmscsim ={ PROC_SCSI_DC390T, 7 ,"tmscsim", S_IFDIR | S_IRUGO | S_IXUGO, 2 };#endif/*********************************************************************** * Functions for access to DC390 EEPROM * and some to emulate it * **********************************************************************/static void __init dc390_EnDisableCE( UCHAR mode, PDEVDECL, PUCHAR regval ){ UCHAR bval; bval = 0; if(mode == ENABLE_CE) *regval = 0xc0; else *regval = 0x80; PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); if(mode == DISABLE_CE) PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); udelay(160);}/* Override EEprom values with explicitly set values */static void __init dc390_EEprom_Override (UCHAR index){ PUCHAR ptr; UCHAR id; ptr = (PUCHAR) dc390_eepromBuf[index]; /* Adapter Settings */ if (tmscsim[0] != -2) ptr[EE_ADAPT_SCSI_ID] = (UCHAR)tmscsim[0]; /* Adapter ID */ if (tmscsim[3] != -2) ptr[EE_MODE2] = (UCHAR)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 */ /* Device Settings */ for (id = 0; id < MAX_SCSI_ID; id++) { if (tmscsim[2] != -2) ptr[id<<2] = (UCHAR)tmscsim[2]; /* EE_MODE1 */ if (tmscsim[1] != -2) ptr[(id<<2) + 1] = (UCHAR)tmscsim[1]; /* EE_Speed */ };}/* Handle "-1" case */static void __init dc390_check_for_safe_settings (void){ if (tmscsim[0] == -1 || tmscsim[0] > 15) /* modules-2.0.0 passes -1 as string */ { tmscsim[0] = 7; tmscsim[1] = 4; tmscsim[2] = 0x09; tmscsim[3] = 0x0f; tmscsim[4] = 2; tmscsim[5] = 10; printk (KERN_INFO "DC390: Using safe settings.\n"); }}#ifndef CONFIG_SCSI_DC390T_NOGENSUPPint __initdata tmscsim_def[] = {7, 0 /* 10MHz */, PARITY_CHK_ | SEND_START_ | EN_DISCONNECT_ | SYNC_NEGO_ | TAG_QUEUEING_, MORE2_DRV | GREATER_1G | RST_SCSI_BUS | ACTIVE_NEGATION /* | NO_SEEK */# ifdef CONFIG_SCSI_MULTI_LUN | LUN_CHECK# endif , 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){ int i; PARSEDEBUG(printk(KERN_INFO "DC390: setup %08x %08x %08x %08x %08x %08x\n", tmscsim[0],\ tmscsim[1], tmscsim[2], tmscsim[3], tmscsim[4], tmscsim[5]);) 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;};#endif/* Override defaults on cmdline: * tmscsim: AdaptID, MaxSpeed (Index), DevMode (Bitmapped), AdaptMode (Bitmapped) */#if LINUX_VERSION_CODE > KERNEL_VERSION(2,3,13)void __init dc390_setup (char *str){ int ints[8]; int i, im; (void)get_options (str, ARRAY_SIZE(ints), ints);#elsevoid __init dc390_setup (char *str, int *ints){ int i, im;#endif 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 (); */};#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,3,13)#ifndef MODULE__setup("tmscsim=", dc390_setup);#endif#endifstatic void __init dc390_EEpromOutDI( PDEVDECL, PUCHAR regval, UCHAR Carry ){ UCHAR bval; bval = 0; if(Carry) { bval = 0x40; *regval = 0x80; PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); } udelay(160); bval |= 0x80; PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); udelay(160); bval = 0; PCI_WRITE_CONFIG_BYTE(PDEV, *regval, bval); udelay(160);}static UCHAR __init dc390_EEpromInDO( PDEVDECL ){ UCHAR bval; 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) return(1); else return(0);}static USHORT __init dc390_EEpromGetData1( PDEVDECL ){ UCHAR i; UCHAR carryFlag; USHORT wval; wval = 0; for(i=0; i<16; i++) { wval <<= 1; carryFlag = dc390_EEpromInDO(PDEV); wval |= carryFlag; } return(wval);}static void __init dc390_Prepare( PDEVDECL, PUCHAR regval, UCHAR EEpromCmd ){ UCHAR i,j; UCHAR carryFlag; carryFlag = 1; j = 0x80; for(i=0; i<9; i++) { dc390_EEpromOutDI(PDEV,regval,carryFlag); carryFlag = (EEpromCmd & j) ? 1 : 0; j >>= 1; }}static void __init dc390_ReadEEprom( PDEVDECL, PUSHORT ptr){ UCHAR regval,cmd; UCHAR 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); }}static void __init dc390_interpret_delay (UCHAR 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 ){ UCHAR i; char EEbuf[128]; USHORT wval, *ptr = (PUSHORT)EEbuf; 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); dc390_interpret_delay (index); wval = 0; for(i=0; i<0x40; i++, ptr++) wval += *ptr; return (wval == 0x1234 ? 0 : 1);}/*********************************************************************** * Functions for the management of the internal structures * (DCBs, SRBs, Queueing) * **********************************************************************/static PDCB __inline__ dc390_findDCB ( PACB pACB, UCHAR id, UCHAR lun){ PDCB pDCB = pACB->pLinkDCB; if (!pDCB) return 0; while (pDCB->TargetID != id || pDCB->TargetLUN != lun) { pDCB = pDCB->pNextDCB; if (pDCB == pACB->pLinkDCB) { DCBDEBUG(printk (KERN_WARNING "DC390: DCB not found (DCB=%p, DCBmap[%2x]=%2x)\n", pDCB, id, pACB->DCBmap[id]);) return 0; } }; DCBDEBUG1( printk (KERN_DEBUG "DCB %p (%02x,%02x) found.\n", \ pDCB, pDCB->TargetID, pDCB->TargetLUN);) return pDCB;};/* Queueing philosphy: * There are a couple of lists: * - Query: Contains the Scsi Commands not yet turned into SRBs (per ACB) * (Note: For new EH, it is unecessary!) * - Waiting: Contains a list of SRBs not yet sent (per DCB) * - Free: List of free SRB slots * * If there are no waiting commands for the DCB, the new one is sent to the bus * otherwise the oldest one is taken from the Waiting list and the new one is * queued to the Waiting List * * Lists are managed using two pointers and eventually a counter */#if 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -