sym895Lib.c
资源名称:ixp425BSP.rar [点击查看]
上传用户:luoyougen
上传日期:2008-05-12
资源大小:23136k
文件大小:160k
源码类别:
VxWorks
开发平台:
C/C++
- /* if ISTAT:ABRT bit is set, reset before reading the DMA status reg */
- if (intrStatus & SYM895_ISTAT_ABRT)
- SYM895_REG8_WRITE(pSiop, SYM895_OFF_ISTAT, 0x00);
- if ((intrStatus & SYM895_ISTAT_SIP) && (intrStatus & SYM895_ISTAT_DIP))
- SYM895_SCSI_DEBUG_MSG (" sym895EventTypeGet:
- Both DMA and SCSI Interrupts n", 0, 0, 0, 0, 0, 0);
- /*
- * Read the interrupt status registers if that type of
- * interrupt occurs
- */
- CACHE_PIPE_FLUSH();
- if (intrStatus & SYM895_ISTAT_DIP)
- {
- dmaStatus = SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT);
- sym895Delay ();
- }
- CACHE_PIPE_FLUSH();
- if (intrStatus & SYM895_ISTAT_SIP)
- {
- scsiStatus_0 = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST0);
- sym895Delay ();
- scsiStatus_1 = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST1);
- }
- intUnlock (key);
- }
- else
- {
- intUnlock (key);
- return (ERROR);
- }
- SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet: ISTAT : 0x%02x SIST0 : 0x%02x
- SIST1 : 0x%02x DSTAT : 0x%02x nn", intrStatus, scsiStatus_0,
- scsiStatus_1,dmaStatus,0,0);
- /* Now start checking for the source of interrupts */
- /* Fatal conditions first !! */
- if (scsiStatus_0 & SYM895_B_SGE)
- {
- SCSI_MSG ("sym895EventTypeGet: SCSI Gross Errorn ", 0, 0, 0, 0, 0, 0);
- return (SYM895_FATAL_ERROR);
- }
- if (scsiStatus_0 & SYM895_B_PAR)
- {
- SCSI_MSG ("sym895EventTypeGet: SCSI Parity Errorn", 0, 0, 0, 0, 0, 0);
- return (SYM895_FATAL_ERROR);
- }
- if (dmaStatus & SYM895_B_IID)
- {
- SCSI_MSG ("sym895EventTypeGet : IIlegal Instruction detectedn ",
- SYM895_REG32_READ (pSiop,SYM895_OFF_DSP), 0, 0, 0, 0, 0);
- return (SYM895_FATAL_ERROR);
- }
- if (dmaStatus & SYM895_B_BF)
- {
- SCSI_MSG ("sym895EventTypeGet : SCSI Bus Faultn",
- SYM895_REG32_READ (pSiop,SYM895_OFF_DSP),
- SYM895_REG32_READ (pSiop,SYM895_OFF_DBC) & 0xffffff, 0, 0, 0, 0);
- return (SYM895_FATAL_ERROR);
- }
- /* Now, non-fatal error checking: The order of checking can be important */
- if (scsiStatus_0 & SYM895_B_RST)
- {
- SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : BusReset n",
- 0, 0, 0, 0, 0, 0);
- /* Clear DMA FIFO */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3,
- SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3) |
- SYM895_CTEST3_CLF);
- return (SYM895_SCSI_BUS_RESET);
- }
- if (scsiStatus_0 & SYM895_B_UDC)
- {
- SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : Unexpected Disconnection n",
- 0, 0, 0, 0, 0, 0);
- /* Clear DMA FIFO */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3,
- SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3) |
- SYM895_CTEST3_CLF);
- return (SYM895_UNEXPECTED_DISCON);
- }
- if (scsiStatus_1 & SYM895_B_STO)
- {
- SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : Bus Timeout n",
- 0, 0, 0, 0, 0, 0);
- /* Clear DMA FIFO */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3,
- SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3) |
- SYM895_CTEST3_CLF);
- return (SYM895_SCSI_TIMEOUT);
- }
- if (scsiStatus_1 &SYM895_B_HTH)
- {
- SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : Bus handshake Timeout n",
- 0, 0, 0, 0, 0, 0);
- /* Clear DMA FIFO */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_CTEST3,
- SYM895_REG8_READ (pSiop,SYM895_OFF_CTEST3) |
- SYM895_CTEST3_CLF);
- return (SYM895_HANDSHAKE_TIMEOUT);
- }
- if (scsiStatus_1 & SYM895_B_SBMC)
- {
- SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : Bus Mode Change Detected n",
- 0, 0, 0, 0, 0, 0);
- return (SYM895_BUSMODE_CHANGED);
- }
- if (scsiStatus_1 & SYM895_B_GEN)
- {
- SYM895_SCSI_DEBUG_MSG ("sym895EventTypeGet : General Timer Expired n",
- 0, 0, 0, 0, 0, 0);
- return (SYM895_GEN_TIMER_EXPIRED);
- }
- if (scsiStatus_0 & SYM895_B_MA)
- {
- /*
- * This is a Phase Misatch interrupt when in Initiator mode and
- * signals arrertion of ATN in Target Mode.
- */
- /*
- * if in Target mode..Fatal error as this intr is supposed to be
- * disabled earlier.
- */
- if (SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL0) & SYM895_SCNTL0_TRG)
- {
- SCSI_MSG (" sym895EventTypeGet : ATN intr. in target mode n",
- 0, 0, 0, 0, 0, 0);
- return (SYM895_FATAL_ERROR);
- }
- else
- {
- /* Initiator mode */
- SYM895_SCSI_DEBUG_MSG (" sym895EventTypeGet : Phase Mismatch n",
- 0, 0, 0, 0, 0, 0);
- return (SYM895_PHASE_MISMATCH);
- }
- }
- if (dmaStatus & SYM895_B_ABT)
- {
- SYM895_SCSI_DEBUG_MSG (" sym895EventTypeGet : Script Aborted n",
- 0, 0, 0, 0, 0, 0);
- return (SYM895_SCRIPT_ABORTED);
- }
- if (dmaStatus & SYM895_B_SIR)
- {
- SYM895_SCSI_DEBUG_MSG (" sym895EventTypeGet : Script Interrupt n",
- 0, 0, 0, 0, 0, 0);
- /* return the stored interrupt vector */
- return SYM895_REG32_READ (pSiop,SYM895_OFF_DSPS);
- }
- if (dmaStatus & SYM895_B_SSI)
- {
- SYM895_SCSI_DEBUG_MSG (" sym895EventTypeGet : Single Step Interrupt n",
- 0, 0, 0, 0, 0, 0);
- return (SYM895_SINGLE_STEP);
- }
- /* No reason for the interrupt ! */
- SCSI_MSG (" sym895EventTypeGet : Spurious Interrupt n",
- 0, 0, 0, 0, 0, 0);
- return (SYM895_FATAL_ERROR);
- }
- /******************************************************************************
- *
- * sym895ThreadEvent - SCSI Controller thread event processing routine
- *
- * Forward the event to the proper handler for the thread's current role.
- *
- * If the thread is still active, update the thread context (including
- * shared memory area) and resume the thread.
- *
- * RETURNS N/A
- */
- LOCAL void sym895ThreadEvent
- (
- SYM895_THREAD * pThread,
- SYM895_EVENT * pEvent
- )
- {
- SCSI_EVENT * pScsiEvent = &pEvent->scsiEvent;
- SCSI_THREAD * pScsiThread = &pThread->scsiThread;
- SIOP * pSiop = (SIOP *) pScsiThread->pScsiCtrl;
- SYM895_SCRIPT_ENTRY entryPt;
- SYM895_SCSI_DEBUG_MSG ("sym895ThreadEvent thread 0x%08x received event %dn",
- (int) pThread, pScsiEvent->type, 0, 0, 0, 0);
- switch (pScsiThread->role)
- {
- case SCSI_ROLE_INITIATOR:
- sym895InitEvent (pThread, pEvent);
- entryPt = SYM895_SCRIPT_INIT_CONTINUE;
- break;
- case SCSI_ROLE_IDENT_INIT:
- sym895InitIdentEvent (pThread, pEvent);
- entryPt = SYM895_SCRIPT_INIT_CONTINUE;
- break;
- case SCSI_ROLE_IDENT_TARG:
- sym895TargIdentEvent (pThread, pEvent);
- entryPt = SYM895_SCRIPT_TGT_DISCONNECT;
- break;
- case SCSI_ROLE_TARGET:
- default:
- SCSI_MSG ("sym895ThreadEvent thread 0x%08x invalid role (%d)n",
- (int) pThread, pScsiThread->role, 0, 0, 0, 0);
- entryPt = SYM895_SCRIPT_TGT_DISCONNECT;
- break;
- }
- /* Resume thread if it is still connected */
- switch (pScsiThread->state)
- {
- case SCSI_THREAD_INACTIVE :
- case SCSI_THREAD_WAITING :
- case SCSI_THREAD_DISCONNECTED :
- break;
- default:
- sym895ThreadUpdate (pThread);
- if (sym895Resume (pSiop, pThread, entryPt) != OK)
- {
- SYM895_SCSI_DEBUG_MSG ("sym895ThreadEvent failed to
- resume threadn",
- 0, 0, 0, 0, 0, 0);
- sym895ThreadFail (pThread, S_scsiLib_DISCONNECTED);
- }
- break;
- }
- }
- /******************************************************************************
- *
- * sym895InitEvent - device 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 sym895InitEvent
- (
- SYM895_THREAD * pThread,
- SYM895_EVENT * pEvent
- )
- {
- SCSI_EVENT * pScsiEvent = &pEvent->scsiEvent;
- SCSI_THREAD * pScsiThread = &pThread->scsiThread;
- SCSI_CTRL * pScsiCtrl = pScsiThread->pScsiCtrl;
- /* Update controller msg in/out state after script completes */
- pScsiCtrl->msgOutState = pThread->msgOutStatus;
- pScsiCtrl->msgInState = pThread->msgInStatus;
- /* Parse script exit status; handle as necessary */
- switch (pScsiEvent->type)
- {
- case SYM895_DISCONNECTED:
- SYM895_SCSI_DEBUG_MSG ("DISCONNECT message inn", 0, 0, 0, 0, 0, 0);
- scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_DISCONNECTED);
- sym895ThreadStateSet (pThread, SCSI_THREAD_DISCONNECTED);
- break;
- case SYM895_CMD_COMPLETE:
- SYM895_SCSI_DEBUG_MSG ("COMMAND COMPLETE message inn",
- 0, 0, 0, 0, 0, 0);
- sym895ThreadComplete (pThread);
- break;
- case SYM895_SELECTED:
- case SYM895_RESELECTED:
- SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x
- (re)selection.n", (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadDefer (pThread);
- break;
- case SYM895_MESSAGE_OUT_SENT:
- (void) scsiMsgOutComplete (pScsiCtrl, pScsiThread);
- break;
- case SYM895_MESSAGE_IN_RECVD:
- (void) scsiMsgInComplete (pScsiCtrl, pScsiThread);
- break;
- case SYM895_NO_MSG_OUT:
- /*
- * The target has requested a message out when there is none
- * pending. Set up a NO-OP message to be sent when thread is
- * resumed.
- *
- * The script could handle this on its own, but arguably the
- * host should be involved as it may represent an error.
- */
- pScsiCtrl->msgOutBuf[0] = SCSI_MSG_NO_OP;
- pScsiCtrl->msgOutLength = 1;
- pScsiCtrl->msgOutState = SCSI_MSG_OUT_NONE; /* sic */
- break;
- case SYM895_EXT_MESSAGE_SIZE:
- /*
- * The SIOP has just read the length byte for an extended
- * message in. The shared memory area is updated with the
- * appropriate length just before the thread is resumed (see
- * "sym895ThreadUpdate()".
- */
- break;
- case SYM895_PHASE_MISMATCH:
- if (sym895PhaseMismatch (pThread, pThread->busPhase,
- pEvent->remCount) != OK)
- {
- sym895ThreadFail (pThread, errno);
- }
- break;
- case SYM895_SCSI_TIMEOUT:
- SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x
- select timeout.n", (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT);
- break;
- /*
- * There is no error no. equivalent to this timeout.
- * So S_scsiLib_SELECT_TIMEOUT is used.
- */
- case SYM895_HANDSHAKE_TIMEOUT:
- SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x
- Bus Handshake timeout.n", (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT);
- break;
- case SYM895_SCRIPT_ABORTED:
- SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x abortedn",
- (int) pThread, 0, 0, 0, 0, 0);
- break;
- case SYM895_NO_IDENTIFY:
- SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x
- No Identify message.n", (int) pThread, 0, 0, 0, 0, 0);
- /*
- * There should be an ErrorNumber for this event. Scsi2Lib.h
- * does'nt define any number for this. So use this for the moment.
- */
- sym895ThreadFail (pThread, S_scsiLib_SELECT_TIMEOUT);
- break;
- case SCSI_EVENT_BUS_RESET:
- SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x bus resetn",
- (int) pThread, 0, 0, 0, 0, 0);
- /* Do not try to resume this thread. SCSI mgr will tidy up. */
- sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
- break;
- case SYM895_UNEXPECTED_DISCON:
- /* not really unexpected after an abort message ... */
- SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x
- unexpected disconnectionn",
- (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadFail (pThread, S_scsiLib_DISCONNECTED);
- break;
- case SYM895_ILLEGAL_PHASE:
- SYM895_SCSI_DEBUG_MSG ("sym895InitEvent thread 0x%08x illegal phase
- requested.n", (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadFail (pThread, S_scsiLib_INVALID_PHASE);
- break;
- default:
- SCSI_MSG ("sym895InitEvent invalid event type (%d)n",
- pScsiEvent->type, 0, 0, 0, 0, 0);
- break;
- }
- }
- /******************************************************************************
- *
- * sym895Activate - activate a script corresponding to a new thread
- *
- * Request activation of (the script for) a new thread, if possible; do not
- * wait for the script to complete (or even start) executing. Activation
- * is requested by signalling the controller, which causes an interrupt.
- * The script is started by the ISR in response to this event.
- *
- * There is a race condition inherent in SCSI between the synchronous
- * activation of a thread (i.e., execution of this routine) and asynchronous
- * activation of a thread as a result of selection or reselection. The SCSI
- * manager is designed to take account of this, and assumes that either the
- * new thread has been successfully activated or a (re)selection has taken
- * place, as determined by the next event it receives. In the case when
- * (re)selection occurs, the current activation request is deferred and
- * retried later.
- *
- * Therefore, an activation request is lodged only if the controller is
- * currently PASSIVE (waiting for (re)selection or a host command). If the
- * controller is IDLE, (re)selection is assumed to have already occurred.
- * Note that this is not an error condition; there is no way for the
- * caller to distinguish the two cases, because even if the thread appears
- * to have been activated it may yet be "pre-empted" by (re)selection.
- *
- * The controller should never be ACTIVE. If it is, the SCSI manager has
- * tried to activate multiple concurrent threads on the controller, which
- * indicates a major (software) disaster.
- *
- * NOTE Interrupt locking is required to ensure that the correct action
- * is taken once the controller state has been checked.
- *
- * RETURNS OK, or ERROR if the controller is in an invalid state (this
- * indicates a major software failure).
- */
- LOCAL STATUS sym895Activate
- (
- SIOP * pSiop, /* pointer to SIOP structure */
- SYM895_THREAD * pThread /* pointer to thread structure */
- )
- {
- STATUS status = OK;
- int key;
- if (pSiop->isCmdPending)
- {
- SCSI_MSG ("sym895Activate: activation request already pending !n",
- 0, 0, 0, 0, 0, 0);
- return (ERROR);
- }
- /*
- * Check Controller state, set a new command pending and signal it
- * if necessary.
- */
- key = intLock ();
- /*
- * If the SIOP is connected and it is in the passive state, means that an
- * asynchronous bus event like a select or reselect just occurred. This
- * event has priority over this thread, therefore change the state of
- * the controller to ACTIVE.
- */
- if ((pSiop->state == SYM895_STATE_PASSIVE) &&
- (SYM895_REG8_READ (pSiop,SYM895_OFF_ISTAT) & SYM895_ISTAT_CON))
- pSiop->state = SYM895_STATE_IDLE;
- switch (pSiop->state)
- {
- case SYM895_STATE_IDLE:
- status = OK;
- break;
- case SYM895_STATE_PASSIVE: /* do nothing */
- pSiop->pNewThread = pThread;
- pSiop->isCmdPending = TRUE;
- /*
- * Signal the wait for (re) select script which then jumps to
- * the relative alternate address.
- */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_ISTAT,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT) |
- SYM895_ISTAT_SIGP));
- status = OK;
- break;
- case SYM895_STATE_ACTIVE:
- default:
- status = ERROR;
- break;
- }
- intUnlock (key);
- if (status != OK)
- {
- SCSI_MSG ("sym895Activate: invalid controller state. n",
- pSiop->state, 0, 0, 0, 0, 0);
- errnoSet (S_scsiLib_SOFTWARE_ERROR);
- }
- return (status);
- }
- /******************************************************************************
- *
- * sym895Abort - abort the active script corresponding to the current thread
- *
- * Check that there is currently an active script running. If so, set the
- * SCSI Controller Abort flag which will halt the script and cause an interrupt.
- *
- * RETURNS N/A
- */
- LOCAL void sym895Abort
- (
- SIOP * pSiop /* pointer to controller structure */
- )
- {
- int key;
- STATUS status;
- key = intLock ();
- switch (pSiop->state)
- {
- case SYM895_STATE_IDLE:
- case SYM895_STATE_PASSIVE:
- status = OK;
- break;
- case SYM895_STATE_ACTIVE:
- SYM895_REG8_WRITE(pSiop, SYM895_OFF_ISTAT,
- (SYM895_REG8_READ (pSiop,SYM895_OFF_ISTAT) |
- SYM895_ISTAT_ABRT));
- status = OK;
- break;
- default:
- status = ERROR;
- break;
- }
- intUnlock (key);
- if (status != OK)
- {
- SCSI_MSG("sym895Abort: thread = 0x%0xx: invalid state (%d) n",
- pSiop->state, 0, 0, 0, 0, 0);
- }
- }
- /******************************************************************************
- *
- * sym895ScriptStart - start the SCSI Controller executing a script
- *
- * Restore the SCSI Controller register context, including the shared memory
- * area, from the thread context. Put the address of the script entry point
- * into the DSP register. If not in single-step mode, start the script.
- *
- * RETURNS N/A
- */
- LOCAL void sym895ScriptStart
- (
- SIOP * pSiop, /* pointer to SCSI Controller info */
- SYM895_THREAD * pThread, /* SM895 thread info */
- SYM895_SCRIPT_ENTRY entryId /* routine address entry point */
- )
- {
- int key;
- BOOL isManualMode;
- SYM895_SCSI_DEBUG_MSG ("sym895ScriptStart: %x %d n",
- (UINT32)pThread, (UINT32)entryId, 0, 0, 0, 0);
- key = intLock ();
- /* Set the Current Thread Pointer */
- pSiop->pCurThread = pThread;
- /* Restore the SCSI Controller register context for this thread. */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHA0, pThread->nHostFlags);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHA1, pThread->msgOutStatus);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHA2, pThread->msgInStatus);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHA3, pThread->targetId);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHA3, pThread->busPhase);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SXFER, pThread->sxfer);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCNTL3, pThread->scntl3);
- /*
- * Scatter Gather operations have to be initiated by Scsi Manager task.
- * As of now, this feature is only implemented, but not tested. The
- * SCSI Scripts include BlockMOVE instructions to perform these operations.
- */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHC0, pThread->isScatTransfer);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHC1, pThread->totalScatElements);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCRATCHC2, pThread->noRemaining);
- /*
- * Set the shared data address, load the script start address,
- * then start the SCSI Controller unless it's in single-step mode.
- */
- SYM895_REG32_WRITE (pSiop, SYM895_OFF_DSA,
- (UINT32)SYM895_VIRT_TO_PHYS (pThread->pShMem));
- /*
- * check if the SCRIPT DMA fetch is manual. If manual, scripts will not
- * start until DMA start bit in DCNTL register is set
- */
- isManualMode = ((SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE) &
- SYM895_DMODE_MAN) == SYM895_DMODE_MAN) ? TRUE : FALSE;
- SYM895_REG32_WRITE (pSiop, SYM895_OFF_DSP,
- (UINT32)SYM895_VIRT_TO_PHYS (
- (UINT32)sym895ScriptEntry [entryId]));
- /*
- * Check if Single stepping is enabled. Otherwise issue the START SCRIPTS
- * command by writing the DMA start bit in DCNTL register.
- */
- if (pSiop->isSingleStep)
- {
- SCSI_MSG ("sym895ScriptStart: Single Step required to start script.n",
- 0, 0, 0, 0, 0, 0);
- }
- else
- {
- CACHE_PIPE_FLUSH();
- if (isManualMode)
- {
- /* Write the DMA Start bit */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL,
- SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
- SYM895_DCNTL_STD);
- /*
- * vxEieio() is a PPC family specific routine that makes sure that
- * the SCSI registers written above are executed in order and
- * completely before continuing on. In the case of the faster PPC
- * processors, it has been found that without this flushing of the
- * pipes the processor is much faster than the SIOP, and causes
- * erratic behaviour like bus errors and invalid events.
- */
- CACHE_PIPE_FLUSH();
- sym895Delay (); /* XXX - needs to be tuned better for fast PPCs */
- CACHE_PIPE_FLUSH();
- }
- }
- intUnlock (key);
- CACHE_PIPE_FLUSH();
- }
- /*******************************************************************************
- *
- * sym895ThreadUpdate - update the thread structure for a current SCSI command
- *
- * Update the dynamic data (e.g. data pointers, transfer parameters) in
- * the thread to reflect the latest state of the corresponding physical device.
- *
- * RETURNS N/A
- *
- * NOMANUAL
- */
- LOCAL void sym895ThreadUpdate
- (
- SYM895_THREAD * pThread /* pointer thread structure */
- )
- {
- SCSI_THREAD * pScsiThread = &pThread->scsiThread;
- SCSI_CTRL * pScsiCtrl = pScsiThread->pScsiCtrl;
- SYM895_SHARED * pShMem = pThread->pShMem;
- UINT msgOutSize;
- UINT msgInSize;
- UINT flags = 0;
- SIOP * pSiop = (SIOP *) pScsiCtrl;
- #ifdef SCATTER_GATHER
- UINT count;
- #endif
- /*
- * If there is an identification message, ensure ATN is asserted
- * during (re)selection.
- */
- if (pScsiThread->identMsgLength != 0)
- flags |= SYM895_FLAGS_IDENTIFY;
- /* update SIOP register context */
- pThread->nHostFlags = flags;
- pThread->msgOutStatus = pScsiCtrl->msgOutState;
- pThread->msgInStatus = pScsiCtrl->msgInState;
- /* Update dynamic message in/out sizes */
- if (pScsiCtrl->msgOutState == SCSI_MSG_OUT_NONE)
- msgOutSize = 0;
- else
- msgOutSize = pScsiCtrl->msgOutLength;
- if (pScsiCtrl->msgInState != SCSI_MSG_IN_EXT_MSG_DATA)
- msgInSize = 0;
- else if ((msgInSize = pScsiCtrl->msgInBuf [SCSI_EXT_MSG_LENGTH_BYTE]) == 0)
- msgInSize = SCSI_EXT_MSG_MAX_LENGTH;
- /* Update commands in shared memory area */
- pShMem->command.size = SYM895_SWAP_32 (pScsiThread->cmdLength);
- pShMem->command.addr = (UINT8 *) SYM895_SWAP_32
- (
- (UINT32) SYM895_VIRT_TO_PHYS
- ((UINT) pScsiThread->cmdAddress)
- );
- #ifdef SCATTER_GATHER /* scatter gather memory support */
- /*
- * For Scatter-Gather moves across SCSI Bus, a series of addresses and
- * byte counts from these addresses are needed. Addresses indicate from
- * where all in memory, data is to be transferred. Byte counts indicate
- * the amount of data to be transferred from individual addresses. These
- * addresses and byte counts are assumed to be residing in contiguous
- * memory. We assume support from SCSI Manager, to provide with the above
- * addresses & counts.Also, the structure elements "activeDataElements" is
- * assumed to be part of SCSI_THREAD structure (which is not as of now).
- */
- /*
- * "activeDataElements" is assumed to be in SCSI_THREAD and is supposed
- * to hold the number of scattered locations from where the data is to
- * be transferred. Its responsibilty of SCSI Manager to initialise this
- * once this is part of SCSI_THREAD.
- */
- pShMem->scatData.noElems = pScsiThread->activeDataElements;
- /*
- * Now initialise the pointers from where data is to transferred.
- * These are set of addresses, which are assumed to contain the
- * data locations. They do not exist now. Compiling this will
- * result in error.
- */
- for (count = 0; count < pShMem->scatData.noElems; count++ )
- {
- pShMem->scatData.Elements[count].size=
- (UINT8 *) SYM895_SWAP_32
- (
- (UINT32) SYM895_VIRT_TO_PHYS
- ((UINT) pScsiThread->activeDataLength[count])
- );
- pShMem->scatData.Elements[count].addr=
- (UINT8 *) SYM895_SWAP_32
- (
- (UINT32) SYM895_VIRT_TO_PHYS
- ((UINT) pScsiThread->activeDataAddress[count])
- );
- }
- /*
- * The way this feature was tested with out any support from SCSI lib...
- * For any data transfer across scsi BUS, the current thread structure
- * contains a pointer and count of the data to be transferred. To emulate
- * scattered operation, the data is split in to 2 parts. Now the byte
- * count will be half of the number as passed by library. The pointers to
- * the data can be obtained by adding the byte count to the pointer
- * initially passed. In SCRIPTS assembly. when it comes to the DATA OUT
- * phase, check whether scattered data transfer is requested or not
- * by checking the value passed in SCRATCHC0. If yes, the SCRIPTS will
- * transfer data from various locations (though contiguous but not
- * scattered).
- */
- #if 0
- pShMem->scatData.noElems = 2;
- pShMem->scatData.Elements[0].size = (SYM895_SWAP_32
- (pScsiThread->activeDataLength))/2;
- pShMem->scatData.Elements[0].addr = (UINT8 *) SYM895_SWAP_32
- (
- (UINT32) SYM895_VIRT_TO_PHYS
- ((UINT) pScsiThread->activeDataAddress)
- );
- pShMem->scatData.Elements[1].size = (SYM895_SWAP_32
- (pScsiThread->activeDataLength))/2;
- pShMem->scatData.Elements[1].addr = (UINT8 *) SYM895_SWAP_32
- (
- (UINT32) SYM895_VIRT_TO_PHYS
- ((UINT)(pScsiThread->activeDataAddress +
- (pScsiThread->activeDataLength)/2))
- );
- #endif
- /* Tell scripts that now it is scattered data to be transferred.. */
- pThread->isScatTransfer = TRUE;
- pThread->totalScatElements = pShMem->scatData.noElems;
- pThread->noRemaining = pShMem->scatData.noElems;
- #else
- pShMem->dataOut.size = SYM895_SWAP_32 (pScsiThread->activeDataLength);
- pShMem->dataOut.addr = (UINT8 *) SYM895_SWAP_32
- (
- (UINT32) SYM895_VIRT_TO_PHYS
- ((UINT) pScsiThread->activeDataAddress)
- );
- pThread->isScatTransfer = FALSE;
- pThread->totalScatElements = 0;
- pThread->noRemaining = 0;
- #endif /* SCATTER_GATHER */
- pShMem->dataIn.size = SYM895_SWAP_32 (pScsiThread->activeDataLength);
- pShMem->dataIn.addr = (UINT8 *) SYM895_SWAP_32
- (
- (UINT32) SYM895_VIRT_TO_PHYS
- ((UINT) pScsiThread->activeDataAddress)
- );
- pShMem->status.size = SYM895_SWAP_32 (pScsiThread->statusLength);
- pShMem->status.addr = (UINT8 *) SYM895_SWAP_32
- (
- (UINT32) SYM895_VIRT_TO_PHYS
- ((UINT) pScsiThread->statusAddress)
- );
- /*
- * The identOut pointer and buffer are initialised to the buffer allocated
- * in the pSiop structure. These used to be intialised to
- * pScsiThread->identMsg/identMsgLength. To suppport Wide/Sync. transfers
- * the MAX message length is increased. Ideally, this should have been taken
- * in Scsi2Lib.h where the MAX Message length is defined.
- */
- pShMem->identOut.size = SYM895_SWAP_32 (pSiop->identMsgLength);
- pShMem->identOut.addr = (UINT8 *) SYM895_SWAP_32
- (
- (UINT32) SYM895_VIRT_TO_PHYS
- ((UINT) pSiop->identMsg)
- );
- pShMem->msgOut.size = SYM895_SWAP_32 (msgOutSize);
- pShMem->msgInRest.size = SYM895_SWAP_32 (msgInSize);
- }
- /******************************************************************************
- *
- * sym895ThreadComplete - 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 sym895ThreadComplete
- (
- SYM895_THREAD * pThread
- )
- {
- SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
- SYM895_SCSI_DEBUG_MSG ("sym895ThreadComplete thread 0x%08x completedn",
- (int) pThread, 0, 0, 0, 0, 0);
- if (pScsiThread->state == SCSI_THREAD_ABORTING)
- {
- pScsiThread->status = ERROR;
- pScsiThread->errNum = S_scsiLib_ABORTED;
- }
- else
- {
- pScsiThread->status = OK;
- pScsiThread->errNum = 0;
- }
- sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
- scsiCacheSynchronize (pScsiThread, SCSI_CACHE_POST_COMMAND);
- scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_COMPLETED);
- }
- /******************************************************************************
- *
- * sym895ThreadDefer - defer execution of a thread
- *
- * Set the thread's state to INACTIVE and notify the SCSI manager of the
- * deferral event.
- *
- * This routine is invoked when a re-selection event occurs.
- *
- * RETURNS N/A
- */
- LOCAL void sym895ThreadDefer
- (
- SYM895_THREAD * pThread
- )
- {
- SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
- SYM895_SCSI_DEBUG_MSG ("sym895ThreadDefer thread 0x%08x deferredn",
- (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
- scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_DEFERRED);
- }
- /******************************************************************************
- *
- * sym895ThreadFail - 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 sym895ThreadFail
- (
- SYM895_THREAD * pThread,
- int errNum
- )
- {
- SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
- SYM895_SCSI_DEBUG_MSG ("sym895ThreadFail 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;
- sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
- scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_COMPLETED);
- }
- /******************************************************************************
- *
- * sym895ThreadStateSet - set the state of a thread
- *
- * This is really just a place-holder for debugging and possible future
- * enhancements such as state-change logging.
- *
- * RETURNS N/A
- */
- LOCAL void sym895ThreadStateSet
- (
- SYM895_THREAD * pThread, /* pointer to thread structure */
- SCSI_THREAD_STATE state
- )
- {
- SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
- SYM895_SCSI_DEBUG_MSG ("sym895ThreadStateSet: thread 0x%08x %d -> %dn",
- (int) pThread, pScsiThread->state, state, 0, 0, 0);
- pScsiThread->state = state;
- }
- /******************************************************************************
- *
- * sym895PhaseMismatch - recover from a SCSI bus phase mismatch
- *
- * This routine does whatever is required to keep the pointers, counts, etc.
- * used by task-level software in step when a SCSI phase mismatch occurs.
- *
- * The interrupt-level mismatch processing has stored the phase of the
- * information transfer before the mismatch, and the number of bytes
- * remaining to be transferred. See "sym895RemainderGet()".
- *
- * Note that the only phase mismatches supported at this level are
- *
- * 1) during data in/out phases - presumably because the target has
- * transferred as much data as it intends to before sending a message
- * in (typically DISCONNECT or COMMAND COMPLETE). Recovery consists
- * of updating the active data pointer/count according to the number
- * of data bytes actually transferred before the mismatch.
- *
- * 2) during a message out phase - presumably because the target does not
- * understand our outgoing message and is sending a MESSAGE REJECT
- * message, or similar. No recovery is needed here - it's all done
- * when the MESSAGE REJECT message has been received (see routine
- * "scsiMsgOutReject()").
- *
- * 3) during a message in phase - presumably because ATN is asserted
- * to abort or reject an incoming message. No recovery is needed here -
- * it's done by the thread management code, which should have enough
- * state information to know what to do.
- *
- * RETURNS OK, or ERROR for an unsupported or invalid phase
- *
- * NOMANUAL
- */
- LOCAL STATUS sym895PhaseMismatch
- (
- SYM895_THREAD * pThread, /* pointer to thread structure */
- int phase, /* bus phase before mismatch */
- UINT remCount /* # bytes not yet transferred */
- )
- {
- SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
- UINT xferCount;
- switch (phase)
- {
- case SCSI_DATA_IN_PHASE:
- xferCount = SYM895_SWAP_32(pThread->pShMem->dataIn.size) - remCount;
- pScsiThread->activeDataAddress += xferCount;
- pScsiThread->activeDataLength -= xferCount;
- SYM895_SCSI_DEBUG_MSG ("sym895PhaseMismatch data transfer aborted
- (%d bytes transferred).n",
- xferCount, 0, 0, 0, 0, 0);
- break;
- case SCSI_DATA_OUT_PHASE:
- xferCount = SYM895_SWAP_32(pThread->pShMem->dataOut.size) - remCount;
- pScsiThread->activeDataAddress += xferCount;
- pScsiThread->activeDataLength -= xferCount;
- SYM895_SCSI_DEBUG_MSG ("sym895PhaseMismatch data transfer aborted
- (%d bytes transferred).n",
- xferCount, 0, 0, 0, 0, 0);
- break;
- case SCSI_MSG_OUT_PHASE:
- SYM895_SCSI_DEBUG_MSG ("sym895PhaseMismatch message out aborted "
- "(%d of %d bytes sent).n",
- pScsiThread->pScsiCtrl->msgOutLength,
- pScsiThread->pScsiCtrl->msgOutLength - remCount,
- 0, 0, 0, 0);
- break;
- case SCSI_MSG_IN_PHASE:
- SYM895_SCSI_DEBUG_MSG("sym895PhaseMismatch message in aborted "
- "(%d bytes received).n",
- pScsiThread->pScsiCtrl->msgInLength,
- 0, 0, 0, 0, 0);
- break;
- case SCSI_COMMAND_PHASE:
- case SCSI_STATUS_PHASE:
- SYM895_SCSI_DEBUG_MSG ("sym895PhaseMismatch unsupported
- phase (%d).n", phase, 0, 0, 0, 0, 0);
- return (ERROR);
- default:
- SCSI_MSG ("sym895PhaseMismatch invalid phase (%d).n",
- phase, 0, 0, 0, 0, 0);
- return (ERROR);
- }
- return (OK);
- }
- /******************************************************************************
- *
- * sym895InitIdentEvent - identification thread event processing
- *
- * 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 sym895InitIdentEvent
- (
- SYM895_THREAD * pThread,
- SYM895_EVENT * pEvent
- )
- {
- SCSI_EVENT * pScsiEvent = (SCSI_EVENT *) pEvent;
- SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
- SCSI_CTRL * pScsiCtrl = pScsiThread->pScsiCtrl;
- /* Update controller msg in/out state after script completes */
- pScsiCtrl->msgOutState = pThread->msgOutStatus;
- pScsiCtrl->msgInState = pThread->msgInStatus;
- /* Parse script exit status; handle as necessary */
- switch (pScsiEvent->type)
- {
- case SYM895_RESELECTED:
- pScsiThread->nBytesIdent = pScsiEvent->nBytesIdent;
- bcopy ((char *) pScsiCtrl->identBuf,
- (char *) pScsiThread->identMsg,
- pScsiThread->nBytesIdent);
- sym895ThreadStateSet (pThread, SCSI_THREAD_IDENT_IN);
- sym895IdentInContinue (pThread);
- break;
- case SYM895_MESSAGE_OUT_SENT:
- /*
- * This will be after "ABORT (TAG)" msg has sent.
- * The target will disconnect any time; it may have already
- * done so, in which case we won't be able to resume the
- * thread, but no matter.
- */
- break;
- case SYM895_MESSAGE_IN_RECVD:
- /*
- * Continue parsing the identification message. It
- * should by now be complete.
- *
- * First byte of ident msg is already in ident buffer.
- * Remaining bytes are in the normal message input buffer.
- * This should always be a two-byte message (viz. QUEUE TAG);
- * it would be nicer if there were a way to avoid hard-coding
- * this.
- */
- bcopy ((char *) pScsiCtrl->msgInBuf,
- (char *) pScsiThread->identMsg + pScsiThread->nBytesIdent,2);
- pScsiThread->nBytesIdent += 2;
- sym895IdentInContinue (pThread);
- break;
- case SYM895_SCRIPT_ABORTED:
- SYM895_SCSI_DEBUG_MSG ("sym895InitIdentEvent thread 0x%08x
- abortedn", (int) pThread, 0, 0, 0, 0, 0);
- break;
- case SYM895_DISCONNECTED:
- SYM895_SCSI_DEBUG_MSG ("sym895InitIdentEvent thread 0x%08x"
- "disconnectedn",
- (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadFail (pThread, S_scsiLib_DISCONNECTED);
- break;
- case SYM895_SCSI_BUS_RESET:
- SYM895_SCSI_DEBUG_MSG ("sym895InitIdentEvent thread 0x%08x bus
- resetn", (int) pThread, 0, 0, 0, 0, 0);
- /* Do not try to resume this thread. SCSI mgr will tidy up. */
- sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
- break;
- case SYM895_UNEXPECTED_DISCON:
- /* not really unexpected after an abort message ... */
- SYM895_SCSI_DEBUG_MSG ("sym895InitIdentEvent thread 0x%08x "
- "unexpected disconnectionn",
- (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadFail (pThread, S_scsiLib_DISCONNECTED);
- break;
- case SYM895_ILLEGAL_PHASE:
- SYM895_SCSI_DEBUG_MSG ("sym895InitIdentEvent thread 0x%08x "
- "illegal phase requested.n",
- (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadFail (pThread, S_scsiLib_INVALID_PHASE);
- break;
- default:
- SCSI_MSG ("sym895InitIdentEvent invalid event type (%d)n",
- pScsiEvent->type, 0, 0, 0, 0, 0);
- break;
- }
- }
- /******************************************************************************
- *
- * sym895TargIdentEvent - SYM 53C895 identification thread event processing
- *
- * 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
- *
- * NOMANUAL
- */
- LOCAL void sym895TargIdentEvent
- (
- SYM895_THREAD * pThread,
- SYM895_EVENT * pEvent
- )
- {
- SCSI_EVENT * pScsiEvent = (SCSI_EVENT *) pEvent;
- SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
- SCSI_CTRL * pScsiCtrl = pScsiThread->pScsiCtrl;
- /*
- * Update controller msg in/out state after script completes
- */
- pScsiCtrl->msgOutState = pThread->msgOutStatus;
- pScsiCtrl->msgInState = pThread->msgOutStatus;
- /*
- * Parse script exit status; handle as necessary
- */
- switch (pScsiEvent->type)
- {
- case SYM895_SELECTED:
- pScsiThread->nBytesIdent = pScsiEvent->nBytesIdent;
- bcopy ((char *) pScsiCtrl->identBuf,
- (char *) pScsiThread->identMsg,
- pScsiThread->nBytesIdent);
- sym895ThreadStateSet (pThread, SCSI_THREAD_IDENT_IN);
- break;
- case SYM895_DISCONNECTED:
- SYM895_SCSI_DEBUG_MSG ("sym895TargIdentEvent: thread 0x%08x:"
- " disconnectedn",
- (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
- break;
- case SYM895_SCSI_BUS_RESET:
- SYM895_SCSI_DEBUG_MSG ("sym895TargIdentEvent: thread 0x%08x:
- bus resetn",(int) pThread, 0, 0, 0, 0, 0);
- /* Do not try to resume this thread. SCSI mgr will tidy up. */
- sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
- break;
- case SYM895_UNEXPECTED_DISCON:
- SYM895_SCSI_DEBUG_MSG ("sym895TargIdentEvent: thread 0x%08x: "
- "unexpected disconnectionn",
- (int) pThread, 0, 0, 0, 0, 0);
- sym895ThreadStateSet (pThread, SCSI_THREAD_INACTIVE);
- break;
- default:
- SCSI_MSG ("sym895TargIdentEvent: invalid event type (%d)n",
- pScsiEvent->type, 0, 0, 0, 0, 0);
- break;
- }
- }
- /******************************************************************************
- *
- * sym895Resume - resume a script corresponding to a suspended thread
- *
- * NOTE the script can only be resumed if the controller is currently idle.
- * To avoid races, interrupts must be locked while this is checked and the
- * script re-started.
- *
- * Reasons why the controller might not be idle include SCSI bus reset and
- * unexpected disconnection, both of which might occur in practice. Hence
- * this is not considered to be a major software error.
- *
- * RETURNS OK, or ERROR if the controller is in an invalid state (this
- * should not be treated as a major software failure).
- */
- LOCAL STATUS sym895Resume
- (
- SIOP * pSiop, /* pointer to controller structure */
- SYM895_THREAD * pThread, /* pointer to thread structure */
- SYM895_SCRIPT_ENTRY entryId /* entry point of script to resume */
- )
- {
- STATUS status;
- int key;
- /* Check validity of connection and start script if OK */
- key = intLock ();
- switch (pSiop->state)
- {
- case SYM895_STATE_IDLE:
- SYM895_SCSI_DEBUG_MSG ("sym895Resume thread 0x%08x"
- " state %d -> %dn",
- (int) pThread,
- SYM895_STATE_IDLE, SYM895_STATE_ACTIVE,
- 0, 0, 0);
- sym895ScriptStart (pSiop, pThread, entryId);
- pSiop->state = SYM895_STATE_ACTIVE;
- status = OK;
- break;
- case SYM895_STATE_PASSIVE:
- case SYM895_STATE_ACTIVE:
- default:
- status = ERROR;
- break;
- }
- intUnlock (key);
- return (status);
- }
- /******************************************************************************
- *
- * sym895IdentInContinue - continue incoming identification
- *
- * Parse the message built up so far. If it is not yet complete, do nothing.
- * If the message is complete, attempt to reconnect the thread it identifies,
- * and deactivate this thread (the identification thread is no longer active).
- * Otherwise (identification has failed), abort the identification sequence.
- *
- * RETURNS N/A
- */
- LOCAL void sym895IdentInContinue
- (
- SYM895_THREAD * pThread
- )
- {
- SCSI_THREAD * pNewThread;
- SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
- SCSI_CTRL * pScsiCtrl = pScsiThread->pScsiCtrl;
- SCSI_IDENT_STATUS status;
- SCSI_THREAD_STATE state;
- status = scsiIdentMsgParse (pScsiCtrl, pScsiThread->identMsg,
- pScsiThread->nBytesIdent,
- &pScsiThread->pScsiPhysDev,
- &pScsiThread->tagNumber);
- switch (status)
- {
- case SCSI_IDENT_INCOMPLETE:
- state = SCSI_THREAD_IDENT_IN;
- break;
- case SCSI_IDENT_COMPLETE:
- scsiMgrThreadEvent (pScsiThread, SCSI_THREAD_EVENT_RECONNECTED);
- if ((pNewThread = scsiMgrPhysDevActiveThreadFind (
- pScsiThread->pScsiPhysDev,
- pScsiThread->tagNumber)) == 0)
- {
- state = SCSI_THREAD_IDENT_ABORTING;
- }
- else
- {
- sym895ThreadReconnect ((SYM895_THREAD *) pNewThread);
- state = SCSI_THREAD_INACTIVE;
- }
- break;
- case SCSI_IDENT_FAILED:
- state = SCSI_THREAD_IDENT_ABORTING;
- break;
- default:
- SCSI_MSG ("sym895IdentInContinue invalid ident status (%d)n",
- status, 0, 0, 0, 0, 0);
- state = SCSI_THREAD_INACTIVE;
- break;
- }
- if (state == SCSI_THREAD_IDENT_ABORTING)
- sym895ThreadAbort ((SIOP *) pScsiCtrl, pThread);
- sym895ThreadStateSet (pThread, state);
- }
- /******************************************************************************
- *
- * sym895ThreadReconnect - reconnect a thread
- *
- * Restore the SCSI pointers for the thread (this really should be in a more
- * generic section of code - perhaps part of the SCSI manager's thread event
- * procesing ?). Update the newly-connected thread's context (including
- * shared memory area) and resume it. Set the thread's state to ESTABLISHED.
- *
- * RETURNS N/A
- *
- * NOMANUAL
- */
- LOCAL void sym895ThreadReconnect
- (
- SYM895_THREAD * pThread
- )
- {
- SCSI_THREAD * pScsiThread = (SCSI_THREAD *) pThread;
- SCSI_CTRL * pScsiCtrl = pScsiThread->pScsiCtrl;
- SIOP * pSiop = (SIOP *) pScsiCtrl;
- SYM895_SCSI_DEBUG_MSG ("sym895ThreadReconnect reconnecting thread 0x%08xn",
- (int) pThread, 0, 0, 0, 0, 0);
- pScsiCtrl->pThread = pScsiThread;
- /* Implied RESTORE POINTERS action see "scsiMsgInComplete ()" */
- pScsiThread->activeDataAddress = pScsiThread->savedDataAddress;
- pScsiThread->activeDataLength = pScsiThread->savedDataLength;
- sym895ThreadUpdate (pThread);
- if (sym895Resume (pSiop, pThread, SYM895_SCRIPT_INIT_CONTINUE) != OK)
- {
- SYM895_SCSI_DEBUG_MSG ("sym895ThreadReconnect failed to resume thread.n",
- 0, 0, 0, 0, 0, 0);
- sym895ThreadFail (pThread, S_scsiLib_DISCONNECTED);
- return;
- }
- sym895ThreadStateSet (pThread, SCSI_THREAD_ESTABLISHED);
- }
- /******************************************************************************
- *
- * sym895StepEnable - Enable/disable script single step
- *
- * Enable/disable single step facility on SYM895 chip. Also, unmask/mask single
- * step interrupt in Dien register. Before any SCSI execution you just have to
- * use sym895StepEnable (pSiop, TRUE) to run in single step mode.
- *
- * To run a script step use sym895SingleStep(pSiop).
- * To disable use sym895StepEnable (pSiop, FALSE).
- *
- * RETURNS: N/A
- *
- * NOMANUAL
- */
- void sym895StepEnable
- (
- SIOP * pSiop, /* pointer to SIOP info */
- BOOL enable /* TRUE => enable single-step */
- )
- {
- if (enable)
- {
- /* enable single-step interrupt */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DIEN,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DIEN) |
- SYM895_B_SSI));
- /* set single-step mode */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
- SYM895_DCNTL_SSM));
- /* disable manual Start */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DMODE,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE) &
- ~SYM895_DMODE_MAN));
- }
- else
- {
- /* unset single-step mode */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) &
- ~SYM895_DCNTL_SSM));
- /* disable single-step interrupt */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DIEN,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DIEN) &
- ~SYM895_B_SSI));
- /* enable manual Start */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DMODE,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE) |
- SYM895_DMODE_MAN));
- }
- pSiop->isSingleStep = enable;
- }
- /******************************************************************************
- *
- * sym895SingleStep - Perform a single step
- *
- * Perform a single step by writing the STD bit in the DCNTL register.
- * The parameter is a pointer to the SIOP information.
- *
- * RETURNS: N/A
- *
- * NOMANUAL
- */
- void sym895SingleStep
- (
- SIOP * pSiop, /* pointer to SIOP info */
- BOOL verbose /* show all registers */
- )
- {
- UINT * siopPc;
- /*
- * Start the SIOP: if not in single-step mode it will then continue
- * the normal instruction sequence. If in single-step mode, wait
- * until one instruction has been executed.
- */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
- SYM895_DCNTL_STD));
- if (!pSiop->isSingleStep)
- return;
- semTake (pSiop->singleStepSem, WAIT_FOREVER);
- /*
- * Allow any tasks using SCSI to get a look-in - they may change the
- * controller state, in which case we'd like to see that change now
- * rather than next time.
- */
- taskDelay (sysClkRateGet()/ 20); /* this needs to be tuned */
- /* Show what the SIOP is about to do */
- if (pSiop->state == SYM895_STATE_IDLE)
- SCSI_MSG("SYM895 is idle.nn", 0, 0, 0, 0, 0, 0);
- else
- {
- siopPc = (UINT *)SYM895_REG32_READ (pSiop, SYM895_OFF_DSP);
- /* mask PCI's view of memory */
- siopPc = (UINT *)((UINT) siopPc & 0x7fffffff);
- printf ("SYM895 [%d] Next Opcode (0x%08x) => 0x%08x 0x%08xnn",
- pSiop->state, (int) siopPc, SYM895_SWAP_32(siopPc[0]),
- SYM895_SWAP_32(siopPc[1]) );
- }
- /* Dump the SIOP registers, if in verbose mode */
- if (verbose)
- sym895Show (pSiop);
- }
- /******************************************************************************
- *
- * sym895Show - display values of all readable SYM 53C8xx SIOP registers.
- *
- * This routine displays the state of the SIOP registers in a user-friendly way.
- * It is useful primarily for debugging. The input parameter is the pointer to
- * the SIOP information structure returned by the sym895CtrlCreate() call.
- *
- * NOTE
- * The only readable register during a script execution is the Istat register.
- * If you use this routine during the execution of a SCSI command, the result
- * could be unpredictable.
- *
- * EXAMPLE:
- * .CS
- * -> sym895Show
- *SYM895 Registers
- *----------------
- * Scntl0 = 0xd0 Scntl1 = 0x00 Scntl2 = 0x00 Scntl3 = 0x00
- * Scid = 0x67 Sxfer = 0x00 Sdid = 0x00 Gpreg = 0x0f
- * Sfbr = 0x0f Socl = 0x00 Ssid = 0x00 Sbcl = 0x00
- * Dstat = 0x80 Sstat0 = 0x00 Sstat1 = 0x0f Sstat2 = 0x02
- * Dsa = 0x07ea9538
- * Istat = 0x00
- * Ctest0 = 0x00 Ctest1 = 0xf0 Ctest2 = 0x35 Ctest3 = 0x10
- * Temp = 0x001d0c54
- * Dfifo = 0x00
- * Dbc0:23-Dcmd24:31 = 0x54000000
- * Dnad = 0x001d0c5c
- * Dsp = 0x001d0c5c
- * Dsps = 0x000000a0
- * Scratch0 = 0x01 Scratch1 = 0x00 Scratch2 = 0x00 Scratch3 = 0x00
- * Dmode = 0x81 Dien = 0x35 Dwt = 0x00 Dcntl = 0x01
- * Sien0 = 0x0f Sien1 = 0x17 Sist0 = 0x00 Sist1 = 0x00
- * Slpar = 0x4c Swide = 0x00 Macntl = 0xd0 Gpcntl = 0x0f
- * Stime0 = 0x00 Stime1 = 0x00 Respid0 = 0x80 Respid1 = 0x00
- * Stest0 = 0x07 Stest1 = 0x00 Stest2 = 0x00 Stest3 = 0x80
- * Sidl = 0x0000 Sodl = 0x0000 Sbdl = 0x0000
- * Scratchb = 0x00000200
- * value = 0 = 0x0
- * .CE
- *
- * RETURNS: OK, or ERROR if <pScsiCtrl> and <pSysScsiCtrl> are both NULL.
- *
- * SEE ALSO: sym895CtrlCreate()
- */
- STATUS sym895Show
- (
- SIOP * pSiop /* pointer to SCSI controller */
- )
- {
- if (pSiop == NULL)
- {
- SCSI_MSG (" Invalid SCSI Controller Info", 0, 0, 0, 0, 0, 0);
- return (ERROR);
- }
- printf ("SYM895 Registers n");
- printf ("---------------- n");
- printf ("Scntl0 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL0));
- printf ("Scntl1 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL1));
- printf ("Scntl2 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL2));
- printf ("Scntl3 = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3));
- printf ("Scid = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SCID));
- printf ("Sxfer = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SXFER));
- printf ("Sdid = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SDID));
- printf ("Gpreg = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_GPREG));
- printf ("Sfbr = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SFBR));
- printf ("Socl = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SOCL));
- printf ("Ssid = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SSID));
- printf ("Sbcl = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL));
- /* Reading this register clears the interrupts */
- printf ("Dstat = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT));
- printf ("Sstat0 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT0));
- printf ("Sstat1 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT1));
- printf ("Sstat2 = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_SSTAT2));
- printf ("Dsa = 0x%08xn", (UINT32)SYM895_REG32_READ (pSiop,
- SYM895_OFF_DSA));
- printf ("Istat = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT));
- printf ("Ctest0 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST0));
- printf ("Ctest1 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST1));
- printf ("Ctest2 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST2));
- printf ("Ctest3 = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_CTEST3));
- printf ("Temp = 0x%08xn", (UINT32)SYM895_REG32_READ (pSiop,
- SYM895_OFF_TEMP));
- printf ("Dfifo = 0x%02xn", SYM895_REG8_READ(pSiop, SYM895_OFF_DFIFO));
- printf ("Dbc0:23-Dcmd24:31 = 0x%08xn",
- (UINT32)SYM895_REG32_READ (pSiop, SYM895_OFF_DBC));
- printf ("Dnad = 0x%08xn",
- (UINT32)SYM895_REG32_READ (pSiop, SYM895_OFF_DNAD));
- printf ("Dsp = 0x%08xn",
- (UINT32)SYM895_REG32_READ (pSiop, SYM895_OFF_DSP));
- printf ("Dsps = 0x%08xn",
- (UINT32)SYM895_REG32_READ (pSiop, SYM895_OFF_DSPS));
- printf ("Scratch0 = 0x%02x ", SYM895_REG8_READ (pSiop,
- SYM895_OFF_SCRATCHA0));
- printf ("Scratch1 = 0x%02x ", SYM895_REG8_READ (pSiop,
- SYM895_OFF_SCRATCHA1));
- printf ("Scratch2 = 0x%02x ", SYM895_REG8_READ (pSiop,
- SYM895_OFF_SCRATCHA2));
- printf ("Scratch3 = 0x%02xn", SYM895_REG8_READ (pSiop,
- SYM895_OFF_SCRATCHA3));
- printf ("Dmode = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE));
- printf ("Dien = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_DIEN));
- printf ("Dwt = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_DWT));
- printf ("Dcntl = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL));
- printf ("Sien0 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SIEN0));
- printf ("Sien1 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SIEN1));
- /* Reading these registers clears the interrupts */
- printf ("Sist0 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SIST0));
- printf ("Sist1 = 0x%02x", SYM895_REG8_READ (pSiop, SYM895_OFF_SIST1));
- printf ("n");
- printf ("Slpar = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SLPAR));
- printf ("Swide = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_SWIDE));
- printf ("Macntl = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_MACNTL));
- printf ("Gpcntl = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_GPCNTL));
- printf ("Stime0 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_STIME0));
- printf ("Stime1 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_STIME1));
- printf ("Respid0 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_RESPID0));
- printf ("Respid1 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_RESPID1));
- printf ("n");
- printf ("Stest0 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_STEST0));
- printf ("Stest1 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_STEST1));
- printf ("Stest2 = 0x%02x ", SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2));
- printf ("Stest3 = 0x%02xn", SYM895_REG8_READ (pSiop, SYM895_OFF_STEST3));
- printf ("Sidl = 0x%04x ", SYM895_REG16_READ (pSiop, SYM895_OFF_SIDL));
- printf ("Sodl = 0x%04x ", SYM895_REG16_READ (pSiop, SYM895_OFF_SODL));
- printf ("Sbdl = 0x%04xn", SYM895_REG16_READ (pSiop, SYM895_OFF_SBDL));
- printf ("Scratchb = 0x%08xn", (UINT32)SYM895_REG32_READ (pSiop,
- SYM895_OFF_SCRATCHB0));
- printf ("Scratchc = 0x%08xn", (UINT32)SYM895_REG32_READ (pSiop,
- SYM895_OFF_SCRATCHC0));
- printf ("Scratchd = 0x%08xn", (UINT32)SYM895_REG32_READ (pSiop,
- SYM895_OFF_SCRATCHD));
- return (OK);
- }
- /*******************************************************************************
- *
- * sym895Delay - Delays the execution for a predefined period;
- *
- * This delay is required for successive reads from the SCSI and DMA status
- * registers. The data manual recommends a delay of 12 SCLK between such
- * successive reads. We are trying to emulate the 12 SCLKs by this routine
- *
- * NOMANUAL
- */
- LOCAL void sym895Delay()
- {
- volatile int i = 0;
- for (i=0; i<sym895DelayCount; i++)
- ;
- }
- /*******************************************************************************
- *
- * sym895GPIOConfig - configures general purpose pins GPIO 0-4.
- *
- * This routine uses the GPCNTL register to configure the general purpose pins
- * available on Sym895 chip. Bits 0-4 of GPCNTL register map to GPIO 0-4 pins.
- * A bit set in GPCNTL configures corresponding pin as input and a bit reset
- * configures the pins as output.
- *
- * .IP <pSiop>
- * pointer to the SIOP structure.
- *
- * .IP <ioEnable>
- * bits 0-4 of this parameter configure GPIO 0-4 pins. 1 => input, 0 => output.
- *
- * .IP <mask>
- * bits 0-4 of this parameter identify valid bits in <ioEnable> parameter. Only
- * those pins are configured, which have a corresonding bit set in this parameter.
- */
- STATUS sym895GPIOConfig
- (
- SIOP * pSiop, /* pointer to SIOP structure */
- UINT8 ioEnable, /* bits indicate input/output */
- UINT8 mask /* mask for ioEnable parameter */
- )
- {
- if (pSiop == NULL)
- {
- SCSI_MSG (" Invalid SCSI Controller Info", 0, 0, 0, 0, 0, 0);
- return (ERROR);
- }
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_GPCNTL,
- ((SYM895_REG8_READ(pSiop,SYM895_OFF_GPCNTL) & ~mask) |
- ioEnable));
- return (OK);
- }
- /*******************************************************************************
- *
- * sym895GPIOCtrl - controls general purpose pins GPIO 0-4.
- *
- * This routine uses the GPREG register to set/reset of the general purpose
- * pins available on Sym895 chip.
- *
- * .IP <pSiop>
- * pointer to the SIOP structure.
- *
- * .IP <ioState>
- * bits 0-4 of this parameter controls GPIO 0-4 pins. 1 => set, 0 => reset.
- *
- * .IP <mask>
- * bits 0-4 of this parameter identify valid bits in <ioState> parameter. Only
- * those pins are activated, which have a corresonding bit set in this parameter.
- */
- STATUS sym895GPIOCtrl
- (
- SIOP * pSiop, /* pointer to SIOP structure */
- UINT8 ioState, /* bits indicate set/reset */
- UINT8 mask /* mask for ioState parameter */
- )
- {
- if (pSiop == NULL)
- {
- SCSI_MSG (" Invalid SCSI Controller Info", 0, 0, 0, 0, 0, 0);
- return (ERROR);
- }
- SYM895_REG8_WRITE(pSiop, SYM895_OFF_GPREG,
- ((SYM895_REG8_READ(pSiop, SYM895_OFF_GPREG) & ~mask) |
- ioState));
- return (OK);
- }
- /******************************************************************************
- *
- * sym895Loopback - This routine performs loopback diagnotics on 895 chip.
- *
- * Loopback mode allows 895 chip to control all signals, regardless of whether
- * it is in initiator or target role. This mode insures proper SCRIPTS instruction
- * fetches and data paths. SYM895 executes initiator instructions through the
- * SCRIPTS, and this routine implements the target role by asserting and polling
- * the appropriate SCSI signals in the SOCL, SODL, SBCL, and SBDL registers.
- *
- * To configure 895 in loopback mode,
- *
- * (1) Bits 3 and 4 of STEST2 should be set to put SCSI pins in High-Impedance
- * mode, so that signals are not asserted on to the SCSI bus.
- *
- * (2) Bit 4 of DCNTL should be set to turn on single step mode. This allows the
- * target program (this routine) to monitor when an initiator SCRIPTS
- * instruction has completed.
- *
- * In this routine, SELECTION, MSG_OUT and DATA_OUT phases are checked. This will
- * ensure that data and control paths are proper.
- *
- */
- STATUS sym895Loopback
- (
- SIOP * pSiop /* pointer to SIOP controller structure */
- )
- {
- UINT8 stest2; /* store for existing STEST2 value */
- UINT8 dcntl ;
- UINT8 sien0 ;
- UINT8 sien1 ;
- UINT8 dien ;
- UINT8 temp;
- int msgInData;
- UINT8 msgBuf = LOOPBACK_MSG_BYTE;
- UINT16 dataBuf = LOOPBACK_DATA;
- STATUS retVal = ERROR;
- SYM895_LOOPBACK loopback;
- SCSI_CTRL * pScsiCtrl = &(pSiop->scsiCtrl);
- if (pSiop == NULL)
- {
- SCSI_MSG ("Invalid SCSI Controller Info", 0, 0, 0, 0, 0, 0);
- return (ERROR);
- }
- /*
- * Initialise the addresss space from where the "sym895Diag" Scripts
- * fetches the table indirect information. This scripts routine selects
- * 895 in loopback mode and then sends out IDENTIFY message.
- */
- loopback.device = SYM895_SWAP_32(
- (SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3) << 24) |
- ((SYM895_REG8_READ (pSiop, SYM895_OFF_SCID)
- & SYM895_SCID_ENC_MASK) << 16) |
- (SYM895_REG8_READ (pSiop, SYM895_OFF_SXFER) << 8));
- loopback.identOut.size = SYM895_SWAP_32(0x01);
- loopback.identOut.addr = (UINT8 *) SYM895_SWAP_32
- ((UINT32)SYM895_VIRT_TO_PHYS(&msgBuf));
- loopback.dataOut.size = SYM895_SWAP_32(0x02);
- loopback.dataOut.addr = (UINT8 *) SYM895_SWAP_32
- ((UINT32)SYM895_VIRT_TO_PHYS(&dataBuf));
- stest2 = SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2);
- dcntl = SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL);
- sien0 = SYM895_REG8_READ (pSiop, SYM895_OFF_SIEN0);
- sien1 = SYM895_REG8_READ (pSiop, SYM895_OFF_SIEN1);
- dien = SYM895_REG8_READ (pSiop, SYM895_OFF_DIEN);
- /* Configure 895 chip in loop back mode */
- /*
- * First, disable all interrupts. DSTAT & SIST0,1 are polled as and when
- * needed determine the possible event. This insures that no interrupts
- * are routed to the sym895 handler and no events get notified to scsi
- * manager.
- */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DIEN, 0x00);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN0, 0x00);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN1, 0x00);
- /*
- * Abort any SCRIPT currently running, to run diagnostic SCRIPTS
- * If the diagnostic SCRIPTS are run once on POR before other scripts are
- * run, then aborting is not needed.
- */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_ISTAT,
- SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT) |
- SYM895_ISTAT_ABRT);
- while ((SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT) &
- (SYM895_ISTAT_SIP | SYM895_ISTAT_DIP)) == 0)
- ;
- if (SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT) & (SYM895_ISTAT_DIP) )
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_ISTAT,0x00);
- temp = SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT);
- /* Set the STEST2 register loopback mode bits. */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST2,
- SYM895_REG8_READ (pSiop, SYM895_OFF_STEST2) |
- (SYM895_STEST2_SCE | SYM895_STEST2_SLB |
- SYM895_STEST2_SZM));
- /* Set Sym895 in Single-Step Mode */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL,
- SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
- SYM895_DCNTL_SSM);
- /* disable manual Start */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DMODE,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE) &
- ~SYM895_DMODE_MAN));
- /*
- * By now, the SCSI pins are in High-Impedance mode. Start with SELECTION
- * in loopback mode. This is initiated by a SCRIPT instruction.SYM895 chip
- * selects itself. The target functionality is implemented here.
- */
- /*
- * Set the shared data address, load the script start address,
- * then start the SCSI Controller unless it's in single-step mode.
- */
- SYM895_REG32_WRITE (pSiop, SYM895_OFF_DSA,
- (UINT32)SYM895_VIRT_TO_PHYS (&loopback));
- SYM895_REG32_WRITE (pSiop, SYM895_OFF_DSP,
- (UINT32)SYM895_VIRT_TO_PHYS (
- (UINT32)sym895ScriptEntry [SYM895_SCRIPT_DIAG]));
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
- SYM895_DCNTL_STD));
- /*
- * Wait till the above SCRIPTS instruction is fetched, and host bus is free.
- * This delay is system-dependent because of chip clock speed, host
- * arbitration times.
- */
- CACHE_PIPE_FLUSH();
- taskDelay (sysClkRateGet()/ 10000); /* This needs to be tuned - now 100us */
- CACHE_PIPE_FLUSH();
- /*
- * Wait for the SEL signal to go HIGH and BSY to go LOW. The above SELECT
- * instruction asserts SEL signal after succeeding in arbitration. It then
- * asserts data lines corresponding to sym895's SCSI ID and the ID of target
- * (which in this case are 7).Then initiator (SELECT instruction) releases
- * the BSY signal.
- */
- temp = 0;
- while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) &
- (SYM895_SBCL_BSY | SYM895_SBCL_SEL)) != 0x10)
- {
- temp++;
- if ( temp == 0)
- {
- SCSI_MSG ("selection timeoutn", 0, 0, 0, 0, 0, 0);
- retVal = ERROR;
- goto despatch;
- }
- }
- SCSI_MSG ("sym895Loopback: Selecting target ID = %xn",
- SYM895_REG16_READ (pSiop, SYM895_OFF_SBDL), 0, 0, 0, 0, 0);
- /*
- * Check whether correct bits are driven on the SCSI data bus during
- * selection.
- */
- if ( SYM895_REG16_READ (pSiop, SYM895_OFF_SBDL) !=
- SYM895_REG16_READ (pSiop, SYM895_OFF_RESPID0))
- {
- SCSI_MSG ("sym895LoopBack: Error in Data Paths n",
- 0, 0, 0, 0, 0, 0);
- retVal = ERROR;
- goto despatch;
- }
- /* Now to respond to selection, BSY signal should be asserted */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,
- (SYM895_REG8_READ(pSiop,SYM895_OFF_SOCL) |
- SYM895_SOCL_BSY));
- /*
- * Once BSY is asserted, the initiator confirms its selection by releasing
- * SEL signal. Wait for SEL to be deasserted.
- */
- temp =0;
- while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & SYM895_SBCL_SEL) != 0)
- {
- temp++;
- if ( temp == 0)
- {
- SCSI_MSG ("selection timeoutn", 0, 0, 0, 0, 0, 0);
- retVal = ERROR;
- goto despatch;
- }
- }
- /*
- * if the initiator has asserted ATN while selecting, assert BSY and
- * MSG_OUT phase. If not ATN, Selection phase is complete.
- */
- if ( SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & SYM895_SBCL_ATN )
- {
- SCSI_MSG ("sym895Loopback: Changing phase to MSG_OUTn",
- 0, 0, 0, 0, 0, 0);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,
- SYM895_REG8_READ (pSiop, SYM895_OFF_SOCL) |
- (SYM895_SOCL_BSY | SYM895_SOCL_MSG | SYM895_SOCL_CD)
- );
- /* Selection Phase (with ATN) is now complete */
- /*
- * Wait for the Single-step status bit to set in DSTAT. This bit is set
- * after successful execution of each SCRIPTS instruction.
- */
- while ((SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT) & SYM895_B_SSI) == 0)
- SCSI_MSG ("Sym895Loopback: Waiting for completion of SCRIPT
- Instruction 1n", 0, 0, 0, 0, 0, 0);
- /*
- * Clear all interrupts just in case. Any pending interrupts whether
- * valid or stray will inhibit the execution of further SCRIPTS
- * instruction.
- */
- temp = SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT);
- sym895Delay();
- CACHE_PIPE_FLUSH();
- temp = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST0);
- sym895Delay();
- CACHE_PIPE_FLUSH();
- temp = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST1);
- sym895Delay();
- CACHE_PIPE_FLUSH();
- temp = SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT);
- /*
- * Set the Start DMA bit in DCNTL register. This restarts execution
- * of SCRIPTS. Now that SELECT instruction is successfully completed
- * and SCSI phase is MSG_OUT, the next SCRIPT instruction sends the
- * IDENTIFY message to target.
- *
- * MOVE FROM IDENT_BUF, WHEN MSG_OUT
- */
- SCSI_MSG ("sym895Loopback: Sending 8-bit Message 0x%xn",
- msgBuf, 0, 0, 0, 0, 0);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
- SYM895_DCNTL_STD));
- /* Wait for the SCRIPT instruction to finish using the host bus */
- CACHE_PIPE_FLUSH();
- taskDelay (sysClkRateGet()/ 1000); /* This needs to be tuned */
- /* now 100us */
- CACHE_PIPE_FLUSH();
- /*
- * The MOVE instruction waits for a phase change indicated by
- * asserting of SREQ signal by the target. So assert SREQ.
- */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,0xae); /* Hard code */
- /* Wait for the ACK to be set by the initiator */
- temp = 0;
- while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & SYM895_SBCL_ACK) == 0)
- {
- temp++;
- if ( temp == 0)
- {
- SCSI_MSG ("ACK timeoutn", 0, 0, 0, 0, 0, 0);
- retVal = ERROR;
- goto despatch;
- }
- }
- msgInData = SYM895_REG8_READ (pSiop, SYM895_OFF_SBDL); /* read data */
- /* Deassert SREQ signal */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_SOCL) &
- ~SYM895_SOCL_REQ));
- /* Wait for the ACK signal to be deasserted by initiator */
- temp = 0;
- while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) & SYM895_SBCL_ACK) != 0)
- {
- temp++;
- if ( temp == 0)
- {
- SCSI_MSG ("ACK timeoutn", 0, 0, 0, 0, 0, 0);
- retVal = ERROR;
- goto despatch;
- }
- }
- SCSI_MSG ("sym895Loopback: Received Message In data = 0x%xn",
- msgInData, 0, 0, 0, 0, 0);
- if ( msgInData != msgBuf)
- {
- SCSI_MSG ("sym895Loopback: Error reading SCSI D0-D7 data busn",
- 0, 0, 0, 0, 0, 0);
- retVal = ERROR;
- goto despatch;
- }
- while ((SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT) & SYM895_B_SSI) == 0)
- logMsg("Sym895Loopback: Waiting for completion of SCRIPT
- Instruction 2n", 0, 0, 0, 0, 0, 0);
- SCSI_MSG ("sym895Loopback: Changing phase to DATA_OUTn",
- 0, 0, 0, 0, 0, 0);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,
- SYM895_REG8_READ (pSiop, SYM895_OFF_SOCL) &
- ~(SYM895_SOCL_MSG | SYM895_SOCL_CD |
- SYM895_SOCL_IO) );
- /*
- * Set the Start DMA bit in DCNTL register. This restarts execution
- * of SCRIPTS. Now that SELECT instruction is successfully completed
- * and SCSI phase is MSG_OUT, the next SCRIPT instruction sends the
- * 16-bit Data to target .
- *
- * MOVE FROM DATA_BUF, WHEN DATA_OUT
- */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SCNTL3,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_SCNTL3) |
- SYM895_SCNTL3_EWS));
- SCSI_MSG ("sym895Loopback: Sending 16-bit Data 0x%xn",
- dataBuf, 0, 0, 0, 0, 0);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DCNTL) |
- SYM895_DCNTL_STD));
- /* Wait for the SCRIPT instruction to finish using the host bus */
- CACHE_PIPE_FLUSH();
- taskDelay (sysClkRateGet()/ 1000); /* This needs to be tuned */
- /* now 100us */
- CACHE_PIPE_FLUSH();
- /*
- * The MOVE instruction waits for a phase change indicated by
- * asserting of SREQ signal by the target. Assert SREQ.
- */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL , 0xa0); /* Hard code */
- /* Wait for the ACK to be set by the initiator */
- temp =0;
- while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) &
- SYM895_SBCL_ACK) == 0)
- {
- temp++;
- if ( temp == 0)
- {
- SCSI_MSG ("ACK timeoutn", 0, 0, 0, 0, 0, 0);
- retVal = ERROR;
- goto despatch;
- }
- }
- msgInData = SYM895_REG16_READ (pSiop, SYM895_OFF_SBDL); /* read data bus */
- /* Deassert SREQ signal */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_SOCL) &
- ~SYM895_SOCL_REQ));
- /* Wait for the ACK signal to be deasserted by initiator */
- temp = 0;
- while ((SYM895_REG8_READ (pSiop, SYM895_OFF_SBCL) &
- SYM895_SBCL_ACK) != 0)
- {
- temp++;
- if ( temp == 0)
- {
- SCSI_MSG ("ACK timeoutn", 0, 0, 0, 0, 0, 0);
- retVal = ERROR;
- goto despatch;
- }
- }
- SCSI_MSG ("sym895Loopback: Received Data In = 0x%xn",
- msgInData, 0, 0, 0, 0, 0);
- if ( msgInData != dataBuf)
- {
- SCSI_MSG ("sym895Loopback: Error reading SCSI D0-D15 data busn",
- 0, 0, 0, 0, 0, 0);
- retVal = ERROR;
- goto despatch;
- }
- SCSI_MSG("sym895Loopback: Loopback diagnostics "
- "successful.n", 0, 0, 0, 0, 0, 0);
- retVal = OK;
- }
- else /* select without ATN */
- {
- SCSI_MSG ("sym895Loopback: Error ATN not asserted during selectionn",
- 0, 0, 0, 0, 0, 0);
- retVal = ERROR;
- }
- despatch:
- /* Set the SCSI control lines to Bus free state */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,
- (SYM895_REG8_READ(pSiop,SYM895_OFF_SOCL) &
- ~(SYM895_SOCL_CD | SYM895_SOCL_MSG | SYM895_SOCL_IO)));
- SYM895_REG8_WRITE ( pSiop, SYM895_OFF_SCNTL2,
- SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL2) &
- ~(SYM895_SCNTL2_SDU) );
- SYM895_REG8_WRITE ( pSiop, SYM895_OFF_SCNTL1,
- SYM895_REG8_READ (pSiop,SYM895_OFF_SCNTL1) &
- ~(SYM895_SCNTL1_CON) );
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SOCL,0x00);
- /* Enable manual Start */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DMODE,
- (SYM895_REG8_READ (pSiop, SYM895_OFF_DMODE) |
- SYM895_DMODE_MAN));
- /* Clear off all interrupts. */
- temp = SYM895_REG8_READ (pSiop, SYM895_OFF_ISTAT);
- sym895Delay();
- CACHE_PIPE_FLUSH();
- temp = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST0);
- sym895Delay();
- CACHE_PIPE_FLUSH();
- temp = SYM895_REG8_READ (pSiop, SYM895_OFF_SIST1);
- sym895Delay();
- CACHE_PIPE_FLUSH();
- temp = SYM895_REG8_READ (pSiop, SYM895_OFF_DSTAT);
- /* Set back the initial interrupt enable bits and bring to normal mode */
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DIEN, dien);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN0, sien0);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_SIEN1, sien1);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_STEST2, stest2);
- SYM895_REG8_WRITE (pSiop, SYM895_OFF_DCNTL, dcntl);
- /*
- * Start the WAIT script.. Again this is needed only if "sym895Loopback" is
- * called while any scripts are running. If the WAIT scripts are not
- * restarted, all SCSI transactions will be aborted as thread activation
- * do not take place.
- */
- sym895ScriptStart (pSiop, (SYM895_THREAD *)pScsiCtrl->pIdentThread,
- SYM895_SCRIPT_WAIT);
- return (retVal);
- }