|
|
/*++
Copyright (C) SCM Micro Systems.
Module Name:
parstl.c
Abstract:
This is the module that generates unique device id for shuttle adapters, that do not have the capability to do so, by themselves.
Author:
Devanathan NR 21-Jun-1999 Sudheendran TL
Environment:
Kernel mode
Revision History :
--*/
#include "pch.h"
#include "parstl.h"
BOOLEAN ParStlCheckIfStl( IN PDEVICE_EXTENSION Extension, IN ULONG ulDaisyIndex ) /*++
Routine Description:
This function checks whether the indicated device is a shuttle device or not.
Arguments:
Extension - Device extension structure.
ulDaisyIndex - The daisy index on which to do the check.
Return Value:
TRUE - Yes, it was a Shuttle device. FALSE - No, not a shuttle.
--*/ { NTSTATUS status ; BOOLEAN bStlNon1284_3Found = FALSE ;
Extension->Ieee1284Flags &= ( ~ ( 1 << ulDaisyIndex ) ) ; bStlNon1284_3Found = ParStlCheckIfNon1284_3Present( Extension ) ;
if ( TRUE == ParStlCheckIfStl1284_3 ( Extension, ulDaisyIndex, bStlNon1284_3Found ) ) { // this adapter is a Shuttle 1284_3 adapter
Extension->Ieee1284Flags |= ( 1 << ulDaisyIndex ) ; return TRUE ; } if ( TRUE == bStlNon1284_3Found ) { if ( TRUE == ParStlCheckIfStlProductId ( Extension, ulDaisyIndex ) ) { // this adapter is Shuttle non-1284_3 adapter
Extension->Ieee1284Flags |= ( 1 << ulDaisyIndex ) ; return TRUE ; } } return FALSE ; }
BOOLEAN ParStlCheckIfNon1284_3Present( IN PDEVICE_EXTENSION Extension ) /*++
Routine Description:
Indicates whether one of the devices of the earlier specification is present in the chain.
Arguments:
Extension - Device Extension structure
Return Value:
TRUE : Atleast one of the adapters are of earlier spec. FALSE : None of the adapters of the earlier spec.
--*/ { BOOLEAN bReturnValue = FALSE ; UCHAR i, value, newvalue, status; ULONG Delay = 3; PUCHAR CurrentPort, CurrentStatus, CurrentControl; UCHAR ucAckStatus ;
CurrentPort = Extension->Controller; CurrentStatus = CurrentPort + 1; CurrentControl = CurrentPort + 2;
// get current ctl reg
value = READ_PORT_UCHAR( CurrentControl );
// make sure 1284.3 devices do not get reseted
newvalue = (UCHAR)((value & ~DCR_SELECT_IN) | DCR_NOT_INIT);
// make sure we can write
newvalue = (UCHAR)(newvalue & ~DCR_DIRECTION); WRITE_PORT_UCHAR( CurrentControl, newvalue ); // make sure we can write
// bring nStrobe high
WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
// send first four bytes of the 1284.3 mode qualifier sequence out
for ( i = 0; i < MODE_LEN_1284_3 - 3; i++ ) { WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[i] ); KeStallExecutionProcessor( Delay ); }
// check for correct status
status = READ_PORT_UCHAR( CurrentStatus );
if ( (status & (UCHAR)0xb8 ) == ( DSR_NOT_BUSY | DSR_PERROR | DSR_SELECT | DSR_NOT_FAULT )) {
ucAckStatus = status & 0x40 ;
// continue with fifth byte of mode qualifier
WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[4] ); KeStallExecutionProcessor( Delay );
// check for correct status
status = READ_PORT_UCHAR( CurrentStatus );
// note busy is high too but is opposite so we see it as a low
if (( status & (UCHAR) 0xb8 ) == (DSR_SELECT | DSR_NOT_FAULT)) {
if ( ucAckStatus != ( status & 0x40 ) ) {
// save current ack status
ucAckStatus = status & 0x40 ;
// continue with sixth byte
WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[5] ); KeStallExecutionProcessor( Delay );
// check for correct status
status = READ_PORT_UCHAR( CurrentStatus );
// if status is valid there is a device out there responding
if ((status & (UCHAR) 0x30 ) == ( DSR_PERROR | DSR_SELECT )) {
bReturnValue = TRUE ;
} // Third status
} // ack of earlier adapters not seen
// last byte
WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[6] );
} // Second status
} // First status
WRITE_PORT_UCHAR( CurrentControl, value ); // restore everything
return bReturnValue ; } // ParStlCheckIfNon1284_3Present
BOOLEAN ParStlCheckIfStl1284_3( IN PDEVICE_EXTENSION Extension, IN ULONG ulDaisyIndex, IN BOOLEAN bNoStrobe ) /*++
Routine Description:
This function checks to see whether the device indicated is a Shuttle 1284_3 type of device.
Arguments:
Extension - Device extension structure.
ulDaisyIndex - The daisy chain id of the device that this function will check on.
bNoStrobe - If set, indicates that the query Ep1284 command issued by this function need not assert strobe to latch the command.
Return Value:
TRUE - Yes. Device is Shuttle 1284_3 type of device. FALSE - No. This may mean that this device is either non-shuttle or Shuttle non-1284_3 type of device.
--*/ { BOOLEAN bReturnValue = FALSE ; UCHAR i, value, newvalue, status; ULONG Delay = 3; UCHAR ucExpectedPattern ; UCHAR ucReadValue, ucReadPattern; PUCHAR CurrentPort, CurrentStatus, CurrentControl;
CurrentPort = Extension->Controller; CurrentStatus = CurrentPort + 1; CurrentControl = CurrentPort + 2;
// get current ctl reg
value = READ_PORT_UCHAR( CurrentControl );
// make sure 1284.3 devices do not get reseted
newvalue = (UCHAR)((value & ~DCR_SELECT_IN) | DCR_NOT_INIT);
// make sure we can write
newvalue = (UCHAR)(newvalue & ~DCR_DIRECTION); WRITE_PORT_UCHAR( CurrentControl, newvalue ); // make sure we can write
// bring nStrobe high
WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
// send first four bytes of the 1284.3 mode qualifier sequence out
for ( i = 0; i < MODE_LEN_1284_3 - 3; i++ ) { WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[i] ); KeStallExecutionProcessor( Delay ); }
// check for correct status
status = READ_PORT_UCHAR( CurrentStatus );
if ( (status & (UCHAR)0xb8 ) == ( DSR_NOT_BUSY | DSR_PERROR | DSR_SELECT | DSR_NOT_FAULT )) {
// continue with fifth byte of mode qualifier
WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[4] ); KeStallExecutionProcessor( Delay );
// check for correct status
status = READ_PORT_UCHAR( CurrentStatus );
// note busy is high too but is opposite so we see it as a low
if (( status & (UCHAR) 0xb8 ) == (DSR_SELECT | DSR_NOT_FAULT)) {
// continue with sixth byte
WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[5] ); KeStallExecutionProcessor( Delay );
// check for correct status
status = READ_PORT_UCHAR( CurrentStatus );
// if status is valid there is a device out there responding
if ((status & (UCHAR) 0x30 ) == ( DSR_PERROR | DSR_SELECT )) {
// Device is out there
KeStallExecutionProcessor( Delay );
// issue shuttle specific CPP command
WRITE_PORT_UCHAR( CurrentPort, (UCHAR) ( 0x88 | ulDaisyIndex ) ); KeStallExecutionProcessor( Delay ); // wait a bit
if ( ulDaisyIndex && ( bNoStrobe == FALSE ) ) {
WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
KeStallExecutionProcessor( Delay ); // wait a bit
WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
KeStallExecutionProcessor( Delay ); // wait a bit
}
ucExpectedPattern = 0xF0 ; bReturnValue = TRUE ;
while ( ucExpectedPattern ) {
KeStallExecutionProcessor( Delay ); // wait a bit
WRITE_PORT_UCHAR( CurrentPort, (UCHAR) (0x80 | ulDaisyIndex )) ;
KeStallExecutionProcessor( Delay ); // wait a bit
WRITE_PORT_UCHAR( CurrentPort, (UCHAR) (0x88 | ulDaisyIndex )) ;
KeStallExecutionProcessor( Delay ); // wait a bit
ucReadValue = READ_PORT_UCHAR( CurrentStatus ) ; ucReadPattern = ( ucReadValue << 1 ) & 0x70 ; ucReadPattern |= ( ucReadValue & 0x80 ) ;
if ( ucReadPattern != ucExpectedPattern ) { // not Shuttle 1284_3 behaviour
bReturnValue = FALSE ; break ; }
ucExpectedPattern -= 0x10 ; }
// last byte
WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[6] );
} // Third status
} // Second status
} // First status
WRITE_PORT_UCHAR( CurrentControl, value ); // restore everything
return bReturnValue ; } // end ParStlCheckIfStl1284_3()
BOOLEAN ParStlCheckIfStlProductId( IN PDEVICE_EXTENSION Extension, IN ULONG ulDaisyIndex ) /*++
Routine Description:
This function checks to see whether the device indicated is a Shuttle non-1284_3 type of device.
Arguments:
Extension - Device extension structure.
ulDaisyIndex - The daisy chain id of the device that this function will check on.
Return Value:
TRUE - Yes. Device is Shuttle non-1284_3 type of device. FALSE - No. This may mean that this device is non-shuttle.
--*/ { BOOLEAN bReturnValue = FALSE ; UCHAR i, value, newvalue, status; ULONG Delay = 3; UCHAR ucProdIdHiByteHiNibble, ucProdIdHiByteLoNibble ; UCHAR ucProdIdLoByteHiNibble, ucProdIdLoByteLoNibble ; UCHAR ucProdIdHiByte, ucProdIdLoByte ; USHORT usProdId ; PUCHAR CurrentPort, CurrentStatus, CurrentControl;
CurrentPort = Extension->Controller; CurrentStatus = CurrentPort + 1; CurrentControl = CurrentPort + 2;
// get current ctl reg
value = READ_PORT_UCHAR( CurrentControl );
// make sure 1284.3 devices do not get reseted
newvalue = (UCHAR)((value & ~DCR_SELECT_IN) | DCR_NOT_INIT);
// make sure we can write
newvalue = (UCHAR)(newvalue & ~DCR_DIRECTION); WRITE_PORT_UCHAR( CurrentControl, newvalue ); // make sure we can write
// bring nStrobe high
WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
// send first four bytes of the 1284.3 mode qualifier sequence out
for ( i = 0; i < MODE_LEN_1284_3 - 3; i++ ) { WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[i] ); KeStallExecutionProcessor( Delay ); }
// check for correct status
status = READ_PORT_UCHAR( CurrentStatus );
if ( (status & (UCHAR)0xb8 ) == ( DSR_NOT_BUSY | DSR_PERROR | DSR_SELECT | DSR_NOT_FAULT )) {
// continue with fifth byte of mode qualifier
WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[4] ); KeStallExecutionProcessor( Delay );
// check for correct status
status = READ_PORT_UCHAR( CurrentStatus );
// note busy is high too but is opposite so we see it as a low
if (( status & (UCHAR) 0xb8 ) == (DSR_SELECT | DSR_NOT_FAULT)) {
// continue with sixth byte
WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[5] ); KeStallExecutionProcessor( Delay );
// check for correct status
status = READ_PORT_UCHAR( CurrentStatus );
// if status is valid there is a device out there responding
if ((status & (UCHAR) 0x30 ) == ( DSR_PERROR | DSR_SELECT )) {
WRITE_PORT_UCHAR ( CurrentPort, (UCHAR) (CPP_QUERY_PRODID | ulDaisyIndex )) ; KeStallExecutionProcessor( Delay );
// Device is out there
KeStallExecutionProcessor( Delay ); ucProdIdLoByteHiNibble = READ_PORT_UCHAR( CurrentStatus ) ; ucProdIdLoByteHiNibble &= 0xF0 ;
KeStallExecutionProcessor( Delay ); WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
KeStallExecutionProcessor( Delay ); // wait a bit
WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
KeStallExecutionProcessor( Delay ); // wait a bit
ucProdIdLoByteLoNibble = READ_PORT_UCHAR( CurrentStatus ) ; ucProdIdLoByteLoNibble >>= 4 ; ucProdIdLoByte = ucProdIdLoByteHiNibble | ucProdIdLoByteLoNibble ;
KeStallExecutionProcessor( Delay ); WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
KeStallExecutionProcessor( Delay ); // wait a bit
WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
KeStallExecutionProcessor( Delay ); // wait a bit
ucProdIdHiByteHiNibble = READ_PORT_UCHAR( CurrentStatus ) ; ucProdIdHiByteHiNibble &= 0xF0 ;
KeStallExecutionProcessor( Delay ); WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
KeStallExecutionProcessor( Delay ); // wait a bit
WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
KeStallExecutionProcessor( Delay ); // wait a bit
ucProdIdHiByteLoNibble = READ_PORT_UCHAR( CurrentStatus ) ; ucProdIdHiByteLoNibble >>= 4 ; ucProdIdHiByte = ucProdIdHiByteHiNibble | ucProdIdHiByteLoNibble ;
// last strobe
KeStallExecutionProcessor( Delay ); WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
KeStallExecutionProcessor( Delay ); // wait a bit
WRITE_PORT_UCHAR( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
KeStallExecutionProcessor( Delay ); // wait a bit
usProdId = ( ucProdIdHiByte << 8 ) | ucProdIdLoByte ;
if ( ( SHTL_EPAT_PRODID == usProdId ) ||\ ( SHTL_EPST_PRODID == usProdId ) ) { // one of the devices that conform to the earlier
// draft is found
bReturnValue = TRUE ; }
// last byte
WRITE_PORT_UCHAR( CurrentPort, ModeQualifier[6] );
} // Third status
} // Second status
} // First status
WRITE_PORT_UCHAR( CurrentControl, value ); // restore everything
return bReturnValue ; } // end ParStlCheckIfStlProductId()
PCHAR ParStlQueryStlDeviceId( IN PDEVICE_EXTENSION Extension, OUT PCHAR CallerDeviceIdBuffer, IN ULONG CallerBufferSize, OUT PULONG DeviceIdSize, IN BOOLEAN bReturnRawString ) /*++
Routine Description:
This routine retrieves/constructs the unique device id string from the selected shuttle device on the chain and updates the caller's buffer with the same.
Arguments:
IN Extension : The device extension OUT CallerDeviceIdBuffer : Caller's buffer IN CallerBufferSize : Size of caller's buffer OUT DeviceIdSize : Updated device id's size IN bReturnRawString : Whether to return raw string with the first two bytes or not.
Return Value:
Pointer to the read device ID string, if successful.
NULL otherwise.
--*/ { PUCHAR Controller = Extension->Controller; NTSTATUS Status; UCHAR idSizeBuffer[2]; ULONG bytesToRead; ULONG bytesRead = 0; USHORT deviceIdSize; USHORT deviceIdBufferSize; PCHAR deviceIdBuffer; PCHAR readPtr;
*DeviceIdSize = 0;
// assert idle state, to recover from undefined state,
// just in case it gets into
ParStlAssertIdleState ( Extension ) ;
//
// If we are currently connected to the peripheral via any 1284 mode
// other than Compatibility/Spp mode (which does not require an IEEE
// negotiation), we must first terminate the current mode/connection.
//
// dvdf - RMT - what if we are connected in a reverse mode?
//
if( (Extension->Connected) && (afpForward[Extension->IdxForwardProtocol].fnDisconnect) ) { afpForward[Extension->IdxForwardProtocol].fnDisconnect (Extension); }
do {
//
// Negotiate the peripheral into nibble device id mode.
//
Status = ParEnterNibbleMode(Extension, REQUEST_DEVICE_ID); if( !NT_SUCCESS(Status) ) { ParTerminateNibbleMode(Extension); break ; }
//
// Read first two bytes to get the total (including the 2 size bytes) size
// of the Device Id string.
//
bytesToRead = 2; Status = ParNibbleModeRead(Extension, idSizeBuffer, bytesToRead, &bytesRead); if( !NT_SUCCESS( Status ) || ( bytesRead != bytesToRead ) ) { break ; }
//
// Compute size of DeviceId string (including the 2 byte size prefix)
//
deviceIdSize = (USHORT)( idSizeBuffer[0]*0x100 + idSizeBuffer[1] );
//
// Allocate a buffer to hold the DeviceId string and read the DeviceId into it.
//
if( bReturnRawString ) { //
// Caller wants the raw string including the 2 size bytes
//
*DeviceIdSize = deviceIdSize; deviceIdBufferSize = (USHORT)(deviceIdSize + sizeof(CHAR)); // ID size + ID + terminating NULL
} else { //
// Caller does not want the 2 byte size prefix
//
*DeviceIdSize = deviceIdSize - 2*sizeof(CHAR); deviceIdBufferSize = (USHORT)(deviceIdSize - 2*sizeof(CHAR) + sizeof(CHAR)); // ID + terminating NULL
}
deviceIdBuffer = (PCHAR)ExAllocatePool(PagedPool, deviceIdBufferSize); if( !deviceIdBuffer ) { break; }
//
// NULL out the ID buffer to be safe
//
RtlZeroMemory( deviceIdBuffer, deviceIdBufferSize );
//
// Does the caller want the 2 byte size prefix?
//
if( bReturnRawString ) { //
// Yes, caller wants the size prefix. Copy prefix to buffer to return.
//
*(deviceIdBuffer+0) = idSizeBuffer[0]; *(deviceIdBuffer+1) = idSizeBuffer[1]; readPtr = deviceIdBuffer + 2; } else { //
// No, discard size prefix
//
readPtr = deviceIdBuffer; }
//
// Read remainder of DeviceId from device
//
bytesToRead = deviceIdSize - 2; // already have the 2 size bytes
Status = ParNibbleModeRead(Extension, readPtr, bytesToRead, &bytesRead);
ParTerminateNibbleMode( Extension );
if( !NT_SUCCESS(Status) || (bytesRead < 1) ) { ExFreePool( deviceIdBuffer ); break ; }
if ( strstr ( readPtr, "MFG:" ) == 0 ) { ExFreePool( deviceIdBuffer ) ; break ; }
deviceIdSize = (USHORT) strlen(deviceIdBuffer); *DeviceIdSize = deviceIdSize; if( (NULL != CallerDeviceIdBuffer) && (CallerBufferSize >= deviceIdSize) ) { // caller supplied buffer is large enough, use it
RtlZeroMemory( CallerDeviceIdBuffer, CallerBufferSize ); RtlCopyMemory( CallerDeviceIdBuffer, deviceIdBuffer, deviceIdSize ); ExFreePool( deviceIdBuffer ); return CallerDeviceIdBuffer; } return deviceIdBuffer;
} while ( FALSE ) ;
// Builds later than 2080 fail to terminate in Compatibility mode.
//IEEETerminate1284Mode fails after Event 23 (Extension->CurrentEvent equals 23)
// with earlier 1284 draft.
//So, we terminate the adapter ourselves, in some cases may be redundant.
WRITE_PORT_UCHAR(Controller + DCR_OFFSET, DCR_SELECT_IN | DCR_NOT_INIT); KeStallExecutionProcessor( 5 ); WRITE_PORT_UCHAR(Controller + DCR_OFFSET, DCR_SELECT_IN | DCR_NOT_INIT | DCR_AUTOFEED); KeStallExecutionProcessor( 5 ); WRITE_PORT_UCHAR(Controller + DCR_OFFSET, DCR_SELECT_IN | DCR_NOT_INIT);
ParStlAssertIdleState ( Extension ) ;
deviceIdBuffer = ParBuildStlDeviceId(Extension);
if( !deviceIdBuffer ) { return NULL; }
deviceIdSize = (USHORT) strlen(deviceIdBuffer); *DeviceIdSize = deviceIdSize; if( (NULL != CallerDeviceIdBuffer) && (CallerBufferSize >= deviceIdSize) ) { // caller supplied buffer is large enough, use it
RtlZeroMemory( CallerDeviceIdBuffer, CallerBufferSize ); RtlCopyMemory( CallerDeviceIdBuffer, deviceIdBuffer, deviceIdSize ); ExFreePool( deviceIdBuffer ); return CallerDeviceIdBuffer; } return deviceIdBuffer; }
PCHAR ParBuildStlDeviceId( IN PDEVICE_EXTENSION Extension ) /*++
Routine Description:
This function detects the type of shuttle adapter and builds an appropriate device id string and returns it back.
It is assumed that the device is already in the selected state.
Arguments:
Nil.
Return Value:
Pointer to the read/built device ID string, if successful.
NULL otherwise.
--*/ { ULONG size = 0x80 ; PCHAR id ; STL_DEVICE_TYPE dtDeviceType ; CHAR szDeviceIdString[0x80] ; CHAR szVidPidString[] = "MFG:VID_04E6;CLS:SCSIADAPTER;MDL:PID_" ; CHAR szVidPidStringScan[] = "MFG:VID_04E6;CLS:IMAGE;MDL:PID_" ;
RtlZeroMemory(szDeviceIdString, sizeof(szDeviceIdString));
// identify the shuttle adapter type by calling
// Devtype routines here and build an unique id
// string here.
dtDeviceType = ParStlGetDeviceType(Extension, DEVICE_TYPE_AUTO_DETECT);
switch ( dtDeviceType ) {
case DEVICE_TYPE_NONE : return NULL;
case DEVICE_TYPE_EPP_DEVICE : dtDeviceType |= 0x80000000 ; sprintf(szDeviceIdString, "%s%08X;", szVidPidStringScan, dtDeviceType); break;
default : dtDeviceType |= 0x80000000 ; sprintf(szDeviceIdString, "%s%08X;", szVidPidString, dtDeviceType); break;
}
id = ExAllocatePool(PagedPool, size); if( id ) { RtlZeroMemory( id, size ); RtlCopyMemory( id, szDeviceIdString, size - sizeof(NULL) ); return id; } return NULL; }
STL_DEVICE_TYPE __cdecl ParStlGetDeviceType ( IN PDEVICE_EXTENSION Extension, IN int nPreferredDeviceType ) { STL_DEVICE_TYPE dtDeviceType = DEVICE_TYPE_NONE ; int nLocalPreferredDeviceType = nPreferredDeviceType ; ATAPIPARAMS atapiParams ; int i;
for ( i=0 ; i<ATAPI_MAX_DRIVES ; i++){ atapiParams.dsDeviceState[i] = DEVICE_STATE_INVALID ; }
do { if ( TRUE == ParStlCheckIfScsiDevice(Extension)) { // SCSI Device identified.
dtDeviceType |= DEVICE_TYPE_SCSI_BIT ; break ; }
if ( TRUE == NeedToEnableIoPads () ) { // in some adapters, the IO pads need to be enabled, before
// doing the device detection
ParStlWriteReg( Extension, CONFIG_INDEX_REGISTER, EP1284_POWER_CONTROL_REG ); ParStlWriteReg( Extension, CONFIG_DATA_REGISTER, ENABLE_IOPADS ); }
if ( TRUE == IsImpactSPresent() ) { // as impact-s has been identified, the device type identification
// can be done through personality configuration info
dtDeviceType |= ParStlGetImpactSDeviceType( Extension, &atapiParams, nPreferredDeviceType ); break; }
if ( TRUE == IsImpactPresent() ) { // as impact has been identified, the device type identification
// can be done through personality configuration info
dtDeviceType |= ParStlGetImpactDeviceType( Extension, &atapiParams, nPreferredDeviceType ); break; }
if (TRUE == ParStlCheckIfEppDevice(Extension)) { // epp device identified
if ( TRUE == ParStlCheckUMAXScannerPresence(Extension) ) { // umax identified
dtDeviceType |= DEVICE_TYPE_UMAX_BIT; break; } if ( TRUE == ParStlCheckAvisionScannerPresence(Extension) ) { // avision identified
dtDeviceType |= DEVICE_TYPE_AVISION_BIT; break; } // generice scanner peripheral detected
dtDeviceType |= DEVICE_TYPE_EPP_DEVICE_BIT; break; }
if (TRUE == ParStlCheckIfSSFDC(Extension)) { // SSFDC identified
dtDeviceType |= DEVICE_TYPE_SSFDC_BIT; break; }
if (TRUE == ParStlCheckIfMMC(Extension,&atapiParams)) { // MMC device identified
dtDeviceType |= DEVICE_TYPE_MMC_BIT; break; }
// set the 16 bit mode of the adapter
ParStlSet16BitOperation(Extension) ;
if (TRUE == ParStlCheckIfAtaAtapiDevice(Extension, &atapiParams)) { // necessary but not sufficient condition has passed
// proceed for sufficency checks
if (TRUE == ParStlCheckIfAtapiDevice(Extension, &atapiParams)) { // sub-classify between HiFD and LS-120.
if ( TRUE == ParStlCheckIfLS120(Extension)) { // LS Engine is found.
dtDeviceType |= DEVICE_TYPE_LS120_BIT ; break ; } // Check for HiFD.
if (TRUE == ParStlCheckIfHiFD(Extension)) { // HiFD device identified.
dtDeviceType |= DEVICE_TYPE_HIFD_BIT ; break ; } // OtherWise, it is a generic ATAPI device.
dtDeviceType |= DEVICE_TYPE_ATAPI_BIT; break ; }
if (TRUE == ParStlCheckIfAtaDevice(Extension, &atapiParams)) { // ata identified
dtDeviceType |= DEVICE_TYPE_ATA_BIT; break; } }
if (TRUE == ParStlCheckIfDazzle(Extension)) { // dazzle identified
dtDeviceType |= DEVICE_TYPE_DAZZLE_BIT; break; }
if (TRUE == ParStlCheckIfFlash(Extension)) { // flash identified
dtDeviceType |= DEVICE_TYPE_FLASH_BIT; break; } } while ( FALSE ) ;
return dtDeviceType & nPreferredDeviceType ; }
VOID ParStlWaitForMicroSeconds ( int nMicroSecondsToWait ) { KeStallExecutionProcessor ( nMicroSecondsToWait ) ; }
BOOLEAN ParStlCheckCardInsertionStatus ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE ; UCHAR byPowerRegData ; do { if ( FALSE == IsEp1284Present() ) { break ; }
ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER , 0x0F ) ; byPowerRegData = (UCHAR) ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) ;
if ( byPowerRegData & SHTL_CARD_INSERTED_STATUS ) { // as the card not inserted status is reported, it is ATA / ATAPI
// possibly, not flash. hence, we break here.
break ; }
bReturnValue = TRUE ; } while ( FALSE ) ;
return ( bReturnValue ) ; }
BOOLEAN ParStlSelectAdapterSocket ( IN PDEVICE_EXTENSION Extension, IN int nSocketNumber ) { BOOLEAN bReturnValue = FALSE ; UCHAR bySCRControlReg , byISAControlReg ;
do { if ( ( nSocketNumber != SOCKET_0 ) && ( nSocketNumber != SOCKET_1 ) ) { // as an invalid socket number is provided, we
// break here with error.
break ; }
ParStlWriteReg(Extension, CONFIG_INDEX_REGISTER , SOCKET_CONTROL_REGISTER ) ; bySCRControlReg = (UCHAR) ParStlReadReg (Extension, CONFIG_DATA_REGISTER ) ;
ParStlWriteReg(Extension, CONFIG_INDEX_REGISTER , ISA_CONTROL_REGISTER ) ; byISAControlReg = (UCHAR) ParStlReadReg (Extension, CONFIG_DATA_REGISTER ) ;
if ( SOCKET_1 == nSocketNumber ) { bySCRControlReg |= (UCHAR)SOCKET_1 ; bySCRControlReg |= (UCHAR)PERIPHERAL_RESET_1 ; byISAControlReg &= ~(UCHAR)ISA_IO_SWAP ; } else { bySCRControlReg &= ~(UCHAR)SOCKET_1 ; bySCRControlReg &= ~(UCHAR)PERIPHERAL_RESET_0 ; }
ParStlWriteReg(Extension, CONFIG_INDEX_REGISTER , ISA_CONTROL_REGISTER ) ; ParStlWriteReg(Extension, CONFIG_DATA_REGISTER , byISAControlReg ) ;
ParStlWriteReg(Extension, CONFIG_INDEX_REGISTER , SOCKET_CONTROL_REGISTER ) ; ParStlWriteReg(Extension, CONFIG_DATA_REGISTER , bySCRControlReg ) ;
if ( SOCKET_1 == nSocketNumber ) { // Wait for a few milliseconds to provide an optimal puse width
// for reset.
ParStlWaitForMicroSeconds(1000); bySCRControlReg &= ~(UCHAR)PERIPHERAL_RESET_1 ; } else { bySCRControlReg &= ~(UCHAR)PERIPHERAL_RESET_0 ; } ParStlWriteReg(Extension, CONFIG_DATA_REGISTER , bySCRControlReg ) ;
bReturnValue = TRUE ; } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckIfAtaAtapiDevice ( IN PDEVICE_EXTENSION Extension, IN OUT PATAPIPARAMS atapiParams ) { BOOLEAN bReturnValue = FALSE; do { if ( TRUE == ParStlCheckCardInsertionStatus(Extension) ) { // as the card insertion status is valid, its probably
// a flash
break ; } if ( FALSE == ParStlCheckDrivePresent(Extension, atapiParams) ) { // as the ATA/ATAPI controller is not present, it cant be
// an ATA/ATAPI device
break ; } bReturnValue = TRUE; } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckIfAtapiDevice ( IN PDEVICE_EXTENSION Extension, IN OUT PATAPIPARAMS atapiParams ) { BOOLEAN bReturnValue = FALSE; do { // return whatever ATAPI initialization module says
bReturnValue = ParStlAtapiInitialize(Extension, atapiParams) ; } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckIfAtaDevice ( IN PDEVICE_EXTENSION Extension, IN OUT PATAPIPARAMS atapiParams ) { BOOLEAN bReturnValue = FALSE; do { // return whatever ATA initialization module says
bReturnValue = ParStlAtaInitialize(Extension, atapiParams) ; } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckDrivePresent ( IN PDEVICE_EXTENSION Extension, IN OUT PATAPIPARAMS atapiParams ) { BOOLEAN bReturnValue = FALSE ; UCHAR byOrgCylHigh, byOrgCylLow ; int nCurrentDrive = 0 , i ; UCHAR nDrvHdArray[]={ATAPI_MASTER, ATAPI_SLAVE};
do { if ( atapiParams->dsDeviceState[nCurrentDrive] == DEVICE_STATE_VALID ) { // this means that the MMC module had detected the presence
// of an ATA/ATAPI device. So, we make use of that and break out
bReturnValue = TRUE ; break ; }
ParStlWriteIoPort(Extension, ATA_DRVHD_REG, nDrvHdArray[nCurrentDrive]);
// The Atapi Fuji MO drive is found to de-assert BSY and still
// does not respond to reg. r/w when configured as slave with no media.
// However, after a delay, it works ok.
if ( nCurrentDrive ) { ParStlWaitForMicroSeconds ( DELAY_1SECOND ) ; }
// this dummy write of 0 is to zero out a possible
// floating bus
for ( i = 0 ; i < 16 ; i++ ) { ParStlWriteReg(Extension, CONFIG_INDEX_REGISTER, i) ; if ( !( ParStlReadIoPort (Extension, ATA_TASK_STAT_REG ) & ATA_ST_BUSY ) ) { break ; } }
if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) ) { // as the busy has been found permanently set, we check
// for the slave also
continue; }
// as the drive head setup might have been performed in a busy state,
// we set it up again after busy clears.
ParStlWriteIoPort(Extension, ATA_DRVHD_REG, nDrvHdArray[nCurrentDrive]);
if ( ( ParStlReadIoPort(Extension, ATA_DRVHD_REG) & ATAPI_SLAVE ) != nDrvHdArray[nCurrentDrive] ) { continue ; }
// read original contents of the cyl ATA high/low registers
byOrgCylLow = (UCHAR) ParStlReadIoPort(Extension, ATA_CYLLOW_REG); byOrgCylHigh = (UCHAR) ParStlReadIoPort(Extension, ATA_CYLHIGH_REG);
// write a test pattern in the cyl ATA high/low registers
ParStlWriteIoPort(Extension, ATA_CYLLOW_REG, TEST_PATTERN_1); ParStlWriteIoPort(Extension, ATA_CYLHIGH_REG, TEST_PATTERN_2);
// read the test pattern in the cyl ATA high/low registers
if ( ( TEST_PATTERN_1 != ParStlReadIoPort(Extension, ATA_CYLLOW_REG) ) ||\ ( TEST_PATTERN_2 != ParStlReadIoPort(Extension, ATA_CYLHIGH_REG) ) ) { // as we were not able to read back the written values
// we break out here, indicating the absence of the device
continue ; }
// write back original contents in the cyl ATA high/low registers
ParStlWriteIoPort(Extension, ATA_CYLLOW_REG, byOrgCylLow); ParStlWriteIoPort(Extension, ATA_CYLHIGH_REG, byOrgCylHigh); bReturnValue = TRUE ; atapiParams->dsDeviceState[nCurrentDrive] = DEVICE_STATE_VALID ; } while ( ++nCurrentDrive < ATAPI_MAX_DRIVES );
// reset back to master state, as check drive present
// will be called successively
ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_MASTER);
return bReturnValue ; }
BOOLEAN ParStlAtapiInitialize ( IN PDEVICE_EXTENSION Extension, IN OUT PATAPIPARAMS atapiParams ) { BOOLEAN bReturnValue = FALSE ; int nCurrentDrive = 0, i ; UCHAR byTempValue ; UCHAR chAtapiIdentifyBuffer [ ATAPI_IDENTIFY_LENGTH ] ; do { if ( DEVICE_STATE_VALID != atapiParams->dsDeviceState[nCurrentDrive] ) { // the device is absent
continue ; }
if ( nCurrentDrive ) { // as it is the next drive, choose the slave
ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_SLAVE); } else { // choose the master
ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_MASTER); }
if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) ) { // as busy has permanently set after master/slave, we fail
// the detection process
continue ; }
// check if the ATAPI signature is present in the cyl hi/lo
// registers. If present, it is definitely an ATAPI device
if ( ( ParStlReadIoPort(Extension, ATA_CYLLOW_REG) == ATAPI_SIGN_LOW ) &&\ ( ParStlReadIoPort(Extension, ATA_CYLHIGH_REG) == ATAPI_SIGN_HI ) ) { // as ATAPI signature is present, it is ATAPI type
bReturnValue = TRUE ;
// set this flag so that, ATA initialize will skip this
// target
atapiParams->dsDeviceState[nCurrentDrive] = DEVICE_STATE_ATAPI ; // for Impact, since Ls120 engine is always present,
// issuing ATAPI_IDENTIFY is mandatory.
if ( !IsImpactPresent()) { continue ; } }
// issue the ata nop command
ParStlWriteIoPort(Extension, ATA_TASK_CMD_REG, ATA_NOP_COMMAND) ;
if ( FALSE == ParStlWaitForIrq(Extension) ) { // ATAPI devices are expected to give interrrupt on NOP command
// mandatorily.
continue ; } if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) ) { // as busy has permanently set, we proceed with the next
// drive
continue ; }
// issue the atapi packet command
ParStlWriteIoPort(Extension, ATA_TASK_CMD_REG, ATAPI_IDENTIFY) ;
if ( FALSE == ParStlWaitForIrq(Extension) ) { // ATAPI devices are expected to give interrrupt on 0xA1 command
// mandatorily.
continue ; } if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) ) { // as busy has permanently set, we proceed with the next
// drive
continue ; }
byTempValue = (UCHAR) ParStlReadIoPort ( Extension, ATA_TASK_STAT_REG ) ; if ( ! ( byTempValue & ATA_ST_ERROR ) ) { // as the drive has passed the packet command, this is an atapi
// drive
// Wait for DRQ to be sit, as some drives are known
// to remove busy too early and set DRQ after some time.
if ( FALSE == ParStlWaitForDrq(Extension) ) { // as there was no DRQ set, we proceed with the next
// drive
continue ; } bReturnValue = TRUE ; // as the DRQ is still asserted, quell it, as certain ATA/ATAPI-4
// spec. dictates it so
// There is a need to check the device identifier returned in the
// ATAPI Identify cmd. to determine the presence of Ls-120.
ParStlReceiveData ( Extension, chAtapiIdentifyBuffer , SKIP_MEMORY_ADDRESS , ATAPI_IDENTIFY_LENGTH ) ; for ( i = 0 ; i < ATAPI_NAME_LENGTH ; i++ ) { atapiParams->szAtapiNameString[i] = chAtapiIdentifyBuffer[ ATAPI_NAME_OFFSET + i ] ; }
// set this flag so that, ATA initialize will skip this
// target
atapiParams->dsDeviceState[nCurrentDrive] = DEVICE_STATE_ATAPI ; } } while ( ++nCurrentDrive < ATAPI_MAX_DRIVES );
// reset back to master state, as check drive present
// will be called successively
ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_MASTER);
return ( bReturnValue ) ; }
BOOLEAN ParStlAtaInitialize ( IN PDEVICE_EXTENSION Extension, IN OUT PATAPIPARAMS atapiParams ) { BOOLEAN bReturnValue = FALSE ; UCHAR byTempValue ; int nCurrentDrive = 0 ; do { if ( DEVICE_STATE_VALID != atapiParams->dsDeviceState[nCurrentDrive] ) { // atapi module has marked its presence or the device is absent
continue ; }
// select the possibly present device
if ( nCurrentDrive ) { ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_SLAVE ) ; } else { ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_MASTER ) ; }
if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) ) { // as busy has permanently set after master/slave, we fail the
// detection process
continue ; }
// issue the ata NOP command
ParStlWriteIoPort(Extension, ATA_TASK_CMD_REG, ATA_NOP_COMMAND) ;
if ( FALSE == ParStlWaitForBusyToClear(Extension, ATA_TASK_STAT_REG) ) { // as busy has permanently set, we fail the detection process
continue ; }
byTempValue = (UCHAR) ParStlReadIoPort ( Extension, ATA_TASK_STAT_REG ) ; if ( ( byTempValue != BUS_LINES_IN_HIGH_IMPEDANCE ) &&\ ( byTempValue & ATA_ST_ERROR ) ) { // as the bus is not reading 0xFF and the status register
// indicates an error, this is likely to be an ATA device
if ( ATA_ERROR_ABORTED_COMMAND == ( (UCHAR) ParStlReadIoPort ( Extension, ATA_ERROR_REG ) & 0x0F ) ) { // as the error register, contains the ata aborted error
// in response to our ATA NOP command, we conclude that
// it is ATA! as it is already known that it is not ATAPI
bReturnValue = TRUE ; break; } } } while ( ++nCurrentDrive < ATAPI_MAX_DRIVES );
// reset back to master state, as check drive present
// will be called successively
ParStlWriteIoPort(Extension, ATA_DRVHD_REG, ATAPI_MASTER);
return ( bReturnValue ) ; }
BOOLEAN ParStlWaitForBusyToClear ( IN PDEVICE_EXTENSION Extension, IN int nRegisterToWaitOn ) { // The default timeout increased to 10secs as Fujitsu MO is found to set
// BUSY for >5secs for 0xA1 command.
int nMaxRetrials = MAX_RETRIES_FOR_10_SECS ; BOOLEAN bRetVal = FALSE ;
while ( nMaxRetrials-- ) { // the following service will be implemented by the caller
// the driver can use the STLMPORT service.
ParStlWaitForMicroSeconds ( DELAY_1MILLISECONDS ) ; if ( ! ( ParStlReadIoPort ( Extension, nRegisterToWaitOn ) & ATA_ST_BUSY ) ) { // as busy has cleared, we return clear here
bRetVal = TRUE ; break ; } } return bRetVal ; }
BOOLEAN ParStlWaitForDrq ( IN PDEVICE_EXTENSION Extension ) { int nMaxRetrials = MAX_RETRIES_FOR_5_SECS ; BOOLEAN bRetVal = FALSE ; while ( nMaxRetrials-- ) { if ( ParStlReadIoPort ( Extension, ATA_TASK_STAT_REG ) & ATA_ST_DRQ ) { // as busy has cleared, we return clear here
bRetVal = TRUE ; break ; } // the following service will be implemented by the caller
// the driver can use the STLMPORT service.
ParStlWaitForMicroSeconds ( DELAY_1MILLISECONDS ) ; } return bRetVal ; }
BOOLEAN ParStlWaitForIrq ( IN PDEVICE_EXTENSION Extension ) { int nMaxRetrials = MAX_RETRIES_FOR_10_SECS ; BOOLEAN bRetVal = FALSE ; while ( nMaxRetrials-- ) { if ( ParStlReadReg ( Extension, EP1284_TRANSFER_CONTROL_REG ) & XFER_IRQ_BIT ) { // as Irq has asserted, we return true here
bRetVal = TRUE ; break ; } ParStlWaitForMicroSeconds ( DELAY_1MILLISECONDS ) ; } return bRetVal ; }
VOID ParStlSet16BitOperation ( IN PDEVICE_EXTENSION Extension ) { int nModeReg ;
nModeReg = ParStlReadReg ( Extension, EP1284_MODE_REGISTER ) ;
if ( 0 == ( nModeReg & EP1284_ENABLE_16BIT ) ) { // as the bit is not already set, this needs to be set now
ParStlWriteReg ( Extension, EP1284_MODE_REGISTER, nModeReg | EP1284_ENABLE_16BIT ) ; } }
BOOLEAN ParStlCheckIfEppDevice ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE; do { if ( FALSE == IsEp1284Present() ) { // as EPPDEVs live only on EP1284 we break here
break; }
bReturnValue = ParStlCheckPersonalityForEppDevice(Extension) ; } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckPersonalityForEppDevice ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE ;
ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER, EP1284_PERSONALITY_REG ) ; if ( EPPDEV_SIGN == ( ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) & PERSONALITY_MASK ) ) { // as the EPPDEV sign is found in the personality
// we break with success here
bReturnValue = TRUE ; }
return bReturnValue ; }
BOOLEAN ParStlCheckIfFlash ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE ;
do { if ( !IsEp1284Present() && !IsImpactPresent() && !IsEpatPlusPresent() ) { // Check the sign-on version checks for the existence of Shuttle
// adapter. If nothing is found, we break here.
break ; }
// Perform a ATA-16bit check just in case, it turns out to be something else
bReturnValue = ParStlCheckFlashPersonality(Extension) ; } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckFlashPersonality ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE ;
if ( IsEp1284Present() ) { // as the personality configuration check only works for
// Ep1284, confim its presence before the actual check.
ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER, EP1284_PERSONALITY_REG ) ; if ( FLASH_SIGN == ( ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) & FLASH_PERSONALITY_MASK ) ) { // as the flash sign ATA-16bit device is found in the personality
// we break with success here
bReturnValue = TRUE ; } } else { // always return true, if a shuttle adapter other than ep1284 is
// identified and assume it might be flash!
bReturnValue = TRUE ; }
return bReturnValue ; }
BOOLEAN ParStlCheckIfDazzle ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE ; UCHAR ucSignature ;
do { if ( !IsEp1284Present() ) { // Check for EP1284 presence, as Dazzle is ONLY on EP1284
// adapters. If the adapter is not EP1284, we break.
break ; }
// Check whether any card insertion is detected, to eliminate
// possible flash adapters with the card in
if ( TRUE == ParStlCheckCardInsertionStatus( Extension ) ) { break ; }
// code to read the pulled up pattern present on dazzle
// adapters.
ParStlWriteReg( Extension, DAZ_SELECT_BLK, DAZ_BLK0 ) ; ucSignature = (UCHAR) ParStlReadReg( Extension, DAZ_REG1 ) ;
if ( ( ucSignature == DAZ_CONFIGURED ) ||\ ( ucSignature == DAZ_NOT_CONFIGURED ) ) { // the pulled up pattern generally found ONLY
// on the DAZZLE adapter is found. So, we
// conclude that it is a Dazzle adapter
bReturnValue = TRUE ; }
} while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckIfHiFD ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE;
do { if ( FALSE == ParStlSelectAdapterSocket(Extension, SOCKET_1) ) { // as the socket 1 selection failed,
// we break out here.
break ; }
// check for the ready status of the floppy controller,
// after clearing the reset bit of the floppy controller.
if ( FALSE == ParStlHIFDCheckIfControllerReady(Extension) ) { // since the controller didnot wake up after the
// reset pin was asserted, we break here.
break ; }
if ( FALSE == ParStlHIFDCheckSMCController(Extension) ) { // as the SMC ID retrieval failed,
// we break out here.
break ; }
bReturnValue = TRUE ;
} while ( FALSE ) ; // Reset the socket to zero.
ParStlSelectAdapterSocket(Extension, SOCKET_0); return bReturnValue ; }
BOOLEAN ParStlHIFDCheckIfControllerReady ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE ; UCHAR bySCRControlReg ; do { ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER , SOCKET_CONTROL_REGISTER ) ; bySCRControlReg = (UCHAR) ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) ; bySCRControlReg |= (UCHAR)PERIPHERAL_RESET_1 ; ParStlWriteReg ( Extension, CONFIG_DATA_REGISTER , bySCRControlReg ) ; ParStlWaitForMicroSeconds ( HIFD_WAIT_10_MILLISEC ) ;
ParStlWriteIoPort ( Extension, HIFD_DIGITAL_OUTPUT_REGISTER , 0x00 ) ; ParStlWaitForMicroSeconds ( HIFD_WAIT_1_MILLISEC ) ;
ParStlWriteIoPort ( Extension, HIFD_DIGITAL_OUTPUT_REGISTER , HIFD_DOR_RESET_BIT | HIFD_ENABLE_DMA_BIT ) ; ParStlWaitForMicroSeconds ( HIFD_WAIT_10_MILLISEC ) ;
if ( HIFD_CONTROLLER_READY_STATUS == ParStlReadIoPort ( Extension, HIFD_MAIN_STATUS_REGISTER ) ) { bReturnValue = TRUE ; }
bySCRControlReg &= ~(UCHAR)PERIPHERAL_RESET_1 ; ParStlWriteReg ( Extension, CONFIG_DATA_REGISTER , bySCRControlReg ) ;
} while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlHIFDCheckSMCController ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE ; do { ParStlWriteIoPort ( Extension, HIFD_STATUS_REGISTER_A , HIFD_COMMAND_TO_CONTROLLER ) ; ParStlWriteIoPort ( Extension, HIFD_STATUS_REGISTER_A , HIFD_COMMAND_TO_CONTROLLER ) ; ParStlWriteIoPort ( Extension, HIFD_STATUS_REGISTER_A , HIFD_CTL_REG_0D ) ; if ( SMC_DEVICE_ID == ParStlReadIoPort ( Extension, HIFD_STATUS_REGISTER_B ) ) { bReturnValue = TRUE ; ParStlWriteIoPort ( Extension, HIFD_STATUS_REGISTER_A , HIFD_CTL_REG_03 ) ; ParStlWriteIoPort ( Extension, HIFD_STATUS_REGISTER_B , SMC_ENABLE_MODE2 ) ; } ParStlWriteReg ( Extension, HIFD_STATUS_REGISTER_A , HIFD_TERMINATE_SEQUENCE ) ;
} while ( FALSE ) ;
return bReturnValue ; }
STL_DEVICE_TYPE ParStlGetImpactDeviceType ( IN PDEVICE_EXTENSION Extension, IN OUT PATAPIPARAMS atapiParams, IN int nPreferredDeviceType ) { IMPACT_DEVICE_TYPE idtImpactDeviceType ; STL_DEVICE_TYPE dtDeviceType = DEVICE_TYPE_NONE ; int nLocalPreferredDeviceType = nPreferredDeviceType ;
ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER, IMPACT_PERSONALITY_REG ) ; idtImpactDeviceType = ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) >> 4 ;
switch ( idtImpactDeviceType ) { case IMPACT_DEVICE_TYPE_ATA_ATAPI:
// set the 16 bit mode of the adapter
ParStlSet16BitOperation(Extension) ;
if (TRUE == ParStlCheckIfAtaAtapiDevice(Extension,atapiParams)) { // necessary but not sufficient condition has passed
// proceed for sufficency checks
if (TRUE == ParStlCheckIfAtapiDevice(Extension,atapiParams)) { // atapi identified
// Check for Impact LS-120 device
if ( TRUE == ParStlCheckIfImpactLS120(Extension, atapiParams)) { dtDeviceType |= DEVICE_TYPE_LS120_BIT ; break ; } dtDeviceType |= DEVICE_TYPE_ATAPI_BIT; break ; }
if (TRUE == ParStlCheckIfAtaDevice(Extension, atapiParams)) { // ata identified
dtDeviceType |= DEVICE_TYPE_ATA_BIT; break; } } break ;
case IMPACT_DEVICE_TYPE_CF: dtDeviceType |= DEVICE_TYPE_FLASH_BIT; break ;
case IMPACT_DEVICE_TYPE_PCMCIA_CF: dtDeviceType |= DEVICE_TYPE_PCMCIA_CF_BIT ; break;
case IMPACT_DEVICE_TYPE_SSFDC: dtDeviceType |= DEVICE_TYPE_SSFDC_BIT ; break;
case IMPACT_DEVICE_TYPE_MMC: dtDeviceType |= DEVICE_TYPE_MMC_BIT ; break;
case IMPACT_DEVICE_TYPE_HIFD: dtDeviceType |= DEVICE_TYPE_HIFD_BIT ; break;
case IMPACT_DEVICE_TYPE_SOUND: dtDeviceType |= DEVICE_TYPE_SOUND_BIT ; break;
case IMPACT_DEVICE_TYPE_FLP_TAPE_DSK: dtDeviceType |= DEVICE_TYPE_FLP_TAPE_DSK_BIT ; break;
case IMPACT_DEVICE_TYPE_ATA_ATAPI_8BIT: dtDeviceType |= DEVICE_TYPE_ATA_ATAPI_8BIT_BIT ; break;
default: break; }
return dtDeviceType & nPreferredDeviceType ; }
STL_DEVICE_TYPE ParStlGetImpactSDeviceType ( IN PDEVICE_EXTENSION Extension, IN OUT PATAPIPARAMS atapiParams, IN int nPreferredDeviceType ) { IMPACT_DEVICE_TYPE idtImpactDeviceType ; IMPACT_DEVICE_TYPE idtImpactSDeviceType ; STL_DEVICE_TYPE dtDeviceType = DEVICE_TYPE_NONE ; int nLocalPreferredDeviceType = nPreferredDeviceType ;
ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER, IMPACT_PERSONALITY_REG ) ; idtImpactDeviceType = ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) >> 4 ;
switch ( idtImpactDeviceType ) { case IMPACT_DEVICE_TYPE_ATA_ATAPI:
// set the 16 bit mode of the adapter
ParStlSet16BitOperation(Extension) ;
if (TRUE == ParStlCheckIfAtaAtapiDevice(Extension,atapiParams)) { // necessary but not sufficient condition has passed
// proceed for sufficency checks
if (TRUE == ParStlCheckIfAtapiDevice(Extension,atapiParams)) { // atapi identified
dtDeviceType |= DEVICE_TYPE_ATAPI_BIT; break ; }
if (TRUE == ParStlCheckIfAtaDevice(Extension,atapiParams)) { // ata identified
dtDeviceType |= DEVICE_TYPE_ATA_BIT; break; } } break ;
case IMPACT_DEVICE_TYPE_CF: dtDeviceType |= DEVICE_TYPE_FLASH_BIT; break ;
case IMPACT_DEVICE_TYPE_PCMCIA_CF: dtDeviceType |= DEVICE_TYPE_PCMCIA_CF_BIT ; break;
case IMPACT_DEVICE_TYPE_SSFDC: dtDeviceType |= DEVICE_TYPE_SSFDC_BIT ; break;
case IMPACT_DEVICE_TYPE_MMC: dtDeviceType |= DEVICE_TYPE_MMC_BIT ; break;
case IMPACT_DEVICE_TYPE_HIFD: dtDeviceType |= DEVICE_TYPE_HIFD_BIT ; break;
case IMPACT_DEVICE_TYPE_SOUND: dtDeviceType |= DEVICE_TYPE_SOUND_BIT ; break;
case IMPACT_DEVICE_TYPE_FLP_TAPE_DSK: dtDeviceType |= DEVICE_TYPE_FLP_TAPE_DSK_BIT ; break;
case IMPACT_DEVICE_TYPE_ATA_ATAPI_8BIT: dtDeviceType |= DEVICE_TYPE_ATA_ATAPI_8BIT_BIT ; break;
case IMPACTS_EXT_PERSONALITY_PRESENT: ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER, IMPACTS_EXT_PERSONALITY_XREG ) ; idtImpactSDeviceType = ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) ; dtDeviceType = DEVICE_TYPE_EXT_HWDETECT ; dtDeviceType |= idtImpactSDeviceType ; break ;
default: break; }
return dtDeviceType & nPreferredDeviceType ; }
BOOLEAN ParStlCheckIfLS120 ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE; do { if ( FALSE == ParStlSelectAdapterSocket(Extension, SOCKET_1) ) { // as the socket 1 selection failed,
// we break out here.
break ; }
// check for engine version.
if ( LS120_ENGINE_VERSION == ParStlReadIoPort( Extension, LS120_ENGINE_VERSION_REGISTER ) ) { // if the ls120 engine version is correct, we have
// found LS120.
bReturnValue = TRUE ; }
// Reset the socket to zero.
ParStlSelectAdapterSocket ( Extension, SOCKET_0 ) ; } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckIfImpactLS120 ( IN PDEVICE_EXTENSION Extension, IN OUT PATAPIPARAMS atapiParams ) { BOOLEAN bReturnValue = FALSE ; BOOLEAN bLs120NameFound= TRUE ; char chLs120Name[] = "HU DlFpoyp"; char *pszAtapiName = atapiParams->szAtapiNameString ; int i , nMemoryOnBoard ;
do { for ( i = 0 ;i < sizeof(chLs120Name)-1 ; i++ ) { if ( pszAtapiName[i] != chLs120Name[i] ) { bLs120NameFound = FALSE ; break ; } } if ( TRUE != bLs120NameFound ) { // as LS-120 name string is not found, we conclude that it is
// not LS-120
break ; } nMemoryOnBoard = ParStlGetMemorySize(Extension) ; if ( ( !IsShtlError ( nMemoryOnBoard ) ) && \ ( nMemoryOnBoard ) ) { // there is memory on-board.
// hence, we return ls120 here
bReturnValue = TRUE ; break ; } } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckIfMMC ( IN PDEVICE_EXTENSION Extension, IN OUT PATAPIPARAMS atapiParams ) { BOOLEAN bReturnValue = FALSE;
do { if ( FALSE == IsEpatPlusPresent() ) { // as mmc device can exist only on EPAT Plus adapter only
// we break out of here
break; } if ( TRUE == ParStlCheckIfAtaAtapiDevice (Extension,atapiParams) ) { // as an ATA/ATAPI device is probably present,
// we break out of here
break; } bReturnValue = ParStlIsMMCEnginePresent(Extension) ; } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlIsMMCEnginePresent( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE;
do { // check if the ATAPI signature is present in the cyl hi/lo
// registers. If present, it is definitely an ATAPI device
if ( ( ParStlReadIoPort(Extension, CYLLOW_REG) == ATAPI_SIGN_LOW ) &&\ ( ParStlReadIoPort(Extension, CYLHIGH_REG) == ATAPI_SIGN_HI ) ) { // as ATAPI signature is present, it cant be MMC
break ; }
// write a zero pattern ( which will be a NOP for ATA/ATAPI devices )
// in the block size / possible ATA/ATAPI command register
ParStlWriteReg(Extension, MMC_ENGINE_INDEX, MMC_BLOCK_SIZE_REG); ParStlWriteReg(Extension, MMC_ENGINE_DATA, MMC_TEST_PATTERN_1); if ( MMC_TEST_PATTERN_1 != ParStlReadReg(Extension, MMC_ENGINE_DATA) ) { // as the written value is not available, it means device present
// has responded to the written value, in a way different from
// how an MMC would have.
break ; }
// write a test pattern in the freq register
ParStlWriteReg(Extension, MMC_ENGINE_INDEX, MMC_FREQ_SELECT_REG); ParStlWriteReg(Extension, MMC_ENGINE_DATA, MMC_TEST_PATTERN_2);
// write another in the block size register
ParStlWriteReg(Extension, MMC_ENGINE_INDEX, MMC_BLOCK_SIZE_REG); ParStlWriteReg(Extension, MMC_ENGINE_DATA, MMC_TEST_PATTERN_3);
ParStlWriteReg(Extension, MMC_ENGINE_INDEX, MMC_FREQ_SELECT_REG); if ( MMC_TEST_PATTERN_2 != ParStlReadReg(Extension, MMC_ENGINE_DATA) ) { // as we were not able to read back the written value
// we quit here
break; }
ParStlWriteReg(Extension, MMC_ENGINE_INDEX, MMC_BLOCK_SIZE_REG); if ( MMC_TEST_PATTERN_3 != ParStlReadReg(Extension, MMC_ENGINE_DATA) ) { // as we were not able to read back the written value
// we quit here
break; } // as all tests have passed, engine presence is confirmed
// here
bReturnValue = TRUE ; } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckIfScsiDevice ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE; do { if ( FALSE == IsEpstPresent() ) { // as SCSI devices live only on EPST we break here
break; }
bReturnValue = TRUE ; } while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckIfSSFDC ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE; UCHAR byMakerCode = 0x00 , byDeviceCode = 0x00 ; do { if ( FALSE == IsEp1284Present() ) { // SSFDC lives on EP1284 alone, other than impact
// which is already taken care
break; }
//check to see if the loop back of the EPCS and EPDO pins
//of the INDEX 00 register read the same. If so, it is
//SSFDC board characteristic
ParStlWriteReg ( Extension, CONFIG_INDEX_REGISTER , 0x00 ) ; ParStlWriteReg ( Extension, CONFIG_DATA_REGISTER , 0x10 ) ; ParStlWriteReg ( Extension, CONFIG_DATA_REGISTER , 0x12 ) ; if ( 0x1A == ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) ) { ParStlWriteReg ( Extension, CONFIG_DATA_REGISTER , 0x10 ) ; if ( ! ( ParStlReadReg ( Extension, CONFIG_DATA_REGISTER ) & 0x08 ) ) { //as they are equal, SSFDC present
bReturnValue = TRUE ; break ; } }
} while ( FALSE ) ;
return bReturnValue ; }
VOID ParStlAssertIdleState ( IN PDEVICE_EXTENSION Extension ) { PUCHAR CurrentPort, CurrentControl ; ULONG Delay = 5 ;
CurrentPort = Extension->Controller; CurrentControl = CurrentPort + 2;
// place op-code for idle state in port base
WRITE_PORT_UCHAR ( CurrentPort, (UCHAR) 0x00 ) ; KeStallExecutionProcessor( Delay );
// bring down DCR_INIT and DCR_STROBE
WRITE_PORT_UCHAR ( CurrentControl, (UCHAR) STB_INIT_LOW ) ; KeStallExecutionProcessor( Delay );
// lift DCR_INIT and DCR_STROBE to high
WRITE_PORT_UCHAR ( CurrentControl, (UCHAR) STB_INIT_AFXT_HI ) ; KeStallExecutionProcessor( Delay ); }
BOOLEAN ParStlCheckAvisionScannerPresence( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE ; UCHAR data;
do {
data = (UCHAR) ParStlReadReg( Extension, STATUSPORT); if((data & 0x80) == 0) { break ; }
ParStlWriteReg( Extension, CONTROLPORT, 0x08 ) ; ParStlWriteReg( Extension, CONTROLPORT, 0x08 ) ;
data = (UCHAR) ParStlReadReg( Extension, STATUSPORT); if((data & 0x80) != 0) { break ; }
ParStlWriteReg( Extension, CONTROLPORT, 0x00 ) ; ParStlWriteReg( Extension, CONTROLPORT, 0x00 ) ;
data = (UCHAR) ParStlReadReg( Extension, STATUSPORT); if((data & 0x80) == 0) { break ; }
ParStlWriteReg( Extension, CONTROLPORT, 0x02 ) ; ParStlWriteReg( Extension, CONTROLPORT, 0x02 ) ;
data = (UCHAR) ParStlReadReg( Extension, STATUSPORT); if((data & 0x80) != 0) { break ; }
ParStlWriteReg( Extension, CONTROLPORT, 0x00 ) ; ParStlWriteReg( Extension, CONTROLPORT, 0x00 ) ;
data = (UCHAR) ParStlReadReg( Extension, STATUSPORT); if((data & 0x80) == 0) { break ; }
bReturnValue = TRUE ;
} while ( FALSE ) ;
return bReturnValue ; }
BOOLEAN ParStlCheckUMAXScannerPresence( IN PDEVICE_EXTENSION Extension ) { UCHAR commandPacket_[6] = {0x55,0xaa,0,0,0,0} ; PUCHAR commandPacket ; USHORT status; UCHAR idx; PUCHAR saveCommandPacket; ULONG dataLength;
ParStlWriteReg ( Extension, CONTROLPORT, 0 ) ; // scannner reset
KeStallExecutionProcessor ( 2000 ) ; // 2 m.secs delay
ParStlWriteReg ( Extension, CONTROLPORT, 0x0C ) ;
commandPacket = commandPacket_ ; saveCommandPacket = commandPacket;
if ( TRUE == ParStlSetEPPMode(Extension) ) {
commandPacket+=2; dataLength = *(ULONG*)commandPacket; dataLength &= 0xffffff; //data bytes ordering (msb to lsb) will
// wrong .What we need here is whether the
// dataLength is 0 or not.
commandPacket = saveCommandPacket;
//Command phase
status = ParStlEPPWrite(Extension, *(commandPacket)++); if((status & 0x700) != 0){ return FALSE; //TIMEOUT_ERROR);
}
status = ParStlEPPWrite(Extension, *(commandPacket)++); if((status & 0x700 ) != 0){ return FALSE; //TIMEOUT_ERROR);
}
for(idx=0; idx<= 6 ;idx++){
if(status & 0x800){ break; }
status = ParStlEPPRead(Extension); }
if(idx == 7){
status = (status & 0xf800) | 0x100; if ( status & 0x700 ) return FALSE; }
status = ParStlEPPWrite(Extension, *(commandPacket)++); if((status & 0x700 ) != 0){ return FALSE; //TIMEOUT_ERROR);
}
status = ParStlEPPWrite(Extension, *(commandPacket)++); if((status & 0x700 ) != 0){ return FALSE; //TIMEOUT_ERROR);
}
status = ParStlEPPWrite(Extension, *(commandPacket)++); if((status & 0x700 ) != 0){ return FALSE; //TIMEOUT_ERROR);
}
status = ParStlEPPWrite(Extension, *commandPacket); if((status & 0x700 ) != 0){ return FALSE; //TIMEOUT_ERROR);
}
//Response phase
status = ParStlEPPRead(Extension); commandPacket = saveCommandPacket;
if((status & 0x700) == 0){
if((commandPacket[5] == 0xc2)&& (dataLength == 0)){
status = ParStlEPPRead(Extension);
if((status & 0x0700) != 0){ return FALSE; //TIMEOUT_ERROR);
} } }
return TRUE; } return FALSE; }
BOOLEAN ParStlSetEPPMode( IN PDEVICE_EXTENSION Extension ) { UCHAR idx; BOOLEAN timeout = TRUE ;
ParStlWriteReg( Extension, CONTROLPORT, 0x0C ) ; ParStlWriteReg( Extension, DATAPORT, 0x40 ) ; ParStlWriteReg( Extension, CONTROLPORT, 0x06 ) ;
for(idx=0; idx<10; idx++){
if((ParStlReadReg(Extension, STATUSPORT) & 0x78) == 0x38){
timeout = FALSE; break;
}
}
if(timeout == FALSE){
ParStlWriteReg( Extension, CONTROLPORT,0x7 ); timeout = TRUE;
for(idx=0; idx<10; idx++){
if((ParStlReadReg( Extension, STATUSPORT) & 0x78) == 0x38){ timeout = FALSE; break; }
}
if(timeout == FALSE){
ParStlWriteReg( Extension, CONTROLPORT,0x4 ) ; timeout = TRUE;
for(idx=0; idx<10; idx++){
if((ParStlReadReg( Extension, STATUSPORT) & 0xf8) == 0xf8){ timeout = FALSE; break; }
}
if(timeout == FALSE){
timeout = TRUE;
ParStlWriteReg( Extension, CONTROLPORT, 0x5 );
for(idx=0; idx<10; idx++){
if( ParStlReadReg( Extension, CONTROLPORT ) == 0x5){
timeout = FALSE; break;
} }
if(timeout == FALSE){
ParStlWriteReg( Extension, CONTROLPORT, 0x84) ; return TRUE ;
} // final check
} // third check
} // second check
} // first check
return(FALSE); }
USHORT ParStlEPPWrite( IN PDEVICE_EXTENSION Extension, IN UCHAR value ) { UCHAR idx; USHORT statusData; BOOLEAN timeout;
timeout = TRUE;
for(idx=0; idx<10; idx++){
if( !( (statusData = (USHORT)ParStlReadReg( Extension, STATUSPORT)) & BUSY)){ timeout = FALSE; break; }
}
if(timeout == TRUE){
return(((statusData<<8) & 0xf800)|0x100);
}
ParStlWriteReg( Extension, EPPDATA0PORT,value ); return(((statusData & 0xf8) << 8)|value); }
USHORT ParStlEPPRead( IN PDEVICE_EXTENSION Extension ) { UCHAR idx; USHORT statusData; USHORT controlData; UCHAR eppData; BOOLEAN timeout = TRUE ;
for(idx=0; idx<10; idx++){
if(!( (statusData = (USHORT)ParStlReadReg( Extension, STATUSPORT)) & PE)){ timeout = FALSE; break; }
}
if(timeout == TRUE){
return(((statusData<<8) & 0xf800)|0x100);
}
eppData = (UCHAR)ParStlReadReg( Extension, EPPDATA0PORT) ; return(((statusData & 0x00f8)<<8) | eppData ); }
int __cdecl ParStlReadReg ( IN PDEVICE_EXTENSION Extension, IN unsigned reg ) { UCHAR byReadNibble ; PUCHAR CurrentPort, CurrentStatus, CurrentControl ; ULONG Delay = 5 ;
CurrentPort = Extension->Controller; CurrentStatus = CurrentPort + 1; CurrentControl = CurrentPort + 2;
// select the register to read
WRITE_PORT_UCHAR ( CurrentPort, (UCHAR)reg ) ; KeStallExecutionProcessor( Delay );
// issue nibble ctl signals to read
WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_LOW ) ; KeStallExecutionProcessor( Delay ); WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_AFXT_LO ) ; KeStallExecutionProcessor( Delay );
// read first nibble
byReadNibble = READ_PORT_UCHAR (CurrentStatus); KeStallExecutionProcessor( Delay ); byReadNibble >>= 4 ;
// issue nibble ctl signals to read
WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_AFXT_HI ) ; KeStallExecutionProcessor( Delay );
// read next nibble
byReadNibble |= ( READ_PORT_UCHAR ( CurrentStatus ) & 0xF0 ) ;
return (int)byReadNibble ; }
int __cdecl ParStlWriteReg ( IN PDEVICE_EXTENSION Extension, IN unsigned reg, IN int databyte ) { PUCHAR CurrentPort, CurrentStatus, CurrentControl ; ULONG Delay = 5 ;
CurrentPort = Extension->Controller; CurrentStatus = CurrentPort + 1; CurrentControl = CurrentPort + 2;
// select the register to write
WRITE_PORT_UCHAR ( CurrentPort, (UCHAR)( reg | 0x60 ) ) ; KeStallExecutionProcessor( Delay );
// write to printer ctl port
WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_LOW ) ; KeStallExecutionProcessor( Delay );
// write the requested data
WRITE_PORT_UCHAR ( CurrentPort, (UCHAR)databyte ) ; KeStallExecutionProcessor( Delay );
// write to printer ctl port
WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_AFXT_HI ) ; KeStallExecutionProcessor( Delay );
return SHTL_NO_ERROR ; }
int __cdecl ParStlReceiveData ( IN PDEVICE_EXTENSION Extension, IN VOID *hostBufferPointer, IN long shuttleMemoryAddress, IN unsigned count ) { PCHAR pchDataBuffer = (PCHAR) hostBufferPointer ; unsigned int i = 0 ; PUCHAR CurrentPort, CurrentStatus, CurrentControl ; ULONG Delay = 5 ;
CurrentPort = Extension->Controller; CurrentStatus = CurrentPort + 1; CurrentControl = CurrentPort + 2;
// set the block address register to ATA/ATAPI data register,
// as this function is currently used ONLY for ATA/ATAPI devices
// ATA/ATAPI data register 0x1F0 corresponds to 0x18 value
ParStlWriteReg ( Extension, EP1284_BLK_ADDR_REGISTER, 0x18 ) ;
// do the nibble block read sequence
// write the nibble block read op-code
WRITE_PORT_UCHAR ( CurrentPort, OP_NIBBLE_BLOCK_READ ) ; KeStallExecutionProcessor( Delay );
// set control ports to correct signals.
WRITE_PORT_UCHAR ( CurrentControl, STB_INIT_AFXT_LO ) ; KeStallExecutionProcessor( Delay );
// set data port to 0xFF
WRITE_PORT_UCHAR ( CurrentPort, 0xFF ) ; KeStallExecutionProcessor( Delay ); WRITE_PORT_UCHAR ( CurrentControl, INIT_AFXT_HIGH ) ; KeStallExecutionProcessor( Delay );
do { // low nibble is available in status after
// toggling sequences as in EP1284 manual
WRITE_PORT_UCHAR ( CurrentControl, AFXT_LO_STB_HI ) ; KeStallExecutionProcessor( Delay ); pchDataBuffer[i] = READ_PORT_UCHAR( CurrentStatus ) >> 4 ; KeStallExecutionProcessor( Delay );
// high nibble is available in status after
// toggling sequences as in EP1284 manual
WRITE_PORT_UCHAR ( CurrentControl, AFXT_HI_STB_HI ) ; KeStallExecutionProcessor( Delay );
pchDataBuffer[i++] |= ( READ_PORT_UCHAR ( CurrentStatus ) & 0xF0 ) ; KeStallExecutionProcessor( Delay ); if ( count - 1 == i ) { // to read the last byte
WRITE_PORT_UCHAR ( CurrentPort, 0xFD ) ; KeStallExecutionProcessor( Delay ); }
WRITE_PORT_UCHAR ( CurrentControl, AFXT_LO_STB_LO ) ; KeStallExecutionProcessor( Delay );
pchDataBuffer[i] = READ_PORT_UCHAR ( CurrentStatus ) >> 4 ; KeStallExecutionProcessor( Delay );
WRITE_PORT_UCHAR ( CurrentControl, AFXT_HI_STB_LO ) ; KeStallExecutionProcessor( Delay ); pchDataBuffer[i++] |= ( READ_PORT_UCHAR ( CurrentStatus ) & 0xF0 ) ; KeStallExecutionProcessor( Delay ); } while ( i <= count ) ;
// clean up
WRITE_PORT_UCHAR ( CurrentPort, 0x00 ) ; KeStallExecutionProcessor( Delay );
// done
return SHTL_NO_ERROR ; }
int __cdecl ParStlReadIoPort ( IN PDEVICE_EXTENSION Extension, IN unsigned reg ) { switch ( reg ) { case 0x08 : reg = 0x16 ; break ; case 0x09 : reg = 0x17 ; break ; default : reg |= 0x18 ; break; } return ParStlReadReg ( Extension, reg ) ; }
int __cdecl ParStlWriteIoPort ( IN PDEVICE_EXTENSION Extension, IN unsigned reg, IN int databyte ) { switch ( reg ) { case 0x08 : reg = 0x16 ; break ; case 0x09 : reg = 0x17 ; break ; default : reg |= 0x18 ; break; } return ParStlWriteReg ( Extension, reg, databyte ) ; }
int __cdecl ParStlGetMemorySize ( IN PDEVICE_EXTENSION Extension ) { BOOLEAN bReturnValue = FALSE ; UCHAR byTempValue ; do { // Issue reset through control register
// first try on DRAM
byTempValue = (UCHAR) ParStlReadReg ( Extension, EP1284_CONTROL_REG ) ; byTempValue |= ENABLE_MEM|SELECT_DRAM|RESET_PTR ; ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ; byTempValue &= ~RESET_PTR ; ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
// write to the first location in the memory
ParStlWriteReg ( Extension, EP1284_BUFFER_DATA_REG, TEST_PATTERN_1 ) ; // write to the next location in the memory
ParStlWriteReg ( Extension, EP1284_BUFFER_DATA_REG, TEST_PATTERN_2 ) ;
byTempValue = (UCHAR) ParStlReadReg ( Extension, EP1284_CONTROL_REG ) ; byTempValue |= ENABLE_MEM|SELECT_DRAM|RESET_PTR ; ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ; byTempValue &= ~RESET_PTR ; ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
// read from the first and next location in the memory
if ( ( TEST_PATTERN_1 == (UCHAR) ParStlReadReg ( Extension, EP1284_BUFFER_DATA_REG ) ) &&\ ( TEST_PATTERN_2 == (UCHAR) ParStlReadReg ( Extension, EP1284_BUFFER_DATA_REG ) ) ) { bReturnValue = TRUE ; break ; }
if ( !IsImpactPresent () ) { // as only DRAM can be present on non-impact adapters
break ; } // Issue reset through control register
// and next try on SRAM
byTempValue = (UCHAR) ParStlReadReg ( Extension, EP1284_CONTROL_REG ) ; byTempValue |= ENABLE_MEM|RESET_PTR ; byTempValue &= SELECT_SRAM ; ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ; byTempValue &= ~RESET_PTR ; ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
// write to the first location in the memory
ParStlWriteReg ( Extension, EP1284_BUFFER_DATA_REG, TEST_PATTERN_1 ) ; // write to the next location in the memory
ParStlWriteReg ( Extension, EP1284_BUFFER_DATA_REG, TEST_PATTERN_2 ) ;
byTempValue = (UCHAR) ParStlReadReg ( Extension, EP1284_CONTROL_REG ) ; byTempValue |= ENABLE_MEM|RESET_PTR ; ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ; byTempValue &= ~RESET_PTR ; ParStlWriteReg ( Extension, EP1284_CONTROL_REG, byTempValue ) ;
// read from the first location in the memory
if ( ( TEST_PATTERN_1 == (UCHAR) ParStlReadReg ( Extension, EP1284_BUFFER_DATA_REG ) ) &&\ ( TEST_PATTERN_2 == (UCHAR) ParStlReadReg ( Extension, EP1284_BUFFER_DATA_REG ) ) ) { bReturnValue = TRUE ; break ; } } while ( FALSE ) ; return bReturnValue ; } // end of file
|