📄 aic7880lib.c
字号:
cmdStatus = pScb->SP_Stat; switch (cmdStatus) { case AIC_7880_CMD_COMPLETE: pScsiEvent.type = AIC_7880_CMD_COMPLETE; break; case AIC_7880_CMD_COMP_WITH_ERROR: haStatus = pScb->SP_HaStat; switch (haStatus) { case AIC_7880_NO_STATUS: SCSI_DEBUG_MSG ("No Status\n", 0, 0, 0, 0, 0, 0); pScsiEvent.type = AIC_7880_CMD_COMPLETE; break; case AIC_7880_CMD_ABORT: case AIC_7880_CMD_ABORT_BY_HA: SCSI_DEBUG_MSG ("SCSI Command Abort\n", 0,0,0,0,0,0); pScsiEvent.type = AIC_7880_CMD_COMPLETE; break; case AIC_7880_UNEXPECTED_BUS_FREE: SCSI_DEBUG_MSG ("Unexpected Bus Free\n", 0,0,0,0,0,0); pScsiEvent.type = AIC_7880_SCSI_BUS_RESET; break; case AIC_7880_PHASE_MISMATCH: SCSI_DEBUG_MSG ("Phase Mismatch occured\n", 0,0,0,0,0,0); pScsiEvent.type = AIC_7880_SCSI_BUS_RESET; break; case AIC_7880_HA_HW_ERROR: SCSI_DEBUG_MSG ("Host Adapter H/W error\n", 0,0,0,0,0,0); pScsiEvent.type = AIC_7880_SCSI_BUS_RESET; break; case AIC_7880_BUS_RESET: case AIC_7880_BUS_RESET_OTHER_DEV: SCSI_DEBUG_MSG ("SCSI Bus Reset\n", 0,0,0,0,0,0); pScsiEvent.type = AIC_7880_SCSI_BUS_RESET; break; case AIC_7880_SELECT_TIMEOUT: SCSI_DEBUG_MSG ("Device Selction Timeout\n", 0,0,0,0,0,0); pScsiEvent.type = AIC_7880_SELECT_TIMEOUT; break; case AIC_7880_REQ_SENSE_FAILED: SCSI_DEBUG_MSG ("Request Sense Failed\n",0,0,0,0,0,0); notify = FALSE; break; default: SCSI_DEBUG_MSG ("aic7880Intr: unexpt'd host adap'r intr\n", 0,0,0,0,0,0); break; } break; default: notify = FALSE; SCSI_DEBUG_MSG ("aic7880ScbCompleted: unexpected interupt\n", 0, 0, 0, 0, 0, 0); break; } if (notify) { aic7880Event (pSiop, &pScsiEvent); semGive (pScsiCtrl->actionSem); } /* restore the current H/W thread */ pScsiCtrl->pThread = pSavedThread; }/********************************************************************************* aic7880Event - AIC 788 SCSI controller event processing routine** Parse the event type and act accordingly. Controller-level events are* handled within this function, and the event is then passed to the completed* thread for thread-level processing. The SCSI Controllers state variables* are set to indicate if the controller is connected or disconnected. When* a thread is activated the Controllers state is set to CONNECTED and when* the thread has completed execution or if a SCSI Bus Reset has occured the* Controllers state is set to DISCONNECTED.** RETURNS: N/A*/LOCAL VOID aic7880Event ( SIOP * pSiop, /* ptr to controller info */ SCSI_EVENT * pScsiEvent /* ptr to SCSI EVENT */ ) { SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop; AIC_7880_THREAD * pThread = (AIC_7880_THREAD *) pScsiCtrl->pThread; SCSI_DEBUG_MSG ("aic7880Event: received event %d (thread = 0x%08x)\n", pScsiEvent->type, (int) pThread, 0, 0, 0, 0); switch (pScsiEvent->type) { case AIC_7880_CMD_COMPLETE: case AIC_7880_SELECT_TIMEOUT: pScsiCtrl->peerBusId = NONE; pScsiCtrl->pThread = 0; scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_DISCONNECTED); break; case AIC_7880_SCSI_BUS_RESET: pScsiCtrl->peerBusId = NONE; pScsiCtrl->pThread = 0; scsiMgrBusReset (pScsiCtrl); break; default: logMsg ("aic7880Event: invalid event type.\n", 0, 0, 0, 0, 0, 0); break; } /* If there's a thread on the controller, forward the event to it */ if (pThread != 0) aic7880ThreadEvent (pThread, pScsiEvent); }/********************************************************************************* aic7880ThreadEvent - AIC 7880 thread event processing routine** Forward the event to the proper handler for the thread's current role.** RETURNS: N/A*/LOCAL VOID aic7880ThreadEvent ( AIC_7880_THREAD * pThread, /* ptr to aci7880 thread info */ SCSI_EVENT * pScsiEvent /* ptr to SCSI EVENT */ ) { SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread; switch (pScsiThread->role) { case SCSI_ROLE_INITIATOR: aic7880InitEvent (pThread, pScsiEvent); break; default: logMsg ("aic7880ThreadEvent: thread 0x%08x: invalid role (%d)\n", (int) pThread, pScsiThread->role, 0, 0, 0, 0); break; } }/********************************************************************************* aic7880InitEvent - AIC 7880 initiator thread event processing routine** Parse the event type and handle it accordingly. This may result in state* changes for the thread, state variables being updated, etc.** RETURNS: N/A*/LOCAL VOID aic7880InitEvent ( AIC_7880_THREAD * pThread, /* ptr to aci7880 thread info */ SCSI_EVENT * pScsiEvent /* ptr to SCSI EVENT */ ) { switch (pScsiEvent->type) { case AIC_7880_CMD_COMPLETE: aic7880ThreadComplete (pThread); break; case AIC_7880_SELECT_TIMEOUT: SCSI_ERROR_MSG ("aic7880InitEvent: thread 0x%08x: timeout.\n", (int) pThread, 0, 0, 0, 0, 0); aic7880ThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT); break; default: logMsg ("aic7880InitEvent: invalid event type (%d)\n", pScsiEvent->type, 0, 0, 0, 0, 0); break; } }/********************************************************************************* aic7880DummyHandler - used by scsi2Lib.c to do special handling ** This routine is used by scsiMgrLib.c and scsi2Lib.c to perform certain* functions specific to the AIC-7880 driver. Wide / Synchronous transfer* negotiations and thread activation are handled differently by scsi2Lib for * this driver.** RETURNS N/A*/LOCAL VOID aic7880DummyHandler ( ) { }/********************************************************************************* aic7880ThreadComplete - successfully complete execution of a client thread** Set the thread status and errno appropriately, depending on whether or* not the thread has been aborted. Set the thread inactive, and notify* the SCSI manager of the completion.** RETURNS: N/A*/LOCAL VOID aic7880ThreadComplete ( AIC_7880_THREAD * pThread /* ptr to aci7880 thread info */ ) { SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread; if (pScsiThread->state == SCSI_THREAD_ABORTING) { pScsiThread->status = ERROR; pScsiThread->errNum = S_scsiLib_ABORTED; } else { pScsiThread->status = OK; pScsiThread->errNum = 0; } aic7880ThreadStateSet (pThread, SCSI_THREAD_INACTIVE); scsiCacheSynchronize (pScsiThread, SCSI_CACHE_POST_COMMAND); scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_COMPLETED); }/********************************************************************************* aic7880ThreadFail - complete execution of a thread, with error status** Set the thread's status and errno according to the type of error. Set* the thread's state to INACTIVE, and notify the SCSI manager of the* completion event.** RETURNS: N/A*/LOCAL VOID aic7880ThreadFail ( AIC_7880_THREAD * pThread, /* ptr to aci7880 thread info */ int errNum /* error number */ ) { SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread; SCSI_DEBUG_MSG ("aic7880ThreadFail: thread 0x%08x failed (errno = %d)\n", (int) pThread, errNum, 0, 0, 0, 0); pScsiThread->status = ERROR; if (pScsiThread->state == SCSI_THREAD_ABORTING) pScsiThread->errNum = S_scsiLib_ABORTED; else pScsiThread->errNum = errNum; aic7880ThreadStateSet (pThread, SCSI_THREAD_INACTIVE); scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_COMPLETED); }/********************************************************************************* aic7880ScsiBusControl - low-level SCSI bus control operations** Currently supports only the SCSI_BUS_RESET operation. After a SCSI Bus* Reset has occured the transfer parameters are re negotiated when a* new SCSI thread begins execution.** RETURNS: OK, or ERROR if an invalid operation is requested.*/LOCAL STATUS aic7880ScsiBusControl ( SIOP * pSiop, /* ptr to controller info */ int operation /* bitmask for operation(s) to be performed */ ) { SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop; cfp_struct * configPtr; int status; int i; if ((operation & ~SCSI_BUS_RESET) != 0) return (ERROR); configPtr = pSiop->aic7880CfpStruct; if (operation & SCSI_BUS_RESET) if ((status = PH_Special (HARD_HA_RESET, configPtr, NULL)) != OK) return (ERROR); for (i = 0; i < configPtr->Cf_MaxTargets; i++) configPtr->Cf_ScsiOption [i] = 0; scsiMgrBusReset (pScsiCtrl); return (OK); }/********************************************************************************* aic7880XferParamsQuery - get synchronous transfer parameters** Query the AIC 7880 and see if it is capable of handling the specified* transfer parameters. If the AIC 7880 does not support the specified * period and offset this routine returns the offset and period values* the AIC 7880 is capable of handling.** RETURNS: OK*/LOCAL STATUS aic7880XferParamsQuery ( SCSI_CTRL * pScsiCtrl, /* ptr to controller info */ UINT8 * pOffset, /* max REQ/ACK offset [in/out] */ UINT8 * pPeriod /* min transfer period [in/out] */ ) { UINT8 unused; (VOID) aic7880XferParamsCvt ((SIOP *) pScsiCtrl, pOffset, pPeriod, &unused); return (OK); }/********************************************************************************* aic7880XferParamsCvt - convert transfer period from SCSI to AIC 7880 units.** Given a "suggested" REQ/ACK offset and transfer period (in SCSI units of* 4 ns), return the nearest offset and transfer period the AIC 7880 is* capable of using.** An offset of zero specifies asynchronous transfer, in which case the period* is irrelevant. Otherwise, the offset specified is used if it lies within* the permissible range allowed by the AIC 7880.** The transfer period is normally rounded towards longer periods if the AIC* 7880 is not capable of using the exact specified value.** RETURNS: N/A.** NOMANUAL*/LOCAL VOID aic7880XferParamsCvt ( FAST SIOP * pSiop, /* ptr to controller info */ FAST UINT8 * pOffset, /* REQ/ACK offset */ FAST UINT8 * pPeriod, /* xfer period, SCSI units (x 4 ns) */ FAST UINT8 * pXferRate /* corresponding Sync Xfer Reg value */ ) { cfp_struct * configPtr = pSiop->aic7880CfpStruct; UINT offset = (UINT) * pOffset; UINT period = (UINT) * pPeriod; /* asynchronous xfer requested */ if (offset == SCSI_SYNC_XFER_ASYNC_OFFSET) period = 0; else { SCSI_DEBUG_MSG ("aic7880XferParamsCvt: requested: " "offset = %d, period = %d\n", offset, period, 0, 0, 0, 0); /* convert to nano seconds */ period *= 4; if (configPtr->CFP_EnableFast20) { if (period <= 50) { period = AIC_7880_DBLSPD_50; *pXferRate = 0x00; } else if ((period > 50) && (period <= 64)) { period = AIC_7880_DBLSPD_64; *pXferRate = 0x10; } else if (period > 65) { period = AIC_7880_DBLSPD_75; *pXferRate = 0x20; } } else
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -