diff options
Diffstat (limited to '')
-rw-r--r-- | private/ntos/miniport/always/scsi.c | 400 |
1 files changed, 400 insertions, 0 deletions
diff --git a/private/ntos/miniport/always/scsi.c b/private/ntos/miniport/always/scsi.c new file mode 100644 index 000000000..89c91ebdd --- /dev/null +++ b/private/ntos/miniport/always/scsi.c @@ -0,0 +1,400 @@ +/* Copyright (C) 1991, 1992 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" + +/* + This function is called by the adapter/chip interrupt service routine + to handle going to SCSI bus free. This means that the bus has gone + to the free state, and the adpter is ready to start a new request. +*/ + + +/* Called from interrupt context */ +void +BusFree (ADAPTER_PTR HA, int StartLevel) +{ + + HA->State.Busy = HA->State.DataIn = HA->State.DoingSync = FALSE; + HA->CurrDev = NILL; + HA->CurrReq = NILL; + HA->ReqCurrentCount = 0; + HA->ReqCurrentIndex = 0; + HA->Service(HA_LED, HA, (long)0); + StartNext(HA, StartLevel); /* Called from interrupt, so level = 2 */ + +} + + + +/* + This functions is called by the adapter drivers when the detect a + bus reset. All requests in the accepted queues of the devices + attached to this adapter will be completed with a HAS_BADPHASE error + + Called from interrupt context +*/ + +void +SCSIBusHasReset (ADAPTER_PTR HA) +{ + + BlowAwayRequests(HA, ACTIVE_REQUESTS, S_AD_RESET); + APINotifyReset(HA); + BusFree(HA, 2); + +} + + + +int +SCSISendAbort (ADAPTER_PTR HA) +{ + + HA->Ext->MO_Buff[0] = MSG_ABORT; + HA->Ext->MO_Index = 0; + HA->Ext->MO_Count = 1; + TRACE(0,("SCSISendAbort(): Abort message requested\n")); + return MI_SEND_MSG; /* Tell driver we have a message to send */ + +} + + + +int +SCSISendReject (ADAPTER_PTR HA) +{ + + HA->Ext->MO_Buff[0] = MSG_REJECT; + HA->Ext->MO_Index = 0; + HA->Ext->MO_Count = 1; + TRACE(0, ("SCSISendReject(): Reject message requested\n")); + return MI_SEND_MSG; /* Tell driver we have a message to send */ + +} + + + +LOCAL void REGPARMS +SCSIAskSyncMsg (ADAPTER_PTR HA, BOOLEAN Initiate) +{ + U8 ALLOC_D *Buff = &HA->Ext->MO_Buff[HA->Ext->MO_Count]; + + *Buff++ = MSG_EXTD_MSG; + *Buff++ = 3; + *Buff++ = XMSG_SYNC_REQ; + + *Buff++ = HA->Sync_Period; + *Buff = HA->Sync_Offset; + + HA->Ext->MO_Count += 5; + HA->Ext->MO_Index = 0; + HA->State.DoingSync = Initiate; + HA->DevInfo[ReqTargetID(HA->CurrReq)].Flags.UseSync = 0; + TRACE(3,("SCSIAskSyncMsg(): Sync. request message created: %d/%d\n", + HA->Sync_Period, HA->Sync_Offset)); + +} + + +void +SCSIMakeIdentify (ADAPTER_PTR HA, unsigned LUN, BOOLEAN AllowDisc) +{ + + HA->Ext->MO_Buff[0] = MSG_IDENTIFY | LUN | (AllowDisc ? MSG_ALLOW_DISC : 0); + HA->Ext->MO_Index = 0; + HA->Ext->MO_Count = 1; + TRACE(3,("SCSIMakeIDentify(): Identify message (%02x) requested\n", + (unsigned)HA->Ext->MO_Buff[0])); + + if (ReqState(HA->CurrReq).ReqType == RTSyncNegReq) { // Allow sync. xfers on this device? + + SCSIAskSyncMsg(HA, TRUE); // Then build sync. message + + } +} + + + +LOCAL U32 +S32toU32 (U8 *b) +{ + +#if defined(NATIVE32) + + return ( ((((U32)(b[0]) * 256) + (U32)(b[1])) * 256) + + (U32)(b[2])) * 256 + (U32)(b[3]); + +#else + struct { + U32 l; + U8 b[4]; + } X32; + + X32.b[0] = b[3]; + X32.b[1] = b[2]; + X32.b[2] = b[1]; + X32.b[3] = b[0]; + return X32.l; + +#endif +} + + +LOCAL int +ExtdMessage(ADAPTER_PTR HA) +{ + I32 Offset; + unsigned char Resp = MSG_NOP; + + TRACE(4,("Inerpret_MSG: Extended message\n")); + switch (HA->Ext->MI_Buff[2]) { /* Extened message code; length is in [1] */ + + case XMSG_MODIFY_PTR: /* Got a Modify data pointers request */ + + TRACE(0,("Interpret_MSG(): The rarely seen Modify Data Ptr message received\n")); + /* Make sure the length of the message is correct and that the signed offset is in range: */ + if (HA->Ext->MI_Buff[1] != 5) + return SCSISendReject(HA); + + Offset = S32toU32(&(HA->Ext->MI_Buff[3])); + + // If the offset is less than zero (going to back up), then see if that + // would make index (the number of bytes xfered so far) less than 0; + // If offset > 0, then check to see if is greater than the number of + // bytes remaining: + + if (Offset < 0) { + + if (((U32)-Offset) > HA->ReqCurrentIndex) + return SCSISendReject(HA); + + } else { + + if ((U32)Offset > HA->ReqCurrentCount) + return SCSISendReject(HA); + + } + + HA->ReqCurrentIndex += Offset; + HA->ReqCurrentCount -= Offset; + Resp = MSG_NOP; + break; + + + case XMSG_SYNC_REQ: + + /* Sync negotiaition request; may be a response to our request */ + TRACE(4,("Interpret_MSG: sync. negotiation\n")); + if ((HA->Ext->MI_Buff[1] != 3) || !HA->Supports.Synchronous) + return SCSISendReject(HA); + + HA->DevInfo[ReqTargetID(HA->CurrReq)].Flags.NeedSync = FALSE; + + if (HA->State.DoingSync) { /* Did we initiate sync. neg? */ + + TRACE(4,(" Response to host initiated negotiation\n")); + HA->State.DoingSync = FALSE; /* then we are done */ + Resp = MI_SYNC_RESP; /* We got a sync response */ + + } else { /* Else, respond */ + + TRACE(4,("Target initiated negotiation\n")); + SCSIAskSyncMsg(HA, FALSE); /* Request sync. negotiation be done */ + + /* use the values most suited for the adapter and target: */ + if (HA->Sync_Period < HA->Ext->MI_Buff[3]) + HA->Ext->MO_Buff[3] = HA->Ext->MI_Buff[3]; + + if (HA->Sync_Offset > HA->Ext->MI_Buff[4]) + HA->Ext->MO_Buff[4] = HA->Ext->MI_Buff[4]; + Resp = MI_SYNC_REQ; /* We got a sync req; so send resp */ + + } + + HA->CurrDev->Sync_Period = HA->Ext->MI_Buff[3]; + HA->CurrDev->Sync_Offset = HA->Ext->MI_Buff[4]; + HA->DevInfo[ReqTargetID(HA->CurrReq)].Flags.UseSync = TRUE; + if (HA->Ext->MI_Buff[4] == 0) { + + /* no sync. support; clear allowed flag; no handling of msg needed */ + HA->DevInfo[ReqTargetID(HA->CurrReq)].Flags.AllowSync = FALSE; + HA->DevInfo[ReqTargetID(HA->CurrReq)].Flags.UseSync = FALSE; + Resp = MSG_NOP; + + } + + TRACE(4,("Using sync period of: %d and offset of: %d\n", (unsigned)HA->Ext->MI_Buff[3], (unsigned)HA->Ext->MI_Buff[4])); + + } + return Resp; + +} + + +int +Interpret_MSG (ADAPTER_PTR HA) +{ + unsigned char Resp = HA->Ext->MI_Buff[0]; + + HA->Ext->MI_Count = HA->Ext->MI_Needed = 0; /* Reset for next time */ + TRACE(3,("Interpret_MSG: 1st Message byte: %02x\n", HA->Ext->MI_Buff[0])); + + if (HA->Ext->MI_Buff[0] & 0x80) /* Identify message? */ + return 0x80; // Return identify code + + switch (HA->Ext->MI_Buff[0]) { + + case MSG_SAVE_PTR: + + TRACE(5, ("Interpret_MSG(): Save Data Ptr, Saved index=%d\n", HA->ReqCurrentIndex)); + ReqSavedIndex(HA->CurrReq) = HA->ReqCurrentIndex; + break; + + + case MSG_RESTORE_PTR: + + HA->ReqCurrentIndex = ReqSavedIndex(HA->CurrReq); + HA->ReqCurrentCount = 0; + TRACE(5, ("Interpret_MSG(): Restore Data Ptr, Saved index=%d\n", HA->ReqCurrentIndex)); + break; + + + case MSG_DISCONNECT: + + ReqState(HA->CurrReq).ReselPending = TRUE; + ReqState(HA->CurrReq).Connected = FALSE; + HA->CurrReq = 0; + break; + + + case MSG_REJECT: + + HA->Ext->MO_Count = HA->Ext->MO_Index = 0; /* Clear message out indicators */ + if (HA->State.DoingSync) { + + TRACE(2,("Synchronous negotiation rejected by target\n")); + HA->DevInfo[ReqTargetID(HA->CurrReq)].Flags.NeedSync = 0; + HA->DevInfo[ReqTargetID(HA->CurrReq)].Flags.AllowSync = 0; + HA->DevInfo[ReqTargetID(HA->CurrReq)].Flags.UseSync = 0; + HA->State.DoingSync = 0; + + } else { + + // See if the reject is in response to an Identify with LUN: + if ((HA->Ext->MO_Buff[0] & 0x80) && (HA->Ext->MO_Buff[0] & 7)) + ReqAPIStatus(HA->CurrReq) = S_REQ_BADLUN; + + } + break; + + + case MSG_EXTD_MSG: + + Resp = ExtdMessage(HA); + break; + + + case MSG_COMPLETE: + case MSG_NOP: + + break; + + + default: + + TRACE(0, ("Interpret_MSG(): Unknown message: 0x%02x %02x %02x %02x\n", HA->Ext->MI_Buff[0], HA->Ext->MI_Buff[1], HA->Ext->MI_Buff[2], HA->Ext->MI_Buff[3])); + Resp = SCSISendReject(HA); + break; + + } + + return Resp; +} + + +LOCAL unsigned +NewMessage (ADAPTER_PTR HA, unsigned char Msg) +{ + + TRACE(4,("NewMessage(): %02x\n", Msg)); + switch (Msg) { + + case MSG_EXTD_MSG: + + HA->Ext->MI_Count = -1; /* Special flag for first byte of extd. msg */ + HA->Ext->MI_Needed = -1; + return MI_MORE; + + + default: + + if ((Msg & 0xf0) == 0x20) { /* Two byte messages */ + + HA->Ext->MI_Buff[0] = Msg; + HA->Ext->MI_Count = 1; + HA->Ext->MI_Needed = 1; /* One more byte needed */ + return MI_MORE; + + } else + Msg = Interpret_MSG(HA); + + break; + } + return Msg; +} + + + +/* Called from interrupt context */ +int +Receive_Msg (ADAPTER_PTR HA, unsigned char Msg) +{ + unsigned char NM; + + TRACE(4,("Receive_Msg(): MI_Count = %d, Needed = %d\n", HA->Ext->MI_Count, HA->Ext->MI_Needed)); + switch (HA->Ext->MI_Count) { + + case 0: /* New first message byte */ + + HA->Ext->MI_Buff[0] = Msg; + NM = NewMessage(HA, Msg); + TRACE(5,("Receive_Msg(): NewMessage says: 0x%02x\n", NM)); + return NM; + + + case -1: /* Second byte (length) of extended message */ + + TRACE(4,("Receive_Msg(): Extd msg length = %d\n", Msg)); + if (Msg == 0) { + + HA->Ext->MI_Needed = 0; + HA->Ext->MI_Buff[1] = 0; + HA->Ext->MI_Count = 0; + return SCSISendReject(HA); + + } + HA->Ext->MI_Needed = Msg; + HA->Ext->MI_Buff[1] = Msg; + HA->Ext->MI_Count = 2; + return MI_MORE; + + + default: /* Subsequent bytes of multi-byte message */ + + HA->Ext->MI_Buff[HA->Ext->MI_Count++] = Msg; + if (--(HA->Ext->MI_Needed) == 0) + return Interpret_MSG(HA); + break; + + } + + return MI_MORE; +} |