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 >
Wrap
Text File
|
1993-10-13
|
10KB
|
433 lines
#include "ntddk.h"
#include "stdarg.h"
#include "CDnow.h" // includes scsi.h
/********************************************************************
Copyright (c) 1993 Sing Li, Media Synergy Inc. All Rights Reserved
Module Name:
Cdread.c
Abstract:
This is the Scsi miniport driver for Panasonic 52x using
native or compatible controllers.
This module contains routines which are specific to the
Panasonic 52x drives and native controllers.
**********************************************************************/
#define BCD_TO_DEC(x) ((((x & 0xF0)>>4)*10) + (x & 0x0F))
#define DEC_TO_BCD(x) (((x / 10) << 4) + (x % 10))
#define SendCmd(x) ScsiPortWritePortUchar( (PUCHAR)(dExt->PortBase), (UCHAR) x )
#define ReadStatus() iRd(dExt,1)
#define ReadDStatus() iRd(dExt,0)
#define ReadPortData() ScsiPortReadPortUchar((PUCHAR)(dExt->PortBase + 2))
#define HardReset() ScsiPortWritePortUchar( (PUCHAR)(dExt->PortBase + 2), (UCHAR) 0)
//***************************************************
// Wait for Status Ready Bit
//***************************************************
NTSTATUS WtStatus( //()
IN PSPECIFIC_DEVICE_EXTENSION dExt
)
{
UCHAR Data;
ULONG loopCount = 0;
ULONG TimesToDelay = (ULONG) 7000;
ULONG MicrosecondsToDelay =20;
ScsiPortStallExecution(MicrosecondsToDelay);
while( (Data = ScsiPortReadPortUchar( (PUCHAR)(dExt->PortBase + 1) ) & ((UCHAR) 4)) &&
(loopCount++ < TimesToDelay))
{
ScsiPortStallExecution(MicrosecondsToDelay);
}
if (loopCount >= TimesToDelay) // Signify Timed Out
{
dExt->TimedOut = TRUE;
return 0;
}
return 1;
}
//********************************************************
//* Wait for Data Ready Bit
//********************************************************
NTSTATUS WtDataStatus( //()
IN PSPECIFIC_DEVICE_EXTENSION dExt
)
{
UCHAR Data;
ULONG loopCount = 0;
ULONG TimesToDelay = (ULONG) 25500; // this should be enough
ULONG MicrosecondsToDelay =20;
while( (Data = ScsiPortReadPortUchar( (PUCHAR)(dExt->PortBase + 1) ) & ((UCHAR) 2)) &&
(loopCount++ < TimesToDelay))
{
ScsiPortStallExecution(MicrosecondsToDelay);
}
if (loopCount >= TimesToDelay) // Signify Timed Out
{
dExt->TimedOut = TRUE;
return 0;
}
return 1;
}
//**************************************************************
// Read Status : a simple wrapper function useful in debugging.
//**************************************************************
UCHAR iRd(
PSPECIFIC_DEVICE_EXTENSION dExt ,
BOOLEAN RealStatusRead
)
{
//** Expensive but great for debug, replace later with MACRO
UCHAR a,b;
a = ScsiPortReadPortUchar( (PUCHAR)(dExt->PortBase) );
return a;
}
//*******************************
// Support Routine for CDRead
// Clear the error code.
//*******************************
USHORT
PanaGetErrorCode(
IN OUT PSPECIFIC_DEVICE_EXTENSION dExt
)
{
USHORT Data, i, errCmd, Code;
Code = 0;
SendCmd(0x0082);
SendCmd(0x0000);
SendCmd(0x0000);
SendCmd(0x0000);
SendCmd(0x0000);
SendCmd(0x0000);
SendCmd(0x0000);
CLEAR_TIMED_OUT;
WtStatus(dExt);
if (!(ANY_TIMED_OUT))
{
errCmd = ReadStatus();
WtStatus(dExt);
Data =ReadStatus();
Code = Data;
for (i=0; i<4; i++)
{
WtStatus(dExt);
Data =ReadStatus();
}
} // of !ANY_TIMED_OUT
return (Code);
}
//************************************************************
//* Actual Read CD routine
//************************************************************
NTSTATUS CDRead( //)
ULONG LogAddr,
USHORT LogBlkRead,
PUCHAR userBuffer,
IN OUT PSPECIFIC_DEVICE_EXTENSION dExt
)
{
NTSTATUS status;
USHORT SectOff, MinOff, SecondOff, LenMsb, LenMid, LenLsb;
USHORT LogMsb, LogMid, LogLsb;
ULONG totalSeconds, LenInSect;
ULONG i,j ;
ULONG AbsSect;
USHORT Data;
ULONG StartAddr;
UCHAR CDBuffer;
USHORT a,b,c,d ;
ULONG e;
ULONG RdRetries;
ULONG ReadCount;
/* do seek separate from read */
LogMsb = (USHORT) (((LogAddr)>>16) & 0xff);
LogMid = (USHORT) (((LogAddr)>>8) & 0xff);
LogLsb = (USHORT) (((LogAddr) & 0xff));
ReadCount = LogBlkRead * 2048;
#define MAX_READ_RETRIES 3
// Figure out address to send out to drive
//
// 1. Find absolute sector offset, divide by 2048
// AbsSect = RtlLargeIntegerShiftRight(startingOffset, 11).LowPart
// + 150 ; // 1st 2 second is RFU
AbsSect = LogAddr + 150;
// determine all parameters
SectOff = (UCHAR) (AbsSect % (ULONG) 75);
totalSeconds = (AbsSect/75);
MinOff = totalSeconds / 60;
SecondOff = totalSeconds % 60;
// convert to BCD
SectOff = DEC_TO_BCD(SectOff);
SecondOff = DEC_TO_BCD(SecondOff);
MinOff =DEC_TO_BCD(MinOff);
// determine transfer length in required format
LenInSect = LogBlkRead;
LenLsb = (UCHAR) (LenInSect & 0xff);
LenMid = (UCHAR) ((LenInSect & 0xff00) >> 8);
LenMsb = (UCHAR) ((LenInSect & 0xff0000) >> 16);
// **** Assume ByteWanted is the size request and startingOffset is buffer
RdRetries = 0;
RetryRead:
SendCmd(0x0002);
SendCmd(MinOff);
SendCmd(SecondOff);
SendCmd(SectOff);
SendCmd(LenMid);
SendCmd(LenLsb);
SendCmd(0x0002); // MSF Format
for(i = 0; i < ReadCount; i++)
{
if (!WtDataStatus(dExt))
{
i=ReadCount + 1;
break;
}
Data = ReadPortData();
*(userBuffer+i) = (UCHAR) Data;
killIt:
j=0 ;
}
// Problemo locato
if ((i > ReadCount) ||
(i == 0))
{
// clear and display any errors
CLEAR_TIMED_OUT;
SendCmd(0x0081);
WtStatus(dExt);
if (!(ANY_TIMED_OUT))
{
Data = ReadStatus();
if (Data & PAN_ERROR)
{
Data = PanaGetErrorCode(dExt);
}
}
status = STATUS_DEVICE_DATA_ERROR;
} // of i>ReadLength
else
{
status = STATUS_SUCCESS;
}
READTerm:
return status;
}
//*************************************************************
// Routines to auto-probe for existence of CD controller card
//*************************************************************
BOOLEAN CheckForCard(
IN OUT PSPECIFIC_DEVICE_EXTENSION dExt
)
{
USHORT Data;
ULONG i;
UCHAR DriveID[25];
CLEAR_TIMED_OUT;
SendCmd(0x0081);
WtStatus(dExt);
if ((ANY_TIMED_OUT))
goto Failit;
Data = ReadStatus();
if( Data != 0x00ff)
{
SendCmd(0x0083); //read drive paramter
SendCmd(0x0000); // byte 1
SendCmd(0x0000); // byte 2
SendCmd(0x0000); // byte 3
SendCmd(0x0000); // byte 4
SendCmd(0x0000); // byte 5
SendCmd(0x0000); // byte 6
for (i = 0; i <= 11; i++)
{
CLEAR_TIMED_OUT;
WtStatus(dExt);
if (ANY_TIMED_OUT)
break;
Data = ReadStatus();
DriveID[i] = (UCHAR) Data;
if ((i == 0) && (Data != 'M'))
goto Failit;
}
DriveID[12] = '\0';
if ((DriveID[0]== 'M') && (DriveID[1] == 'A') && (DriveID[2] == 'T'))
{
HardReset(); // Reset the drive for prosperity sake...
return (TRUE);
}
} // Status = 0xff
Failit:
return(FALSE);
}
USHORT LocateAdapterSpecific(
PSPECIFIC_DEVICE_EXTENSION dExt,
IN PVOID Context,
IN OUT PPORT_CONFIGURATION_INFORMATION ConfigInfo
)
{
ULONG baseAddresses[] =
{
0x00000300, // Panasonic Card Locations
0x00000310,
0x00000320,
0x00000360,
0x00000380,
0
};
ULONG PortBase; // Port location, in NT's address form.
ULONG PortCount; // Count of contiguous I/O ports
ULONG PortIncrements;
ULONG PortSlots;
USHORT Data, Data1, i;
NTSTATUS status;
USHORT curBaseAddress;
BOOLEAN CardFound;
ULONG HintPort;
PUCHAR ioSpace;
HintPort = dExt->PortBase;
ioSpace = ScsiPortGetDeviceBase(
Context, // device extension
ConfigInfo->AdapterInterfaceType, // AdapterInterfaceType
ConfigInfo->SystemIoBusNumber, //Bus number
ScsiPortConvertUlongToPhysicalAddress(HintPort),
NUMBER_PORTS,
TRUE) // InIoSpace
;
if ( ioSpace != NULL) // cannot claim port
{
PortBase = dExt->PortBase = (ULONG) ioSpace;
if (CheckForCard(dExt))
return(PortBase);
else
ScsiPortFreeDeviceBase(dExt, ioSpace);
}
curBaseAddress = 0;
CardFound = FALSE;
while((baseAddresses[curBaseAddress] != 0) &&
(!CardFound))
{
ioSpace = ScsiPortGetDeviceBase(
Context, // device extension
ConfigInfo->AdapterInterfaceType, // AdapterInterfaceType
ConfigInfo->SystemIoBusNumber, //Bus number
ScsiPortConvertUlongToPhysicalAddress(baseAddresses[curBaseAddress]),
NUMBER_PORTS,
TRUE) // InIoSpace
;
if ( ioSpace == NULL) // cannot claim port
{
curBaseAddress++;
continue;
}
else
PortBase = dExt->PortBase = (ULONG) ioSpace;
// mapped port
if (CheckForCard(dExt))
{
CardFound = TRUE;
continue;
}
else
{
ScsiPortFreeDeviceBase(dExt, ioSpace);
curBaseAddress++;
}
} // of while
if (baseAddresses[curBaseAddress] != 0)
return(PortBase);
else
return(0);
}