360 lines
9.5 KiB
C
360 lines
9.5 KiB
C
|
/* Copyright (C) 1994 by Always Technology Corporation.
|
||
|
This module contains information proprietary to
|
||
|
Always Technology Corporation, and is be treated as confidential.
|
||
|
*/
|
||
|
|
||
|
#include "environ.h"
|
||
|
#include "rqm.h"
|
||
|
#include "api.h"
|
||
|
#include "apiscsi.h"
|
||
|
#include "debug.h"
|
||
|
|
||
|
|
||
|
LOCAL void REGPARMS StartNextInternalRequest(ADAPTER_PTR HA);
|
||
|
LOCAL void REGPARMS DeviceInfo(const ADAPTER_PTR HA);
|
||
|
LOCAL void REGPARMS AutoSense(ADAPTER_PTR HA);
|
||
|
LOCAL void REGPARMS CompleteDeferedRequest(ADAPTER_PTR HA, APIStatus Status);
|
||
|
LOCAL void REGPARMS ExecuteDeferedRequest(ADAPTER_PTR HA);
|
||
|
LOCAL void DoTestUnitReadyComplete(IO_REQ_PTR IReq);
|
||
|
LOCAL void REGPARMS DoTestUnitReady(ADAPTER_PTR HA);
|
||
|
|
||
|
|
||
|
#if !defined(LocalPostCallback)
|
||
|
extern U32 LocalPostCallback(void (*CallBack)(IO_REQ_PTR));
|
||
|
#endif
|
||
|
|
||
|
enum ASPI_Priority {NORMAL_REQ, PRIORTY_REQ, IPRIORTY_REQ};
|
||
|
extern void IExecuteReq(ADAPTER_PTR HA, DEVICE_PTR DevP, IO_REQ_PTR Req,
|
||
|
enum ASPI_Priorty Priorty);
|
||
|
|
||
|
void
|
||
|
QueueInternalRequest (ADAPTER_PTR HA, IO_REQ_PTR XReq, RequestType Type)
|
||
|
{
|
||
|
IO_REQ_PTR *ReqScan = &(HA->Ext->InternalReqDeferQueue);
|
||
|
|
||
|
critical(HA);
|
||
|
ReqState(XReq).ReqType = Type;
|
||
|
while(*ReqScan != (IO_REQ_PTR)NILL)
|
||
|
ReqScan = &ReqNext(*ReqScan);
|
||
|
|
||
|
*ReqScan = XReq;
|
||
|
uncritical(HA);
|
||
|
|
||
|
StartNextInternalRequest(HA);
|
||
|
}
|
||
|
|
||
|
|
||
|
LOCAL void REGPARMS
|
||
|
StartNextInternalRequest (ADAPTER_PTR HA)
|
||
|
{
|
||
|
IO_REQ_PTR IReq = &HA->Ext->InternalRequest;
|
||
|
IO_REQ_PTR XReq;
|
||
|
int i;
|
||
|
|
||
|
TRACE(2, ("StartNextInternalRequest(): InUse flag == %s\n",
|
||
|
(HA->State.InternalReqInUse) ? "True" : "False"));
|
||
|
|
||
|
critical(HA);
|
||
|
while (!HA->State.InternalReqInUse
|
||
|
&& HA->Ext->InternalReqDeferQueue != (IO_REQ_PTR)NILL) {
|
||
|
|
||
|
HA->State.InternalReqInUse = TRUE;
|
||
|
XReq = HA->Ext->InternalReqDeferQueue;
|
||
|
|
||
|
uncritical(HA);
|
||
|
|
||
|
ReqTargetID(IReq) = ReqTargetID(XReq);
|
||
|
ReqTargetLUN(IReq) = ReqTargetLUN(XReq);
|
||
|
ReqDevP(IReq) = ReqDevP(XReq);
|
||
|
|
||
|
for (i=0; i<12;i++)
|
||
|
ReqCDB(IReq)[i] = 0;
|
||
|
|
||
|
ReqState(IReq).ReqType = ReqState(XReq).ReqType;
|
||
|
switch(ReqState(XReq).ReqType) {
|
||
|
|
||
|
case RTGetInfoReq:
|
||
|
|
||
|
DeviceInfo(HA);
|
||
|
break;
|
||
|
|
||
|
|
||
|
case RTAutoSenseReq:
|
||
|
|
||
|
AutoSense(HA);
|
||
|
break;
|
||
|
|
||
|
|
||
|
case RTSyncNegReq:
|
||
|
|
||
|
DoTestUnitReady(HA);
|
||
|
break;
|
||
|
|
||
|
|
||
|
default:
|
||
|
CompleteDeferedRequest(HA, S_REQ_REQUEST);
|
||
|
continue;
|
||
|
|
||
|
}
|
||
|
|
||
|
critical(HA);
|
||
|
}
|
||
|
uncritical(HA);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
void AutoSenseReqComplete(IO_REQ_PTR Req);
|
||
|
|
||
|
LOCAL void REGPARMS
|
||
|
AutoSense (ADAPTER_PTR HA)
|
||
|
{
|
||
|
IO_REQ_PTR IReq = &HA->Ext->InternalRequest;
|
||
|
IO_REQ_PTR XReq = HA->Ext->InternalReqDeferQueue;
|
||
|
|
||
|
TRACE(4, ("AutoSense(): Starting auto sense for request %lx\n", XReq));
|
||
|
|
||
|
ReqCDBLen(IReq) = 6;
|
||
|
ReqSenseCount(IReq) = 0;
|
||
|
ReqDataCount(IReq) = ReqSenseCount(XReq);
|
||
|
ReqDataPtr(IReq) = ReqSensePtr(XReq);
|
||
|
TRACE(4, ("AutoSense(): Sense data pointer = %lx, sense count = %d\n",
|
||
|
ReqSensePtr(XReq), ReqSenseCount(XReq)));
|
||
|
|
||
|
ReqSetDataInFlags(IReq);
|
||
|
|
||
|
// First do a request sense to clear the reset, etc conditions:
|
||
|
ReqCDB(IReq)[0] = 0x03; // Request Sense is command 0x03
|
||
|
ReqCDB(IReq)[4] = min(255, ReqSenseCount(XReq));
|
||
|
ReqPost(IReq) = LocalPostCallback(AutoSenseReqComplete);
|
||
|
|
||
|
TRACE(3, ("AutoSense(): request built, calling IExecuteReq()\n"));
|
||
|
QueueReq(HA, IReq, TRUE);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
LOCAL void
|
||
|
AutoSenseReqComplete (IO_REQ_PTR Req)
|
||
|
{
|
||
|
IO_REQ_PTR XReq = ReqAdapterPtr(Req)->Ext->InternalReqDeferQueue;
|
||
|
|
||
|
TRACE(3, ("AutoSenseReqComplete(): Completion of autosense for request %lx ", XReq));
|
||
|
TRACE(3, ("cmd = %02x\n", ReqCommand(XReq)));
|
||
|
DmsPause(7, 200);
|
||
|
|
||
|
FreeMemHandle(Req->ReqDataPtr);
|
||
|
|
||
|
TRACE(3, ("AutoSenseReqComplete(): Completion of auto sense\n"));
|
||
|
DmsPause(7, 100);
|
||
|
CompleteDeferedRequest(ReqAdapterPtr(Req),
|
||
|
(APIStatus)((ReqAPIStatus(Req) == S_TAR_NOERROR) ? S_AD_AUTOSENSE_OK : S_AD_AUTOSENSE_FAIL));
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// The request completed
|
||
|
LOCAL void
|
||
|
DevInfoDone (ADAPTER_PTR HA, APIStatus Status)
|
||
|
{
|
||
|
if (Status == S_TAR_NOERROR)
|
||
|
ExecuteDeferedRequest(HA); // Queue up request
|
||
|
else
|
||
|
CompleteDeferedRequest(HA, Status);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// This is the POST routine called when the second step (Inquiry) of the device info completes
|
||
|
// This completes this devices inquiry. Start the next DevInfoReq for this adapter.
|
||
|
LOCAL void
|
||
|
DevInfoInqDone (IO_REQ_PTR Req)
|
||
|
{
|
||
|
DEVICE_PTR DevP = ReqDevP(Req);
|
||
|
ADAPTER_PTR HA = ReqAdapterPtr(Req);
|
||
|
|
||
|
TRACE(4, ("DevInfoInqDone(): Status of Inquiry: %04x\n", ReqAPIStatus(Req)));
|
||
|
if (ReqAPIStatus(Req) == S_TAR_NOERROR) {
|
||
|
|
||
|
TRACE(4, ("DevInfoInqDone(): Inquiry completed without error\n"));
|
||
|
if (HA->Ext->InternalReqBuffer[0] == 0x7f) { // Check for LUN not present
|
||
|
|
||
|
TRACE(2, ("DeviceInfo(): LUN not present\n"));
|
||
|
DevInfoDone(HA, S_REQ_NOTAR);
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
DevP->Device_Type = HA->Ext->InternalReqBuffer[0]; // Get device type
|
||
|
TRACE(2, ("DevInfoInqDone(): Device type = %02x\n", DevP->Device_Type));
|
||
|
TRACE(3, ("DevInfoInqDone(): Device is SCSI-%d, Flags = %02x\n",
|
||
|
(HA->Ext->InternalReqBuffer[3] & 0x0f), (unsigned)HA->Ext->InternalReqBuffer[7]));
|
||
|
|
||
|
if ((HA->Ext->InternalReqBuffer[3] & 0x0f) > 1) { // Is this dev. SCSI2 or later?
|
||
|
|
||
|
DevP->Flags.IsSCSI2 = 1; // Set SCSI-2 params valid flag
|
||
|
DevP->SCSI2_Flags.Byte = HA->Ext->InternalReqBuffer[7]; // Get the SCSI-2 parameter bytes
|
||
|
if (DevP->SCSI_LUN == 0)
|
||
|
HA->DevInfo[DevP->SCSI_ID].Flags.NeedSync = (HA->DevInfo[DevP->SCSI_ID].Flags.AllowSync &= DevP->SCSI2_Flags.Bits.Sync); // Use the inquiry info on Sync xfer
|
||
|
|
||
|
} else { // All right; we'll do thigns the SCSI-1 way
|
||
|
|
||
|
DevP->SCSI2_Flags.Byte = 0; // Clear all SCSI-2 mode bits
|
||
|
HA->DevInfo[DevP->SCSI_ID].Flags.NeedSync =
|
||
|
HA->DevInfo[DevP->SCSI_ID].Flags.AllowSync;
|
||
|
TRACE(2, ("DevInfoInqDone(): Setting NEED_SYNC flag to %d\n",
|
||
|
HA->DevInfo[DevP->SCSI_ID].Flags.NeedSync));
|
||
|
|
||
|
}
|
||
|
DevP->Flags.Allow_Disc = HA->Supports.Identify; // If the adapter supports identify messages, is allows disconnects
|
||
|
DevP->Flags.Initialized = 1;
|
||
|
|
||
|
}
|
||
|
|
||
|
DevInfoDone(HA, ReqAPIStatus(Req));
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
// This is the POST routine called when the first step (Request Sense) of the device info completes
|
||
|
// The next step will be to do the inquiry, initiated here, completed above
|
||
|
LOCAL void
|
||
|
DevInfoSenseDone (IO_REQ_PTR Req)
|
||
|
{
|
||
|
ADAPTER_PTR HA = ReqAdapterPtr(Req);
|
||
|
|
||
|
TRACE(3, ("DevInfoSenseDone(): Status of ReqSense: %02x\n", ReqAPIStatus(Req)));
|
||
|
if (ReqAPIStatus(Req) != S_TAR_NOERROR) {
|
||
|
|
||
|
TRACE(4, ("DevInfoSenseDone(): Completed with error\n"));
|
||
|
DevInfoDone(HA, ReqAPIStatus(Req));
|
||
|
return;
|
||
|
|
||
|
}
|
||
|
|
||
|
// OK, the Request Sense completed OK, now do the inquiry
|
||
|
TRACE(3, ("DevInfoSenseDone(): Req. sense completed OK, setting up inquiry\n"));
|
||
|
ReqCDB(Req)[0] = (U8)0x12; // Inquiry is command 0x12
|
||
|
|
||
|
ReqDataCount(Req) = DevInfoInqSize;
|
||
|
ReqDataPtr(Req) = HA->Ext->InternalReqBuffer;
|
||
|
|
||
|
ReqPost(Req) = DevInfoInqDone;
|
||
|
|
||
|
QueueReq(ReqAdapterPtr(Req), Req, FALSE); // Queue up request
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
LOCAL void REGPARMS
|
||
|
DeviceInfo (const ADAPTER_PTR HA)
|
||
|
{
|
||
|
int i;
|
||
|
DEVICE_PTR DevP=ReqDevP(HA->Ext->InternalReqDeferQueue);
|
||
|
IO_REQ_PTR IReq = &(HA->Ext->InternalRequest);
|
||
|
|
||
|
TRACE(2, ("DeviceInfo(): for adapter %x\n"));
|
||
|
|
||
|
for (i = 0; i < sizeof(DevP->Flags); i++)
|
||
|
((char ALLOC_D *)&(DevP->Flags))[i] = 0;
|
||
|
|
||
|
DevP->SCSI_ID = ReqTargetID(IReq);
|
||
|
DevP->SCSI_LUN = ReqTargetLUN(IReq);
|
||
|
if (DevP->SCSI_LUN == 0) {
|
||
|
|
||
|
HA->DevInfo[ReqTargetID(IReq)].Flags.AllowSync = HA->Supports.Synchronous
|
||
|
/* && (HA->Parms[DRIVE_PL(ReqTargetID(IReq))] & PL_ALLOW_SYNC) */;
|
||
|
|
||
|
}
|
||
|
|
||
|
DevP->HA = HA;
|
||
|
DevP->MaxDepth = 1;
|
||
|
DevP->CurrDepth = 0;
|
||
|
DevP->Device_Type = 0xff;
|
||
|
|
||
|
DevP->PendingReqList = DevP->AcceptedList = (IO_REQ_PTR)NILL;
|
||
|
ReqCDBLen(IReq) = 6;
|
||
|
ReqSenseCount(IReq) = 0;
|
||
|
ReqDataCount(IReq) = DevInfoInqSize;
|
||
|
ReqDataPtr(IReq) = HA->Ext->InternalReqBuffer;
|
||
|
|
||
|
ReqSetDataInFlags(IReq);
|
||
|
|
||
|
// First do a request sense to clear the reset, etc conditions:
|
||
|
ReqCDB(IReq)[0] = 0x03; // Request Sense is command 0x03
|
||
|
ReqCDB(IReq)[4] = (unsigned char)DevInfoInqSize;
|
||
|
ReqPost(IReq) = DevInfoSenseDone;
|
||
|
|
||
|
QueueReq(HA, IReq, FALSE); // Queue up request
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
|
||
|
LOCAL void REGPARMS
|
||
|
DoTestUnitReady (ADAPTER_PTR HA)
|
||
|
{
|
||
|
IO_REQ_PTR IReq = &HA->Ext->InternalRequest;
|
||
|
IO_REQ_PTR XReq = HA->Ext->InternalReqDeferQueue;
|
||
|
|
||
|
TRACE(4, ("DoTestUnitReady(): Starting Test Unit Ready for request %lx\n", XReq));
|
||
|
|
||
|
ReqCDBLen(IReq) = 6;
|
||
|
ReqSenseCount(IReq) = 0;
|
||
|
ReqDataCount(IReq) = 0;
|
||
|
|
||
|
ReqPost(IReq) = LocalPostCallback(DoTestUnitReadyComplete);
|
||
|
|
||
|
TRACE(3, ("DoTestUnitReady(): request built, calling IExecuteReq()\n"));
|
||
|
QueueReq(HA, IReq, FALSE); // Queue up request
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
LOCAL void
|
||
|
DoTestUnitReadyComplete (IO_REQ_PTR IReq)
|
||
|
{
|
||
|
|
||
|
ExecuteDeferedRequest(ReqAdapterPtr(IReq)); // Queue up original request
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
LOCAL void REGPARMS
|
||
|
CompleteDeferedRequest (ADAPTER_PTR HA, APIStatus Status)
|
||
|
{
|
||
|
IO_REQ_PTR XReq = HA->Ext->InternalReqDeferQueue;
|
||
|
HA->Ext->InternalReqDeferQueue = ReqNext(XReq);
|
||
|
|
||
|
TRACE(3, ("CompleteDeferedRequest(): Completing defered request %x on adapter %x\n", XReq, HA));
|
||
|
HA->State.InternalReqInUse = FALSE;
|
||
|
StartNextInternalRequest(HA);
|
||
|
ReqState(XReq).ReqType = RTNormalReq;
|
||
|
APISetStatus(XReq, Status, Terminal, NotSenseable);
|
||
|
|
||
|
}
|
||
|
|
||
|
|
||
|
|
||
|
LOCAL void REGPARMS
|
||
|
ExecuteDeferedRequest (ADAPTER_PTR HA)
|
||
|
{
|
||
|
IO_REQ_PTR XReq = HA->Ext->InternalReqDeferQueue;
|
||
|
HA->Ext->InternalReqDeferQueue = ReqNext(XReq);
|
||
|
|
||
|
TRACE(3, ("ExecuteDeferedRequest(): Executing defered request %x on adapter %x\n", XReq, HA));
|
||
|
HA->State.InternalReqInUse = FALSE;
|
||
|
StartNextInternalRequest(HA);
|
||
|
ReqState(XReq).ReqType = RTNormalReq;
|
||
|
IExecuteReq(HA, ReqDevP(XReq), XReq, NORMAL_REQ); // Queue up request
|
||
|
|
||
|
}
|