📄 templatescsi2.c
字号:
else { templateScriptStart (pSiop, pSiop->pIdentThread, TEMPLATE_SCRIPT_WAIT); pSiop->state = TEMPLATE_STATE_PASSIVE; } pSiop->cmdPending = FALSE; SCSI_INT_DEBUG_MSG ("templateIntr: state %d -> %d\n", oldState, pSiop->state, 0, 0, 0, 0); /* Send the event to the SCSI manager to be processed. */ if (notify) scsiMgrEventNotify ((SCSI_CTRL *) pSiop, pScsiEvent, sizeof (event)); }/********************************************************************************* templateEvent - 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 current* thread (if any) for thread-level processing.** RETURNS: N/A*/LOCAL void templateEvent ( SIOP * pSiop, TEMPLATE_EVENT * pEvent ) { SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop; SCSI_EVENT * pScsiEvent = &pEvent->scsiEvent; TEMPLATE_THREAD * pThread = (TEMPLATE_THREAD *) pScsiCtrl->pThread; SCSI_DEBUG_MSG ("templateEvent: received event %d (thread = 0x%08x)\n", pScsiEvent->type, (int) pThread, 0, 0, 0, 0); /* Do controller-level event processing */ switch (pScsiEvent->type) { case SCSI_EVENT_SELECTED: case SCSI_EVENT_RESELECTED: /* * Forward event to current thread, if any (it should defer) * then install a reserved thread for identification purposes. */ if (pThread != 0) templateThreadEvent (pThread, pEvent); pScsiCtrl->peerBusId = pScsiEvent->busId; pScsiCtrl->pThread = pScsiCtrl->pIdentThread; pScsiCtrl->pThread->role = (pScsiEvent->type == SCSI_EVENT_SELECTED) ? SCSI_ROLE_IDENT_TARG : SCSI_ROLE_IDENT_INIT; pThread = (TEMPLATE_THREAD *) pScsiCtrl->pThread; scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_CONNECTED); break; case SCSI_EVENT_DISCONNECTED: case TEMPLATE_SCSI_COMPLETE: case TEMPLATE_UNEXPECTED_DISCON: case TEMPLATE_SCSI_TIMEOUT: pScsiCtrl->peerBusId = NONE; pScsiCtrl->pThread = 0; scsiMgrCtrlEvent (pScsiCtrl, SCSI_EVENT_DISCONNECTED); break; case SCSI_EVENT_BUS_RESET: pScsiCtrl->peerBusId = NONE; pScsiCtrl->pThread = 0; scsiMgrBusReset (pScsiCtrl); break; default: /* * Any other event type is assumed to be thread-specific. * The thread event handler will report an error if it's * not a valid type. */ if (pThread == 0) { logMsg ("templateEvent: invalid event type (%d)\n", pScsiEvent->type, 0, 0, 0, 0, 0); } break; } /* If there's a thread on the controller, forward the event to it */ if (pThread != 0) templateThreadEvent (pThread, pEvent); } /********************************************************************************* templateThreadInit - initialize a client thread structure** Initialize the fixed data for a thread (i.e., independent of the command).* Called once when a thread structure is first created.** RETURNS: OK, or ERROR if an error occurs*/LOCAL STATUS templateThreadInit ( SIOP * pSiop, TEMPLATE_THREAD * pThread ) { scsiThreadInit (&pThread->scsiThread); /* TODO - device specific thread initialization */ return (OK); }/********************************************************************************* templateThreadActivate - activate a SCSI connection for an initiator thread** Set whatever thread/controller state variables need to be set. Ensure that* all buffers used by the thread are coherent with the contents of the* system caches (if any).** Set transfer parameters for the thread based on what its target device* last negotiated.** Update the thread context (including shared memory area) and note that* there is a new client script to be activated (see "templateActivate()").** Set the thread's state to ESTABLISHED.* Do not wait for the script to be activated. Completion of the script will* be signalled by an event which is handled by "templateEvent()".** RETURNS: OK or ERROR*/LOCAL STATUS templateThreadActivate ( SIOP * pSiop, /* ptr to controller info */ TEMPLATE_THREAD * pThread /* ptr to thread info */ ) { SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop; SCSI_THREAD * pScsiThread = &pThread->scsiThread; SCSI_TARGET * pScsiTarget = pScsiThread->pScsiTarget; SCSI_DEBUG_MSG ("templateThreadActivate: thread 0x%08x: activating\n", (int) pThread, 0, 0, 0, 0, 0); scsiCacheSynchronize (pScsiThread, SCSI_CACHE_PRE_COMMAND); /* Reset controller state variables: set sync xfer parameters */ pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE; pScsiCtrl->msgInState = SCSI_MSG_IN_NONE; /* * A wide transfer is initiated before a synchronous transfer. However, * when a wide transfer has been done the next activation causes the * synchronous transfer to be activated. Another possible but more * complicated way to implement this would be to have both wide and * synchronous negotiations in the same activation or thread i.e. * the same SCSI transaction. */ scsiWideXferNegotiate (pScsiCtrl, pScsiTarget, WIDE_XFER_NEW_THREAD); scsiSyncXferNegotiate (pScsiCtrl, pScsiTarget, SYNC_XFER_NEW_THREAD); if (templateThreadParamsSet (pThread, pScsiTarget->xferOffset, pScsiTarget->xferPeriod) != OK) { SCSI_ERROR_MSG ("templateThreadActivate: failed to set thread " \ "params.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } /* Update thread context; activate the thread */ templateThreadUpdate (pThread); if (templateActivate (pSiop, pThread) != OK) { SCSI_ERROR_MSG ("templateThreadActivate: failed to activate thread.\n", 0, 0, 0, 0, 0, 0); return (ERROR); } pScsiCtrl->pThread = pScsiThread; templateThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED); return (OK); }/********************************************************************************* templateThreadAbort - 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.** RETURNS: TRUE if the thread is being aborted by this driver (i.e. it is* currently active on the controller, else FALSE.*/LOCAL BOOL templateThreadAbort ( SIOP * pSiop, /* ptr to controller info */ TEMPLATE_THREAD * pThread /* ptr to thread info */ ) { BOOL tagged; SCSI_CTRL * pScsiCtrl = (SCSI_CTRL *) pSiop; SCSI_THREAD * pScsiThread = &pThread->scsiThread; SCSI_DEBUG_MSG ("templateThreadAbort: 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: case SCSI_THREAD_WAITING: case SCSI_THREAD_DISCONNECTED: return (FALSE); break; default: /* * Build an ABORT (or ABORT TAG) message. When this has been * sent, the target should disconnect. Mark the thread aborted * and continue until disconnection. */ tagged = (pScsiThread->tagNumber != NONE); pScsiCtrl->msgOutBuf[0] = tagged ? SCSI_MSG_ABORT_TAG : SCSI_MSG_ABORT; pScsiCtrl->msgOutLength = 1; pScsiCtrl->msgOutState = SCSI_MSG_OUT_PENDING; templateAbort (pSiop); templateThreadStateSet (pThread, SCSI_THREAD_ABORTING); break; } return (TRUE); }/********************************************************************************* templateScsiBusControl - miscellaneous low-level SCSI bus control operations** Currently supports only the SCSI_BUS_RESET operation; other operations are* not used explicitly by the driver because they are carried out automatically* by the script program.** NOTE: after the SCSI bus has been reset, we expect the device* to create a TEMPLATE_BUS_RESET event to be sent to the SCSI manager.* See "templateIntr()".** RETURNS: OK, or ERROR if an invalid operation is requested.** NOMANUAL*/LOCAL STATUS templateScsiBusControl ( SIOP * pSiop, /* ptr to controller info */ int operation /* bitmask for operation(s) to be performed */ ) { if (operation & SCSI_BUS_RESET) { /* TODO - assert & deassert the RST line */ return OK; } return ERROR; /* unknown operation */ }/********************************************************************************* templateXferParamsQuery - get synchronous transfer parameters** Updates the synchronous transfer parameters suggested in the call to match* the TEMPLATE SCSI Controller's capabilities. Transfer period is in SCSI units* (multiples * of 4 ns).** RETURNS: OK*/LOCAL STATUS templateXferParamsQuery ( SCSI_CTRL *pScsiCtrl, /* ptr to controller info */ UINT8 *pOffset, /* max REQ/ACK offset [in/out] */ UINT8 *pPeriod /* min transfer period [in/out] */ ) { /* TODO - alter the offset and period variables to acceptable values */ return (OK); } /********************************************************************************* templateXferParamsSet - set transfer parameters** Validate the requested parameters, convert to the TEMPLATE SCSI Controller's * native format and save in the current thread for later use (the chip's* registers are not actually set until the next script activation for this * thread).** Transfer period is specified in SCSI units (multiples of 4 ns). An offset* of zero specifies asynchronous transfer.** RETURNS: OK if transfer parameters are OK, else ERROR.*/LOCAL STATUS templateXferParamsSet ( SCSI_CTRL *pScsiCtrl, /* ptr to controller info */ UINT8 offset, /* max REQ/ACK offset */ UINT8 period /* min transfer period */ ) { return (templateThreadParamsSet ((TEMPLATE_THREAD*)pScsiCtrl->pThread, offset, period)); }/********************************************************************************* templateWideXferParamsQuery - get wide data transfer parameters** Updates the wide data transfer parameters suggested in the call to match* the TEMPLATE SCSI Controller's capabilities. Transfer width is in the units * of the WIDE DATA TRANSFER message's transfer width exponent field. This is* an 8 bit field where 0 represents a narrow transfer of 8 bits, 1 represents* a wide transfer of 16 bits and 2 represents a wide transfer of 32 bits.** RETURNS: OK*/LOCAL STATUS templateWideXferParamsQuery ( SCSI_CTRL *pScsiCtrl, /* ptr to controller info */ UINT8 *xferWidth /* suggested transfer width */ ) { if (*xferWidth > TEMPLATE_MAX_XFER_WIDTH) *xferWidth = TEMPLATE_MAX_XFER_WIDTH; templateWideXferParamsSet (pScsiCtrl, *xferWidth); return (OK); }/********************************************************************************* templateWideXferParamsSet - set wide transfer parameters** Assume valid parameters and set the TEMPLATE's thread parameters to the* appropriate values. The actual registers are not written yet, but will* be written from the thread values when it is activated.** Transfer width is specified in SCSI transfer width exponent units. ** RETURNS: OK */LOCAL STATUS templateWideXferParamsSet ( SCSI_CTRL *pScsiCtrl, /* ptr to controller info */ UINT8 xferWidth /* wide data transfer width */ ) { /* TODO - update thread to enable/disable wide data xfers */ return OK; }/********************************************************************************* templateThreadParamsSet - 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 if parameters are OK, else ERROR.** NOMANUAL*/LOCAL STATUS templateThreadParamsSet ( TEMPLATE_THREAD * pThread, /* thread to be affected */ UINT8 offset, /* max REQ/ACK offset */ UINT8 period /* min transfer period */ ) { /* TODO - setup synch/asynch control bits */ /* TODO - setup wide control bits */ /* TODO - update device control registers if needed */ return (OK); }/******************************************************************************** templateEventTypeGet - parse status registers at interrupt time** This routine examines the device state to determine what type of event* is pending. If none is pending then a fatal error code is returned.** RETURNS: Returns an interrupt (event) type code or TEMPLATE_FATAL_ERROR.*/LOCAL int templateEventTypeGet ( SIOP * pSiop ) { int key; /* * We should be locked in interrupt context while the status * registers are being read so that there is no contention between * a synchronous thread and a bus initiated thread (reselect) */ key = intLock (); /* TODO - Read and save device status registers */ intUnlock (key); SCSI_INT_DEBUG_MSG ("templateEventTypeGet: \n", 0, 0, 0, 0, 0, 0); if (0) /* TODO - check for fatal error */ return TEMPLATE_ABORT; /* TODO - try the rest (NB order of tests can be important !) */ if (0) /* TODO - check for SCSI Bus reset */ {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -