📄 tmscsim.c
字号:
USHORT wval; ULONG flags; save_flags(flags); cli(); DC390_EnableCfg(mechnum,regval); if(mechnum == 2) { wval = mech2Agent; wval <<= 8; wval |= regval; wval = inw(wval); } else { regval &= 3; wval = inw(PCI_CFG1_DATA_REG | regval); } DC390_DisableCfg(mechnum); restore_flags(flags); return(wval);}ULONGDC390_inDword(USHORT mechnum, UCHAR regval ){ ULONG wlval; ULONG flags; USHORT wval; save_flags(flags); cli(); DC390_EnableCfg(mechnum,regval); if(mechnum == 2) { wval = mech2Agent; wval <<= 8; wval |= regval; wlval = inl(wval); } else { wlval = inl(PCI_CFG1_DATA_REG); } DC390_DisableCfg(mechnum); restore_flags(flags); return(wlval);}voidDC390_OutB(USHORT mechnum, UCHAR regval, UCHAR bval ){ USHORT wval; ULONG flags; save_flags(flags); cli(); DC390_EnableCfg(mechnum,regval); if(mechnum == 2) { wval = mech2Agent; wval <<= 8; wval |= regval; outb(bval, wval); } else { regval &= 3; outb(bval, PCI_CFG1_DATA_REG | regval); } DC390_DisableCfg(mechnum); restore_flags(flags);}voidDC390_EnDisableCE( UCHAR mode, USHORT mechnum, PUCHAR regval ){ UCHAR bval; bval = 0; if(mode == ENABLE_CE) *regval = 0xc0; else *regval = 0x80; DC390_OutB(mechnum,*regval,bval); if(mode == DISABLE_CE) DC390_OutB(mechnum,*regval,bval); udelay(160);}voidDC390_EEpromOutDI( USHORT mechnum, PUCHAR regval, USHORT Carry ){ UCHAR bval; bval = 0; if(Carry) { bval = 0x40; *regval = 0x80; DC390_OutB(mechnum,*regval,bval); } udelay(160); bval |= 0x80; DC390_OutB(mechnum,*regval,bval); udelay(160); bval = 0; DC390_OutB(mechnum,*regval,bval); udelay(160);}UCHARDC390_EEpromInDO( USHORT mechnum ){ UCHAR bval,regval; regval = 0x80; bval = 0x80; DC390_OutB(mechnum,regval,bval); udelay(160); bval = 0x40; DC390_OutB(mechnum,regval,bval); udelay(160); regval = 0x0; bval = DC390_inByte(mechnum,regval); if(bval == 0x22) return(1); else return(0);}USHORTEEpromGetData1( USHORT mechnum ){ UCHAR i; UCHAR carryFlag; USHORT wval; wval = 0; for(i=0; i<16; i++) { wval <<= 1; carryFlag = DC390_EEpromInDO(mechnum); wval |= carryFlag; } return(wval);}voidDC390_Prepare( USHORT mechnum, PUCHAR regval, UCHAR EEpromCmd ){ UCHAR i,j; USHORT carryFlag; carryFlag = 1; j = 0x80; for(i=0; i<9; i++) { DC390_EEpromOutDI(mechnum,regval,carryFlag); carryFlag = (EEpromCmd & j) ? 1 : 0; j >>= 1; }}voidDC390_ReadEEprom( USHORT mechnum, USHORT index ){ UCHAR regval,cmd; PUSHORT ptr; USHORT i; ptr = (PUSHORT) &eepromBuf[index][0]; cmd = EEPROM_READ; for(i=0; i<0x40; i++) { DC390_EnDisableCE(ENABLE_CE, mechnum, ®val); DC390_Prepare(mechnum, ®val, cmd); *ptr = EEpromGetData1(mechnum); ptr++; cmd++; DC390_EnDisableCE(DISABLE_CE,mechnum,®val); }}USHORTDC390_CheckEEpromCheckSum( USHORT MechNum, USHORT index ){ USHORT wval, rc, *ptr; UCHAR i; DC390_ReadEEprom( MechNum, index ); wval = 0; ptr = (PUSHORT) &eepromBuf[index][0]; for(i=0; i<128 ;i+=2, ptr++) wval += *ptr; if( wval == 0x1234 ) rc = 0; else rc = -1; return( rc );}USHORTDC390_ToMech( USHORT Mechnum, USHORT BusDevFunNum ){ USHORT devnum; devnum = BusDevFunNum; if(Mechnum == 2) { if(devnum & 0x80) return(-1); mech2bus = (UCHAR)((devnum & 0xff00) >> 8); /* Bus num */ mech2Agent = ((UCHAR)(devnum & 0xff)) >> 3; /* Dev num */ mech2Agent |= 0xc0; mech2CfgSPenR = ((UCHAR)(devnum & 0xff)) & 0x07; /* Fun num */ mech2CfgSPenR = (mech2CfgSPenR << 1) | 0x20; } else /* use mech #1 method */ { mech1addr = 0x80000000 | ((ULONG)devnum << 8); } return(0);}/*********************************************************************** * 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/ * * Preconditions : when this function is called, the chip_type * field of the pACB structure MUST have been set. ***********************************************************************/static intDC390_init (PSHT psht, ULONG io_port, UCHAR Irq, USHORT index, USHORT MechNum){ PSH psh; PACB pACB; if( !DC390_CheckEEpromCheckSum( MechNum, index) ) { psh = scsi_register( psht, sizeof(DC390_ACB) ); if( !psh ) return( -1 ); if( !pSH_start ) { pSH_start = psh; pSH_current = psh; } else { pSH_current->next = psh; pSH_current = psh; }#ifdef DC390_DEBUG0 printk("DC390: pSH = %8x,", (UINT) psh); printk("DC390: Index %02i,", index);#endif DC390_initACB( psh, io_port, Irq, index ); if( !DC390_initAdapter( psh, io_port, Irq, index ) ) { pACB = (PACB) psh->hostdata; if( !pACB_start ) { pACB_start = pACB; pACB_current = pACB; pACB->pNextACB = (PACB) -1; } else { pACB_current->pNextACB = pACB; pACB_current = pACB; pACB->pNextACB = (PACB) -1; }#ifdef DC390_DEBUG0 printk("DC390: pACB = %8x, pDCB_array = %8x, pSRB_array = %8x\n", (UINT) pACB, (UINT) pACB->DCB_array, (UINT) pACB->SRB_array); printk("DC390: ACB size= %4x, DCB size= %4x, SRB size= %4x\n", sizeof(DC390_ACB), sizeof(DC390_DCB), sizeof(DC390_SRB) );#endif } else { pSH_start = NULL; scsi_unregister( psh ); return( -1 ); } return( 0 ); } else { printk("DC390_init: EEPROM reading error!\n"); return( -1 ); }}/*********************************************************************** * Function : int DC390_detect(Scsi_Host_Template *psht) * * Purpose : detects and initializes AMD53C974 SCSI chips * that were autoprobed, overridden on the LILO command line, * or specified at compile time. * * Inputs : psht - template for this SCSI adapter * * Returns : number of host adapters detected * ***********************************************************************/intDC390_detect(Scsi_Host_Template *psht){#ifdef FOR_PCI_OK UCHAR pci_bus, pci_device_fn; int error = 0; USHORT chipType = 0; USHORT i;#endif UCHAR irq; UCHAR istatus;#ifndef VERSION_ELF_1_2_13 UINT io_port;#else ULONG io_port;#endif USHORT adaptCnt = 0; /* Number of boards detected */ USHORT pci_index = 0; /* Device index to PCI BIOS calls */ USHORT MechNum, BusDevFunNum; ULONG wlval;#ifndef VERSION_ELF_1_2_13 psht->proc_dir = &proc_scsi_tmscsim;#endif InitialTime = 1; pSHT_start = psht; pACB_start = NULL; MechNum = 1; for( ; (MechNum < 3) && (!adaptCnt); MechNum++) { BusDevFunNum = 0; for (; adaptCnt < MAX_ADAPTER_NUM ;) { if( !DC390_ToMech( MechNum, BusDevFunNum) ) { wlval = DC390_inDword( MechNum, PCI_VENDOR_ID); if(wlval == ( (PCI_DEVICE_ID_AMD53C974 << 16)+ PCI_VENDOR_ID_AMD) ) { io_port =DC390_inDword(MechNum,PCI_BASE_ADDRESS_0) & 0xFFFE; irq = DC390_inByte( MechNum, PCI_INTERRUPT_LINE);#ifdef DC390_DEBUG0 printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);#endif if( !DC390_init(psht, io_port, irq, pci_index, MechNum) ) { adaptCnt++; pci_index++; istatus = inb( (USHORT)io_port+INT_Status ); /* Reset Pending INT */#ifdef DC390_DEBUG0 printk("DC390: Mech=%2x,\n",(UCHAR) MechNum);#endif } } } if( BusDevFunNum != 0xfff8 ) BusDevFunNum += 8; /* next device # */ else break; } }#ifdef FOR_PCI_OK if ( pcibios_present() ) { for (i = 0; i < MAX_ADAPTER_NUM; ++i) { if( !pcibios_find_device( PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD53C974, pci_index, &pci_bus, &pci_device_fn) ) { chipType = PCI_DEVICE_ID_AMD53C974; pci_index++; } if( chipType ) { error = pcibios_read_config_dword(pci_bus, pci_device_fn, PCI_BASE_ADDRESS_0, &io_port); error |= pcibios_read_config_byte(pci_bus, pci_device_fn, PCI_INTERRUPT_LINE, &irq); if( error ) { printk("DC390_detect: reading configuration registers error!\n"); InitialTime = 0; return( 0 ); } (USHORT) io_port = (USHORT) io_port & 0xFFFE;#ifdef DC390_DEBUG0 printk("DC390: IO_PORT=%4x,IRQ=%x,\n",(UINT) io_port, irq);#endif if( !DC390_init(psht, io_port, irq, i) ) adaptCnt++; chipType = 0; } else break; } }#endif InitialTime = 0; adapterCnt = adaptCnt; return( adaptCnt );}#ifndef VERSION_ELF_1_2_13/******************************************************************** * Function: tmscsim_set_info() * * Purpose: Set adapter info (!) * * Not yet implemented * *******************************************************************/int tmscsim_set_info(char *buffer, int length, struct Scsi_Host *shpnt){ return(-ENOSYS); /* Currently this is a no-op */}/******************************************************************** * Function: tmscsim_proc_info(char* buffer, char **start, * off_t offset, int length, int hostno, int inout) * * Purpose: return SCSI Adapter/Device Info * * Input: buffer: Pointer to a buffer where to write info * start : * offset: * hostno: Host adapter index * inout : Read (=0) or set(!=0) info * * Output: buffer: contains info * length; length of info in buffer * * return value: length * ********************************************************************//* KG: proc_info taken from driver aha152x.c */#undef SPRINTF#define SPRINTF(args...) pos += sprintf(pos, ## args)#define YESNO(YN)\if (YN) SPRINTF(" Yes ");\else SPRINTF(" No ")int tmscsim_proc_info(char *buffer, char **start, off_t offset, int length, int hostno, int inout){ int dev, spd, spd1; char *pos = buffer; PSH shpnt; PACB acbpnt; PDCB dcbpnt; unsigned long flags;/* Scsi_Cmnd *ptr; */ acbpnt = pACB_start; while(acbpnt != (PACB)-1) { shpnt = acbpnt->pScsiHost; if (shpnt->host_no == hostno) break; acbpnt = acbpnt->pNextACB; } if (acbpnt == (PACB)-1) return(-ESRCH); if(!shpnt) return(-ESRCH); if(inout) /* Has data been written to the file ? */ return(tmscsim_set_info(buffer, length, shpnt)); SPRINTF("Tekram DC390(T) PCI SCSI Host Adadpter, "); SPRINTF("Driver Version 1.10, 1996/12/05\n"); save_flags(flags); cli(); SPRINTF("SCSI Host Nr %i, ", shpnt->host_no); SPRINTF("DC390 Adapter Nr %i\n", acbpnt->AdapterIndex); SPRINTF("IOPortBase 0x%04x, ", acbpnt->IOPortBase); SPRINTF("IRQLevel 0x%02x\n", acbpnt->IRQLevel); SPRINTF("MaxID %i, MaxLUN %i, ",acbpnt->max_id, acbpnt->max_lun); SPRINTF("AdapterID %i, AdapterLUN %i\n", acbpnt->AdaptSCSIID, acbpnt->AdaptSCSILUN); SPRINTF("TagMaxNum %i, Status %i\n", acbpnt->TagMaxNum, acbpnt->status); SPRINTF("Nr of attached devices: %i\n", acbpnt->DeviceCnt); SPRINTF("Un ID LUN Prty Sync DsCn SndS TagQ NegoPeriod SyncSpeed SyncOffs\n"); dcbpnt = acbpnt->pLinkDCB; for (dev = 0; dev < acbpnt->DeviceCnt; dev++) { SPRINTF("%02i %02i %02i ", dev, dcbpnt->UnitSCSIID, dcbpnt->UnitSCSILUN); YESNO(dcbpnt->DevMode & PARITY_CHK_); YESNO(dcbpnt->SyncMode & SYNC_NEGO_DONE); YESNO(dcbpnt->DevMode & EN_DISCONNECT_); YESNO(dcbpnt->DevMode & SEND_START_); YESNO(dcbpnt->SyncMode & EN_TAG_QUEUING); SPRINTF(" %03i ns ", (dcbpnt->NegoPeriod) << 2); if (dcbpnt->SyncOffset & 0x0f) { spd = 1000/(dcbpnt->NegoPeriod <<2); spd1 = 1000%(dcbpnt->NegoPeriod <<2); spd1 = (spd1 * 10)/(dcbpnt->NegoPeriod <<2); SPRINTF(" %2i.%1i M %02i\n", spd, spd1, (dcbpnt->SyncOffset & 0x0f)); } else SPRINTF("\n"); /* Add more info ...*/ dcbpnt = dcbpnt->pNextDCB; } restore_flags(flags); *start = buffer + offset; if (pos - buffer < offset) return 0; else if (pos - buffer - offset < length) return pos - buffer - offset; else return length;}#endif /* VERSION_ELF_1_2_13 */#ifdef MODULE/*********************************************************************** * 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 intDC390_shutdown (struct Scsi_Host *host){ UCHAR bval; USHORT ioport; unsigned long flags; PACB pACB = (PACB)(host->hostdata); ioport = (unsigned int) pACB->IOPortBase; save_flags (flags); cli();/* pACB->soft_reset(host); */#ifdef DC390_DEBUG0 printk("DC390: shutdown,");#endif bval = inb(ioport+CtrlReg1); bval |= DIS_INT_ON_SCSI_RST; outb(bval,ioport+CtrlReg1); /* disable interrupt */ DC390_ResetSCSIBus( pACB ); restore_flags (flags); return( 0 );}int DC390_release(struct Scsi_Host *host){ int irq_count; struct Scsi_Host *tmp; DC390_shutdown (host); if (host->irq != IRQ_NONE) { for (irq_count = 0, tmp = pSH_start; tmp; tmp = tmp->next) { if ( tmp->irq == host->irq ) ++irq_count; } if (irq_count == 1) {#ifdef DC390_DEBUG0 printk("DC390: Free IRQ %i.",host->irq);#endif#ifndef VERSION_ELF_1_2_13 free_irq(host->irq,NULL);#else free_irq(host->irq);#endif } } release_region(host->io_port,host->n_io_port); return( 1 );}Scsi_Host_Template driver_template = DC390_T;#include "scsi_module.c"#endif /* def MODULE */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -