📄 daisychain.c
字号:
// check for correct status
status = P5ReadPortUchar( CurrentStatus );
if ( (status & (UCHAR)0xb8 )
== ( DSR_NOT_BUSY | DSR_PERROR | DSR_SELECT | DSR_NOT_FAULT )) {
// continue with fifth byte of mode qualifier
P5WritePortUchar( CurrentPort, ModeQualifier[4] );
KeStallExecutionProcessor( Delay );
// check for correct status
status = P5ReadPortUchar( 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
P5WritePortUchar( CurrentPort, ModeQualifier[5] );
KeStallExecutionProcessor( Delay );
// check for correct status
status = P5ReadPortUchar( CurrentStatus );
// if status is valid there is a device out there responding
if ((status & (UCHAR) 0x30 ) == ( DSR_PERROR | DSR_SELECT )) {
P5WritePortUchar ( CurrentPort, (UCHAR) (CPP_QUERY_PRODID | ulDaisyIndex )) ;
KeStallExecutionProcessor( Delay );
// Device is out there
KeStallExecutionProcessor( Delay );
ucProdIdLoByteHiNibble = P5ReadPortUchar( CurrentStatus ) ;
ucProdIdLoByteHiNibble &= 0xF0 ;
KeStallExecutionProcessor( Delay );
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
KeStallExecutionProcessor( Delay ); // wait a bit
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
KeStallExecutionProcessor( Delay ); // wait a bit
ucProdIdLoByteLoNibble = P5ReadPortUchar( CurrentStatus ) ;
ucProdIdLoByteLoNibble >>= 4 ;
ucProdIdLoByte = ucProdIdLoByteHiNibble | ucProdIdLoByteLoNibble ;
KeStallExecutionProcessor( Delay );
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
KeStallExecutionProcessor( Delay ); // wait a bit
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
KeStallExecutionProcessor( Delay ); // wait a bit
ucProdIdHiByteHiNibble = P5ReadPortUchar( CurrentStatus ) ;
ucProdIdHiByteHiNibble &= 0xF0 ;
KeStallExecutionProcessor( Delay );
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
KeStallExecutionProcessor( Delay ); // wait a bit
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
KeStallExecutionProcessor( Delay ); // wait a bit
ucProdIdHiByteLoNibble = P5ReadPortUchar( CurrentStatus ) ;
ucProdIdHiByteLoNibble >>= 4 ;
ucProdIdHiByte = ucProdIdHiByteHiNibble | ucProdIdHiByteLoNibble ;
// issue the last strobe
KeStallExecutionProcessor( Delay );
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
KeStallExecutionProcessor( Delay ); // wait a bit
P5WritePortUchar( 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
P5WritePortUchar( CurrentPort, ModeQualifier[6] );
} // Third status
} // Second status
} // First status
P5WritePortUchar( CurrentControl, value ); // restore everything
return bReturnValue ;
} // end PptCheckIfStlProductId()
BOOLEAN
PptSend1284_3Command(
IN PUCHAR CurrentPort,
IN UCHAR Command
)
/*++
Routine Description:
This routine sends the 1284_3 Command given to it
down the parallel bus.
Arguments:
Return Value:
None.
--*/
{
UCHAR i, value, newvalue, test;//, status;
ULONG ii;
PUCHAR CurrentStatus, CurrentControl;
ULONG Delay = 3;
BOOLEAN success = FALSE;
CurrentStatus = CurrentPort + 1;
CurrentControl = CurrentPort + 2;
// Get Upper 4 bits to see what Command it is
test = (UCHAR)(Command & (UCHAR)CPP_COMMAND_FILTER);
// get current ctl reg
value = P5ReadPortUchar( 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);
P5WritePortUchar( CurrentControl, newvalue ); // make sure we can write
// bring nStrobe high
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) );
KeStallExecutionProcessor( Delay );
// send first four bytes of the 1284.3 mode qualifier sequence out
for ( i = 0; i < MODE_LEN_1284_3 - 3; i++ ) {
P5WritePortUchar( CurrentPort, ModeQualifier[i] );
KeStallExecutionProcessor( Delay );
}
// wait up to 5 us : Spec says about 2 but we will be lienient
if (CHECK_DSR(CurrentPort, INACTIVE, DONT_CARE, ACTIVE, ACTIVE, ACTIVE, 5 )) {
// continue with fifth byte of mode qualifier
P5WritePortUchar( CurrentPort, ModeQualifier[4] );
KeStallExecutionProcessor( Delay );
// wait up to 5 us : Spec says about 2 but we will be lienient
if (CHECK_DSR(CurrentPort, ACTIVE, DONT_CARE, INACTIVE, ACTIVE, ACTIVE, 5 )) {
// continue with sixth byte
P5WritePortUchar( CurrentPort, ModeQualifier[5] );
KeStallExecutionProcessor( Delay );
// wait up to 5 us : Spec says about 2 but we will be lienient
if (CHECK_DSR(CurrentPort, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE, DONT_CARE, 5 )) {
// Device is out there
KeStallExecutionProcessor( Delay );
// Command byte
P5WritePortUchar( CurrentPort, Command );
KeStallExecutionProcessor( Delay ); // wait a bit
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue | DCR_STROBE) ); // bring nStrobe low
KeStallExecutionProcessor( Delay ); // wait a bit
// NOTE NOTE NOTE
// Assertion of strobe to be done ONLY after checking for the
// FAULT feedback, as per the 1284_3 specification.
// Selection does not work correctly yet to be able to check for lines
switch ( test ) {
case CPP_SELECT:
// Check to make sure we are selected
// wait for upto 250 micro Secs for for selection time out.
for ( ii = 25000; ii > 0; ii-- ) {
if ( ( P5ReadPortUchar( CurrentStatus ) & DSR_NOT_FAULT ) == DSR_NOT_FAULT ) {
// selection...
success = TRUE;
break;
}
}
break;
case CPP_DESELECT:
// Check to make sure we are deselected
// wait for upto 250 micro Secs for for deselection time out.
for ( ii = 25000; ii > 0; ii-- ) {
if ( (P5ReadPortUchar( CurrentStatus ) & DSR_NOT_FAULT) != DSR_NOT_FAULT ) {
// deselection...
success = TRUE;
break;
}
}
break;
default :
// there is a device out there and Command completed sucessfully
KeStallExecutionProcessor( Delay ); // wait a bit
success = TRUE;
break;
} // End Switch
// NOTE NOTE NOTE
// the strobe is de-asserted now and the command is completed here
P5WritePortUchar( CurrentControl, (UCHAR)(newvalue & ~DCR_STROBE) ); // bring nStrobe high
KeStallExecutionProcessor( Delay ); // wait a bit
// last byte
P5WritePortUchar( CurrentPort, ModeQualifier[6] );
} // Third status
} // Second status
} // First status
P5WritePortUchar( CurrentControl, value ); // restore everything
// return TRUE if command succeeded, FALSE otherwise
return success;
}
BOOLEAN
ParSelectDevice(
IN PPDO_EXTENSION Pdx,
IN BOOLEAN HavePort
)
/*++
Routine Description:
This routine acquires the ParPort and selects a 1284.3 device
Arguments:
Pdx - Supplies the device extension.
HavePort - TRUE indicates that caller has already acquired port
so we should only do a SELECT_DEVICE
- FALSE indicates that caller has not already acquired port
so we should do a combination ACQUIRE_PORT/SELECT_DEVICE
Return Value:
TRUE - success - the device was selected (and port acquired if needed)
FALSE - failure
--*/
{
NTSTATUS status;
PDEVICE_OBJECT pPortDeviceObject;
PARALLEL_1284_COMMAND par1284Command;
LARGE_INTEGER timeOut;
enum _PdoType pdoType;
//
// Initialize command structure and extract parameters from the DeviceExtension
//
// reserved - always set to 0
par1284Command.Port = 0;
if( HavePort ) {
par1284Command.CommandFlags = PAR_HAVE_PORT_KEEP_PORT;
} else {
par1284Command.CommandFlags = 0;
}
pdoType = Pdx->PdoType;
switch( pdoType ) {
case PdoTypeRawPort:
case PdoTypeEndOfChain:
par1284Command.ID = 0; // ignored, but set anyway
par1284Command.CommandFlags |= PAR_END_OF_CHAIN_DEVICE;
break;
case PdoTypeLegacyZip:
par1284Command.ID = DOT3_LEGACY_ZIP_ID;
break;
case PdoTypeDaisyChain:
par1284Command.ID = Pdx->Ieee1284_3DeviceId;
break;
default:
DD((PCE)Pdx,DDE,"Invalid pdoType = %x\n",pdoType);
PptAssert(FALSE);
break;
}
pPortDeviceObject = Pdx->PortDeviceObject;
//
// Send the request
//
timeOut.QuadPart = -(10*1000*500); // 500ms ( 100ns units )
status = ParBuildSendInternalIoctl(IOCTL_INTERNAL_SELECT_DEVICE,
pPortDeviceObject,
&par1284Command, sizeof(PARALLEL_1284_COMMAND),
NULL, 0,
&timeOut);
if( NT_SUCCESS( status ) ) {
// SELECT succeeded
DD((PCE)Pdx,DDT,"ParSelectDevice - SUCCESS\n");
if( !HavePort ) {
// note in the device extension that we have the port
Pdx->bAllocated = TRUE;
}
return TRUE;
} else {
// SELECT failed
DD((PCE)Pdx,DDT,"ParSelectDevice - FAIL\n");
return FALSE;
}
}
BOOLEAN
ParDeselectDevice(
IN PPDO_EXTENSION Pdx,
IN BOOLEAN KeepPort
)
/*++
Routine Description:
This routine deselects a 1284.3 or Legacy Zip device and optionally
releases the ParPort
Arguments:
Pdx - Supplies the device extension.
KeepPort - TRUE indicates that we should keep the port acquired,
so we should only do a DESELECT_DEVICE
- FALSE indicates that we should not keep the port acquired,
so we should do a combination DESELECT_DEVICE/FREE_PORT
Return Value:
TRUE - The device was deselected (and the port released if requested)
--*/
{
PARALLEL_1284_COMMAND par1284Command;
NTSTATUS status;
enum _PdoType pdoType;
PDEVICE_OBJECT fdo = Pdx->Fdo;
PFDO_EXTENSION fdx = fdo->DeviceExtension;
//
// If we don't have the port, succeed and return
//
if( !Pdx->bAllocated ) {
DD((PCE)Pdx,DDW,"ParDeselectDevice - we do not have the port\n");
return TRUE;
}
//
// Initialize command structure and extract parameters from the DeviceExtension
//
// reserved - always set to 0
par1284Command.Port = 0;
if( KeepPort ) {
par1284Command.CommandFlags = PAR_HAVE_PORT_KEEP_PORT;
} else {
par1284Command.CommandFlags = 0;
}
pdoType = Pdx->PdoType;
switch( pdoType ) {
case PdoTypeRawPort:
case PdoTypeEndOfChain:
par1284Command.ID = 0; // ignored, but set anyway
par1284Command.CommandFlags |= PAR_END_OF_CHAIN_DEVICE;
break;
case PdoTypeLegacyZip:
par1284Command.ID = DOT3_LEGACY_ZIP_ID;
break;
case PdoTypeDaisyChain:
par1284Command.ID = Pdx->Ieee1284_3DeviceId;
break;
default:
DD((PCE)Pdx,DDE,"Invalid pdoType = %x\n",pdoType);
par1284Command.ID = 0; // choose a 1284.3 type deselect since this is harmless
PptAssert(FALSE);
break;
}
status = PptDeselectDevice( fdx, &par1284Command );
if( status != STATUS_SUCCESS ) {
// DESELECT failed?!? - there isn't anything that we can do
DD((PCE)Pdx,DDE,"ParDeselectDevice - FAILED - nothing we can do - status=%x\n", status);
} else {
DD((PCE)Pdx,DDT,"ParDeselectDevice - SUCCESS\n", status);
}
if( !KeepPort ) {
// note in the device extension that we gave up the port
DD((PCE)Pdx,DDT,"ParDeselectDevice - gave up port\n");
Pdx->bAllocated = FALSE;
}
return TRUE;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -