📄 aic7880lib.c
字号:
{ /* standard fast SCSI mode */ if (period <= 100) { period = AIC_7880_PERIOD_100; *pXferRate = 0x00; } else if ((period > 100) && (period <= 125)) { period = AIC_7880_PERIOD_125; *pXferRate = 0x10; } else if ((period > 125) && (period <= 150)) { period = AIC_7880_PERIOD_150; *pXferRate = 0x20; } else if ((period > 150) && (period <= 175)) { period = AIC_7880_PERIOD_175; *pXferRate = 0x30; } else if ((period > 175) && (period <= 200)) { period = AIC_7880_PERIOD_200; *pXferRate = 0x40; } else if ((period > 200) && (period <= 225)) { period = AIC_7880_PERIOD_225; *pXferRate = 0x50; } else if ((period > 225) && (period <= 250)) { period = AIC_7880_PERIOD_250; *pXferRate = 0x60; } else if (period > 250) { period = AIC_7880_PERIOD_275; *pXferRate = 0x70; } } /* adjust the synchronous offset to fit the allowable range */ if (offset < AIC_7880_MIN_REQ_ACK_OFFSET) offset = AIC_7880_MIN_REQ_ACK_OFFSET; else if (offset > AIC_7880_MAX_REQ_ACK_OFFSET) offset = AIC_7880_MAX_REQ_ACK_OFFSET; } SCSI_DEBUG_MSG ("aic7880XferParamsCvt: converted to: " "offset = %d, period = %d\n", offset, period, 0,0, 0, 0); *pOffset = offset; *pPeriod = period; }/********************************************************************************* aic7880XferParamsSet - set transfer parameters** Set the transfer parameters specific to a thread.** Transfer period is specified in SCSI units (multiples of 4 ns). An offset* of zero specifies asynchronous transfer.** RETURNS: OK or ERROR.*/LOCAL STATUS aic7880XferParamsSet ( SCSI_CTRL * pScsiCtrl, /* ptr to controller info */ UINT8 offset, /* max REQ/ACK offset */ UINT8 period /* min transfer period */ ) { AIC_7880_THREAD * pThread = (AIC_7880_THREAD *) pScsiCtrl->pThread; return (aic7880ThreadParamsSet (pThread, offset, period)); }/********************************************************************************* aic7880ThreadParamsSet - set various parameters for a thread** Parameters include transfer offset and period, as well as the ID of the* target device. All of these end up as encoded values stored either in* the thread's register context or its associated shared memory area.** Transfer period is specified in SCSI units (multiples of 4 ns). An offset* of zero specifies asynchronous transfer.** RETURNS: OK or ERROR if it failed negotiation.*/LOCAL STATUS aic7880ThreadParamsSet ( AIC_7880_THREAD * pThread, /* thread to be affected */ UINT8 offset, /* max REQ/ACK offset */ UINT8 period /* min transfer period */ ) { SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread; SIOP * pSiop = (SIOP *) pScsiThread->pScsiCtrl; cfp_struct * pCfpStruct; sp_struct * pScb; UINT8 xferRate; UINT8 devBusId; STATUS status; pScb = pThread->pScb; devBusId = (pScb->SP_Tarlun >> 4) & 0x0f; pCfpStruct = pSiop->aic7880CfpStruct; aic7880XferParamsCvt (pSiop, &offset, &period, &xferRate); offset = (offset - 1) << 1; offset &= SOFS; pCfpStruct->Cf_ScsiOption [devBusId] &= 0x80; pCfpStruct->Cf_ScsiOption [devBusId] |= (xferRate | offset | SYNC_MODE); pCfpStruct->CFP_SuppressNego = 0; if ((status = (PH_Special (FORCE_RENEGOTIATE, pCfpStruct, pScb))) != OK) { SCSI_DEBUG_MSG ("aic7880ThreadParamsSet: Sync Negotiation Failed.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } return (OK); }/********************************************************************************* aic7880WideXferParamsSet - set wide transfer parameters** Assume valid parameters and set the AIC 7880's thread parameters to the* appropriate values.** RETURNS: OK or ERROR if it failed wide negotiation.*/LOCAL STATUS aic7880WideXferParamsSet ( SCSI_CTRL * pScsiCtrl, /* ptr to controller info */ UINT8 xferWidth /* wide data transfer width */ ) { AIC_7880_THREAD * pThread = (AIC_7880_THREAD *) pScsiCtrl->pThread; SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread; SIOP * pSiop = (SIOP *) pScsiThread->pScsiCtrl; cfp_struct * pCfpStruct; sp_struct * pScb; UINT8 devBusId; STATUS status; pScb = pThread->pScb; devBusId = (pScb->SP_Tarlun >> 4) & 0x0f; pCfpStruct = pSiop->aic7880CfpStruct; if (xferWidth != SCSI_WIDE_XFER_SIZE_NARROW) { pCfpStruct->Cf_ScsiOption [devBusId] |= WIDE_MODE; SCSI_DEBUG_MSG ("aic7880WideXferParamsSet: %x %x\n", devBusId, pCfpStruct->Cf_ScsiOption [devBusId], 0, 0, 0, 0); pCfpStruct->CFP_SuppressNego = 0; if ((status = (PH_Special (FORCE_RENEGOTIATE, pCfpStruct, pScb))) != OK) { SCSI_DEBUG_MSG ("aic7880WideParamsSet: Wide Negotiation Failed.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } } else pCfpStruct->Cf_ScsiOption [devBusId] = NARROW_MODE; return (OK); }/********************************************************************************* aic7880EnableFast20 - enable double speed SCSI data transfers** This routine enables double speed SCSI data transfers for the SCSI host* adapter. This allows the host adapter to transfer data upto 20 MB/s for* an 8 bit device and upto 40 MB/s for a 16 bit device.** RETURNS: N/A*/VOID aic7880EnableFast20 ( SCSI_CTRL * pScsiCtrl, /* ptr to SCSI controller */ BOOL enable /* enable = 1 / disable = 0 */ ) { SIOP * pSiop = (SIOP *) pScsiCtrl; cfp_struct * configPtr = pSiop->aic7880CfpStruct; if (enable) configPtr->CFP_EnableFast20 = 1; else configPtr->CFP_EnableFast20 = 0; }/********************************************************************************* aic7880dFifoThresholdSet - set the data FIFO threshold.** This routine specifies to the AIC-7880 host adapter how to manage its* data FIFO. Below is a description of the threshold values for SCSI* reads and writes.** SCSI READS* .iP* 0 Xfer data from FIFO as soon as it is available.* .iP* 1 Xfer data from FIFO as soon as the FIFO is half full.* .iP* 2 Xfer data from FIFO as soon as the FIFO is 75% full.* .iP* 3 Xfer data from FIFO as soon as the FIFO is 100% full.** SCSI WRITES* .iP* 0 Xfer data as soon as there is room in the FIFO.* .iP* 1 Xfer data to FIFO as soon as it is 50% empty. * .iP* 2 Xfer data to FIFO as soon as it is 75% empty.* .iP* 3 Xfer data to FIFO as soon as the FIFO is empty.** RETURNS: OK or ERROR if the threshold value is not within the valid range.*/STATUS aic7880dFifoThresholdSet ( SCSI_CTRL * pScsiCtrl, /* ptr to SCSI controller */ UBYTE threshHold /* data FIFO threshold value */ ) { SIOP * pSiop = (SIOP *) pScsiCtrl; cfp_struct * configPtr = pSiop->aic7880CfpStruct; if (threshHold > 3) return (ERROR); configPtr->Cf_Threshold = threshHold; return (OK); }/********************************************************************************* aic7880ThreadAbort - abort a thread** If the thread is not currently connected, do nothing and return FALSE to* indicate that the SCSI manager should abort the thread. Otherwise the* thread is active on the controller. Invoke the PH_Special routine with the * Abort SCB opcode passing in the address of the SCB to be aborted. The HIM * reacts as follows:** If the SCB has not become active, the status is set to aborted and* it is returned. If the SCB has already completed, it returns completion * status. If the SCB is active and connected, the abort is issued and the SCB* is returned with an aborted status. If the target fails to transition to* the Message out or Bus Free phase, a SCSI Reset is issued. If the SCB is* active but disconnected, the HIM selects the target and issues an abort * message. If the target does not respond correctly to the selection and* abort sequence a SCSI Bus Reset is issued. If the HIM does not find a * valid SCB at the specified address, the abort command is simply ignored.** RETURNS: TRUE if the thread is being aborted by this driver (i.e. it is* currently active on the controller) else FALSE.*/LOCAL BOOL aic7880ThreadAbort ( SIOP * pSiop, /* ptr to controller info */ AIC_7880_THREAD * pThread /* ptr to SCSI controller thread */ ) { SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop; SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread; sp_struct * pScb = pThread->pScb; cfp_struct * configPtr = pSiop->aic7880CfpStruct; SCSI_DEBUG_MSG ("aic7880ThreadAbort: thread 0x%08x state = %d aborting\n", (int) pThread, pScsiThread->state, 0, 0, 0, 0); if (pScsiThread != pScsiCtrl->pThread) return (FALSE); switch (pScsiThread->state) { case SCSI_THREAD_INACTIVE: return (FALSE); break; default: PH_Special (ABORT_SCB, configPtr, pScb); aic7880ThreadStateSet (pThread, SCSI_THREAD_ABORTING); break; } return (TRUE); }/********************************************************************************* aic7880GetNumOfBuses - perform a PCI bus scan** This routine provides a callback mechanism from the HIM to the OSM* It allows the OSM to scan the PCI bus, before the HIM is allowed * to perform the bus scan.** RETURNS: 0x55555555 if the OSM is not able to conduct its own bus scan*/DWORD aic7880GetNumOfBuses () { return (0x55555555); }/********************************************************************************* aic7880ReadConfig - read from PCI config space** This routine provides a callback mechanism from the HIM to the OSM.* The purpose of this routine is to allow the OSM to do its own Read* access of the PCI configuration space. If the OSM cannot successfully* complete the Read access, the OSM returns 0x55555555. If this happens* the HIM attempts to conduct the configuration space Read access.** RETURNS: value read or 0x55555555, if the OSM is not able to conduct * read access to the PCI configuration space.*/DWORD aic7880ReadConfig ( cfp_struct * configPtr, /* ptr to cf_struct */ UBYTE busNo, /* PCI bus number */ UBYTE devNo, /* PCI device number */ UBYTE regNo /* register */ ) { int funcNo = 0; DWORD regVal; if ((pciConfigInLong (busNo, devNo, funcNo, (int) regNo, ®Val)) != OK) { logMsg ("aic7880ReadConfig: PCI read failed\n", 0, 0, 0, 0, 0, 0); return (0x55555555); } else return (regVal); }/********************************************************************************* aic7880WriteConfig - read to PCI config space** This routine provides a callback mechanism from the HIM to the OSM.* The purpose of this routine is to allow the OSM to do its own write* access of the PCI configuration space. If the OSM cannot successfully* complete the write access, the OSM returns 0x55555555. If this happens* the HIM attempts to conduct the configuration space write access.** RETURNS: OK or 0x55555555, if the OSM is not able to conduct write access * to the PCI configuration space.*/DWORD aic7880WriteConfig ( cfp_struct * config_ptr, /* ptr to cf_struct */ UBYTE busNo, /* PCI bus number */ UBYTE devNo, /* PCI device number */ UBYTE regNo, /* register */ DWORD regVal /* register value */ ) { int funcNo = 0; if ((pciConfigOutLong (busNo, devNo, funcNo, (int) regNo, regVal)) != OK) { logMsg ("aic7880WriteConfig: PCI read failed\n", 0, 0, 0, 0, 0, 0); return (0x55555555); } else return (OK); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -