home *** CD-ROM | disk | FTP | other *** search
/ Media Share 13 / mediashare_13.zip / mediashare_13 / ZIPPED / PROGRAM / DDJ9403A.ZIP / CDROM.ZIP / CDREAD.C < prev    next >
Text File  |  1993-10-13  |  10KB  |  433 lines

  1. #include "ntddk.h"
  2. #include "stdarg.h"
  3. #include "CDnow.h"      // includes scsi.h
  4.  
  5. /********************************************************************
  6. Copyright (c) 1993  Sing Li, Media Synergy Inc.  All Rights Reserved
  7.  
  8. Module Name:
  9.  
  10.     Cdread.c
  11.  
  12. Abstract:
  13.     This is the Scsi miniport driver for Panasonic 52x using
  14.      native or compatible controllers.
  15.  
  16.      This module contains routines which are specific to the
  17.      Panasonic 52x drives and native controllers.
  18. **********************************************************************/
  19.  
  20.  
  21. #define BCD_TO_DEC(x) ((((x & 0xF0)>>4)*10) + (x & 0x0F))
  22. #define DEC_TO_BCD(x) (((x / 10) << 4) + (x % 10))
  23. #define SendCmd(x)    ScsiPortWritePortUchar(    (PUCHAR)(dExt->PortBase), (UCHAR) x )
  24. #define ReadStatus()  iRd(dExt,1)
  25. #define ReadDStatus()  iRd(dExt,0)
  26. #define ReadPortData() ScsiPortReadPortUchar((PUCHAR)(dExt->PortBase + 2))
  27.  
  28. #define HardReset()    ScsiPortWritePortUchar( (PUCHAR)(dExt->PortBase + 2), (UCHAR) 0)
  29.  
  30.  
  31.  
  32. //***************************************************
  33. // Wait for Status Ready Bit
  34. //***************************************************
  35.  
  36. NTSTATUS WtStatus(                        //()
  37.   IN PSPECIFIC_DEVICE_EXTENSION dExt
  38.  )
  39. {
  40.  
  41.     UCHAR Data;
  42.  
  43.     ULONG loopCount = 0;
  44.     ULONG TimesToDelay = (ULONG) 7000;
  45.     ULONG MicrosecondsToDelay =20;
  46.  
  47.      ScsiPortStallExecution(MicrosecondsToDelay);
  48.  
  49.    while( (Data = ScsiPortReadPortUchar( (PUCHAR)(dExt->PortBase + 1) ) & ((UCHAR) 4)) &&
  50.                   (loopCount++ < TimesToDelay))
  51.      {
  52.       ScsiPortStallExecution(MicrosecondsToDelay);
  53.  
  54.      }
  55.  
  56.  if (loopCount >= TimesToDelay) // Signify Timed Out
  57.   {
  58.  
  59.    dExt->TimedOut = TRUE;
  60.     return 0;
  61.     }
  62.  return 1;  
  63. }
  64.  
  65. //********************************************************
  66. //*  Wait for Data Ready Bit
  67. //********************************************************
  68. NTSTATUS WtDataStatus(                        //()
  69.   IN PSPECIFIC_DEVICE_EXTENSION dExt
  70.  )
  71. {
  72.     UCHAR Data;
  73.  
  74.     ULONG loopCount = 0;
  75.     ULONG TimesToDelay = (ULONG) 25500; // this should be enough
  76.     ULONG MicrosecondsToDelay =20;
  77.  
  78.      
  79.  
  80.  
  81.    while( (Data = ScsiPortReadPortUchar( (PUCHAR)(dExt->PortBase + 1) ) & ((UCHAR) 2)) &&
  82.                   (loopCount++ < TimesToDelay))
  83.      {
  84.  
  85.       ScsiPortStallExecution(MicrosecondsToDelay);
  86.  
  87.      }
  88.  
  89.   if (loopCount >= TimesToDelay) // Signify Timed Out
  90.     {
  91.  
  92.     dExt->TimedOut = TRUE;
  93.     return 0;
  94.      }
  95.    return 1;  
  96.  
  97.  
  98. }
  99.  
  100. //**************************************************************
  101. // Read Status : a simple wrapper function useful in debugging.
  102. //**************************************************************
  103.  
  104. UCHAR iRd(
  105.    PSPECIFIC_DEVICE_EXTENSION dExt ,
  106.     BOOLEAN RealStatusRead
  107. )
  108. {
  109.  //** Expensive but great for debug, replace later with MACRO
  110.  UCHAR a,b;
  111.  a =  ScsiPortReadPortUchar( (PUCHAR)(dExt->PortBase) );
  112.  
  113.  return a;
  114. }
  115.  
  116. //*******************************
  117. // Support Routine for CDRead
  118. // Clear the error code.
  119. //*******************************
  120. USHORT
  121. PanaGetErrorCode(
  122.  IN OUT PSPECIFIC_DEVICE_EXTENSION dExt
  123. )
  124. {
  125.   USHORT Data, i, errCmd, Code;
  126.   Code = 0;
  127.        SendCmd(0x0082);
  128.        SendCmd(0x0000);
  129.        SendCmd(0x0000);
  130.            SendCmd(0x0000);
  131.        SendCmd(0x0000);
  132.        SendCmd(0x0000);
  133.        SendCmd(0x0000);
  134.  
  135.         CLEAR_TIMED_OUT;
  136.        WtStatus(dExt);
  137.         if (!(ANY_TIMED_OUT))
  138.         {
  139.              errCmd = ReadStatus();
  140.           WtStatus(dExt);
  141.           Data =ReadStatus();
  142.  
  143.             Code = Data;
  144.               for (i=0; i<4; i++)
  145.            {
  146.               WtStatus(dExt);
  147.               Data =ReadStatus();
  148.             }
  149.          } // of !ANY_TIMED_OUT
  150.  
  151.     return (Code);
  152. }
  153.  
  154. //************************************************************
  155. //*    Actual Read CD routine
  156. //************************************************************
  157. NTSTATUS CDRead(  //)
  158.  ULONG LogAddr,
  159.  USHORT LogBlkRead,
  160.  PUCHAR userBuffer,
  161.  IN OUT PSPECIFIC_DEVICE_EXTENSION dExt
  162. )
  163. {
  164.    NTSTATUS status;
  165.    USHORT SectOff, MinOff, SecondOff, LenMsb, LenMid, LenLsb;
  166.     USHORT LogMsb, LogMid, LogLsb;
  167.    ULONG totalSeconds, LenInSect;
  168.    ULONG i,j ;
  169.    ULONG AbsSect;
  170.     USHORT Data;
  171.    ULONG StartAddr;
  172.    UCHAR CDBuffer;
  173.    USHORT a,b,c,d ;
  174.    ULONG e;
  175.    ULONG RdRetries;
  176.    ULONG ReadCount;
  177.  
  178.      /* do seek separate from read */
  179.      LogMsb = (USHORT) (((LogAddr)>>16) & 0xff);
  180.      LogMid = (USHORT) (((LogAddr)>>8) & 0xff);
  181.      LogLsb = (USHORT) (((LogAddr) & 0xff));
  182.  
  183.  
  184.      ReadCount =  LogBlkRead * 2048;
  185. #define MAX_READ_RETRIES    3
  186.  
  187.   // Figure out address to send out to drive
  188.   //
  189.   // 1. Find absolute sector offset, divide by 2048
  190.   //  AbsSect = RtlLargeIntegerShiftRight(startingOffset, 11).LowPart
  191.   //               + 150 ;    // 1st 2 second is RFU
  192.   AbsSect = LogAddr + 150;
  193.  
  194.    // determine all parameters
  195.     SectOff = (UCHAR) (AbsSect % (ULONG) 75);
  196.    totalSeconds = (AbsSect/75);
  197.    MinOff = totalSeconds / 60;
  198.    SecondOff = totalSeconds % 60;
  199.  
  200.  
  201.  
  202.    // convert to BCD
  203.      SectOff = DEC_TO_BCD(SectOff);
  204.      SecondOff = DEC_TO_BCD(SecondOff);
  205.      MinOff =DEC_TO_BCD(MinOff);
  206.  
  207.  
  208.  
  209.     // determine transfer length in required format
  210.         LenInSect = LogBlkRead;
  211.       LenLsb = (UCHAR) (LenInSect & 0xff);
  212.       LenMid = (UCHAR) ((LenInSect & 0xff00) >> 8);
  213.       LenMsb = (UCHAR) ((LenInSect & 0xff0000) >> 16);
  214.  
  215.  
  216.  
  217. //  **** Assume ByteWanted is the size request and startingOffset is buffer
  218. RdRetries = 0;
  219.  
  220. RetryRead:          
  221.            SendCmd(0x0002);
  222.              SendCmd(MinOff);
  223.              SendCmd(SecondOff);
  224.              SendCmd(SectOff);
  225.              SendCmd(LenMid);
  226.              SendCmd(LenLsb);
  227.              SendCmd(0x0002); // MSF Format
  228.             
  229.           for(i = 0; i < ReadCount; i++)
  230.           {
  231.              if (!WtDataStatus(dExt))
  232.                   {
  233.                    i=ReadCount + 1;
  234.                    break;
  235.                     }
  236.                
  237.                 Data = ReadPortData();
  238.                  *(userBuffer+i) = (UCHAR) Data;
  239.  
  240.     
  241. killIt: 
  242.              j=0 ;
  243.           }
  244.  
  245.  
  246.  
  247.       // Problemo locato
  248.       if ((i > ReadCount) ||
  249.           (i == 0))
  250.       {
  251.          // clear and display any errors
  252.  
  253.          CLEAR_TIMED_OUT;
  254.        SendCmd(0x0081);
  255.        WtStatus(dExt);
  256.           if (!(ANY_TIMED_OUT))
  257.           {
  258.             Data = ReadStatus();
  259.              if (Data & PAN_ERROR)
  260.               {
  261.                Data = PanaGetErrorCode(dExt);
  262.               }
  263.           }
  264.  
  265.  
  266.  
  267.         status = STATUS_DEVICE_DATA_ERROR;
  268.          } // of i>ReadLength
  269.           else
  270.         {
  271.           status = STATUS_SUCCESS;
  272.          }
  273.  
  274.  
  275.  
  276. READTerm:
  277.          return status;
  278.  
  279.  
  280. }
  281.  
  282. //*************************************************************
  283. //  Routines to auto-probe for existence of CD controller card
  284. //*************************************************************
  285.  
  286. BOOLEAN CheckForCard(
  287. IN OUT PSPECIFIC_DEVICE_EXTENSION    dExt
  288. )
  289. {
  290. USHORT Data;
  291. ULONG i;
  292. UCHAR DriveID[25];
  293.  
  294.  
  295.  CLEAR_TIMED_OUT;
  296.   SendCmd(0x0081);
  297.   WtStatus(dExt);
  298.  if ((ANY_TIMED_OUT))
  299.   goto Failit; 
  300.  
  301.  Data = ReadStatus();
  302.  
  303. if( Data != 0x00ff)
  304.     SendCmd(0x0083);  //read drive paramter
  305.     SendCmd(0x0000);  // byte 1
  306.     SendCmd(0x0000);  // byte 2
  307.     SendCmd(0x0000);  // byte 3
  308.     SendCmd(0x0000);  // byte 4
  309.     SendCmd(0x0000);  // byte 5
  310.     SendCmd(0x0000);  // byte 6
  311.  
  312.     for (i = 0; i <= 11; i++)
  313.    {
  314.     CLEAR_TIMED_OUT;
  315.    WtStatus(dExt);
  316.     if (ANY_TIMED_OUT)
  317.      break;  
  318.    Data = ReadStatus();
  319.    DriveID[i] = (UCHAR) Data;
  320.      if ((i == 0) && (Data != 'M'))
  321.              goto Failit;
  322.  
  323.     }
  324.  
  325. DriveID[12] = '\0';
  326.  
  327.  
  328.   if ((DriveID[0]== 'M') && (DriveID[1] == 'A') && (DriveID[2] == 'T'))
  329.    {
  330.      HardReset();   // Reset the drive for prosperity sake...
  331.  
  332.      return (TRUE);
  333.      }
  334.  } // Status = 0xff
  335. Failit:
  336.     return(FALSE);
  337. }
  338.  
  339. USHORT LocateAdapterSpecific(
  340.     PSPECIFIC_DEVICE_EXTENSION    dExt,
  341.      IN PVOID                    Context,
  342.     IN OUT PPORT_CONFIGURATION_INFORMATION  ConfigInfo
  343.     
  344. )
  345. {
  346.     ULONG baseAddresses[] =
  347.      { 
  348.          0x00000300,   // Panasonic Card Locations
  349.         0x00000310,
  350.          0x00000320, 
  351.         0x00000360, 
  352.         0x00000380,
  353.         0
  354.         };
  355.     ULONG PortBase;                 // Port location, in NT's address form.
  356.     ULONG PortCount;                // Count of contiguous I/O ports
  357.      ULONG PortIncrements;
  358.      ULONG PortSlots;
  359.     USHORT Data, Data1, i;
  360.      NTSTATUS status;
  361.      USHORT     curBaseAddress;
  362.      BOOLEAN CardFound;
  363.      ULONG HintPort;
  364.      PUCHAR ioSpace;
  365.  
  366.      HintPort = dExt->PortBase;
  367.  
  368.   ioSpace = ScsiPortGetDeviceBase(
  369.                  Context,                          // device extension
  370.                 ConfigInfo->AdapterInterfaceType,     // AdapterInterfaceType
  371.                 ConfigInfo->SystemIoBusNumber,          //Bus number
  372.     ScsiPortConvertUlongToPhysicalAddress(HintPort),
  373.      NUMBER_PORTS,
  374.      TRUE)     // InIoSpace
  375.      ;
  376.  
  377.  
  378.               if (  ioSpace != NULL) // cannot claim port
  379.               {
  380.                 PortBase = dExt->PortBase = (ULONG) ioSpace;
  381.  
  382.     
  383.             if (CheckForCard(dExt))
  384.                    return(PortBase);
  385.              else
  386.                      ScsiPortFreeDeviceBase(dExt, ioSpace);
  387.               }
  388.  
  389.      curBaseAddress = 0;
  390.      CardFound = FALSE;
  391.      while((baseAddresses[curBaseAddress] != 0)  &&
  392.                              (!CardFound))
  393.         {
  394.           ioSpace = ScsiPortGetDeviceBase(
  395.                            Context,                          // device extension
  396.                 ConfigInfo->AdapterInterfaceType,     // AdapterInterfaceType
  397.                 ConfigInfo->SystemIoBusNumber,          //Bus number
  398.     ScsiPortConvertUlongToPhysicalAddress(baseAddresses[curBaseAddress]),
  399.      NUMBER_PORTS,
  400.      TRUE)     // InIoSpace
  401.      ;
  402.  
  403.               if (  ioSpace == NULL) // cannot claim port
  404.                {
  405.                   curBaseAddress++;
  406.                   continue;
  407.                 }
  408.               else
  409.                 PortBase = dExt->PortBase = (ULONG) ioSpace;
  410.  
  411.     
  412.                 // mapped port
  413.               if (CheckForCard(dExt))
  414.                  {
  415.                   CardFound = TRUE;
  416.                   continue;
  417.                  }
  418.               else
  419.                {
  420.                  ScsiPortFreeDeviceBase(dExt, ioSpace);
  421.                  curBaseAddress++;
  422.                 }
  423.          } // of while
  424.  
  425.  
  426.   if (baseAddresses[curBaseAddress] != 0)
  427.     return(PortBase);
  428.   else
  429.     return(0);
  430. }
  431.  
  432.