home *** CD-ROM | disk | FTP | other *** search
- /*DDK*************************************************************************/
- /* */
- /* COPYRIGHT Copyright (C) 1995 IBM Corporation */
- /* */
- /* The following IBM OS/2 WARP source code is provided to you solely for */
- /* the purpose of assisting you in your development of OS/2 WARP device */
- /* drivers. You may use this code in accordance with the IBM License */
- /* Agreement provided in the IBM Device Driver Source Kit for OS/2. This */
- /* Copyright statement may not be removed. */
- /* */
- /*****************************************************************************/
- /*static char *SCCSID = "src/dev/dasd/os2aspi/aspisrb.c, aspi, r206 93/03/20";*/
- /**************************************************************************
- *
- * SOURCE FILE NAME = ASPISRB.C
- *
- * DESCRIPTIVE NAME = OS2ASPI.DMD - OS/2 ASPI Device Manager
- * ASPI SRB Processor
- *
- *
- * VERSION = V2.0
- *
- * DATE
- *
- * DESCRIPTION Converts ASPI SRBs to corresponding IORB(s).
- *
- *
- *
- */
-
- #define INCL_NOBASEAPI
- #define INCL_NOPMAPI
- #include <os2.h>
- #include <strat2.h>
-
- #include <devcmd.h>
- #include <devclass.h>
-
- #include <reqpkt.h>
- #include <iorb.h>
- #include <dhcalls.h>
- #include <dskinit.h>
- #include <scsi.h>
-
- #include <aspi.h>
- #include <aspicons.h>
- #include <aspitype.h>
- #include <aspipro.h>
- #include <aspiextn.h>
-
- extern PVOID pDataSeg;
- extern ULONG ppDataSeg;
- extern USHORT IORBWaitSem;
- extern UCHAR numberOfASPIAdapters;
- extern CHAR OS2ASPI_Text[];
- extern NPACB npACBAnchor;
- extern NPATE npFirstATE;
- extern NPSRB_LINK npSRBLinkFreeList;
- extern NPIORB_UNIT_CONTROL npIORBUnitControl;
- extern USHORT allocationOverride;
- extern USHORT shareTargets;
-
- /*********************************************************
- * *
- * Procedure Name : ASPISRBEntr *
- * *
- * Description : This procedure routes all ASPI *
- * requests to the appropriate function. *
- * *
- * Input : *
- * pSRBH - A pointer to SRB header *
- * virtualASPI - Flags indicating the status of *
- * the VDM that MAY be associated with the SRB. *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID NEAR _loadds ASPISRBEntr(PASPI_SRB_HEADER pSRBH,USHORT virtualASPI)
-
- {
- switch (pSRBH->CommandCode)
- {
- case ASPI_CMD_ADAPTER_INQUIRY:
- DoASPIInquiry((PASPI_SRB_INQUIRY) pSRBH,virtualASPI);
- break;
-
- case ASPI_CMD_GET_DEVICE_TYPE:
- DoASPIDeviceType((PASPI_SRB_DEVICE_TYPE) pSRBH, virtualASPI);
- break;
-
- case ASPI_CMD_EXECUTE_IO:
- DoASPIExecuteIO((PASPI_SRB_EXECUTE_IO) pSRBH,virtualASPI);
- break;
-
- case ASPI_CMD_ABORT_IO:
- DoASPIAbortIO((PASPI_SRB_ABORT_IO) pSRBH,virtualASPI);
- break;
-
- case ASPI_CMD_RESET_DEVICE:
- DoASPIExecuteIO((PASPI_SRB_EXECUTE_IO) pSRBH,virtualASPI);
- break;
-
- case ASPI_CMD_SET_ADAPTER_PARMS:
- DoASPISetAdapterParms((PASPI_SRB_ADAPTER_PARMS) pSRBH,virtualASPI);
- break;
-
- default:
- pSRBH->ASPIStatus = ASPI_STATUS_INVALID_COMMAND;
- }
- }
-
-
- /*********************************************************
- * *
- * Procedure Name : DoASPIInquiry *
- * *
- * Description : This procedure handles host adapter *
- * inquires. *
- * *
- * Input : *
- * pSRBI - A pointer to the SRB for host adapter *
- * inquiries *
- * virtualASPI - Flags indicating the status of *
- * the VDM that MAY be associated with the SRB. *
- * *
- * Output : This function returns the status for the *
- * request packet that was just handled by it. *
- * *
- *********************************************************/
- USHORT NEAR DoASPIInquiry(PASPI_SRB_INQUIRY pSRBI, USHORT virtualASPI)
-
- {
- UCHAR adapterIndex;
- NPACB pACB;
- UCHAR ASPIStatus;
- USHORT extendedByteCount; /*@V53040*/
- USHORT requestPacketStatus = STDON;
-
- /* Verify that host adapter is valid */
- adapterIndex = pSRBI->SRBHdr.AdapterIndex;
-
- if (adapterIndex >= numberOfASPIAdapters)
- {
- ASPIStatus = ASPI_STATUS_INVALID_ADAPTER;
- requestPacketStatus |= STERR;
- }
- else
- {
- pACB = FindAdapter(adapterIndex);
-
- /* Copy all of the information of the current host adapter */
- /* into the SRB */
- memcpy(pSRBI->ManagerName,
- OS2ASPI_Text,
- sizeof(pSRBI->ManagerName));
- memset(pSRBI->AdapterParms,
- 0,
- sizeof(pSRBI->AdapterParms));
-
- pSRBI->AdapterCount = numberOfASPIAdapters;
- pSRBI->AdapterTargetID = pACB->AdapterTargetID;
- memcpy(pSRBI->AdapterName,
- pACB->AdapterName,
- sizeof(pSRBI->ManagerName));
-
- /* Determine if we should return EXTENDED adapter information */
- if (*((PUSHORT) &pSRBI->Reserved_1) == 0xAA55)
- { /*@V53040*/
- /* Determine how many extended bytes should be returned */ /*@V53040*/
- extendedByteCount = *(((PUSHORT) &(pSRBI->Reserved_1)) + 1);/*@V53040*/
- if (extendedByteCount > MAX_EXTENDED_ADAPTER_COUNT)
- extendedByteCount = MAX_EXTENDED_ADAPTER_COUNT;
- /*@V53040*/
- memcpy((PBYTE) &(pSRBI->AdapterFeatures),
- (PBYTE) &(pACB->AdapterFeatures),
- extendedByteCount);
- /*@V53040*/
- /* Update number of bytes transferred and signature */
- *(((PUSHORT) &(pSRBI->Reserved_1)) + 1) = extendedByteCount;/*@V53040*/
- *((PUSHORT) &pSRBI->Reserved_1) == 0x55AA;
- } /*@V53040*/
-
- ASPIStatus = ASPI_STATUS_NO_ERROR;
- }
-
- pSRBI->SRBHdr.ASPIStatus = ASPIStatus;
-
- if ((virtualASPI & VDM_REQUEST) != 0)
- CallVirtPostRoutine((PVOID) pSRBI);
-
- return(requestPacketStatus);
- }
-
- /*********************************************************
- * *
- * Procedure Name : DoASPIDeviceType *
- * *
- * Description : This procedure handles ASPI inquiries *
- * about a device. *
- * *
- * Input : *
- * pSRBDT - A pointer to the SRB for device *
- * inquiries *
- * virtualASPI - Flags indicating the status of *
- * the VDM that MAY be associated with the SRB. *
- * *
- * Output : This function returns the status for the *
- * request packet that was just handled by it. *
- * *
- *********************************************************/
- USHORT NEAR DoASPIDeviceType(PASPI_SRB_DEVICE_TYPE pSRBDT, USHORT virtualASPI)
-
- {
- UCHAR adapterIndex;
- UCHAR ASPIStatus;
- NPATE npATE;
- USHORT requestPacketStatus = STDON;
- USHORT allocationResult; /*@V64399*/
- USHORT allocationStatus; /*@V64399*/
- USHORT extendedByteCount;
- /*@V64399*/
- /* Assume the target is accessible */ /*@V64399*/
- allocationResult = 0; /*@V64399*/
-
- /* Verify that the host adapter is valid */
- adapterIndex = pSRBDT->SRBHdr.AdapterIndex;
-
- if (adapterIndex >= numberOfASPIAdapters)
- {
- ASPIStatus = ASPI_STATUS_INVALID_ADAPTER;
- requestPacketStatus |= STERR;
- }
- else
- {
- /* Verify that the target device is attached to the host adapter */
- npATE = FindTarget(adapterIndex,
- pSRBDT->DeviceTargetID,
- pSRBDT->DeviceTargetLUN);
-
- if (npATE)
- {
- /* Remember if the target is ALREADY allocated */
- allocationStatus = npATE->Flags & (ATEF_ASPI_ALLOCATED |
- ATEF_IGNORE_ALLOCATION);
-
- /* If the target is not already allocated, allocate it */ /*@V64399*/
- if (!allocationStatus)
- allocationResult = SendUnitControlCommand(npATE, /*@V64399*/
- IOCM_ALLOCATE_UNIT); /*@V64399*/
- /*@V64399*/
- /* If allocation failed, it was most like allocated AFTER */
- /* the ASPI manager was initialized. If allocation checking */
- /* is being ignored, update the allocation status and continue */
- if ((allocationOverride) &&
- (allocationResult))
- {
- npATE->Flags |= ATEF_IGNORE_ALLOCATION;
- npATE->TargetFeatures |= ASPI_DEVICE_ALLOCATION_SHARED;
- allocationResult = 0;
- }
-
- /* If target has been allocated to us, return device type *//*@V64399*/
- if (!allocationResult) /*@V64399*/
- { /*@V64399*/
- /* The device is available, so return the type reported */
- pSRBDT->DeviceType = npATE->DeviceType;
-
- /* If the device was not already allocated to us, */ /*@V64399*/
- /* release it so that we can return information about */ /*@V64399*/
- /* all available targets. The target will be */ /*@V64399*/
- /* permanently allocated when the first command is */ /*@V64399*/
- /* passed down to it. */ /*@V64399*/
-
- /* If allocation failed earlier and we are now sharing it */
- /* with another manager there is no deallocation needed. */
- if ((!allocationStatus) &&
- (!(npATE->Flags & ATEF_IGNORE_ALLOCATION)))
- SendUnitControlCommand(npATE,IOCM_DEALLOCATE_UNIT);
-
- /* Determine if we should return EXTENDED target information */
- if (*((PUSHORT) &pSRBDT->Reserved_1) == 0xAA55)
- {
- /* Determine how many extended bytes should be returned */
- extendedByteCount = *(((PUSHORT) &(pSRBDT->Reserved_1)) + 1);
- if (extendedByteCount > MAX_EXTENDED_TARGET_COUNT)
- extendedByteCount = MAX_EXTENDED_TARGET_COUNT;
-
- memcpy((PBYTE) &(pSRBDT->TargetFeatures),
- (PBYTE) &(npATE->TargetFeatures),
- extendedByteCount);
-
- /* Update number of bytes transferred and signature */
- *(((PUSHORT) &(pSRBDT->Reserved_1)) + 1) = extendedByteCount;
- *((PUSHORT) &pSRBDT->Reserved_1) == 0x55AA;
- }
-
- ASPIStatus = ASPI_STATUS_NO_ERROR;
- }
- else
- {
- ASPIStatus = ASPI_STATUS_INVALID_TARGET;
- requestPacketStatus |= STERR;
- }
- } /*@V64399*/
- else
- {
- ASPIStatus = ASPI_STATUS_INVALID_TARGET;
- requestPacketStatus |= STERR;
- }
- }
-
- pSRBDT->SRBHdr.ASPIStatus = ASPIStatus;
-
- if ((virtualASPI & VDM_REQUEST) != 0)
- CallVirtPostRoutine((PVOID) pSRBDT);
-
- return(requestPacketStatus);
- }
-
-
- /*********************************************************
- * *
- * Procedure Name : DoASPIExecuteIO *
- * *
- * Description : This procedure handles requests to *
- * send commands directly to a device. *
- * *
- * Input : *
- * pSRBIO - A pointer to the SRB for I/O *
- * virtualASPI - Flags indicating the status of *
- * the VDM that MAY be associated with the SRB. *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID NEAR DoASPIExecuteIO(PASPI_SRB_EXECUTE_IO pSRBIO, USHORT virtualASPI)
-
- {
- UCHAR adapterIndex;
- UCHAR ASPIStatus;
- UCHAR ASPICmd;
- NPATE npATE;
- USHORT allocationResult = 0;
-
- adapterIndex = pSRBIO->SRBHdr.AdapterIndex;
- ASPICmd = pSRBIO->SRBHdr.CommandCode;
-
- /* Verify that the host adapter is valid */
- if (adapterIndex >= numberOfASPIAdapters)
- ASPIStatus = ASPI_STATUS_INVALID_ADAPTER;
- else
- {
- /* Verify that the target device is attached to the host adapter */
- npATE = FindTarget(adapterIndex,
- pSRBIO->DeviceTargetID,
- pSRBIO->DeviceTargetLUN);
-
- if (npATE)
- {
- /* If the device was allocated by OS2ASPI or if access is being */
- /* shared with another manager WITHOUT deallocation, send the SRB. */
- /* Otherwise, allocate the target and then send the SRB */
- if (!((npATE->Flags & ATEF_ASPI_ALLOCATED) ||
- (npATE->Flags & ATEF_IGNORE_ALLOCATION)))
- allocationResult = SendUnitControlCommand(npATE,
- IOCM_ALLOCATE_UNIT);
-
- /* If allocation failed, it was most like allocated AFTER */
- /* the ASPI manager was initialized. If allocation checking */
- /* is being ignored, update the allocation status and continue */
- if ((allocationOverride) &&
- (allocationResult))
- {
- npATE->Flags |= ATEF_IGNORE_ALLOCATION;
- npATE->TargetFeatures |= ASPI_DEVICE_ALLOCATION_SHARED;
- allocationResult = 0;
- }
-
- if (!allocationResult)
- {
- /* The unit is available, so mark the SRB in progress */
- /* and issue the command to the target */
- ASPIStatus = ASPI_STATUS_IN_PROGRESS;
- pSRBIO->SRBHdr.ASPIStatus = ASPI_STATUS_IN_PROGRESS;
-
- switch (ASPICmd)
- {
- case ASPI_CMD_EXECUTE_IO:
- SRBToIORBPassThru(npATE, /*@V61092*/
- pSRBIO,
- 0,
- virtualASPI);
- break;
- case ASPI_CMD_RESET_DEVICE :
- SRBToIORBReset(npATE, /*@V61092*/
- (PASPI_SRB_RESET_DEVICE) pSRBIO,
- 0,
- virtualASPI);
- break;
- default :
- ASPIStatus = ASPI_STATUS_INVALID_COMMAND;
- }
- }
- else
- {
- /* The selected target is already in use */
- ASPIStatus = ASPI_STATUS_ERROR;
- pSRBIO->HostStatus = ASPI_HSTATUS_SELECTION_TIMEOUT;
- }
- }
- else
- ASPIStatus = ASPI_STATUS_INVALID_TARGET;
- }
-
- /* If the request is not pending, report the error. */
- /* All successful completions are reported in NotifyIORBDone */
- if (ASPIStatus != ASPI_STATUS_IN_PROGRESS)
- {
- pSRBIO->SRBHdr.ASPIStatus = ASPIStatus;
-
- /* Call the ASPI posting routine (if necessary) */
- if ((virtualASPI & VDM_REQUEST) != 0)
- CallVirtPostRoutine((PVOID)pSRBIO);
- else
- if (pSRBIO->SRBHdr.ASPIReqFlags & ASPI_REQFLAG_POST_ENABLE)
- CallPostRoutine(pSRBIO);
- }
- }
-
- #pragma optimize("cegl",off) /* Disable optimization switches that */
- /* are illegal for routines that contain */
- /* inline assembly code */
- /*********************************************************
- * *
- * Procedure Name : DoASPIAbortIO *
- * *
- * Description : This procedure handles requests to *
- * abort commands being executed by a device. *
- * *
- * Input : *
- * pSRBIO - A pointer to the SRB for I/O *
- * virtualASPI - Flags indicating the status of *
- * the VDM that MAY be associated with the SRB. *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID NEAR DoASPIAbortIO(PASPI_SRB_ABORT_IO pSRBIO, USHORT virtualASPI)
-
- {
- UCHAR adapterIndex;
- NPATE npATE;
- USHORT resultCode;
- USHORT modeFlag;
- PASPI_SRB_EXECUTE_IO pAbortSRB;
- PASPI_SRBWORK pASPIWork;
-
- /* Verify that the host adapter is valid */
- adapterIndex = pSRBIO->SRBHdr.AdapterIndex;
-
- if (adapterIndex >= numberOfASPIAdapters)
- pSRBIO->SRBHdr.ASPIStatus = ASPI_STATUS_INVALID_ADAPTER;
- else
- {
- /* Convert physical address of SRB being aborted to virtual address */
- /* and release it after extracting the targetID and targetLUN */
- resultCode = DevHelp_PhysToVirt(pSRBIO->ppSRB,
- (USHORT) sizeof(ASPI_SRB_EXECUTE_IO),
- (PPVOID)&pAbortSRB,
- &modeFlag);
-
- /* The driver must not yield while the virtual address is being used */
- DISABLE
- npATE = FindTarget(adapterIndex,
- pAbortSRB->DeviceTargetID,
- pAbortSRB->DeviceTargetLUN);
- if (npATE)
- {
- /* Retrieve the virtual pointer used by the VDD */
- /* in case this request is part of a VDM_DESTROY event. */
- pASPIWork = (PASPI_SRBWORK) pAbortSRB->ASPIWorkSpace;
- }
- ENABLE
-
- DevHelp_UnPhysToVirt(&modeFlag);
-
- if (npATE)
- {
- /* Abort IORB pending on the device for specified SRB. */
- /* Queues will automatically be cleaned up by NotifyIORBDone */
- /* as each SRB is aborted. */
- AbortIORB(npATE,
- pSRBIO,
- pASPIWork,
- 0,
- virtualASPI);
-
- }
- else
- pSRBIO->SRBHdr.ASPIStatus = ASPI_STATUS_INVALID_TARGET;
- }
- }
-
- #pragma optimize("cegl",on) /* Enable optimization switches again */
-
- /*********************************************************
- * *
- * Procedure Name : AbortIORB *
- * *
- * Description : This procedure attempts to abort the *
- * IORB that was created for a specified SRB. Since *
- * this IORB has already been passed to the ADD we *
- * cannot assume it will succeed. The actual success *
- * or failure of this command must be verified in the *
- * status of the ABORT SRB. *
- * *
- * Input : *
- * npATE - A pointer to the command target's ATE *
- * pSRBIO - A pointer to the SRB *
- * pSRBToAbortWork - A pointer to the work space *
- * of the SRB being aborted. *
- * npSRBLink - A pointer to the SRB_LINK that is *
- * allocated for the current command. *
- * virtualASPI - Flags indicating the status of *
- * the VDM that MAY be associated with the SRB. *
- * *
- * Output : *
- * *
- *********************************************************/ /*@V61092*/
- VOID NEAR AbortIORB(NPATE npATE,PASPI_SRB_ABORT_IO pSRBIO,
- PASPI_SRBWORK pSRBToAbortWork, NPSRB_LINK npSRBLink,
- USHORT virtualASPI)
-
- {
- PIORB_DEVICE_CONTROL pIORB;
- PIORB_DMWORK pDMWork;
- ULONG physSRBIO;
- ULONG SRBLockHandle;
- PIORBH pIORBToAbort;
-
- /* Allocate an IORB for the current SRB if one is not already available */
- if (!npSRBLink) /*@V61092*/
- npSRBLink = AllocateIORB(npATE,
- (PASPI_SRB_HEADER) pSRBIO,
- AbortIORB,
- virtualASPI);/*@V61092*/
- /*@V61092*/
- if (npSRBLink) /*@V61092*/
- {
- /* Create an IORB that the ADD can handle */
- pIORB = (PIORB_DEVICE_CONTROL) &npSRBLink->IORB;
- pDMWork = (PIORB_DMWORK) &(pIORB->iorbh.DMWorkSpace);
-
- memset((PBYTE) pIORB,0,sizeof(IORB_DEVICE_CONTROL));
- pIORB->iorbh.Length = sizeof(IORB_DEVICE_CONTROL);
- pIORB->iorbh.UnitHandle = npATE->UnitHandle;
- pIORB->iorbh.CommandCode = IOCC_DEVICE_CONTROL;
- pIORB->iorbh.CommandModifier = IOCM_ABORT;
-
- pIORB->iorbh.NotifyAddress = &NotifyIORBDone;
- pIORB->iorbh.StatusBlockLen = sizeof(SCSI_STATUS_BLOCK);
- pIORB->iorbh.pStatusBlock = (NPBYTE) &npSRBLink->commandStatus;
-
- /* Clear the status block before using it */
- memset((PBYTE) &npSRBLink->commandStatus,0,sizeof(SCSI_STATUS_BLOCK));
-
- /* Save DS and pointers to the request packet and current ATE */
- pDMWork->npATE = npATE;
- pDMWork->virtualASPI = virtualASPI;
- npSRBLink->OrigSRBPtr = (PVOID) pSRBIO;
-
-
- /* Lock the SRB selector in place and record its location. */
- /* This really should have been done by the caller, but it is */
- /* nice to try and be sure. */
- DevHelp_Lock(SELECTOROF(pSRBIO),
- 1,
- 1,
- &SRBLockHandle);
-
- DevHelp_VirtToPhys(pSRBIO,
- &physSRBIO);
-
- /* Copy the SRB selector to the GDT so we can use it later */
- pDMWork->SRBGDTSelector = npSRBLink->SRBGDTSelector; /*@V58231*/
- DevHelp_PhysToGDTSelector(physSRBIO,
- sizeof(ASPI_SRB_ABORT_IO),
- pDMWork->SRBGDTSelector);
-
- /* Release our lock on the SRB because it cannot be done */
- /* at interrupt time!! */
- DevHelp_UnLock(SRBLockHandle);
-
- /* Place the SRB_LINK in the active queue of the ATE */
- InsertSRBActiveQueue(npATE,
- npSRBLink,
- (PASPI_SRB_HEADER) MAKEP(pDMWork->SRBGDTSelector,
- 0));
-
- /* If we are aborting a VDM request in response to the destruction */
- /* of the VDM itself, we will fake the VDM out to avoid any chance */
- /* that the VDM will have to wait a really long time for the command */
- /* to be aborted. This would occur if the device has disconnected */
- /* from the SCSI bus and will not see the abort request until the */
- /* command has completed and it reconnects to the bus. */
- if ((virtualASPI & VDM_DESTROY_EVENT) != 0)
- {
- /* Modify the IORB workspace of the SRB being aborted */
- /* to remember that the VDM was already destroyed. */
- pIORBToAbort = (PIORBH) pSRBToAbortWork->pIORB;
- ((PIORB_DMWORK) (pIORBToAbort->DMWorkSpace))->virtualASPI |= VDM_DESTROY_EVENT;
-
- /* Simulate the post to the VDD now. */
- CallVirtPostRoutine((PASPI_SRB_EXECUTE_IO) pSRBToAbortWork->pSRB);
- }
-
- /* Send the abort IORB to the ADD */
- SendIORB((PIORBH) pIORB,npATE->TargetADD_Entry);
- }
- }
-
- /*********************************************************
- * *
- * Procedure Name : DoASPISetAdapterParms *
- * *
- * Description : This procedure is intended to allow *
- * adapter parameters to be modified and is therefore *
- * quite vendor specific. Currently NOTHING is done. *
- * *
- * Input : *
- * pSRAP - A pointer to the current SRB *
- * virtualASPI - Flags indicating the status of *
- * the VDM that MAY be associated with the SRB. *
- * *
- * Output : *
- * *
- *********************************************************/
- USHORT NEAR DoASPISetAdapterParms(PASPI_SRB_ADAPTER_PARMS pSRAP, USHORT virtualASPI)
-
- {
- pSRAP->SRBHdr.ASPIStatus = ASPI_STATUS_NO_ERROR;
- return(STDON);
- }
-
- /*********************************************************
- * *
- * Procedure Name : SRBToIORBPassThru *
- * *
- * Description : This procedure creates an IORB from *
- * the ASPI SRB and issues the command to the ADD. *
- * *
- * Input : *
- * npATE - A pointer to the command target's ATE *
- * pSRBIO - A pointer to the SRB *
- * npSRBLink - A pointer to the SRB_LINK that is *
- * allocated for the current command. *
- * virtualASPI - Flags indicating the status of *
- * the VDM that MAY be associated with the SRB. *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID NEAR SRBToIORBPassThru(NPATE npATE,PASPI_SRB_EXECUTE_IO pSRBIO,
- NPSRB_LINK npSRBLink,USHORT virtualASPI)
-
- {
- /* Allocate an IORB for the current SRB if one is not already available */
- if (!npSRBLink)
- npSRBLink = AllocateIORB(npATE,
- (PASPI_SRB_HEADER) pSRBIO,
- SRBToIORBPassThru,
- virtualASPI);
-
- if (npSRBLink)
- {
- /* Create an IORB that the ADD can handle */
- BuildPassThruIORB(npATE,
- pSRBIO,
- npSRBLink,
- virtualASPI);
-
- /* Place the SRB_LINK in the active queue of the ATE */
- InsertSRBActiveQueue(npATE,
- npSRBLink,
- (PASPI_SRB_HEADER) pSRBIO);
-
- /* Send the IORB to the ADD */
- SendIORB((PIORBH) &npSRBLink->IORB,
- npATE->TargetADD_Entry);
- }
- }
-
- /*********************************************************
- * *
- * Procedure Name : SRBToIORBReset *
- * *
- * Description : This procedure creates an IORB that *
- * will reset the selected adapter target. *
- * *
- * Input : *
- * npATE - A pointer to the current ATE *
- * pSRBRD - A pointer to the current SRB *
- * npSRBLink - A pointer to the SRB_LINK that is *
- * allocated for the current command. *
- * virtualASPI - Flags indicating the status of *
- * the VDM that MAY be associated with the SRB. *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID NEAR SRBToIORBReset(NPATE npATE,PASPI_SRB_RESET_DEVICE pSRBRD,
- NPSRB_LINK npSRBLink,USHORT virtualASPI)
-
- {
- PIORB_DEVICE_CONTROL pIORB;
- PIORB_DMWORK pDMWork;
- PASPI_SRBWORK pASPIWork;
- ULONG physSRBIO;
- ULONG SRBLockHandle;
-
- /* Allocate an IORB for the current SRB if one is not already available */
- if (!npSRBLink)
- npSRBLink = AllocateIORB(npATE,
- (PASPI_SRB_HEADER) pSRBRD,
- SRBToIORBReset,
- virtualASPI);
-
- if (npSRBLink)
- {
- /* Create an IORB that the ADD can handle */
- pIORB = (PIORB_DEVICE_CONTROL) &npSRBLink->IORB;
- pDMWork = (PIORB_DMWORK) &(pIORB->iorbh.DMWorkSpace);
-
- memset((PBYTE) pIORB,0,sizeof(IORB_DEVICE_CONTROL));
- pIORB->iorbh.Length = sizeof(IORB_DEVICE_CONTROL);
- pIORB->iorbh.UnitHandle = npATE->UnitHandle;
- pIORB->iorbh.CommandCode = IOCC_DEVICE_CONTROL;
- pIORB->iorbh.CommandModifier = IOCM_RESET;
-
- pIORB->iorbh.NotifyAddress = &NotifyIORBDone;
- pIORB->iorbh.StatusBlockLen = sizeof(SCSI_STATUS_BLOCK);
- pIORB->iorbh.pStatusBlock = (NPBYTE) &npSRBLink->commandStatus;
-
- /* Clear the status block before using it */
- memset((PBYTE) &npSRBLink->commandStatus,0,sizeof(SCSI_STATUS_BLOCK));
-
- /* Save DS and pointers to the request packet and current ATE */
- pDMWork->npATE = npATE;
- pDMWork->virtualASPI = virtualASPI;
- npSRBLink->OrigSRBPtr = (PVOID) pSRBRD;
-
- /* Save the virtual pointer to the SRB and the IORB ptr */
- /* in the SRB workspace. These will be used if the request */
- /* originated in a VDM and the VDM is destroyed while the */
- /* request is still pending. */
- pASPIWork = (PASPI_SRBWORK) pSRBRD->ASPIWorkSpace;
- pASPIWork->pSRB = npSRBLink->OrigSRBPtr;
- pASPIWork->pIORB = (PIORBH) pIORB;
-
- /* Lock the SRB selector in place and record its location. */
- /* This really should have been done by the caller, but it is */
- /* nice to try and be sure. */
- DevHelp_Lock(SELECTOROF(pSRBRD),
- 1,
- 1,
- &SRBLockHandle);
-
- DevHelp_VirtToPhys(pSRBRD,
- &physSRBIO);
-
- pDMWork->SRBGDTSelector = npSRBLink->SRBGDTSelector; /*@V58231*/
- DevHelp_PhysToGDTSelector(physSRBIO,
- sizeof(ASPI_SRB_RESET_DEVICE),
- pDMWork->SRBGDTSelector);
-
- /* Release our lock on the SRB because it cannot be done */
- /* at interrupt time!! */
- DevHelp_UnLock(SRBLockHandle);
-
- /* Place the SRB_LINK in the active queue of the ATE */
- InsertSRBActiveQueue(npATE,
- npSRBLink,
- (PASPI_SRB_HEADER) MAKEP(pDMWork->SRBGDTSelector,
- 0));
-
- /* Send the IORB to the ADD */
- SendIORB((PIORBH) pIORB,
- npATE->TargetADD_Entry);
- }
- }
-
- /*********************************************************
- * *
- * Procedure Name : FindAdapter *
- * *
- * Description : This procedure scans the list of *
- * host adapters that are accepting ASPI commands and *
- * tries to find a match. *
- * *
- * Input : *
- * adapterIndex - The adapter being searched for *
- * *
- * Output : A pointer to the ACB of the host adapter *
- * that was found or a NULL pointer if there was no *
- * match. *
- * *
- *********************************************************/
- NPACB FindAdapter(UCHAR adapterIndex)
-
- {
- NPACB npACB;
- USHORT adapterCount;
-
- /* Start at the beginning of the ACB list */
- npACB = npACBAnchor;
- adapterCount = 0;
-
- /* Search until a match is found or all the adapters have been scanned */
- while ((npACB->AdapterIndex != adapterIndex) &&
- (adapterCount < numberOfASPIAdapters))
- {
- npACB = npACB->npNextACB;
- adapterCount++;
- }
-
- if (npACB->AdapterIndex != adapterIndex)
- npACB = 0;
-
- return(npACB);
- }
-
- /*********************************************************
- * *
- * Procedure Name : FindTarget *
- * *
- * Description : This procedure scans the list of *
- * targets attached to the current ACB and tries to *
- * find a match. *
- * *
- * Input : *
- * adapterIndex - The adapter being searched *
- * targetID - The SCSI ID being searched for *
- * targetLUN - The SCSI LUN being searched for *
- * *
- * Output : A pointer to the ATE of the target device *
- * that was found or a NULL pointer if there was no *
- * match. *
- * *
- *********************************************************/
- NPATE FindTarget(UCHAR adapterIndex,UCHAR targetID, UCHAR targetLUN)
-
- {
- NPACB npACB;
- NPATE npATE;
-
- /* Find the ACB of the target's host adapter and start searching */
- /* with the first target attached to it */
- npACB = FindAdapter(adapterIndex);
- npATE = npACB->npFirstATE;
-
- /* Search until the targetID is found or there are no more targets */
- while ((targetID != npATE->DeviceTargetID) &&
- (adapterIndex == npATE->npOwnerACB->AdapterIndex) &&
- (npATE))
- npATE = npATE->npNextATE;
-
-
- if ((targetID == npATE->DeviceTargetID) &&
- (adapterIndex == npATE->npOwnerACB->AdapterIndex) &&
- (npATE))
- {
- /* Search until the targetLUN is found or there are no more targets */
- while ((targetLUN != npATE->DeviceTargetLUN) &&
- (targetID == npATE->DeviceTargetID) &&
- (adapterIndex == npATE->npOwnerACB->AdapterIndex) &&
- (npATE))
- npATE = npATE->npNextATE;
-
- if ((targetLUN != npATE->DeviceTargetLUN) ||
- (targetID != npATE->DeviceTargetID) ||
- (adapterIndex != npATE->npOwnerACB->AdapterIndex))
- npATE = 0;
- }
- else
- /* No target was found so DON'T return a pointer */
- npATE = 0;
- return(npATE);
- }
-
- #pragma optimize("cegl",off) /* Disable optimization switches that */
- /* are illegal for routines that contain */
- /* inline assembly code */
-
- /*********************************************************
- * *
- * Procedure Name : AllocateIORB *
- * *
- * Description : This procedure takes the next *
- * available SRB_LINK, which contains an IORB and *
- * returns a pointer to it. If no IORB is available *
- * the SRB will be inserted in a queue of waiting SRB *
- * until all SRB_LINK required by it are available. *
- * *
- * Input : *
- * *
- * Output : A pointer to the next available SRB_LINK *
- * or 0 if there are an insufficient number *
- * of SRB_LINK available for the request. *
- * *
- *********************************************************/
- NPSRB_LINK AllocateIORB(NPATE npATE, PASPI_SRB_HEADER pSRBH,
- VOID (NEAR *ASPIRequestRoutine)(), USHORT virtualASPI)
-
- {
- NPSRB_LINK npSRBLink = 0;
-
- /* If an SRB_LINK is available return a pointer to it */
- /* otherwise place the SRB in the queue of waiting requests */
-
- DISABLE
-
- if (npSRBLinkFreeList)
- {
- npSRBLink = npSRBLinkFreeList;
- npSRBLinkFreeList = npSRBLinkFreeList->npNextSRBLink;
- npSRBLink->OrigSRBPtr = (PVOID) pSRBH;
- }
- else
- {
- SRBWaitQueue[IORBWaitSem].SRBPtr = pSRBH; /*@V61092*/
- SRBWaitQueue[IORBWaitSem].ATEPtr = npATE; /*@V61092*/
- SRBWaitQueue[IORBWaitSem].callbackFunction = ASPIRequestRoutine;/*@V61092*/
- SRBWaitQueue[IORBWaitSem].virtualASPI = virtualASPI;
- IORBWaitSem++; /*@V61092*/
- } /*@V61092*/
-
- ENABLE
-
- return(npSRBLink);
- }
-
- /*********************************************************
- * *
- * Procedure Name : FreeIORB *
- * *
- * Description : This procedure releases the IORB or *
- * that was just completed and places it back in the *
- * pool of available SRB_LINKs. If SRBs are waiting, *
- * the next one will be started. *
- * *
- * Input : A pointer to the SRB_LINK(s) *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID FreeIORB(NPSRB_LINK npSRBLink)
-
- {
- DISABLE /*@V61092*/
- /*@V61092*/
- /* If anyone is waiting for an IORB, wake them up */ /*@V61092*/
- if (IORBWaitSem) /*@V61092*/
- { /*@V61092*/
- IORBWaitSem--; /*@V61092*/
- /*@V61092*/
- npSRBLink->OrigSRBPtr = (PVOID) (SRBWaitQueue[IORBWaitSem].SRBPtr);
- /* Resubmit SRB with SRB_LINK already allocated */ /*@V61092*/
- (VOID) (SRBWaitQueue[IORBWaitSem].callbackFunction) /*@V61092*/
- (SRBWaitQueue[IORBWaitSem].ATEPtr, /*@V61092*/
- SRBWaitQueue[IORBWaitSem].SRBPtr, /*@V61092*/
- npSRBLink,
- SRBWaitQueue[IORBWaitSem].virtualASPI);
- ENABLE /*@V61092*/
- } /*@V61092*/
- else /*@V61092*/
- { /*@V61092*/
- /* Insert the completed IORB at the front of the free list */ /*@V61092*/
- npSRBLink->npNextSRBLink = npSRBLinkFreeList; /*@V61092*/
- npSRBLinkFreeList = npSRBLink; /*@V61092*/
- ENABLE /*@V61092*/
- } /*@V61092*/
- }
-
- /* Removed optimization from this routine because of compiler */ /*@V58231*/
- /* in MSC 6.00A.04. */ /*@V58231*/
- #pragma optimize("gl",on) /* Enable optimization switches again *//*@V58231*/
-
- /*********************************************************
- * *
- * Procedure Name : BuildPassThruIORB *
- * *
- * Description : This procedure builds an IORB for the *
- * current SRB within a freshly allocated SRB_LINK. *
- * *
- * Input : *
- * npATE - A pointer to the current ATE *
- * pSRBIO - A pointer to the current SRB *
- * npSRBLink - A pointer to the new SRB_LINK *
- * virtualASPI - Flags indicating the status of *
- * the VDM that MAY be associated with the SRB. *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID BuildPassThruIORB(NPATE npATE,PASPI_SRB_EXECUTE_IO pSRBIO,
- NPSRB_LINK npSRBLink, USHORT virtualASPI)
-
- {
- PIORB_ADAPTER_PASSTHRU pIORB;
- PIORB_DMWORK pDMWork;
- PASPI_SRBWORK pASPIWork;
-
- pIORB = (PIORB_ADAPTER_PASSTHRU) &npSRBLink->IORB;
- pDMWork = (PIORB_DMWORK) &(pIORB->iorbh.DMWorkSpace);
-
- memset((PBYTE) pIORB,
- 0,
- sizeof(IORB_ADAPTER_PASSTHRU));
- pIORB->iorbh.Length = sizeof(IORB_ADAPTER_PASSTHRU);
- pIORB->iorbh.UnitHandle = npATE->UnitHandle;
- pIORB->iorbh.CommandCode = IOCC_ADAPTER_PASSTHRU;
- pIORB->iorbh.CommandModifier = IOCM_EXECUTE_CDB;
-
- npSRBLink->OrigSRBPtr = (PVOID) pSRBIO;
-
- /* Save the virtual pointer to the SRB and the IORB ptr */
- /* in the SRB workspace. These will be used if the request */
- /* originated in a VDM and the VDM is destroyed when the */
- /* request is still pending. */
- pASPIWork = (PASPI_SRBWORK) pSRBIO->ASPIWorkSpace;
- pASPIWork->pSRB = npSRBLink->OrigSRBPtr;
- pASPIWork->pIORB = (PIORBH) pIORB;
-
- /* Copy the SRB selector to the GDT so we can use it later */
- pDMWork->SRBGDTSelector = npSRBLink->SRBGDTSelector; /*@V58231*/
- DevHelp_PhysToGDTSelector(pSRBIO->ppSRB,
- sizeof(ASPI_SRB_EXECUTE_IO) +
- pSRBIO->SenseDataLen +
- pSRBIO->SCSICDBLen,
- pDMWork->SRBGDTSelector);
-
- /* Convert the SRB pointer to the "safe" GDT selector */
- pSRBIO = (PASPI_SRB_EXECUTE_IO) MAKEP(pDMWork->SRBGDTSelector,0);
-
- pIORB->iorbh.NotifyAddress = &NotifyIORBDone;
- pIORB->ControllerCmdLen = pSRBIO->SCSICDBLen;
- pIORB->pControllerCmd = pSRBIO->SCSICDBStart;
- pIORB->iorbh.StatusBlockLen = sizeof(SCSI_STATUS_BLOCK);
- pIORB->iorbh.pStatusBlock = (NPBYTE) &npSRBLink->commandStatus;
-
- /* Clear the status block before using it */
- memset((PBYTE) &npSRBLink->commandStatus,0,sizeof(SCSI_STATUS_BLOCK));
-
- ((PSCSI_STATUS_BLOCK)(pIORB->iorbh.pStatusBlock))->SenseData =
- (PSCSI_REQSENSE_DATA) (pSRBIO->SCSICDBStart + pSRBIO->SCSICDBLen);
-
- ((PSCSI_STATUS_BLOCK)(pIORB->iorbh.pStatusBlock))->ReqSenseLen =
- pSRBIO->SenseDataLen;
-
- /* Set up a pointer to the scatter/gather list or data buffer */
- if (pSRBIO->SRBHdr.ASPIReqFlags & ASPI_REQFLAG_SG_ENABLE)
- {
- pIORB->cSGList = pSRBIO->SGListLen;
- pIORB->ppSGLIST = pSRBIO->ppDataBuffer;
-
- /* Get a pointer to the scatter/gather list by using the GDT */
- /* allocated to the current target for scatter/gather. */
- pDMWork->SGGDTSelector = npSRBLink->SGGDTSelector; /*@V58231*/
- DevHelp_PhysToGDTSelector(pIORB->ppSGLIST,
- pIORB->cSGList * sizeof(SCATGATENTRY),
- pDMWork->SGGDTSelector); /*@V58231*/
-
- pIORB->pSGList = (PSCATGATENTRY) MAKEP(pDMWork->SGGDTSelector,0);/*@V61092*/
- }
- else
- {
- /* Treat a standard data buffer as a scatter/gather list */
- /* with only one element. If there is no data transfer, then */
- /* do NOT build a scatter/gather list. */
- if (pSRBIO->DataXferLen) /*@V58231*/
- { /*@V58231*/
- pIORB->cSGList = 1; /*@V58231*/
- pIORB->pSGList = (PVOID) pIORB;
- OFFSETOF(pIORB->pSGList) = (USHORT)((ULONG)&(pDMWork->SGList));
- pIORB->ppSGLIST = (ULONG) (ppDataSeg +
- (USHORT)((ULONG) &(pDMWork->SGList)));
-
- /* Insert the single element in the scatter/gather list */
- (ULONG) (pDMWork->SGList.ppXferBuf) = pSRBIO->ppDataBuffer;
- (ULONG) (pDMWork->SGList.XferBufLen) = pSRBIO->DataXferLen;
- } /*@V58231*/
- }
-
- /* Give all commands the MAXIMUM timeout since ASPI does not */
- /* really require this option. Commands that don't finish will */
- /* be aborted by the driver that requested them. */
- pIORB->iorbh.Timeout = 0xFFFFFFFF;
-
- /* Record the direction of the data transfer */
- DetermineDirectionBits(npATE, pIORB, pSRBIO);
-
- /* Save pointer to the current ATE */
- pDMWork->npATE = npATE;
- pDMWork->virtualASPI = virtualASPI;
- }
-
- #pragma optimize("ce",on) /* Enable optimization switches */ /*@V58231*/
-
- /*********************************************************
- * *
- * Function Name : DetermineDirectionBits *
- * *
- * Description : This function determines command *
- * direction and inserts the appropriate bits into *
- * the IORB. *
- * *
- * Input : *
- * pSRBIO - A pointer to the SRB being processed *
- * pIORB - A pointer to the IORB being created *
- * *
- * Output : *
- * *
- *********************************************************/
- USHORT DetermineDirectionBits( NPATE npATE,
- PIORB_ADAPTER_PASSTHRU pIORB,
- PASPI_SRB_EXECUTE_IO pSRBIO )
- {
- USHORT OpCode = pSRBIO->SCSICDBStart[0];
- USHORT rc = 1;
- NPUCHAR npDIRM;
- NPUCHAR npDIREX;
- USHORT DirBits;
- USHORT i, n;
-
- /**
- ** Was the direction of the command given in the SRB?
- **/
-
- DirBits = pSRBIO->SRBHdr.ASPIReqFlags & ASPI_REQFLAG_DIRECTION_BITS;
-
- if ( (DirBits == ASPI_REQFLAG_DIR_TO_HOST) ||
- (DirBits == ASPI_REQFLAG_DIR_NO_DATA_XFER ) )
- {
- pIORB->Flags = PT_DIRECTION_IN;
- }
- else if ( DirBits == ASPI_REQFLAG_DIR_TO_TARGET )
- {
- pIORB->Flags = 0;
- }
- else
- {
- /**
- ** Determine the transfer direction based on the CDB
- **
- ** The appropriate direction mask is determined at INIT
- ** time. If the device does not have a known SCSI device
- ** type and we do not have a specific direction mask for
- ** it, then the ASPI client driver must specify direction!
- **
- ** The table is encodeded so that a 1-bit indicates
- ** direction of transfer is Initiator-to-Target,
- ** i.e. a WRITE to the target.
- **/
- if ( npDIREX = npATE->npDirExcept )
- {
- n = npDIREX[0] * 2 + 1;
- for (i=1; i < n; i+=2 )
- {
- if ( OpCode == npDIREX[i] )
- {
- pIORB->Flags = ( npDIREX[i+1] ) ? 0 : PT_DIRECTION_IN;
- goto Exit_Dir;
- }
- }
- }
- if ( npDIRM = npATE->npDirTable )
- {
- pIORB->Flags = ( npDIRM[OpCode/8] & (0x80>>(OpCode % 8)) )
- ? 0: PT_DIRECTION_IN;
- }
- else
- {
- rc = 0;
- }
-
- }
-
- Exit_Dir:
- return rc;
- }
-
- /*********************************************************
- * *
- * Function Name : SendIORB *
- * *
- * Description : This function sends an IORB to the *
- * ADD and returns immediately after submitting it. *
- * *
- * Input : *
- * npIORB - A pointer to the IORB being issued *
- * pADD_IORB_Entry - A pointer to the ADD *
- * entry point for the unit receiving the IORB *
- * *
- * Output : This function returns the error status *
- * reported by the IORB. *
- * *
- *********************************************************/
- VOID SendIORB(PIORBH pIORB, VOID (FAR *pADD_IORB_Entry)(PIORB))
-
- {
- pIORB->RequestControl = IORB_ASYNC_POST | IORB_REQ_STATUSBLOCK |
- IORB_DISABLE_RETRY;
-
- (*pADD_IORB_Entry)(pIORB);
- }
-
-
- #pragma optimize("cegl",off) /* Disable optimization switches that */
- /* are illegal for routines that contain */
- /* inline assembly code */
-
- /*********************************************************
- * *
- * Function Name : SendIORBandWait *
- * *
- * Description : This function sends an IORB to the *
- * ADD and waits for completion before returning. *
- * *
- * Input : *
- * npIORB - A pointer to the IORB being issued *
- * pADD_IORB_Entry - A pointer to the ADD *
- * entry point *
- * *
- * Output : This function returns the error status *
- * reported by the IORB. *
- * *
- *********************************************************/
- USHORT SendIORBandWait(NPIORBH npIORB, VOID (FAR *pADD_IORB_Entry)(PIORB))
-
- {
- npIORB->RequestControl = IORB_ASYNC_POST;
-
- (*pADD_IORB_Entry)(npIORB);
-
- DISABLE
- while (!(npIORB->Status & IORB_DONE))
- {
- DevHelp_ProcBlock((ULONG) OFFSETOF(npIORB),
- (ULONG) -1,
- WAIT_IS_NOT_INTERRUPTABLE);
- DISABLE
- }
- ENABLE
-
- return(npIORB->ErrorCode);
- }
-
- /*********************************************************
- * *
- * Procedure Name : NotifyIORBDone *
- * *
- * Description : This procedure is called by the ADD *
- * when it has completed processing the IORB. *
- * *
- * Input : *
- * fpIORB - A far pointer to the IORB that has *
- * just been completed *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID FAR _loadds NotifyIORBDone(PIORB fpIORB) /*@V61779*/
-
- {
- PASPI_SRB_EXECUTE_IO pSRBIO;
- NPSRB_LINK npSRBLink;
- PIORB_DMWORK pWorkSpace;
- NPATE npATE;
-
- /* Restore DS and pointer to current ATE */
- pWorkSpace = (PIORB_DMWORK) fpIORB->DMWorkSpace;
- npATE = pWorkSpace->npATE;
-
- npSRBLink = (NPSRB_LINK) OFFSETOF(fpIORB);
- ((NPBYTE) npSRBLink) -= ((NPBYTE)&npSRBLink->IORB - (NPBYTE)npSRBLink);
-
- pSRBIO = (PASPI_SRB_EXECUTE_IO) MAKEP(pWorkSpace->SRBGDTSelector,0);
-
- /* Immediately verify that this request does not belong to VDM */
- /* that no longer exists. */
- if ((pWorkSpace->virtualASPI & VDM_DESTROY_EVENT) != 0)
- {
- /* Deallocate the target if we are sharing it with another device */
- /* manager and we allocated it for our request. This will impact */
- /* performance slightly when /SHARE is used, but it is necessary to */
- /* avoid leaving a device unaccessible to another manager. */
- if ((npATE->Flags & ATEF_SHARE_ALLOCATION) &&
- ((pSRBIO->SRBHdr.CommandCode == ASPI_CMD_EXECUTE_IO) ||
- (pSRBIO->SRBHdr.CommandCode == ASPI_CMD_RESET_DEVICE)))
- SendUnitControlCommand(npATE,
- IOCM_DEALLOCATE_UNIT);
-
- /* The command now being handled is either a VDM request or an abort */
- /* of a VDM request. The former was posted to the VDD before sending */
- /* the latter. The latter is actually a standard OS/2 request and */
- /* does not need to be posted. However, the OS/2 request does need */
- /* to be marked complete. */
-
- /* Create error the error status for the OS/2 request */
- if ((pWorkSpace->virtualASPI & VDM_REQUEST) == 0)
- ConvertIORBError((PIORBH) fpIORB,
- pSRBIO);
-
- /* Clean up the queues and get out!! */
- DeleteSRBActiveQueue(npATE,
- npSRBLink);
- FreeIORB(npSRBLink);
- }
- else
- {
- /* Create error messages for ASPI from the IORB errors */
- ConvertIORBError((PIORBH) fpIORB,
- pSRBIO);
-
- /* Update data transfer length if residual byte count was requested *//*@V53040*/
- if (pSRBIO->SRBHdr.ASPIReqFlags & ASPI_REQFLAG_RESIDUAL) /*@V53040*/
- {
- /* We must ALWAYS return the residual byte count reported because */
- /* certain host adapters only detect OVERRUNs. *//*@V53040*/
- pSRBIO->DataXferLen =
- ((PSCSI_STATUS_BLOCK)((PIORBH) fpIORB->pStatusBlock))->ResidualLength;
- }
-
- /* Deallocate the target if we are sharing it with another device */
- /* manager and we allocated it for our request. This will impact */
- /* performance slightly when /SHARE is used, but it is necessary to */
- /* avoid leaving a device unaccessible to another manager. */
- if ((npATE->Flags & ATEF_SHARE_ALLOCATION) &&
- ((pSRBIO->SRBHdr.CommandCode == ASPI_CMD_EXECUTE_IO) ||
- (pSRBIO->SRBHdr.CommandCode == ASPI_CMD_RESET_DEVICE)))
- SendUnitControlCommand(npATE,
- IOCM_DEALLOCATE_UNIT);
-
- /* Submit the next linked SRB (if necessary) */
- if (pSRBIO->SRBHdr.ASPIReqFlags & ASPI_REQFLAG_LINKED_SRB)
- SRBToIORBPassThru(npATE, /*@V61092*/
- (PASPI_SRB_EXECUTE_IO) pSRBIO->ppNxtSRB,
- 0,
- pWorkSpace->virtualASPI);
-
- /* Call the ASPI posting routine (if necessary) */
- if (pWorkSpace->virtualASPI & VDM_REQUEST)
- CallVirtPostRoutine(npSRBLink->OrigSRBPtr);
- else
- if (pSRBIO->SRBHdr.ASPIReqFlags & ASPI_REQFLAG_POST_ENABLE)
- CallPostRoutine(pSRBIO); /*@V61092*/
-
- /* Remove the SRB_LINK from the active queue of the ATE */
- /* and place it back in the list of free IORB */
- DeleteSRBActiveQueue(npATE,
- npSRBLink);
- FreeIORB(npSRBLink);
- }
- }
- #pragma optimize("cegl",on) /* Enable optimization switches again */
-
- /******************************************************
- * *
- * Procedure Name : ConvertIORBError *
- * *
- * Description : This procedure converts any error *
- * returned in the IORB to an ASPI error code and *
- * inserts it in the SRB. *
- * *
- * Input : *
- * pIORB - A pointer to the IORB that has just *
- * been completed *
- * pSRBIO - A pointer to the SRB that owns the *
- * IORB that was just completed *
- * *
- * Output : *
- * *
- ******************************************************/
- VOID ConvertIORBError(PIORBH pIORBH,PASPI_SRB_EXECUTE_IO pSRBIO)
-
- {
- /* Was there an error detected by the ADD? */
- if (pIORBH->Status & IORB_ERROR)
- {
- /* What is the general error condition? */
- switch (pIORBH->ErrorCode)
- {
- case IOERR_CMD_ABORTED :
- pSRBIO->SRBHdr.ASPIStatus = ASPI_STATUS_ABORTED;
- break;
-
- case IOERR_CMD_NOT_SUPPORTED :
- pSRBIO->SRBHdr.ASPIStatus = ASPI_STATUS_INVALID_COMMAND;
- break;
-
- default :
- pSRBIO->SRBHdr.ASPIStatus = ASPI_STATUS_ERROR;
- }
-
-
- /* Does the SRB support adapter status and target status? */
- if (pSRBIO->SRBHdr.CommandCode == ASPI_CMD_EXECUTE_IO)
- {
- /* Did the host adapter detect an error? */
- switch (pIORBH->ErrorCode)
- {
- case IOERR_ADAPTER_TIMEOUT:
- case IOERR_ADAPTER_DEVICE_TIMEOUT:
- pSRBIO->HostStatus = ASPI_HSTATUS_SELECTION_TIMEOUT;
- break;
- case IOERR_ADAPTER_OVERRUN:
- case IOERR_ADAPTER_UNDERRUN:
- case IOERR_DEVICE_OVERRUN:
- case IOERR_DEVICE_UNDERRUN:
- pSRBIO->HostStatus = ASPI_HSTATUS_DATA_OVERRUN;
- break;
- case IOERR_ADAPTER_HOSTBUSCHECK:
- case IOERR_ADAPTER_DEVICEBUSCHECK:
- pSRBIO->HostStatus = ASPI_HSTATUS_BUS_PHASE_ERROR;
- break;
- case IOERR_CMD_SGLIST_BAD: /*@V53040*/
- pSRBIO->HostStatus = ASPI_HSTATUS_BAD_SGLIST; /*@V53040*/
- break; /*@V53040*/
- default:
-
- /* If residual byte count was requested in the SRB we must */
- /* make sure that an underrun is reported when there is */
- /* a valid residual byte count in the status block */
- if ((pSRBIO->SRBHdr.ASPIReqFlags & ASPI_REQFLAG_RESIDUAL) &&
- (((PSCSI_STATUS_BLOCK) (pIORBH->pStatusBlock))->Flags &
- STATUS_RESIDUAL_VALID) &&
- (((PSCSI_STATUS_BLOCK) (pIORBH->pStatusBlock))->ResidualLength))
- pSRBIO->HostStatus = ASPI_HSTATUS_DATA_OVERRUN;
- else
- pSRBIO->HostStatus = ASPI_HSTATUS_NO_ERROR;
- }
-
- /* Did the target detect an error? */
- switch (pIORBH->ErrorCode)
- {
- case IOERR_DEVICE_BUSY:
- pSRBIO->TargetStatus = ASPI_TSTATUS_BUSY;
- break;
- case IOERR_UNIT_NOT_ALLOCATED:
- pSRBIO->TargetStatus = ASPI_TSTATUS_RESERV_CONFLICT;
- break;
- default:
-
- /* If there was sense data returned then record check condition */
- if (((PSCSI_STATUS_BLOCK) (pIORBH->pStatusBlock))->Flags &
- STATUS_SENSEDATA_VALID)
- pSRBIO->TargetStatus = ASPI_TSTATUS_CHECK_CONDITION;
- else
- pSRBIO->TargetStatus = ASPI_TSTATUS_NO_ERROR;
-
- }
- }
- }
- else
- {
- /* There was no error detected */
- pSRBIO->SRBHdr.ASPIStatus = ASPI_STATUS_NO_ERROR;
-
- /* Does the SRB support adapter status and target status? */
- if (pSRBIO->SRBHdr.CommandCode == ASPI_CMD_EXECUTE_IO)
- {
- pSRBIO->TargetStatus = ASPI_TSTATUS_NO_ERROR;
- pSRBIO->HostStatus = ASPI_HSTATUS_NO_ERROR;
- }
- }
- }
-
- #pragma optimize("cegl",off) /* Disable optimization switches that */
- /* are illegal for routines that contain */
- /* inline assembly code */
-
- /*********************************************************
- * *
- * Function Name : CallPostRoutine *
- * *
- * Description : This function calls the post routine *
- * of the driver whose request has just completed. *
- * *
- * Input : *
- * pSRBIO - A pointer to the SRB for I/O *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID CallPostRoutine(PASPI_SRB_EXECUTE_IO pSRBIO)
-
- {
- /* Save the data segment since posting will trash it */
-
- _asm push ds
- _asm push es
- _asm push si
- _asm push di
- (*pSRBIO->PM_PostAddress)(pSRBIO->PM_DataSeg,
- (PASPI_SRB_HEADER) pSRBIO->ppSRB);
- _asm pop di
- _asm pop si
- _asm pop es
- _asm pop ds
- }
-
- /*********************************************************
- * *
- * Function Name : SendUnitControlCommand *
- * *
- * Description : This function reserves/frees the *
- * current target by issuing the appropriate IORB *
- * *
- * Input : *
- * npATE - A pointer to the targets's ATE *
- * unitControlCommand - The command to send *
- * *
- * Output : This function returns 0 if the command was*
- * successfully sent and a positive integer if an *
- * error was detected. *
- * *
- *********************************************************/
- USHORT SendUnitControlCommand(NPATE npATE,USHORT unitControlCommand)
-
- {
- USHORT resultCode;
- NPIORB_UNIT_CONTROL npIORBUnitControl = (NPIORB_UNIT_CONTROL) npATE->UnitControlIORB; /*@V64399*/
- PIORB_DMWORK pDMWork = (PIORB_DMWORK) (npIORBUnitControl->iorbh.DMWorkSpace); /*@V64399*/
-
- memset((PBYTE) npIORBUnitControl,
- 0,
- sizeof(IORB_UNIT_CONTROL));
- npIORBUnitControl->iorbh.Length = sizeof(IORB_UNIT_CONTROL);
- npIORBUnitControl->iorbh.UnitHandle = npATE->UnitHandle;
- npIORBUnitControl->iorbh.CommandCode = IOCC_UNIT_CONTROL;
- npIORBUnitControl->iorbh.CommandModifier = unitControlCommand;
- npIORBUnitControl->iorbh.Status = 0;
- npIORBUnitControl->iorbh.ErrorCode = 0;
- npIORBUnitControl->Flags = 0;
- npIORBUnitControl->iorbh.NotifyAddress = &AllocationPost; /*@V64399*/
- /*@V64399*/
- /* Save a pointer to the current ATE */ /*@V64399*/
- pDMWork->npATE = npATE; /*@V64399*/
-
- resultCode = SendIORBandWait((NPIORB) npIORBUnitControl,
- npATE->TargetADD_Entry);
-
- return(resultCode);
- }
-
- /*********************************************************
- * *
- * Procedure Name : InsertSRBActiveQueue *
- * *
- * Description : This procedure places the SRB link *
- * at the front of the queue of active IORBs that *
- * belong to the current ATE. *
- * *
- * Input : *
- * npATE - A pointer to the current ATE *
- * npSRBLink - A pointer to the new SRB link *
- * pSRB - A pointer to the current SRB *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID InsertSRBActiveQueue(NPATE npATE,NPSRB_LINK npSRBLink,PASPI_SRB_HEADER pSRBH)
-
- {
- /* Place the new SRB at the front of the queue */
- DISABLE
-
- npSRBLink->pSRB = pSRBH;
- npATE->SRBActiveQueueCount++;
- npSRBLink->npNextSRBLink = npATE->npSRBActiveQueue;
- npATE->npSRBActiveQueue = npSRBLink;
- ENABLE
- }
-
- /*********************************************************
- * *
- * Procedure Name : DeleteSRBActiveQueue *
- * *
- * Description : This procedure deletes the SRB link *
- * for the IORB that has just been completed from the *
- * active queue of its ATE. *
- * *
- * Input : *
- * npATE - A pointer to the current ATE *
- * npSRBLink - A pointer to the SRB link that *
- * has just been completed *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID DeleteSRBActiveQueue(NPATE npATE,NPSRB_LINK npSRBLink)
-
- {
- USHORT SRBCount = 0;
- NPSRB_LINK currentSRBLink;
- NPSRB_LINK previousSRBLink;
-
- /* Start at the front of the queue */
- currentSRBLink = previousSRBLink = npATE->npSRBActiveQueue;
-
- DISABLE
- while (SRBCount < npATE->SRBActiveQueueCount)
- {
- /* Is this the correct queue element to delete? */
- if (currentSRBLink->pSRB == npSRBLink->pSRB)
- {
- /* If this is the only element on the queue, then */ /*@V61092*/
- /* clear the whole queue. */ /*@V61092*/
- if ((!SRBCount) && /*@V61092*/
- (!previousSRBLink->npNextSRBLink)) /*@V61092*/
- npATE->npSRBActiveQueue = 0; /*@V61092*/
- else /*@V61092*/
- previousSRBLink->npNextSRBLink = currentSRBLink->npNextSRBLink;
- break;
- }
- else
- {
- /* No match yet, so try the next element in the queue */
- previousSRBLink = currentSRBLink;
- currentSRBLink = currentSRBLink->npNextSRBLink;
- SRBCount++;
- }
- }
- npATE->SRBActiveQueueCount--;
-
- ENABLE
- }
-
- #pragma optimize("cegl",on) /* Enable optimization switches again */
-
- /*********************************************************
- * *
- * Procedure Name : AllocationPost *
- * *
- * Description : This procedure is called by the ADD *
- * whenever an allocation or deallocation request has *
- * completed. *
- * *
- * Input : *
- * pIORB - A far pointer to the IORB that has *
- * just been completed *
- * *
- * Output : *
- * *
- *********************************************************/
- VOID FAR _loadds AllocationPost(PIORB pIORB) /*@V64399*/
- /*@V64399*/
- { /*@V64399*/
- NPATE npATE; /*@V64399*/
- PIORB_DMWORK pDMWork; /*@V64399*/
- /*@V64399*/
- /* If the command completed successfully update our structures. *//*@V64399*/
- if (((PIORB_UNIT_CONTROL) pIORB)->iorbh.Status == IORB_DONE) /*@V64399*/
- { /*@V64399*/
- /* Get a pointer to the appropriate ATE */ /*@V64399*/
- pDMWork = (PIORB_DMWORK) &(((PIORB_UNIT_CONTROL) pIORB)->iorbh.DMWorkSpace);/*@V64399*/
- npATE = pDMWork->npATE; /*@V64399*/
- /*@V64399*/
- /* If we are doing an allocate or deallocate we must set the *//*@V64399*/
- /* appropriate bits in the ATE, when the request finishes. *//*@V64399*/
- if (pIORB->CommandCode == IOCC_UNIT_CONTROL) /*@V64399*/
- switch (pIORB->CommandModifier) /*@V64399*/
- { /*@V64399*/
- case IOCM_ALLOCATE_UNIT: /*@V64399*/
- npATE->Flags |= ATEF_ASPI_ALLOCATED;
- break; /*@V64399*/
- /*@V64399*/
- case IOCM_DEALLOCATE_UNIT: /*@V64399*/
- npATE->Flags &= ~ATEF_ASPI_ALLOCATED;
- break; /*@V64399*/
- } /*@V64399*/
- } /*@V64399*/
- } /*@V64399*/
-
-