📄 i91uscsi.c
字号:
return -1;/*---------------------- Is ckecksum ok ? ----------------------*/ np = (USHORT *) i91unvramp; for (i = 0; i < 31; i++) chksum += *np++; if (i91unvramp->NVM_CheckSum != (USHORT) chksum) return -1; return 1;}/*********************************************************************** Update SCSI H/A configuration parameters from serial EEPROM************************************************************************/void tul_se2_update_all(WORD CurBase){ /* setup default pattern */ int i; ULONG chksum = 0; USHORT *np, *np1; i91unvramp = &i91unvram; /* Calculate checksum first */ np = (USHORT *) i91udftNvRam; for (i = 0; i < 31; i++) chksum += *np++; *np = (USHORT) chksum; tul_se2_ew_en(CurBase); /* Enable write */ np = (USHORT *) i91udftNvRam; np1 = (USHORT *) i91unvramp; for (i = 0; i < 32; i++, np++, np1++) { if (*np != *np1) { tul_se2_wr(CurBase, i, *np); } } tul_se2_ew_ds(CurBase); /* Disable write */ return;}/************************************************************************* Function name : read_eeprom**************************************************************************/void tul_read_eeprom(WORD CurBase){ UCHAR gctrl; i91unvramp = &i91unvram;/*------Enable EEProm programming ---*/ gctrl = TUL_RD(CurBase, TUL_GCTRL); TUL_WR(CurBase + TUL_GCTRL, gctrl | TUL_GCTRL_EEPROM_BIT); if (tul_se2_rd_all(CurBase) != 1) { tul_se2_update_all(CurBase); /* setup default pattern */ tul_se2_rd_all(CurBase); /* load again */ }/*------ Disable EEProm programming ---*/ gctrl = TUL_RD(CurBase, TUL_GCTRL); TUL_WR(CurBase + TUL_GCTRL, gctrl & ~TUL_GCTRL_EEPROM_BIT);} /* read_eeprom */int Addi91u_into_Adapter_table(WORD wBIOS, WORD wBASE, BYTE bInterrupt, BYTE bBus, BYTE bDevice){ int i, j; for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { if (i91u_adpt[i].ADPT_BIOS < wBIOS) continue; if (i91u_adpt[i].ADPT_BIOS == wBIOS) { if (i91u_adpt[i].ADPT_BASE == wBASE) { if (i91u_adpt[i].ADPT_Bus != 0xFF) return (FAILURE); } else if (i91u_adpt[i].ADPT_BASE < wBASE) continue; } for (j = MAX_SUPPORTED_ADAPTERS - 1; j > i; j--) { i91u_adpt[j].ADPT_BASE = i91u_adpt[j - 1].ADPT_BASE; i91u_adpt[j].ADPT_INTR = i91u_adpt[j - 1].ADPT_INTR; i91u_adpt[j].ADPT_BIOS = i91u_adpt[j - 1].ADPT_BIOS; i91u_adpt[j].ADPT_Bus = i91u_adpt[j - 1].ADPT_Bus; i91u_adpt[j].ADPT_Device = i91u_adpt[j - 1].ADPT_Device; } i91u_adpt[i].ADPT_BASE = wBASE; i91u_adpt[i].ADPT_INTR = bInterrupt; i91u_adpt[i].ADPT_BIOS = wBIOS; i91u_adpt[i].ADPT_Bus = bBus; i91u_adpt[i].ADPT_Device = bDevice; return (SUCCESSFUL); } return (FAILURE);}void init_i91uAdapter_table(void){ int i; for (i = 0; i < MAX_SUPPORTED_ADAPTERS; i++) { /* Initialize adapter structure */ i91u_adpt[i].ADPT_BIOS = 0xffff; i91u_adpt[i].ADPT_BASE = 0xffff; i91u_adpt[i].ADPT_INTR = 0xff; i91u_adpt[i].ADPT_Bus = 0xff; i91u_adpt[i].ADPT_Device = 0xff; } return;}void tul_stop_bm(HCS * pCurHcb){ if (TUL_RD(pCurHcb->HCS_Base, TUL_XStatus) & XPEND) { /* if DMA xfer is pending, abort DMA xfer */ TUL_WR(pCurHcb->HCS_Base + TUL_XCmd, TAX_X_ABT | TAX_X_CLR_FIFO); /* wait Abort DMA xfer done */ while ((TUL_RD(pCurHcb->HCS_Base, TUL_Int) & XABT) == 0); } TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_FLUSH_FIFO);}/***************************************************************************/void get_tulipPCIConfig(HCS * pCurHcb, int ch_idx){ pCurHcb->HCS_Base = i91u_adpt[ch_idx].ADPT_BASE; /* Supply base address */ pCurHcb->HCS_BIOS = i91u_adpt[ch_idx].ADPT_BIOS; /* Supply BIOS address */ pCurHcb->HCS_Intr = i91u_adpt[ch_idx].ADPT_INTR; /* Supply interrupt line */ return;}/***************************************************************************/int tul_reset_scsi(HCS * pCurHcb, int seconds){ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_BUS); while (!((pCurHcb->HCS_JSInt = TUL_RD(pCurHcb->HCS_Base, TUL_SInt)) & TSS_SCSIRST_INT)); /* reset tulip chip */ TUL_WR(pCurHcb->HCS_Base + TUL_SSignal, 0); /* Stall for a while, wait for target's firmware ready,make it 2 sec ! */ /* SONY 5200 tape drive won't work if only stall for 1 sec */ tul_do_pause(seconds * HZ); TUL_RD(pCurHcb->HCS_Base, TUL_SInt); return (SCSI_RESET_SUCCESS);}/***************************************************************************/int init_tulip(HCS * pCurHcb, SCB * scbp, int tul_num_scb, BYTE * pbBiosAdr, int seconds){ int i; BYTE *pwFlags; BYTE *pbHeads; SCB *pTmpScb, *pPrevScb = NULL; pCurHcb->HCS_NumScbs = tul_num_scb; pCurHcb->HCS_Semaph = 1;#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) pCurHcb->HCS_SemaphLock = SPIN_LOCK_UNLOCKED;#endif pCurHcb->HCS_JSStatus0 = 0; pCurHcb->HCS_Scb = scbp; pCurHcb->HCS_NxtPend = scbp; pCurHcb->HCS_NxtAvail = scbp; for (i = 0, pTmpScb = scbp; i < tul_num_scb; i++, pTmpScb++) { pTmpScb->SCB_TagId = i; if (i != 0) pPrevScb->SCB_NxtScb = pTmpScb; pPrevScb = pTmpScb; } pPrevScb->SCB_NxtScb = NULL; pCurHcb->HCS_ScbEnd = pTmpScb; pCurHcb->HCS_FirstAvail = scbp; pCurHcb->HCS_LastAvail = pPrevScb;#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) pCurHcb->HCS_AvailLock = SPIN_LOCK_UNLOCKED;#endif pCurHcb->HCS_FirstPend = NULL; pCurHcb->HCS_LastPend = NULL; pCurHcb->HCS_FirstBusy = NULL; pCurHcb->HCS_LastBusy = NULL; pCurHcb->HCS_FirstDone = NULL; pCurHcb->HCS_LastDone = NULL; pCurHcb->HCS_ActScb = NULL; pCurHcb->HCS_ActTcs = NULL; tul_read_eeprom(pCurHcb->HCS_Base);/*---------- get H/A configuration -------------*/ if (i91unvramp->NVM_SCSIInfo[0].NVM_NumOfTarg == 8) pCurHcb->HCS_MaxTar = 8; else pCurHcb->HCS_MaxTar = 16; pCurHcb->HCS_Config = i91unvramp->NVM_SCSIInfo[0].NVM_ChConfig1; pCurHcb->HCS_SCSI_ID = i91unvramp->NVM_SCSIInfo[0].NVM_ChSCSIID; pCurHcb->HCS_IdMask = ~(1 << pCurHcb->HCS_SCSI_ID);#if CHK_PARITY /* Enable parity error response */ TUL_WR(pCurHcb->HCS_Base + TUL_PCMD, TUL_RD(pCurHcb->HCS_Base, TUL_PCMD) | 0x40);#endif /* Mask all the interrupt */ TUL_WR(pCurHcb->HCS_Base + TUL_Mask, 0x1F); tul_stop_bm(pCurHcb); /* --- Initialize the tulip --- */ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl0, TSC_RST_CHIP); /* program HBA's SCSI ID */ TUL_WR(pCurHcb->HCS_Base + TUL_SScsiId, pCurHcb->HCS_SCSI_ID << 4); /* Enable Initiator Mode ,phase latch,alternate sync period mode, disable SCSI reset */ if (pCurHcb->HCS_Config & HCC_EN_PAR) pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT | TSC_EN_SCSI_PAR); else pCurHcb->HCS_SConf1 = (TSC_INITDEFAULT); TUL_WR(pCurHcb->HCS_Base + TUL_SConfig, pCurHcb->HCS_SConf1); /* Enable HW reselect */ TUL_WR(pCurHcb->HCS_Base + TUL_SCtrl1, TSC_HW_RESELECT); TUL_WR(pCurHcb->HCS_Base + TUL_SPeriod, 0); /* selection time out = 250 ms */ TUL_WR(pCurHcb->HCS_Base + TUL_STimeOut, 153);/*--------- Enable SCSI terminator -----*/ TUL_WR(pCurHcb->HCS_Base + TUL_XCtrl, (pCurHcb->HCS_Config & (HCC_ACT_TERM1 | HCC_ACT_TERM2))); TUL_WR(pCurHcb->HCS_Base + TUL_GCTRL1, ((pCurHcb->HCS_Config & HCC_AUTO_TERM) >> 4) | (TUL_RD(pCurHcb->HCS_Base, TUL_GCTRL1) & 0xFE)); for (i = 0, pwFlags = & (i91unvramp->NVM_SCSIInfo[0].NVM_Targ0Config), pbHeads = pbBiosAdr + 0x180; i < pCurHcb->HCS_MaxTar; i++, pwFlags++) { pCurHcb->HCS_Tcs[i].TCS_Flags = *pwFlags & ~(TCF_SYNC_DONE | TCF_WDTR_DONE); if (pCurHcb->HCS_Tcs[i].TCS_Flags & TCF_EN_255) pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63; else pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0; pCurHcb->HCS_Tcs[i].TCS_JS_Period = 0; pCurHcb->HCS_Tcs[i].TCS_SConfig0 = pCurHcb->HCS_SConf1; pCurHcb->HCS_Tcs[i].TCS_DrvHead = *pbHeads++; if (pCurHcb->HCS_Tcs[i].TCS_DrvHead == 255) pCurHcb->HCS_Tcs[i].TCS_DrvFlags = TCF_DRV_255_63; else pCurHcb->HCS_Tcs[i].TCS_DrvFlags = 0; pCurHcb->HCS_Tcs[i].TCS_DrvSector = *pbHeads++; pCurHcb->HCS_Tcs[i].TCS_Flags &= ~TCF_BUSY; pCurHcb->HCS_ActTags[i] = 0; pCurHcb->HCS_MaxTags[i] = 0xFF; } /* for */ printk("i91u: PCI Base=0x%04X, IRQ=%d, BIOS=0x%04X0, SCSI ID=%d\n", pCurHcb->HCS_Base, pCurHcb->HCS_Intr, pCurHcb->HCS_BIOS, pCurHcb->HCS_SCSI_ID);/*------------------- reset SCSI Bus ---------------------------*/ if (pCurHcb->HCS_Config & HCC_SCSI_RESET) { printk("i91u: Reset SCSI Bus ... \n"); tul_reset_scsi(pCurHcb, seconds); } TUL_WR(pCurHcb->HCS_Base + TUL_SCFG1, 0x17); TUL_WR(pCurHcb->HCS_Base + TUL_SIntEnable, 0xE9); return (0);}/***************************************************************************/SCB *tul_alloc_scb(HCS * hcsp){ SCB *pTmpScb; ULONG flags;#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);#else save_flags(flags); cli();#endif if ((pTmpScb = hcsp->HCS_FirstAvail) != NULL) {#if DEBUG_QUEUE printk("find scb at %08lx\n", (ULONG) pTmpScb);#endif if ((hcsp->HCS_FirstAvail = pTmpScb->SCB_NxtScb) == NULL) hcsp->HCS_LastAvail = NULL; pTmpScb->SCB_NxtScb = NULL; pTmpScb->SCB_Status = SCB_RENT; }#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);#else restore_flags(flags);#endif return (pTmpScb);}/***************************************************************************/void tul_release_scb(HCS * hcsp, SCB * scbp){ ULONG flags;#if DEBUG_QUEUE printk("Release SCB %lx; ", (ULONG) scbp);#endif#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_lock_irqsave(&(hcsp->HCS_AvailLock), flags);#else save_flags(flags); cli();#endif scbp->SCB_Srb = 0; scbp->SCB_Status = 0; scbp->SCB_NxtScb = NULL; if (hcsp->HCS_LastAvail != NULL) { hcsp->HCS_LastAvail->SCB_NxtScb = scbp; hcsp->HCS_LastAvail = scbp; } else { hcsp->HCS_FirstAvail = scbp; hcsp->HCS_LastAvail = scbp; }#if LINUX_VERSION_CODE >= CVT_LINUX_VERSION(2,1,95) spin_unlock_irqrestore(&(hcsp->HCS_AvailLock), flags);#else restore_flags(flags);#endif}/***************************************************************************/void tul_append_pend_scb(HCS * pCurHcb, SCB * scbp){#if DEBUG_QUEUE printk("Append pend SCB %lx; ", (ULONG) scbp);#endif scbp->SCB_Status = SCB_PEND; scbp->SCB_NxtScb = NULL; if (pCurHcb->HCS_LastPend != NULL) { pCurHcb->HCS_LastPend->SCB_NxtScb = scbp; pCurHcb->HCS_LastPend = scbp; } else { pCurHcb->HCS_FirstPend = scbp; pCurHcb->HCS_LastPend = scbp; }}/***************************************************************************/void tul_push_pend_scb(HCS * pCurHcb, SCB * scbp){#if DEBUG_QUEUE printk("Push pend SCB %lx; ", (ULONG) scbp);#endif scbp->SCB_Status = SCB_PEND; if ((scbp->SCB_NxtScb = pCurHcb->HCS_FirstPend) != NULL) { pCurHcb->HCS_FirstPend = scbp; } else { pCurHcb->HCS_FirstPend = scbp; pCurHcb->HCS_LastPend = scbp; }}/***************************************************************************/SCB *tul_find_first_pend_scb(HCS * pCurHcb){ SCB *pFirstPend; pFirstPend = pCurHcb->HCS_FirstPend; while (pFirstPend != NULL) { if (pFirstPend->SCB_Opcode != ExecSCSI) { return (pFirstPend); } if (pFirstPend->SCB_TagMsg == 0) { if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] == 0) && !(pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) { return (pFirstPend); } } else { if ((pCurHcb->HCS_ActTags[pFirstPend->SCB_Target] >= pCurHcb->HCS_MaxTags[pFirstPend->SCB_Target]) | (pCurHcb->HCS_Tcs[pFirstPend->SCB_Target].TCS_Flags & TCF_BUSY)) { pFirstPend = pFirstPend->SCB_NxtScb; continue; } return (pFirstPend); } pFirstPend = pFirstPend->SCB_NxtScb; } return (pFirstPend);}/***************************************************************************/SCB *tul_pop_pend_scb(HCS * pCurHcb){ SCB *pTmpScb; if ((pTmpScb = pCurHcb->HCS_FirstPend) != NULL) { if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) pCurHcb->HCS_LastPend = NULL; pTmpScb->SCB_NxtScb = NULL; }#if DEBUG_QUEUE printk("Pop pend SCB %lx; ", (ULONG) pTmpScb);#endif return (pTmpScb);}/***************************************************************************/void tul_unlink_pend_scb(HCS * pCurHcb, SCB * pCurScb){ SCB *pTmpScb, *pPrevScb;#if DEBUG_QUEUE printk("unlink pend SCB %lx; ", (ULONG) pCurScb);#endif pPrevScb = pTmpScb = pCurHcb->HCS_FirstPend; while (pTmpScb != NULL) { if (pCurScb == pTmpScb) { /* Unlink this SCB */ if (pTmpScb == pCurHcb->HCS_FirstPend) { if ((pCurHcb->HCS_FirstPend = pTmpScb->SCB_NxtScb) == NULL) pCurHcb->HCS_LastPend = NULL; } else { pPrevScb->SCB_NxtScb = pTmpScb->SCB_NxtScb; if (pTmpScb == pCurHcb->HCS_LastPend) pCurHcb->HCS_LastPend = pPrevScb; } pTmpScb->SCB_NxtScb = NULL; break; } pPrevScb = pTmpScb; pTmpScb = pTmpScb->SCB_NxtScb; } return;}/***************************************************************************/void tul_append_busy_scb(HCS * pCurHcb, SCB * scbp){#if DEBUG_QUEUE printk("append busy SCB %lx; ", (ULONG) scbp);#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -