📄 par12843.c
字号:
/*++
Copyright (C) Microsoft Corporation, 1993 - 1999
Module Name:
par12843.c
Abstract:
This is the main module for 1284.3 functionality. These
function enable the selection and deselection of 1284.3
compatable devices on the parallel port.
The devices can be selected and deselected IRQL <= DISPATCH_LEVEL
by calling IOCTL_INTERNAL_SELECT_DEVICE, or 'TrySelectDevice'.
The first call is the simplest: the IRP will be queued in the
parallel port driver until the port is free and then it will
try to select the device with the given ID from the structure
PARALLEL_1284_COMMAND. If successful it will with a successful
status, otherwise it will return with an unsuccessful status.
The class driver may cancel this IRP at any time which serves
as a mechanism to timeout an allocate request.
The 'TrySelectDevice' call returns immediately from the port
driver with a TRUE status if the port was allocated and the
device was able to be selected or a FALSE status if the port
was either busy or the device was not able to be selected.
Once the device is selected, the port is owned by the selecting class
driver until a 'DeselectDevice' call is made. This deselects the
device and also releases the port and wakes up the next caller.
Author:
Don E. Redford 3-Mar-1998
Environment:
Kernel mode
Revision History :
--*/
#include "pch.h"
ULONG
PptInitiate1284_3(
IN PVOID Extension
);
NTSTATUS
PptTrySelectDevice(
IN PVOID Context,
IN PVOID TrySelectCommand
);
NTSTATUS
PptDeselectDevice(
IN PVOID Context,
IN PVOID DeselectCommand
);
ULONG
Ppt1284_3AssignAddress(
IN PDEVICE_EXTENSION DeviceExtension
);
BOOLEAN
PptSend1284_3Command(
IN PDEVICE_EXTENSION DeviceExtension,
IN UCHAR Command
);
BOOLEAN
PptCheckIfStl1284_3(
IN PDEVICE_EXTENSION DeviceExtension,
IN ULONG ulDaisyIndex,
IN BOOLEAN bNoStrobe
);
BOOLEAN
PptCheckIfNon1284_3Present(
IN PDEVICE_EXTENSION Extension
);
BOOLEAN
PptCheckIfStlProductId(
IN PDEVICE_EXTENSION Extension,
IN ULONG ulDaisyIndex
);
//
// Beginning of functions
//
ULONG
PptInitiate1284_3(
IN PVOID Extension
)
/*++
Routine Description:
This routine initializes all of the 1284.3 devices out on the
given parallel port. It does this by assigning 1284.3 addresses to
each device on the port.
Arguments:
Extensioon - Device extension structure.
Return Value:
None.
--*/
{
ULONG deviceCount1 = 0;
ULONG deviceCount2 = 0;
ULONG loopCount = 0;
ULONG maxTries = 3; // picked 3 out of thin air as a "reasonable" value
// Send command to assign addresses and count number of 1284.3 daisy chain devices
// Try multiple times to make sure we get the same count
do {
KeStallExecutionProcessor( 5 );
deviceCount1 = Ppt1284_3AssignAddress( Extension );
KeStallExecutionProcessor( 5 );
deviceCount2 = Ppt1284_3AssignAddress( Extension );
} while( (deviceCount1 != deviceCount2) && (++loopCount < maxTries) );
return deviceCount2;
}
NTSTATUS
PptTrySelectDevice(
IN PVOID Context,
IN PVOID TrySelectCommand
)
/*++
Routine Description:
This routine first tries to allocate the port. If successful
it will then try to select the device with the ID given.
Arguments:
Extension - Driver extension.
Device - 1284.3 Device Id.
Command - Command to know whether to allocate the port
Return Value:
TRUE - Able to allocate the port and select the device
FALSE - 1: Invalid ID 2: Not able to allocate port 3: Not able to select device
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_EXTENSION Extension = Context;
PPARALLEL_1284_COMMAND Command = TrySelectCommand;
BOOLEAN success = FALSE;
SYNCHRONIZED_COUNT_CONTEXT SyncContext;
KIRQL CancelIrql;
UCHAR i, DeviceID;
PptDump2( PARENTRY, ("Enter PptTrySelectDevice()\n") );
if( ( Command->CommandFlags & PAR_LEGACY_ZIP_DRIVE ) ||
( Command->ID == DOT3_LEGACY_ZIP_ID )) {
return PptTrySelectLegacyZip(Context, TrySelectCommand);
}
// get device ID to select
DeviceID = Command->ID;
// validate parameters - we will accept:
// - a Dot3 device with a valid DeviceID
// - an End-of-Chain device indicated by the PAR_END_OF_CHAIN_DEVICE flag, or
// - an End-of-Chain device indicated by a DeviceID value one past the last Dot3 device
if ( !(Command->CommandFlags & PAR_END_OF_CHAIN_DEVICE) &&
DeviceID > Extension->PnpInfo.Ieee1284_3DeviceCount ) {
// Requested device is not flagged as End-of-Chain device and DeviceID
// is more than one past the end of the Dot3 Devices, so FAIL the IRP
PptDump2( PARERRORS, ("Dot3 SELECT_DEVICE IRP %S ID=%d - FAIL - invalid ID\n",
Extension->PnpInfo.PortName, DeviceID) );
Status = STATUS_INVALID_PARAMETER;
} else {
//
// Request appears valid
//
// test to see if we need to grab port
if( Command->CommandFlags & PAR_HAVE_PORT_KEEP_PORT ) {
//
// requester has already acquired port, just do a SELECT
//
if ( !(Command->CommandFlags & PAR_END_OF_CHAIN_DEVICE) &&
DeviceID < Extension->PnpInfo.Ieee1284_3DeviceCount ) {
// SELECT the device
for ( i = 0; i < PptDot3Retries && !success; i++ ) {
// Send command to to select device in compatability mode
success = PptSend1284_3Command( Extension, (UCHAR)(CPP_SELECT | DeviceID) );
// Stall a little in case we have to retry
KeStallExecutionProcessor( 5 );
}
if ( success ) {
PptDump2( PARINFO, ("DOT3 SELECT_DEVICE IRP - SUCCESS\n") );
Status = STATUS_SUCCESS;
} else {
PptDump2( PARERRORS, ("DOT3 SELECT_DEVICE IRP - FAIL\n") );
Status = STATUS_UNSUCCESSFUL;
}
} else {
// End-of-Chain device, no SELECT required, SUCCEED the request
PptDumpV( ("DOT3 SELECT_DEVICE IRP - End-of-Chain - SUCCESS\n") );
Status = STATUS_SUCCESS;
}
} else {
// Don't have the port
//
// Try to acquire port and select device
//
PptDump2( PARINFO, ("Dot3 SELECT_DEVICE IRP %S ID=%d - attempting to SELECT...\n",
Extension->PnpInfo.PortName, DeviceID) );
IoAcquireCancelSpinLock(&CancelIrql);
SyncContext.Count = &Extension->WorkQueueCount;
if (Extension->InterruptRefCount) {
KeSynchronizeExecution(Extension->InterruptObject,
PptSynchronizedIncrement,
&SyncContext);
} else {
PptSynchronizedIncrement(&SyncContext);
}
if (SyncContext.NewCount) {
// Port is busy, queue request
IoReleaseCancelSpinLock(CancelIrql);
Status = STATUS_PENDING;
} else {
IoReleaseCancelSpinLock(CancelIrql);
// Port is acquired
PptDump2( PARINFO, ("DOT3 SELECT_DEVICE IRP - Port ALLOCATE (ACQUIRED) - SUCCESS\n") );
Extension->WmiPortAllocFreeCounts.PortAllocates++;
if ( !(Command->CommandFlags & PAR_END_OF_CHAIN_DEVICE) &&
DeviceID < Extension->PnpInfo.Ieee1284_3DeviceCount ) {
// SELECT the device
for ( i = 0; i < PptDot3Retries && !success; i++ ) {
// Send command to to select device in compatability mode
success = PptSend1284_3Command( Extension, (UCHAR)(CPP_SELECT | DeviceID) );
// Stall a little in case we have to retry
KeStallExecutionProcessor( 5 );
}
if ( success ) {
PptDump2( PARINFO, ("DOT3 SELECT_DEVICE IRP - SUCCESS\n") );
Status = STATUS_SUCCESS;
} else {
PptDump2( PARERRORS, ("DOT3 SELECT_DEVICE IRP - FAIL\n") );
Status = STATUS_UNSUCCESSFUL;
}
} else {
// End-of-Chain device, no SELECT required, SUCCEED the request
PptDump2( PARINFO, ("DOT3 SELECT_DEVICE IRP - End-of-Chain device - no select required\n") );
Status = STATUS_SUCCESS;
}
} // endif - test for port busy
} // endif - test if already have port
} // endif - test for valid parameters
return( Status );
}
NTSTATUS
PptDeselectDevice(
IN PVOID Context,
IN PVOID DeselectCommand
)
/*++
Routine Description:
This routine deselects the current device and then frees the port
Arguments:
DriverObject - Supplies the driver object controlling all of the
devices.
Return Value:
TRUE - Able to deselect the device and free the port
FALSE - 1: Invalid ID 2: Not able to deselect the drive
--*/
{
NTSTATUS Status = STATUS_SUCCESS;
PDEVICE_EXTENSION Extension = Context;
PPARALLEL_1284_COMMAND Command = DeselectCommand;
BOOLEAN success = FALSE;
UCHAR i, DeviceID;
PptDump2( PARENTRY, ("Enter PptDeselectDevice()\n") );
if( ( Command->CommandFlags & PAR_LEGACY_ZIP_DRIVE ) ||
( Command->ID == DOT3_LEGACY_ZIP_ID ) ) {
return PptDeselectLegacyZip( Context, DeselectCommand );
}
// get device ID to deselect
DeviceID = Command->ID;
// validate ID
if ( !(Command->CommandFlags & PAR_END_OF_CHAIN_DEVICE) &&
DeviceID > Extension->PnpInfo.Ieee1284_3DeviceCount ) {
// not End-of-Chain device and Dot3 DeviceID is invalid
PptDump2( PARERRORS, ("DOT3 DESELECT_DEVICE %S - ID=%d - FAIL - invalid parameter\n",
Extension->PnpInfo.PortName, DeviceID) );
Status = STATUS_INVALID_PARAMETER;
} else {
// Check for End-of-Chain device
if ( !(Command->CommandFlags & PAR_END_OF_CHAIN_DEVICE) &&
DeviceID < Extension->PnpInfo.Ieee1284_3DeviceCount ) {
// first deselect the device
for ( i = 0; i < PptDot3Retries && !success; i++ ) {
success = PptSend1284_3Command( Extension, (UCHAR)CPP_DESELECT );
// Stall a little in case we have to retry
KeStallExecutionProcessor( 5 );
}
if ( success ) {
// Deselecting device was a success
PptDumpV( ("DOT3 DESELECT_DEVICE %S - ID=%d - SUCCESS\n",
Extension->PnpInfo.PortName, DeviceID) );
// check if requester wants to keep port or free port
if( !(Command->CommandFlags & PAR_HAVE_PORT_KEEP_PORT) ) {
PptFreePort( Extension );
}
Status = STATUS_SUCCESS;
} else {
// Unable to deselect device, something went very wrong,
// port is now in an unknown/blocked state
PptDump2( PARERRORS, ("DOT3 DESELECT_DEVICE %S - ID=%d - SERIOUS FAILURE\n",
Extension->PnpInfo.PortName, DeviceID) );
// ASSERT(FALSE);
Status = STATUS_UNSUCCESSFUL;
}
} else {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -