home *** CD-ROM | disk | FTP | other *** search
/ Media Share 13 / mediashare_13.zip / mediashare_13 / ZIPPED / PROGRAM / DDJ9403A.ZIP / CDROM.ASC < prev    next >
Text File  |  1994-01-30  |  14KB  |  366 lines

  1. _WRITING NON-SCSI CD-ROM DEVICE DRIVERS_
  2. by Sing Li
  3.  
  4. Listing One
  5.  
  6. /****************************************************************************
  7. CDNOW.C -- SCSI miniport driver for Panasonic 52x using native or compatible
  8. controllers. Module contains general routines which are independent of 
  9. specific drive models.
  10. Copyright (c) 1993  Sing Li, Media Synergy Inc.  All Rights Reserved
  11. ****************************************************************************/
  12. #include "ntddk.h"
  13. #include "stdarg.h"
  14. #include "CDnow.h"      // includes scsi.h
  15.  
  16. //****** Function ProtoTyping ******
  17. USHORT
  18. LocateAdapterSpecific(
  19.     PSPECIFIC_DEVICE_EXTENSION  deviceExtension,
  20.      IN PVOID                   Context,
  21.     IN OUT PPORT_CONFIGURATION_INFORMATION  ConfigInfo
  22. );
  23. BOOLEAN
  24. CDnowInitialize(
  25.     IN PVOID Context
  26.     );
  27. NTSTATUS
  28. CDRead(  //)
  29.  ULONG LogAddr,
  30.  USHORT LogBlkRead,
  31.  PUCHAR userBuffer,
  32.  PSPECIFIC_DEVICE_EXTENSION dExt
  33. );
  34. ULONG
  35. DriverEntry(
  36.     IN PVOID DriverObject,
  37.     IN PVOID Argument2
  38.     );
  39. ULONG
  40. CDnowFindAdapter(
  41.     IN PVOID                    Context,
  42.     IN PVOID                    AdaptersFound,
  43.     IN PVOID                    BusInformation,
  44.     IN PCHAR                    ArgumentString,
  45.     IN OUT PPORT_CONFIGURATION_INFORMATION  ConfigInfo,
  46.     OUT PBOOLEAN                Again
  47.     );
  48. BOOLEAN
  49. CDnowStartIo(
  50.     IN PVOID           Context,
  51.     IN PSCSI_REQUEST_BLOCK Srb
  52.     );
  53. BOOLEAN
  54. CDnowInterrupt(
  55.     IN PVOID Context
  56.     );
  57. BOOLEAN
  58. CDnowResetBus(
  59.     IN PVOID Context,
  60.     IN ULONG PathId
  61.     );
  62. /***************************************************************************
  63. Handles interrupts for CDnow. Necessary for March Beta of Windows NT; left 
  64. in for compatibility. Arguments: Context - Device adapter context pointer.
  65. Return Value: FALSE indicates that this interrupt was NOT from us. 
  66. ****************************************************************************/
  67. BOOLEAN
  68. CDnowInterrupt(
  69.     IN PVOID Context
  70.     )
  71. {
  72.     PSPECIFIC_DEVICE_EXTENSION deviceExtension = Context;
  73.     return FALSE;
  74. } // end CDnowInterrupt()
  75. /***** Reset Bus from the SCSI Port driver. We basically do nothing here. ****/
  76. BOOLEAN
  77. CDnowResetBus(
  78.     IN PVOID Context,
  79.     IN ULONG PathId
  80.     )
  81. {
  82.     PSPECIFIC_DEVICE_EXTENSION deviceExtension = Context;
  83.     return TRUE;
  84. } // end CDnowResetBus()
  85. /**************************************************************************** 
  86. Simulate response the SCSI INQUIRY op-code. We make the port driver 
  87. believe that a SCSI CD-ROM is connected. 
  88. *****************************************************************************/
  89. void
  90. Cdrom_Inquiry(PSPECIFIC_LU_EXTENSION luExtension)
  91. {
  92. INQUIRYDATA *cdromInquiry;
  93. cdromInquiry = (INQUIRYDATA *) luExtension->SavedDataPointer;
  94. cdromInquiry->DeviceType = READ_ONLY_DIRECT_ACCESS_DEVICE;
  95. cdromInquiry->DeviceTypeQualifier = DEVICE_CONNECTED;
  96. memcpy(cdromInquiry->VendorId, "MedSyn", 8);
  97. memcpy(cdromInquiry->ProductId, "Cd-Rom Now", 11);
  98. }
  99. /****************************************************************************
  100. Simulate a response to the SCSI Read Capacity opcode. We hardcode sector size 
  101. and volume size for compatibility with drives which cannot determine capacity. 
  102. The little endian to big endian conversion was a major gottcha. 
  103. /****************************************************************************/
  104. VOID CapacityRead(PSPECIFIC_LU_EXTENSION luExtension)
  105. {
  106. READ_CAPACITY_DATA *capacityRead;
  107. ULONG FixBlockEnd;
  108. ULONG FixBlockSize;
  109. PFOUR_BYTE pEnd = (PFOUR_BYTE)&FixBlockEnd;
  110. PFOUR_BYTE pSize = (PFOUR_BYTE)&FixBlockSize;
  111. // Convert to big Endian
  112. capacityRead = (READ_CAPACITY_DATA *) luExtension->SavedDataPointer;
  113. FixBlockEnd = 270000;
  114. FixBlockSize = 2048;
  115. ((PFOUR_BYTE)&(capacityRead->LogicalBlockAddress))->Byte3=  
  116.    pEnd->Byte0;
  117. ((PFOUR_BYTE)&(capacityRead->LogicalBlockAddress))->Byte2=  
  118.    pEnd->Byte1;
  119. ((PFOUR_BYTE)&(capacityRead->LogicalBlockAddress))->Byte1=  
  120.    pEnd->Byte2;
  121. ((PFOUR_BYTE)&(capacityRead->LogicalBlockAddress))->Byte0=  
  122.    pEnd->Byte3;
  123. ((PFOUR_BYTE)&(capacityRead->BytesPerBlock))->Byte3=  
  124.    pSize->Byte0;
  125. ((PFOUR_BYTE)&(capacityRead->BytesPerBlock))->Byte2=  
  126.    pSize->Byte1;
  127. ((PFOUR_BYTE)&(capacityRead->BytesPerBlock))->Byte2=  
  128.    pSize->Byte2;
  129. ((PFOUR_BYTE)&(capacityRead->BytesPerBlock))->Byte0=  
  130.    pSize->Byte3;
  131. }
  132. /*****************************************************************************
  133. ReadCDRom: Transform the Logical block address and size into our 
  134. format for access by read routine. 
  135. *****************************************************************************/
  136. NTSTATUS ReadCDRom(PSPECIFIC_DEVICE_EXTENSION  deviceExtension,
  137.            PSPECIFIC_LU_EXTENSION      luExtension)
  138. {
  139.   struct MYCDB {
  140.     UCHAR OperationCode;
  141.     UCHAR RelativeAddress : 1;
  142.     UCHAR Reserved1 : 2;
  143.     UCHAR ForceUnitAccess : 1;
  144.     UCHAR DisablePageOut : 1;
  145.     UCHAR LogicalUnitNumber : 3;
  146.     UCHAR LogicalBlockByte0;
  147.     UCHAR LogicalBlockByte1;
  148.     UCHAR LogicalBlockByte2;
  149.     UCHAR LogicalBlockByte3;
  150.     UCHAR Reserved2;
  151.     UCHAR TransferBlocksMsb;
  152.     UCHAR TransferBlocksLsb;
  153.     UCHAR Control;
  154.     } *cdb;
  155. ULONG logicalBlockAddress;
  156. USHORT transferBlocks;
  157. cdb =(struct MYCDB *) luExtension->ActiveLuRequest->Cdb;
  158. ((PFOUR_BYTE)&logicalBlockAddress)->Byte3=  cdb->LogicalBlockByte0;
  159. ((PFOUR_BYTE)&logicalBlockAddress)->Byte2=  cdb->LogicalBlockByte1;
  160. ((PFOUR_BYTE)&logicalBlockAddress)->Byte1=  cdb->LogicalBlockByte2;
  161. ((PFOUR_BYTE)&logicalBlockAddress)->Byte0=  cdb->LogicalBlockByte3;
  162. ((PFOUR_BYTE)&transferBlocks)->Byte1= cdb->TransferBlocksMsb;
  163. ((PFOUR_BYTE)&transferBlocks)->Byte0= cdb->TransferBlocksLsb;
  164. return( CDRead(logicalBlockAddress, transferBlocks,
  165.        luExtension->ActiveLuRequest->DataBuffer, deviceExtension));
  166. }
  167. /****************************************************************************
  168. Called from SCSI port driver synchronized with kernel with a request 
  169. to be executed. 
  170. ****************************************************************************/
  171. BOOLEAN
  172. CDnowStartIo(
  173.     IN PVOID           Context,
  174.     IN PSCSI_REQUEST_BLOCK Srb
  175.     )
  176. {
  177.     PSPECIFIC_DEVICE_EXTENSION  deviceExtension = Context;
  178.     PSPECIFIC_LU_EXTENSION  luExtension;
  179.     // Determine the logical unit that this request is for.
  180.     deviceExtension->PathId = Srb->PathId;
  181.     luExtension = ScsiPortGetLogicalUnit(deviceExtension,
  182.                      deviceExtension->PathId,
  183.                      Srb->TargetId, Srb->Lun);
  184.     Srb->SrbStatus = SRB_STATUS_PENDING;
  185.     switch (Srb->Function) {
  186.     case SRB_FUNCTION_ABORT_COMMAND:
  187.         Srb->SrbStatus = SRB_STATUS_SUCCESS;
  188.         break;
  189.     case SRB_FUNCTION_RESET_BUS:
  190.         Srb->SrbStatus = SRB_STATUS_SUCCESS;
  191.         break;
  192.     case SRB_FUNCTION_EXECUTE_SCSI:
  193.     if ((Srb->TargetId == 3)  && (Srb->Lun == 0))    // not at 0 or 1
  194.      {
  195.         luExtension->ActiveLuRequest = Srb;
  196.         luExtension->LuState = LS_COMPLETE;
  197.         luExtension->SavedDataPointer = (ULONG) Srb->DataBuffer;
  198.         luExtension->SavedDataLength = Srb->DataTransferLength;
  199.         switch( Srb->Cdb[0])
  200.              {
  201.              // Get CD-ROM Inquiry Data
  202.              case (SCSIOP_INQUIRY):
  203.                 // Setup the context for this target/lun.
  204.                 Cdrom_Inquiry(luExtension);
  205.                 Srb->SrbStatus = SRB_STATUS_SUCCESS;
  206.                 break;
  207.              // ReadCapacity: Hardwired data
  208.              case(SCSIOP_READ_CAPACITY):
  209.                  CapacityRead(luExtension);
  210.                  Srb->SrbStatus = SRB_STATUS_SUCCESS;
  211.                 break;
  212.              // Read Cd-ROM
  213.              case(SCSIOP_READ):
  214.                  if NT_SUCCESS(ReadCDRom(deviceExtension,
  215.                        luExtension))
  216.                  Srb->SrbStatus = SRB_STATUS_SUCCESS;
  217.                  else
  218.                      Srb->SrbStatus = SRB_STATUS_ERROR;
  219.                 break;
  220.               case (SCSIOP_TEST_UNIT_READY):
  221.                  Srb->SrbStatus = SRB_STATUS_SUCCESS;
  222.                break;
  223.              // Invalid Scsi Op code
  224.              default:
  225.                  Srb->SrbStatus = SRB_STATUS_SUCCESS;
  226.                 break;
  227.              } // of switch
  228.         } // of if
  229.         else
  230.         {
  231.            Srb->SrbStatus = SRB_STATUS_INVALID_TARGET_ID;
  232.         }
  233.        ScsiPortNotification(RequestComplete, (PVOID) deviceExtension, Srb);
  234.        break;
  235.     // Unexpected Scsi Function Call
  236.     default:
  237.        Srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
  238.        ScsiPortNotification(RequestComplete, (PVOID) deviceExtension, Srb);
  239.        break;
  240.     }
  241.     // Adapter ready for next request.
  242.     ScsiPortNotification(NextRequest, deviceExtension, NULL);
  243.     return TRUE;
  244. } // end CDnowStartIo()
  245. /***** findAdapterPort: locate the Io port address of the adaptor *****/
  246. USHORT findAdapterPort(
  247.     PSPECIFIC_DEVICE_EXTENSION  deviceExtension,
  248.     IN PVOID                    Context,
  249.     IN OUT PPORT_CONFIGURATION_INFORMATION  ConfigInfo
  250.      )
  251. {
  252.      ULONG PortBase = BASE_PORT;
  253.      deviceExtension->PortBase = PortBase;
  254.     return LocateAdapterSpecific(deviceExtension, Context, ConfigInfo);   
  255.                                                                   // PortBase;
  256. }
  257. /****************************************************************************
  258. Locates the CD controller card, and allocate the IO ports from NT IO manager. 
  259. Return Value: SP_RETURN_FOUND   - if an adapter is found.
  260.     SP_RETURN_NOT_FOUND - if no adapter is found. 
  261. *****************************************************************************/
  262. ULONG
  263. CDnowFindAdapter(
  264.     IN PVOID                    Context,
  265.     IN PVOID                    AdaptersFound,
  266.     IN PVOID                    BusInformation,
  267.     IN PCHAR                    ArgumentString,
  268.     IN OUT PPORT_CONFIGURATION_INFORMATION  ConfigInfo,
  269.     OUT PBOOLEAN                Again
  270.     )
  271. {
  272.     USHORT          portAddress;
  273.     USHORT          adaptersFound;
  274.     ULONG           returnStatus = SP_RETURN_NOT_FOUND;
  275.     PSPECIFIC_DEVICE_EXTENSION  deviceExtension = Context;
  276.     *Again = FALSE;
  277.     returnStatus = SP_RETURN_FOUND;  // assum found  a valid card
  278.     // If there was no previously configured value for the IRQ,
  279.     // look at the other way to configure the value or use a default.
  280.     ConfigInfo->BusInterruptLevel = 10;
  281.     //  fill in a default a target ID.
  282.     ConfigInfo->NumberOfBuses = 1;
  283.     ConfigInfo->ScatterGather = FALSE;
  284.     ConfigInfo->Master = FALSE;
  285.     portAddress= findAdapterPort(deviceExtension, Context, ConfigInfo);
  286.     deviceExtension->PortBase = portAddress;
  287.      if(portAddress == 0)
  288.      {
  289.     returnStatus = SP_RETURN_NOT_FOUND;
  290.      goto NotFound;
  291.      }
  292.    // Fill in the access array information.
  293.    ConfigInfo->NumberOfAccessRanges = 1;
  294.    (*ConfigInfo->AccessRanges)[0].RangeStart =
  295.            ScsiPortConvertUlongToPhysicalAddress(portAddress);
  296.    (*ConfigInfo->AccessRanges)[0].RangeLength = 4;
  297.    (*ConfigInfo->AccessRanges)[0].RangeInMemory = FALSE;
  298.    ConfigInfo->NumberOfBuses = 1;
  299.    adaptersFound = 1;
  300.    *((PULONG) AdaptersFound) == (ULONG) adaptersFound;
  301.     returnStatus = SP_RETURN_FOUND;  // assum found  a valid card
  302. NotFound:
  303.           return (returnStatus);
  304. } // end CDnowFindAdapter()
  305. /***** Driver initialization entry point for system. *****/
  306. ULONG
  307. DriverEntry(
  308.     IN PVOID DriverObject,
  309.     IN PVOID Argument2
  310.     )
  311.  {
  312.     HW_INITIALIZATION_DATA  hwInitializationData;
  313.     ULONG           i,status;
  314.     // Zero out the hwInitializationData structure.
  315.     for (i = 0; i < sizeof(HW_INITIALIZATION_DATA); i++) {
  316.     *(((PUCHAR)&hwInitializationData + i)) = 0;
  317.     }
  318.     hwInitializationData.HwInitializationDataSize = 
  319.                                                 sizeof(HW_INITIALIZATION_DATA);
  320.     // Set entry points.
  321.     hwInitializationData.HwInitialize   = CDnowInitialize;
  322.     hwInitializationData.HwStartIo  = CDnowStartIo;
  323.     hwInitializationData.HwInterrupt    = CDnowInterrupt;
  324.     hwInitializationData.HwFindAdapter  = CDnowFindAdapter;
  325.     hwInitializationData.HwResetBus = CDnowResetBus;
  326.     // features not supported
  327.     hwInitializationData.HwDmaStarted   = NULL;
  328.     hwInitializationData.HwAdapterState = NULL;
  329.     hwInitializationData.NeedPhysicalAddresses = FALSE;
  330.     // Specify size of extensions.
  331.     // Indicate need buffer mapping but not physical addresses.
  332.     hwInitializationData.MapBuffers     = TRUE;
  333.     hwInitializationData.NeedPhysicalAddresses  = FALSE;
  334.     hwInitializationData.NumberOfAccessRanges   = 1;
  335.     // Specify size of device extension.
  336.     hwInitializationData.DeviceExtensionSize = 
  337.                                              sizeof(SPECIFIC_DEVICE_EXTENSION);
  338.     // Specify size of logical unit extension.
  339.     hwInitializationData.SpecificLuExtensionSize = 
  340.                                                 sizeof(SPECIFIC_LU_EXTENSION);
  341.     // Fourth parameter below (i)  will appear as AdaptersFound parameter
  342.     // when FindAdapter() is called. First try to configure for Isa bus.
  343.     hwInitializationData.AdapterInterfaceType = Isa;
  344.     i = 0;
  345.     status = ScsiPortInitialize(DriverObject, Argument2,
  346.                 &hwInitializationData, &(i));
  347.     return status;
  348. } // end DriverEntry()
  349. /****************************************************************************
  350. Inititialize adapter. Dummied out this function for compatibility purposes.
  351. Arguments: Context - Adapter object device extension.
  352. *****************************************************************************/
  353. BOOLEAN
  354. CDnowInitialize(
  355.     IN PVOID Context
  356.     )
  357. {
  358.     PSPECIFIC_DEVICE_EXTENSION deviceExtension = Context;
  359.     return TRUE;
  360. } // end CDnow<Initialize()
  361.  
  362.  
  363.  
  364.  
  365.  
  366.