home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Media Share 13
/
mediashare_13.zip
/
mediashare_13
/
ZIPPED
/
PROGRAM
/
DDJ9403A.ZIP
/
CDROM.ASC
< prev
next >
Wrap
Text File
|
1994-01-30
|
14KB
|
366 lines
_WRITING NON-SCSI CD-ROM DEVICE DRIVERS_
by Sing Li
Listing One
/****************************************************************************
CDNOW.C -- SCSI miniport driver for Panasonic 52x using native or compatible
controllers. Module contains general routines which are independent of
specific drive models.
Copyright (c) 1993 Sing Li, Media Synergy Inc. All Rights Reserved
****************************************************************************/
#include "ntddk.h"
#include "stdarg.h"
#include "CDnow.h" // includes scsi.h
//****** Function ProtoTyping ******
USHORT
LocateAdapterSpecific(
PSPECIFIC_DEVICE_EXTENSION deviceExtension,
IN PVOID Context,
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
);
BOOLEAN
CDnowInitialize(
IN PVOID Context
);
NTSTATUS
CDRead( //)
ULONG LogAddr,
USHORT LogBlkRead,
PUCHAR userBuffer,
PSPECIFIC_DEVICE_EXTENSION dExt
);
ULONG
DriverEntry(
IN PVOID DriverObject,
IN PVOID Argument2
);
ULONG
CDnowFindAdapter(
IN PVOID Context,
IN PVOID AdaptersFound,
IN PVOID BusInformation,
IN PCHAR ArgumentString,
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
OUT PBOOLEAN Again
);
BOOLEAN
CDnowStartIo(
IN PVOID Context,
IN PSCSI_REQUEST_BLOCK Srb
);
BOOLEAN
CDnowInterrupt(
IN PVOID Context
);
BOOLEAN
CDnowResetBus(
IN PVOID Context,
IN ULONG PathId
);
/***************************************************************************
Handles interrupts for CDnow. Necessary for March Beta of Windows NT; left
in for compatibility. Arguments: Context - Device adapter context pointer.
Return Value: FALSE indicates that this interrupt was NOT from us.
****************************************************************************/
BOOLEAN
CDnowInterrupt(
IN PVOID Context
)
{
PSPECIFIC_DEVICE_EXTENSION deviceExtension = Context;
return FALSE;
} // end CDnowInterrupt()
/***** Reset Bus from the SCSI Port driver. We basically do nothing here. ****/
BOOLEAN
CDnowResetBus(
IN PVOID Context,
IN ULONG PathId
)
{
PSPECIFIC_DEVICE_EXTENSION deviceExtension = Context;
return TRUE;
} // end CDnowResetBus()
/****************************************************************************
Simulate response the SCSI INQUIRY op-code. We make the port driver
believe that a SCSI CD-ROM is connected.
*****************************************************************************/
void
Cdrom_Inquiry(PSPECIFIC_LU_EXTENSION luExtension)
{
INQUIRYDATA *cdromInquiry;
cdromInquiry = (INQUIRYDATA *) luExtension->SavedDataPointer;
cdromInquiry->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
cdromInquiry->DeviceTypeQualifier = DEVICE_CONNECTED;
memcpy(cdromInquiry->VendorId, "MedSyn", 8);
memcpy(cdromInquiry->ProductId, "Cd-Rom Now", 11);
}
/****************************************************************************
Simulate a response to the SCSI Read Capacity opcode. We hardcode sector size
and volume size for compatibility with drives which cannot determine capacity.
The little endian to big endian conversion was a major gottcha.
/****************************************************************************/
VOID CapacityRead(PSPECIFIC_LU_EXTENSION luExtension)
{
READ_CAPACITY_DATA *capacityRead;
ULONG FixBlockEnd;
ULONG FixBlockSize;
PFOUR_BYTE pEnd = (PFOUR_BYTE)&FixBlockEnd;
PFOUR_BYTE pSize = (PFOUR_BYTE)&FixBlockSize;
// Convert to big Endian
capacityRead = (READ_CAPACITY_DATA *) luExtension->SavedDataPointer;
FixBlockEnd = 270000;
FixBlockSize = 2048;
((PFOUR_BYTE)&(capacityRead->LogicalBlockAddress))->Byte3=
pEnd->Byte0;
((PFOUR_BYTE)&(capacityRead->LogicalBlockAddress))->Byte2=
pEnd->Byte1;
((PFOUR_BYTE)&(capacityRead->LogicalBlockAddress))->Byte1=
pEnd->Byte2;
((PFOUR_BYTE)&(capacityRead->LogicalBlockAddress))->Byte0=
pEnd->Byte3;
((PFOUR_BYTE)&(capacityRead->BytesPerBlock))->Byte3=
pSize->Byte0;
((PFOUR_BYTE)&(capacityRead->BytesPerBlock))->Byte2=
pSize->Byte1;
((PFOUR_BYTE)&(capacityRead->BytesPerBlock))->Byte2=
pSize->Byte2;
((PFOUR_BYTE)&(capacityRead->BytesPerBlock))->Byte0=
pSize->Byte3;
}
/*****************************************************************************
ReadCDRom: Transform the Logical block address and size into our
format for access by read routine.
*****************************************************************************/
NTSTATUS ReadCDRom(PSPECIFIC_DEVICE_EXTENSION deviceExtension,
PSPECIFIC_LU_EXTENSION luExtension)
{
struct MYCDB {
UCHAR OperationCode;
UCHAR RelativeAddress : 1;
UCHAR Reserved1 : 2;
UCHAR ForceUnitAccess : 1;
UCHAR DisablePageOut : 1;
UCHAR LogicalUnitNumber : 3;
UCHAR LogicalBlockByte0;
UCHAR LogicalBlockByte1;
UCHAR LogicalBlockByte2;
UCHAR LogicalBlockByte3;
UCHAR Reserved2;
UCHAR TransferBlocksMsb;
UCHAR TransferBlocksLsb;
UCHAR Control;
} *cdb;
ULONG logicalBlockAddress;
USHORT transferBlocks;
cdb =(struct MYCDB *) luExtension->ActiveLuRequest->Cdb;
((PFOUR_BYTE)&logicalBlockAddress)->Byte3= cdb->LogicalBlockByte0;
((PFOUR_BYTE)&logicalBlockAddress)->Byte2= cdb->LogicalBlockByte1;
((PFOUR_BYTE)&logicalBlockAddress)->Byte1= cdb->LogicalBlockByte2;
((PFOUR_BYTE)&logicalBlockAddress)->Byte0= cdb->LogicalBlockByte3;
((PFOUR_BYTE)&transferBlocks)->Byte1= cdb->TransferBlocksMsb;
((PFOUR_BYTE)&transferBlocks)->Byte0= cdb->TransferBlocksLsb;
return( CDRead(logicalBlockAddress, transferBlocks,
luExtension->ActiveLuRequest->DataBuffer, deviceExtension));
}
/****************************************************************************
Called from SCSI port driver synchronized with kernel with a request
to be executed.
****************************************************************************/
BOOLEAN
CDnowStartIo(
IN PVOID Context,
IN PSCSI_REQUEST_BLOCK Srb
)
{
PSPECIFIC_DEVICE_EXTENSION deviceExtension = Context;
PSPECIFIC_LU_EXTENSION luExtension;
// Determine the logical unit that this request is for.
deviceExtension->PathId = Srb->PathId;
luExtension = ScsiPortGetLogicalUnit(deviceExtension,
deviceExtension->PathId,
Srb->TargetId, Srb->Lun);
Srb->SrbStatus = SRB_STATUS_PENDING;
switch (Srb->Function) {
case SRB_FUNCTION_ABORT_COMMAND:
Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
case SRB_FUNCTION_RESET_BUS:
Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
case SRB_FUNCTION_EXECUTE_SCSI:
if ((Srb->TargetId == 3) && (Srb->Lun == 0)) // not at 0 or 1
{
luExtension->ActiveLuRequest = Srb;
luExtension->LuState = LS_COMPLETE;
luExtension->SavedDataPointer = (ULONG) Srb->DataBuffer;
luExtension->SavedDataLength = Srb->DataTransferLength;
switch( Srb->Cdb[0])
{
// Get CD-ROM Inquiry Data
case (SCSIOP_INQUIRY):
// Setup the context for this target/lun.
Cdrom_Inquiry(luExtension);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
// ReadCapacity: Hardwired data
case(SCSIOP_READ_CAPACITY):
CapacityRead(luExtension);
Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
// Read Cd-ROM
case(SCSIOP_READ):
if NT_SUCCESS(ReadCDRom(deviceExtension,
luExtension))
Srb->SrbStatus = SRB_STATUS_SUCCESS;
else
Srb->SrbStatus = SRB_STATUS_ERROR;
break;
case (SCSIOP_TEST_UNIT_READY):
Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
// Invalid Scsi Op code
default:
Srb->SrbStatus = SRB_STATUS_SUCCESS;
break;
} // of switch
} // of if
else
{
Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
}
ScsiPortNotification(RequestComplete, (PVOID) deviceExtension, Srb);
break;
// Unexpected Scsi Function Call
default:
Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
ScsiPortNotification(RequestComplete, (PVOID) deviceExtension, Srb);
break;
}
// Adapter ready for next request.
ScsiPortNotification(NextRequest, deviceExtension, NULL);
return TRUE;
} // end CDnowStartIo()
/***** findAdapterPort: locate the Io port address of the adaptor *****/
USHORT findAdapterPort(
PSPECIFIC_DEVICE_EXTENSION deviceExtension,
IN PVOID Context,
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
)
{
ULONG PortBase = BASE_PORT;
deviceExtension->PortBase = PortBase;
return LocateAdapterSpecific(deviceExtension, Context, ConfigInfo);
// PortBase;
}
/****************************************************************************
Locates the CD controller card, and allocate the IO ports from NT IO manager.
Return Value: SP_RETURN_FOUND - if an adapter is found.
SP_RETURN_NOT_FOUND - if no adapter is found.
*****************************************************************************/
ULONG
CDnowFindAdapter(
IN PVOID Context,
IN PVOID AdaptersFound,
IN PVOID BusInformation,
IN PCHAR ArgumentString,
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo,
OUT PBOOLEAN Again
)
{
USHORT portAddress;
USHORT adaptersFound;
ULONG returnStatus = SP_RETURN_NOT_FOUND;
PSPECIFIC_DEVICE_EXTENSION deviceExtension = Context;
*Again = FALSE;
returnStatus = SP_RETURN_FOUND; // assum found a valid card
// If there was no previously configured value for the IRQ,
// look at the other way to configure the value or use a default.
ConfigInfo->BusInterruptLevel = 10;
// fill in a default a target ID.
ConfigInfo->NumberOfBuses = 1;
ConfigInfo->ScatterGather = FALSE;
ConfigInfo->Master = FALSE;
portAddress= findAdapterPort(deviceExtension, Context, ConfigInfo);
deviceExtension->PortBase = portAddress;
if(portAddress == 0)
{
returnStatus = SP_RETURN_NOT_FOUND;
goto NotFound;
}
// Fill in the access array information.
ConfigInfo->NumberOfAccessRanges = 1;
(*ConfigInfo->AccessRanges)[0].RangeStart =
ScsiPortConvertUlongToPhysicalAddress(portAddress);
(*ConfigInfo->AccessRanges)[0].RangeLength = 4;
(*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
ConfigInfo->NumberOfBuses = 1;
adaptersFound = 1;
*((PULONG) AdaptersFound) == (ULONG) adaptersFound;
returnStatus = SP_RETURN_FOUND; // assum found a valid card
NotFound:
return (returnStatus);
} // end CDnowFindAdapter()
/***** Driver initialization entry point for system. *****/
ULONG
DriverEntry(
IN PVOID DriverObject,
IN PVOID Argument2
)
{
HW_INITIALIZATION_DATA hwInitializationData;
ULONG i,status;
// Zero out the hwInitializationData structure.
for (i = 0; i < sizeof(HW_INITIALIZATION_DATA); i++) {
*(((PUCHAR)&hwInitializationData + i)) = 0;
}
hwInitializationData.HwInitializationDataSize =
sizeof(HW_INITIALIZATION_DATA);
// Set entry points.
hwInitializationData.HwInitialize = CDnowInitialize;
hwInitializationData.HwStartIo = CDnowStartIo;
hwInitializationData.HwInterrupt = CDnowInterrupt;
hwInitializationData.HwFindAdapter = CDnowFindAdapter;
hwInitializationData.HwResetBus = CDnowResetBus;
// features not supported
hwInitializationData.HwDmaStarted = NULL;
hwInitializationData.HwAdapterState = NULL;
hwInitializationData.NeedPhysicalAddresses = FALSE;
// Specify size of extensions.
// Indicate need buffer mapping but not physical addresses.
hwInitializationData.MapBuffers = TRUE;
hwInitializationData.NeedPhysicalAddresses = FALSE;
hwInitializationData.NumberOfAccessRanges = 1;
// Specify size of device extension.
hwInitializationData.DeviceExtensionSize =
sizeof(SPECIFIC_DEVICE_EXTENSION);
// Specify size of logical unit extension.
hwInitializationData.SpecificLuExtensionSize =
sizeof(SPECIFIC_LU_EXTENSION);
// Fourth parameter below (i) will appear as AdaptersFound parameter
// when FindAdapter() is called. First try to configure for Isa bus.
hwInitializationData.AdapterInterfaceType = Isa;
i = 0;
status = ScsiPortInitialize(DriverObject, Argument2,
&hwInitializationData, &(i));
return status;
} // end DriverEntry()
/****************************************************************************
Inititialize adapter. Dummied out this function for compatibility purposes.
Arguments: Context - Adapter object device extension.
*****************************************************************************/
BOOLEAN
CDnowInitialize(
IN PVOID Context
)
{
PSPECIFIC_DEVICE_EXTENSION deviceExtension = Context;
return TRUE;
} // end CDnow<Initialize()