home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 10 Tools
/
10-Tools.zip
/
ddkx86v5.zip
/
DDKX86
/
SRC
/
DEV
/
TESTCFG
/
TCFGSCSI.C
< prev
next >
Wrap
C/C++ Source or Header
|
1995-04-14
|
17KB
|
528 lines
/*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 = "@(#)tcfgscsi.c 6.1 92/02/13";*/
/*********************************************************************
*
*
*
*
*********************************************************************/
/*** TCFGSCSI.C - SCSI Inquiry routine for TESTCFG device driver
* DESCRIPTION
*
* This file contains the routines for issuing SCSI inquiry
* commands.
*
*
*/
#include "testcfg.h"
#include "IORB.h"
#include "SCSI.h"
#include "devclass.h"
#include "tcfgscsi.h"
#include "tcfgx.h"
#define RMCode SWAPCODE
#include "rmcalls.h"
#include "tcfgex.h"
/*** CFG_SCSI_Inquiry - Issue SCSI Inquiry for specified device type
*
* This routine is used to issue SCSI INQUIRY command a specified
* device type
*
* ENTRY
* PREQPACKET rp - pointer to Device driver request packet
*
* EXIT
* returns Device Driver Completion Code
*
*/
USHORT far CFG_SCSI_Inquiry(PREQPACKET rp)
{
PINQUIRYPARMPACKET pParm;
PINQUIRYDATAPACKET pBuffer;
/* Get and Verify Command Information Field */
pParm = (PINQUIRYPARMPACKET)rp->s.IOCtl.parameters;
if(VerifyAccess(pParm,sizeof(PINQUIRYPARMPACKET),VERIFY_READACCESS))
return(RPDONE | RPERR | ERROR_INVALID_PARAMETER);
if(pParm->CmdWord==0) {
/* Get and Verify Buffer Field */
pBuffer = (PINQUIRYDATAPACKET)rp->s.IOCtl.buffer;
if(VerifyAccess(pBuffer,sizeof(INQUIRYDATAPACKET),VERIFY_READWRITEACCESS))
return(RPDONE | RPERR | ERROR_INVALID_PARAMETER);
Build_UnitCBs(pBuffer,pParm->Dev_Type);
}
else
return(RPDONE | RPERR | ERROR_INVALID_PARAMETER);
return(RPDONE);
}
/********************** START OF SPECIFICATIONS *****************************
* *
* SUBROUTINE NAME: Build_UnitCBs *
* *
* *
* ENTRY POINT: Build_UnitCBs *
* *
* LINKAGE: Call Near *
* *
* INPUT: *
* *
* EXIT-NORMAL: 0 *
* *
* EXIT-ERROR: -1 *
* *
* *
*********************** END OF SPECIFICATIONS *******************************/
unsigned near Build_UnitCBs(PINQUIRYDATAPACKET pBuffer, UCHAR DevType)
{
PIORB_CONFIGURATION pIORBDT; // ptr to IORB
PADAPTERINFO pAdapterInfo; // ptr to AdapterInfo
PDEVICETABLE pDeviceTable; // ptr to Device table
PUNITINFO pUnitInfo; // ptr to UnitInfo
USHORT rc;
USHORT i,j,k;
USHORT NumDrivers;
USHORT DevBus;
/*--------------------------------------------------------------------*/
/* Get the adapter device tables for each adapter driver and */
/* issue SCSI INQUIRY command to each unit */
/*--------------------------------------------------------------------*/
pBuffer->nDevices = 0;
pDeviceTable = (PDEVICETABLE)&DeviceTableBuffer;
rc = GetDCTable((POINTER) &pDriverTable);
if (!rc)
{
/*----------------------------------------------------*/
/* For each .ADD registered in the DEVICE CLASS TABLE */
/*----------------------------------------------------*/
NumDrivers = pDriverTable->DCCount;
for (i= 0; i < NumDrivers; i++)
{
pIORBDT = (PIORB_CONFIGURATION)&ConfigIORB;
pIORBDT->iorbh.Length = sizeof(IORB_CONFIGURATION);
pIORBDT->iorbh.CommandCode = IOCC_CONFIGURATION;
pIORBDT->iorbh.CommandModifier = IOCM_GET_DEVICE_TABLE;
pIORBDT->iorbh.Status = 0;
pIORBDT->iorbh.ErrorCode = 0;
pIORBDT->iorbh.RequestControl = IORB_ASYNC_POST;
pIORBDT->iorbh.NotifyAddress = &IORBPost;
pIORBDT->pDeviceTable = pDeviceTable;
pIORBDT->DeviceTableLen = MAX_DT_SIZE;
OFFSETOF(DriverEP) = pDriverTable->DCTableEntries[i].DCOffset;
SELECTOROF(DriverEP) = pDriverTable->DCTableEntries[i].DCSelector;
ZeroCB((PBYTE)pDeviceTable, MAX_DT_SIZE);
(*DriverEP) ((FARPOINTER)(pIORBDT));
PUSHFLAGS;
DISABLE;
while ( !( pIORBDT->iorbh.Status & IORB_DONE ) )
{
ProcBlock ((ULONG)pIORBDT, -1L, 1);
DISABLE; /* Block does an enable */
}
ENABLE;
POPFLAGS;
if (!(pIORBDT->iorbh.Status & IORB_ERROR))
{
for (j = 0; j < pDeviceTable->TotalAdapters; j++)
{
pAdapterInfo = pDeviceTable->pAdapter[j];
DevBus = (pAdapterInfo->AdapterDevBus & 0x00ff);
if (( DevBus == AI_DEVBUS_SCSI_1) ||
( DevBus == AI_DEVBUS_SCSI_2) ||
( DevBus == AI_DEVBUS_SCSI_3) ||
( DevBus == AI_DEVBUS_NONSCSI_CDROM) ||
((DevBus == AI_DEVBUS_ST506) && (DevType == UIB_TYPE_CDROM)) )
{
for (k = 0; k < pAdapterInfo->AdapterUnits; k++)
{
/* Inquiry only types devices requested */
/* that are not "defective" */
if ((pAdapterInfo->UnitInfo[k].UnitType == DevType) &&
!(pAdapterInfo->UnitInfo[k].UnitFlags & UF_DEFECTIVE) )
{
pUnitInfo = &(pAdapterInfo->UnitInfo[k]);
/* Do inquiry */
rc = Do_Inquiry(pUnitInfo, pBuffer, DevBus);
/* If Error (might not be allocated */
/* but we can't depend on the error code) */
if (rc & IORB_ERROR)
{
/* then allocate it and dos inquiry */
rc = Do_AllocDeallocUnit(IOCM_ALLOCATE_UNIT,
pUnitInfo);
/* Skip if allocate fails */
if (!(rc & IORB_ERROR))
{
rc = Do_Inquiry(pUnitInfo, pBuffer, DevBus);
rc = Do_AllocDeallocUnit(IOCM_DEALLOCATE_UNIT,
pUnitInfo);
} /* endif */
}
}
} /* end unit loop */
} /* endif */
} /* end adapter loop */
}
} // end driver loop
return(0);
}
else
{
return(-1);
}
}
/*---------------------------------------------------------------------------
;
;** BuildCDB_Inquiry - Setup SCSI Inquiry Command Descriptor Block
;
; This routine builds a SCSI Inquiry CDB.
;
; BuildCDB_Inquiry (PUNITINFO pUnitInfo, PIORB_CDB pIORB)
;
; ENTRY: pUnitInfo - pointer to UnitInfo
; pIORB - IORB
;
; RETURN:
;
----------------------------------------------------------------------------*/
void near BuildCDB_Inquiry(pUnitInfo, pIORB, DevBus)
PUNITINFO pUnitInfo;
PIORB_CDB pIORB; /* ptr to IORB */
USHORT DevBus;
{
struct
CDB_Inquiry *pCDB; /* ptr to CDB */
/* Build a CDB passthru IORB */
BuildIORB_PassthruCDB (pUnitInfo,
sizeof(INQUIRYDATA),
(ULONG) (ppDataSeg+(ULONG)((USHORT)&(InquiryData))),
(PIORB_CDB) pIORB );
if (DevBus == AI_DEVBUS_ST506)
{
pIORB->apt.ControllerCmdLen = ATAPI_Cmd_Length;
}
else
pIORB->apt.ControllerCmdLen = sizeof(struct CDB_Inquiry);
pIORB->apt.Flags |= PT_DIRECTION_IN;
/* Setup the CDB */
pCDB = (struct CDB_Inquiry *) &pIORB->CDB;
pCDB->OpCode = SCSI_INQUIRY;
pCDB->LUN = pUnitInfo->UnitSCSILUN;
pCDB->alloc_length = sizeof(INQUIRYDATA);
}
/*---------------------------------------------------------------------------
;
;** BuildIORB_PassthruCDB - Setup a passthru IORB for a CDB
;
; This routine allocates and sets up a CDB passthru IORB
;
; BuildIORB_PassthruCDB (PUNITINFO pUnitInfo, ULONG data_length,
; ULONG ppData, PIORB_CDB pIORB)
;
; ENTRY: pUnitInfo - pointer to UnitInfo
; data_length - length of data to transfer
; ppData - physical address of data buffer
; pIORB - pointer to IORB
;
; RETURN:
;
----------------------------------------------------------------------------*/
void near BuildIORB_PassthruCDB (pUnitInfo, data_length, ppData, pIORB)
PUNITINFO pUnitInfo;
ULONG data_length;
ULONG ppData;
PIORB_CDB pIORB;
{
PIORB_DMWORK pDMWork;
pDMWork = (PIORB_DMWORK) &(pIORB->apt.iorbh.DMWorkSpace);
pIORB->apt.iorbh.UnitHandle = pUnitInfo->UnitHandle;
pIORB->apt.iorbh.NotifyAddress = &IORBPost;
/* If data transfer involved, setup the scatter/gather list */
if (data_length != 0)
{
pIORB->apt.cSGList = 1;
pIORB->apt.pSGList = (FARPOINTER) pIORB;
OFFSETOF(pIORB->apt.pSGList) = (USHORT) ( &(pDMWork->SGList) );
pIORB->apt.ppSGLIST =
(ULONG) (ppDataSeg + (ULONG) ((USHORT) &(pDMWork->SGList)) );
if (ppData == -1)
pDMWork->SGList.ppXferBuf =
(ULONG)(ppDataSeg+(ULONG)((USHORT)&(pIORB->CDB_data)));
else
pDMWork->SGList.ppXferBuf = ppData;
pDMWork->SGList.XferBufLen = data_length;
}
/* Fill in the pointer to the SCSI CDB */
pIORB->apt.pControllerCmd = (FARPOINTER) pIORB;
OFFSETOF(pIORB->apt.pControllerCmd) = (USHORT) ( &(pIORB->CDB) );
pIORB->apt.ppSCB =
(ULONG) (ppDataSeg + (ULONG) ((USHORT) &(pIORB->CDB)) );
ZeroCB((PBYTE)pIORB->apt.iorbh.ADDWorkSpace, ADD_WORKSPACE_SIZE);
}
/*---------------------------------------------------------------------------
;
;** Do_Inquiry - Do the actual inquiry for one unit
;
; This routine does the acutal inquiry for one unit.
;
; Do_Inquiry (PUNITINFO pUnitInfo, PINQUIRYDATAPACKET pBuffer);
;
; ENTRY: pUnitInfo - pointer to UnitInfo
; pBuffer - pointer to user buffer
;
; RETURN NORMAL : 0
;
; RETURN: IORB.Status
;
----------------------------------------------------------------------------*/
USHORT near Do_Inquiry(pUnitInfo,pBuffer,DevBus)
PUNITINFO pUnitInfo; // ptr to UnitInfo
PINQUIRYDATAPACKET pBuffer;
USHORT DevBus;
{
PIORB_CDB pIORBPT; // ptr to IORB
pIORBPT = &PassthruIORB;
pIORBPT->apt.iorbh.Length = sizeof(IORB_ADAPTER_PASSTHRU);
pIORBPT->apt.iorbh.CommandCode = IOCC_ADAPTER_PASSTHRU;
pIORBPT->apt.iorbh.CommandModifier= IOCM_EXECUTE_CDB;
pIORBPT->apt.iorbh.Status = 0;
pIORBPT->apt.iorbh.ErrorCode = 0;
pIORBPT->apt.iorbh.RequestControl = IORB_ASYNC_POST;
pIORBPT->apt.iorbh.NotifyAddress = &IORBPost;
BuildCDB_Inquiry(pUnitInfo, (PIORB_CDB) pIORBPT, DevBus);
ZeroCB((PBYTE)&InquiryData,
(USHORT) sizeof(INQUIRYDATA));
FilterADDHandle = pUnitInfo->FilterADDHandle;
if ( !FilterADDHandle )
{
(*DriverEP)((FARPOINTER)(pIORBPT));
}
else
{
OFFSETOF(DriverEPF) =
pDriverTable->DCTableEntries[FilterADDHandle-1].DCOffset;
SELECTOROF(DriverEPF) =
pDriverTable->DCTableEntries[FilterADDHandle-1].DCSelector;
(*DriverEPF)((FARPOINTER)(pIORBPT));
}
PUSHFLAGS;
DISABLE;
while ( !( pIORBPT->apt.iorbh.Status & IORB_DONE ) )
{
ProcBlock ((ULONG)pIORBPT, -1L, 1);
DISABLE; /* Block does an enable */
}
ENABLE;
POPFLAGS;
if (!( pIORBPT->apt.iorbh.Status & IORB_ERROR))
{
/* Copy into buffer then increment nDevices */
BlockCopy((PBYTE)&(pBuffer->InquiryEntry[pBuffer->nDevices]),
(PBYTE)&InquiryData,
(USHORT) sizeof(INQUIRYDATA)) ;
pBuffer->nDevices++;
}
return(pIORBPT->apt.iorbh.Status);
}
/*---------------------------------------------------------------------------
;
;** Do_AllocDeallocUnit - Allocate or Deallocate a unit
;
; This routine does allocates one unit or Deallocates one unit
;
; Do_AllocDeallocUnit (USHORT command_modifier,PUNITINFO pUnitInfo)
;
; ENTRY: command_modifier - either ALLOCATE or DEALLOCATE IORB command
; pUnitInfo - pointer to UnitInfo
;
; RETURN: IORB.Status
;
----------------------------------------------------------------------------*/
USHORT near Do_AllocDeallocUnit(command_modifier, pUnitInfo)
USHORT command_modifier;
PUNITINFO pUnitInfo; // ptr to UnitInfo
{
PIORB_UNIT_CONTROL pIORB;
pIORB = (NPIORB_UNIT_CONTROL)&UnitControlIORB;
BuildIORB_UnitControl (command_modifier,
pUnitInfo->UnitHandle);
FilterADDHandle = pUnitInfo->FilterADDHandle;
if ( !FilterADDHandle )
{
(*DriverEP) ((FARPOINTER)(pIORB));
}
else
{
OFFSETOF(DriverEPF) =
pDriverTable->DCTableEntries[FilterADDHandle-1].DCOffset;
SELECTOROF(DriverEPF) =
pDriverTable->DCTableEntries[FilterADDHandle-1].DCSelector;
(*DriverEPF) ((FARPOINTER)(pIORB));
}
PUSHFLAGS;
DISABLE;
while ( !( pIORB->iorbh.Status & IORB_DONE ) )
{
ProcBlock ((ULONG)pIORB, -1L, 1);
DISABLE; /* Block does an enable */
}
ENABLE;
POPFLAGS;
return(pIORB->iorbh.Status);
}
/*---------------------------------------------------------------------------
;
;** BuildIORB_UnitControl - Build a Unit Control IORB
;
; This routine build a unit control IORB.
;
; VOID Build_UnitControl(USHORT command_modifier, USHORT unit_handle);
;
; ENTRY: command_modifier - IORB command modifier code
; unit_handle - unit handle
;
;
; RETURN:
;
; NOTES:
;
;---------------------------------------------------------------------------*/
void near BuildIORB_UnitControl (command_modifier, unit_handle)
USHORT command_modifier;
USHORT unit_handle;
{
NPIORB_UNIT_CONTROL pIORB;
pIORB = (NPIORB_UNIT_CONTROL)&UnitControlIORB;
pIORB->iorbh.Length = sizeof(IORB_UNIT_CONTROL);
pIORB->iorbh.CommandCode = IOCC_UNIT_CONTROL;
pIORB->iorbh.CommandModifier = command_modifier;
pIORB->iorbh.Status = 0;
pIORB->iorbh.ErrorCode = 0;
pIORB->iorbh.UnitHandle = unit_handle;
pIORB->iorbh.RequestControl = IORB_ASYNC_POST;
pIORB->iorbh.NotifyAddress = &IORBPost;
pIORB->Flags = 0;
pIORB->pUnitInfo = 0;
pIORB->UnitInfoLen = 0;
ZeroCB((PBYTE)pIORB->iorbh.ADDWorkSpace, ADD_WORKSPACE_SIZE);
}
/* Dummy notification callout for ADDs */
void _loadds far IORBPost(PIORBH pIORB)
{
USHORT AwakeCount;
ProcRun((ULONG)pIORB, &AwakeCount);
return;
}