1011 lines
26 KiB
C
1011 lines
26 KiB
C
/*++
|
||
|
||
Copyright (C) Microsoft Corporation, 1993 - 1999
|
||
|
||
Module Name:
|
||
|
||
swecp.c
|
||
|
||
Abstract:
|
||
|
||
Enhanced Capabilities Port (ECP)
|
||
|
||
This module contains the code to perform all ECP related tasks (including
|
||
ECP Software and ECP Hardware modes.)
|
||
|
||
Author:
|
||
|
||
Tim Wells (WESTTEK) - April 16, 1997
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History :
|
||
|
||
--*/
|
||
|
||
#include "pch.h"
|
||
#include "ecp.h"
|
||
|
||
BOOLEAN
|
||
ParIsEcpSwWriteSupported(
|
||
IN PDEVICE_EXTENSION Extension
|
||
);
|
||
|
||
BOOLEAN
|
||
ParIsEcpSwReadSupported(
|
||
IN PDEVICE_EXTENSION Extension
|
||
);
|
||
|
||
NTSTATUS
|
||
ParEnterEcpSwMode(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN BOOLEAN DeviceIdRequest
|
||
);
|
||
|
||
VOID
|
||
ParCleanupSwEcpPort(
|
||
IN PDEVICE_EXTENSION Extension
|
||
);
|
||
|
||
VOID
|
||
ParTerminateEcpMode(
|
||
IN PDEVICE_EXTENSION Extension
|
||
);
|
||
|
||
NTSTATUS
|
||
ParEcpSetAddress(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN UCHAR Address
|
||
);
|
||
|
||
NTSTATUS
|
||
ParEcpSwWrite(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN PVOID Buffer,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG BytesTransferred
|
||
);
|
||
|
||
NTSTATUS
|
||
ParEcpSwRead(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN PVOID Buffer,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG BytesTransferred
|
||
);
|
||
|
||
NTSTATUS
|
||
ParEcpForwardToReverse(
|
||
IN PDEVICE_EXTENSION Extension
|
||
);
|
||
|
||
NTSTATUS
|
||
ParEcpReverseToForward(
|
||
IN PDEVICE_EXTENSION Extension
|
||
);
|
||
|
||
|
||
|
||
BOOLEAN
|
||
ParIsEcpSwWriteSupported(
|
||
IN PDEVICE_EXTENSION Extension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine determines whether or not ECP mode is suported
|
||
in the write direction by trying to negotiate when asked.
|
||
|
||
Arguments:
|
||
|
||
Extension - The device extension.
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
|
||
if (Extension->BadProtocolModes & ECP_SW)
|
||
return FALSE;
|
||
|
||
if (Extension->ProtocolModesSupported & ECP_SW)
|
||
return TRUE;
|
||
|
||
Status = ParEnterEcpSwMode (Extension, FALSE);
|
||
ParTerminateEcpMode (Extension);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
Extension->ProtocolModesSupported |= ECP_SW;
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
|
||
}
|
||
|
||
BOOLEAN
|
||
ParIsEcpSwReadSupported(
|
||
IN PDEVICE_EXTENSION Extension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine determines whether or not ECP mode is suported
|
||
in the read direction (need to be able to float the data register
|
||
drivers in order to do byte wide reads) by trying negotiate when asked.
|
||
|
||
Arguments:
|
||
|
||
Extension - The device extension.
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
|
||
if (!(Extension->HardwareCapabilities & PPT_ECP_PRESENT) &&
|
||
!(Extension->HardwareCapabilities & PPT_BYTE_PRESENT)) {
|
||
|
||
// Only use ECP Software in the reverse direction if an
|
||
// ECR is present or we know that we can put the data register into Byte mode.
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
if (Extension->BadProtocolModes & ECP_SW)
|
||
return FALSE;
|
||
|
||
if (Extension->ProtocolModesSupported & ECP_SW)
|
||
return TRUE;
|
||
|
||
// Must use SWECP Enter and Terminate for this test.
|
||
// Internel state machines will fail otherwise. --dvrh
|
||
Status = ParEnterEcpSwMode (Extension, FALSE);
|
||
ParTerminateEcpMode (Extension);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
Extension->ProtocolModesSupported |= ECP_SW;
|
||
return TRUE;
|
||
}
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEnterEcpSwMode(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN BOOLEAN DeviceIdRequest
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine performs 1284 negotiation with the peripheral to the
|
||
ECP mode protocol.
|
||
|
||
Arguments:
|
||
|
||
Controller - Supplies the port address.
|
||
|
||
DeviceIdRequest - Supplies whether or not this is a request for a device
|
||
id.
|
||
|
||
Return Value:
|
||
|
||
STATUS_SUCCESS - Successful negotiation.
|
||
|
||
otherwise - Unsuccessful negotiation.
|
||
|
||
--*/
|
||
|
||
{
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
|
||
if ( Extension->ModeSafety == SAFE_MODE ) {
|
||
if (DeviceIdRequest) {
|
||
Status = IeeeEnter1284Mode (Extension, ECP_EXTENSIBILITY | DEVICE_ID_REQ);
|
||
} else {
|
||
Status = IeeeEnter1284Mode (Extension, ECP_EXTENSIBILITY);
|
||
}
|
||
} else {
|
||
ParDump2(PARINFO, ("ParEnterEcpSwMode: In UNSAFE_MODE.\n"));
|
||
Extension->Connected = TRUE;
|
||
}
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = ParEcpSetupPhase(Extension);
|
||
}
|
||
|
||
return Status;
|
||
}
|
||
|
||
VOID
|
||
ParCleanupSwEcpPort(
|
||
IN PDEVICE_EXTENSION Extension
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Cleans up prior to a normal termination from ECP mode. Puts the
|
||
port HW back into Compatibility mode.
|
||
|
||
Arguments:
|
||
|
||
Controller - Supplies the parallel port's controller address.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PUCHAR Controller;
|
||
UCHAR dcr; // Contents of DCR
|
||
|
||
Controller = Extension->Controller;
|
||
|
||
//----------------------------------------------------------------------
|
||
// Set data bus for output
|
||
//----------------------------------------------------------------------
|
||
dcr = READ_PORT_UCHAR(Controller + OFFSET_DCR); // Get content of DCR
|
||
dcr = UPDATE_DCR( dcr, DIR_WRITE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE );
|
||
WRITE_PORT_UCHAR( Controller + OFFSET_DCR, dcr );
|
||
return;
|
||
}
|
||
|
||
|
||
VOID
|
||
ParTerminateEcpMode(
|
||
IN PDEVICE_EXTENSION Extension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine terminates the interface back to compatibility mode.
|
||
|
||
Arguments:
|
||
|
||
Controller - Supplies the parallel port's controller address.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
ParCleanupSwEcpPort(Extension);
|
||
if ( Extension->ModeSafety == SAFE_MODE ) {
|
||
IeeeTerminate1284Mode (Extension);
|
||
} else {
|
||
ParDump2(PARINFO, ("ParTerminateEcpMode: In UNSAFE_MODE.\n"));
|
||
Extension->Connected = FALSE;
|
||
}
|
||
return;
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEcpSetAddress(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN UCHAR Address
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Sets the ECP Address.
|
||
|
||
Arguments:
|
||
|
||
Extension - Supplies the device extension.
|
||
|
||
Address - The bus address to be set.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PUCHAR Controller;
|
||
PUCHAR DCRController;
|
||
UCHAR dsr;
|
||
UCHAR dcr;
|
||
|
||
ParDump2( PARENTRY, ("ParEcpSetAddress: Start: Channel [%x]\n", Address));
|
||
Controller = Extension->Controller;
|
||
DCRController = Controller + OFFSET_DCR;
|
||
|
||
//
|
||
// Event 34
|
||
//
|
||
// HostAck low indicates a command byte
|
||
Extension->CurrentEvent = 34;
|
||
dcr = READ_PORT_UCHAR(DCRController);
|
||
dcr = UPDATE_DCR( dcr, DIR_WRITE, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE );
|
||
WRITE_PORT_UCHAR(DCRController, dcr);
|
||
// Place the channel address on the bus
|
||
// Bit 7 of the byte sent must be 1 to indicate that this is an address
|
||
// instead of run length count.
|
||
//
|
||
WRITE_PORT_UCHAR(Controller + DATA_OFFSET, (UCHAR)(Address | 0x80));
|
||
|
||
//
|
||
// Event 35
|
||
//
|
||
// Start handshake by dropping HostClk
|
||
Extension->CurrentEvent = 35;
|
||
dcr = UPDATE_DCR( dcr, DIR_WRITE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE );
|
||
WRITE_PORT_UCHAR(DCRController, dcr);
|
||
|
||
|
||
// =============== Periph State 36 ===============8
|
||
// PeriphAck/PtrBusy = High (signals state 36)
|
||
// PeriphClk/PtrClk = Don't Care
|
||
// nAckReverse/AckDataReq = Don't Care
|
||
// XFlag = Don't Care
|
||
// nPeriphReq/nDataAvail = Don't Care
|
||
Extension->CurrentEvent = 35;
|
||
if (!CHECK_DSR(Controller,
|
||
ACTIVE, DONT_CARE, DONT_CARE,
|
||
DONT_CARE, DONT_CARE,
|
||
DEFAULT_RECEIVE_TIMEOUT))
|
||
{
|
||
ParDump2(PARERRORS, ("ECP::SendChannelAddress:State 36 Failed: Controller %x\n",
|
||
Controller));
|
||
// Make sure both HostAck and HostClk are high before leaving
|
||
// HostClk should be high in forward transfer except when handshaking
|
||
// HostAck should be high to indicate that what follows is data (not commands)
|
||
//
|
||
dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE );
|
||
WRITE_PORT_UCHAR(DCRController, dcr);
|
||
return STATUS_IO_DEVICE_ERROR;
|
||
}
|
||
|
||
//
|
||
// Event 37
|
||
//
|
||
// Finish handshake by raising HostClk
|
||
// HostClk is high when it's 0
|
||
//
|
||
Extension->CurrentEvent = 37;
|
||
dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE );
|
||
WRITE_PORT_UCHAR(DCRController, dcr);
|
||
|
||
// =============== Periph State 32 ===============8
|
||
// PeriphAck/PtrBusy = Low (signals state 32)
|
||
// PeriphClk/PtrClk = Don't Care
|
||
// nAckReverse/AckDataReq = Don't Care
|
||
// XFlag = Don't Care
|
||
// nPeriphReq/nDataAvail = Don't Care
|
||
Extension->CurrentEvent = 32;
|
||
if (!CHECK_DSR(Controller,
|
||
INACTIVE, DONT_CARE, DONT_CARE,
|
||
DONT_CARE, DONT_CARE,
|
||
DEFAULT_RECEIVE_TIMEOUT))
|
||
{
|
||
ParDump2(PARERRORS, ("ECP::SendChannelAddress:State 32 Failed: Controller %x\n",
|
||
Controller));
|
||
// Make sure both HostAck and HostClk are high before leaving
|
||
// HostClk should be high in forward transfer except when handshaking
|
||
// HostAck should be high to indicate that what follows is data (not commands)
|
||
//
|
||
dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE );
|
||
WRITE_PORT_UCHAR(DCRController, dcr);
|
||
return STATUS_IO_DEVICE_ERROR;
|
||
}
|
||
|
||
// Make sure both HostAck and HostClk are high before leaving
|
||
// HostClk should be high in forward transfer except when handshaking
|
||
// HostAck should be high to indicate that what follows is data (not commands)
|
||
//
|
||
dcr = UPDATE_DCR( dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, ACTIVE );
|
||
WRITE_PORT_UCHAR(DCRController, dcr);
|
||
|
||
ParDump2( PAREXIT, ("ParEcpSetAddress, Exit [%d]\n", NT_SUCCESS(STATUS_SUCCESS)));
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEcpSwWrite(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN PVOID Buffer,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG BytesTransferred
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Writes data to the peripheral using the ECP protocol under software
|
||
control.
|
||
|
||
Arguments:
|
||
|
||
Extension - Supplies the device extension.
|
||
|
||
Buffer - Supplies the buffer to write from.
|
||
|
||
BufferSize - Supplies the number of bytes in the buffer.
|
||
|
||
BytesTransferred - Returns the number of bytes transferred.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PUCHAR Controller;
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
PUCHAR pBuffer;
|
||
LARGE_INTEGER Timeout;
|
||
LARGE_INTEGER StartWrite;
|
||
LARGE_INTEGER Wait;
|
||
LARGE_INTEGER Start;
|
||
LARGE_INTEGER End;
|
||
UCHAR dsr;
|
||
UCHAR dcr;
|
||
ULONG i;
|
||
|
||
Controller = Extension->Controller;
|
||
pBuffer = Buffer;
|
||
|
||
Status = ParTestEcpWrite(Extension);
|
||
|
||
if (!NT_SUCCESS(Status))
|
||
{
|
||
Extension->CurrentPhase = PHASE_UNKNOWN;
|
||
Extension->Connected = FALSE;
|
||
ParDump2(PARERRORS,("ParEcpSwWrite: Invalid Entry State\r\n"));
|
||
goto ParEcpSwWrite_ExitLabel;
|
||
}
|
||
|
||
Wait.QuadPart = DEFAULT_RECEIVE_TIMEOUT * 10 * 1000 + KeQueryTimeIncrement();
|
||
|
||
Timeout.QuadPart = Extension->AbsoluteOneSecond.QuadPart *
|
||
Extension->TimerStart;
|
||
|
||
KeQueryTickCount(&StartWrite);
|
||
|
||
dcr = GetControl (Controller);
|
||
|
||
// clear direction bit - enable output
|
||
dcr &= ~(DCR_DIRECTION);
|
||
StoreControl(Controller, dcr);
|
||
KeStallExecutionProcessor(1);
|
||
|
||
for (i = 0; i < BufferSize; i++) {
|
||
|
||
//
|
||
// Event 34
|
||
//
|
||
Extension->CurrentEvent = 34;
|
||
WRITE_PORT_UCHAR(Controller + DATA_OFFSET, *pBuffer++);
|
||
|
||
//
|
||
// Event 35
|
||
//
|
||
Extension->CurrentEvent = 35;
|
||
dcr &= ~DCR_AUTOFEED;
|
||
dcr |= DCR_STROBE;
|
||
StoreControl (Controller, dcr);
|
||
|
||
//
|
||
// Waiting for Event 36
|
||
//
|
||
Extension->CurrentEvent = 36;
|
||
while (TRUE) {
|
||
|
||
KeQueryTickCount(&End);
|
||
|
||
dsr = GetStatus(Controller);
|
||
if (!(dsr & DSR_NOT_BUSY)) {
|
||
break;
|
||
}
|
||
|
||
if ((End.QuadPart - StartWrite.QuadPart) *
|
||
KeQueryTimeIncrement() > Timeout.QuadPart) {
|
||
|
||
dsr = GetStatus(Controller);
|
||
if (!(dsr & DSR_NOT_BUSY)) {
|
||
break;
|
||
}
|
||
//
|
||
// Return the device to Idle.
|
||
//
|
||
dcr &= ~(DCR_STROBE);
|
||
StoreControl (Controller, dcr);
|
||
|
||
*BytesTransferred = i;
|
||
Extension->log.SwEcpWriteCount += *BytesTransferred;
|
||
return STATUS_DEVICE_BUSY;
|
||
}
|
||
}
|
||
|
||
//
|
||
// Event 37
|
||
//
|
||
Extension->CurrentEvent = 37;
|
||
dcr &= ~DCR_STROBE;
|
||
StoreControl (Controller, dcr);
|
||
|
||
//
|
||
// Waiting for Event 32
|
||
//
|
||
Extension->CurrentEvent = 32;
|
||
KeQueryTickCount(&Start);
|
||
while (TRUE) {
|
||
|
||
KeQueryTickCount(&End);
|
||
|
||
dsr = GetStatus(Controller);
|
||
if (dsr & DSR_NOT_BUSY) {
|
||
break;
|
||
}
|
||
|
||
if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() >
|
||
Wait.QuadPart) {
|
||
|
||
dsr = GetStatus(Controller);
|
||
if (dsr & DSR_NOT_BUSY) {
|
||
break;
|
||
}
|
||
#if DVRH_BUS_RESET_ON_ERROR
|
||
BusReset(Controller+OFFSET_DCR); // Pass in the dcr address
|
||
#endif
|
||
*BytesTransferred = i;
|
||
Extension->log.SwEcpWriteCount += *BytesTransferred;
|
||
return STATUS_IO_DEVICE_ERROR;
|
||
}
|
||
}
|
||
}
|
||
|
||
ParEcpSwWrite_ExitLabel:
|
||
|
||
*BytesTransferred = i;
|
||
Extension->log.SwEcpWriteCount += *BytesTransferred;
|
||
ParDumpReg(PAREXIT | PARECPTRACE, ("ParEcpSwWrite: Exit[%d] BytesTransferred[%lx]",
|
||
NT_SUCCESS(Status),
|
||
(long)*BytesTransferred),
|
||
Controller + ECR_OFFSET,
|
||
Controller + OFFSET_DCR,
|
||
Controller + OFFSET_DSR);
|
||
|
||
|
||
return Status;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEcpSwRead(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN PVOID Buffer,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG BytesTransferred
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine performs a 1284 ECP mode read under software control
|
||
into the given buffer for no more than 'BufferSize' bytes.
|
||
|
||
Arguments:
|
||
|
||
Extension - Supplies the device extension.
|
||
|
||
Buffer - Supplies the buffer to read into.
|
||
|
||
BufferSize - Supplies the number of bytes in the buffer.
|
||
|
||
BytesTransferred - Returns the number of bytes transferred.
|
||
|
||
--*/
|
||
|
||
{
|
||
PUCHAR Controller;
|
||
PUCHAR pBuffer;
|
||
USHORT usTime;
|
||
LARGE_INTEGER End;
|
||
UCHAR dsr;
|
||
UCHAR dcr;
|
||
ULONG i;
|
||
UCHAR ecr;
|
||
|
||
Controller = Extension->Controller;
|
||
pBuffer = Buffer;
|
||
|
||
dcr = GetControl (Controller);
|
||
|
||
Extension->CurrentPhase = PHASE_REVERSE_XFER;
|
||
|
||
//
|
||
// Put ECR into PS/2 mode and float the drivers.
|
||
//
|
||
if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
|
||
// Save off the ECR register
|
||
ecr = READ_PORT_UCHAR(Controller + ECR_OFFSET);
|
||
|
||
#if (1 == PARCHIP_ECR_ARBITRATOR)
|
||
#else
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_PS2);
|
||
#endif
|
||
}
|
||
|
||
dcr |= DCR_DIRECTION;
|
||
StoreControl (Controller, dcr);
|
||
KeStallExecutionProcessor(1);
|
||
|
||
for (i = 0; i < BufferSize; i++) {
|
||
|
||
// dvtw - READ TIMEOUTS
|
||
//
|
||
// If it is the first byte then give it more time
|
||
//
|
||
if (!(GetStatus (Controller) & DSR_NOT_FAULT) || i == 0) {
|
||
|
||
usTime = DEFAULT_RECEIVE_TIMEOUT;
|
||
|
||
} else {
|
||
|
||
usTime = IEEE_MAXTIME_TL;
|
||
}
|
||
|
||
// *************** State 43 Reverse Phase ***************8
|
||
// PeriphAck/PtrBusy = DONT CARE
|
||
// PeriphClk/PtrClk = LOW ( State 43 )
|
||
// nAckReverse/AckDataReq = LOW
|
||
// XFlag = HIGH
|
||
// nPeriphReq/nDataAvail = DONT CARE
|
||
|
||
Extension->CurrentEvent = 43;
|
||
if (!CHECK_DSR(Controller, DONT_CARE, INACTIVE, INACTIVE, ACTIVE, DONT_CARE,
|
||
usTime)) {
|
||
|
||
Extension->CurrentPhase = PHASE_UNKNOWN;
|
||
|
||
dcr &= ~DCR_DIRECTION;
|
||
StoreControl (Controller, dcr);
|
||
|
||
// restore ecr register
|
||
if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
|
||
#if (1 == PARCHIP_ECR_ARBITRATOR)
|
||
#else
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
|
||
#endif
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
|
||
}
|
||
|
||
*BytesTransferred = i;
|
||
Extension->log.SwEcpReadCount += *BytesTransferred;
|
||
return STATUS_IO_DEVICE_ERROR;
|
||
|
||
}
|
||
|
||
// *************** State 44 Setup Phase ***************8
|
||
// DIR = DONT CARE
|
||
// IRQEN = DONT CARE
|
||
// 1284/SelectIn = DONT CARE
|
||
// nReverseReq/**(ECP only)= DONT CARE
|
||
// HostAck/HostBusy = HIGH ( State 44 )
|
||
// HostClk/nStrobe = DONT CARE
|
||
//
|
||
Extension->CurrentEvent = 44;
|
||
dcr = READ_PORT_UCHAR(Controller + OFFSET_DCR);
|
||
dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE);
|
||
WRITE_PORT_UCHAR(Controller + OFFSET_DCR, dcr);
|
||
|
||
// *************** State 45 Reverse Phase ***************8
|
||
// PeriphAck/PtrBusy = DONT CARE
|
||
// PeriphClk/PtrClk = HIGH ( State 45 )
|
||
// nAckReverse/AckDataReq = LOW
|
||
// XFlag = HIGH
|
||
// nPeriphReq/nDataAvail = DONT CARE
|
||
Extension->CurrentEvent = 45;
|
||
if (!CHECK_DSR(Controller, DONT_CARE, ACTIVE, INACTIVE, ACTIVE, DONT_CARE,
|
||
IEEE_MAXTIME_TL)) {
|
||
|
||
Extension->CurrentPhase = PHASE_UNKNOWN;
|
||
|
||
dcr &= ~DCR_DIRECTION;
|
||
StoreControl (Controller, dcr);
|
||
|
||
// restore ecr register
|
||
if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
|
||
#if (1 == PARCHIP_ECR_ARBITRATOR)
|
||
#else
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
|
||
#endif
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
|
||
}
|
||
|
||
*BytesTransferred = i;
|
||
Extension->log.SwEcpReadCount += *BytesTransferred;
|
||
return STATUS_IO_DEVICE_ERROR;
|
||
|
||
}
|
||
|
||
//
|
||
// Read the data
|
||
//
|
||
*pBuffer = READ_PORT_UCHAR (Controller + DATA_OFFSET);
|
||
pBuffer++;
|
||
|
||
// *************** State 46 Setup Phase ***************8
|
||
// DIR = DONT CARE
|
||
// IRQEN = DONT CARE
|
||
// 1284/SelectIn = DONT CARE
|
||
// nReverseReq/**(ECP only)= DONT CARE
|
||
// HostAck/HostBusy = LOW ( State 46 )
|
||
// HostClk/nStrobe = DONT CARE
|
||
//
|
||
Extension->CurrentEvent = 46;
|
||
dcr = READ_PORT_UCHAR(Controller + OFFSET_DCR);
|
||
dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, INACTIVE, DONT_CARE);
|
||
WRITE_PORT_UCHAR(Controller + OFFSET_DCR, dcr);
|
||
|
||
}
|
||
|
||
Extension->CurrentPhase = PHASE_REVERSE_IDLE;
|
||
|
||
dcr &= ~DCR_DIRECTION;
|
||
StoreControl (Controller, dcr);
|
||
|
||
// restore ecr register
|
||
if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
|
||
#if (1 == PARCHIP_ECR_ARBITRATOR)
|
||
#else
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
|
||
#endif
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
|
||
}
|
||
|
||
*BytesTransferred = i;
|
||
Extension->log.SwEcpReadCount += *BytesTransferred;
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEcpForwardToReverse(
|
||
IN PDEVICE_EXTENSION Extension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine reverses the channel (ECP).
|
||
|
||
Arguments:
|
||
|
||
Extension - Supplies the device extension.
|
||
|
||
--*/
|
||
|
||
{
|
||
PUCHAR Controller;
|
||
LARGE_INTEGER Wait35ms;
|
||
LARGE_INTEGER Start;
|
||
LARGE_INTEGER End;
|
||
UCHAR dsr;
|
||
UCHAR dcr;
|
||
UCHAR ecr;
|
||
|
||
Controller = Extension->Controller;
|
||
|
||
Wait35ms.QuadPart = 10*35*1000 + KeQueryTimeIncrement();
|
||
|
||
dcr = GetControl (Controller);
|
||
|
||
//
|
||
// Put ECR into PS/2 mode to flush the FIFO.
|
||
//
|
||
// Save off the ECR register
|
||
|
||
// Note: Don't worry about checking to see if it's
|
||
// safe to touch the ecr since we've already checked
|
||
// that before we allowed this mode to be activated.
|
||
ecr = READ_PORT_UCHAR(Controller + ECR_OFFSET);
|
||
|
||
#if (1 == PARCHIP_ECR_ARBITRATOR)
|
||
#else
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_PS2);
|
||
#endif
|
||
//
|
||
// Event 38
|
||
//
|
||
Extension->CurrentEvent = 38;
|
||
dcr |= DCR_AUTOFEED;
|
||
StoreControl (Controller, dcr);
|
||
KeStallExecutionProcessor(1);
|
||
|
||
//
|
||
// Event 39
|
||
//
|
||
Extension->CurrentEvent = 39;
|
||
dcr &= ~DCR_NOT_INIT;
|
||
StoreControl (Controller, dcr);
|
||
|
||
//
|
||
// Wait for Event 40
|
||
//
|
||
Extension->CurrentEvent = 40;
|
||
KeQueryTickCount(&Start);
|
||
while (TRUE) {
|
||
|
||
KeQueryTickCount(&End);
|
||
|
||
dsr = GetStatus(Controller);
|
||
if (!(dsr & DSR_PERROR)) {
|
||
break;
|
||
}
|
||
|
||
if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() >
|
||
Wait35ms.QuadPart) {
|
||
|
||
dsr = GetStatus(Controller);
|
||
if (!(dsr & DSR_PERROR)) {
|
||
break;
|
||
}
|
||
#if DVRH_BUS_RESET_ON_ERROR
|
||
BusReset(Controller+OFFSET_DCR); // Pass in the dcr address
|
||
#endif
|
||
// restore the ecr register
|
||
if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
|
||
#if (1 == PARCHIP_ECR_ARBITRATOR)
|
||
#else
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
|
||
#endif
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
|
||
}
|
||
|
||
ParDump2(PARERRORS,("ParEcpForwardToReverse: Failed to get State 40\r\n"));
|
||
return STATUS_IO_DEVICE_ERROR;
|
||
}
|
||
}
|
||
|
||
// restore the ecr register
|
||
if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
|
||
#if (1 == PARCHIP_ECR_ARBITRATOR)
|
||
#else
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
|
||
#endif
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
|
||
}
|
||
|
||
Extension->CurrentPhase = PHASE_REVERSE_IDLE;
|
||
return STATUS_SUCCESS;
|
||
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEcpReverseToForward(
|
||
IN PDEVICE_EXTENSION Extension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine puts the channel back into forward mode (ECP).
|
||
|
||
Arguments:
|
||
|
||
Extension - Supplies the device extension.
|
||
|
||
--*/
|
||
|
||
{
|
||
PUCHAR Controller;
|
||
LARGE_INTEGER Wait35ms;
|
||
LARGE_INTEGER Start;
|
||
LARGE_INTEGER End;
|
||
UCHAR dsr;
|
||
UCHAR dcr;
|
||
UCHAR ecr;
|
||
|
||
Controller = Extension->Controller;
|
||
|
||
Wait35ms.QuadPart = 10*35*1000 + KeQueryTimeIncrement();
|
||
|
||
dcr = GetControl (Controller);
|
||
|
||
//
|
||
// Put ECR into PS/2 mode to flush the FIFO.
|
||
//
|
||
// Save off the ECR register
|
||
|
||
// Note: Don't worry about checking to see if it's
|
||
// safe to touch the ecr since we've already checked
|
||
// that before we allowed this mode to be activated.
|
||
ecr = READ_PORT_UCHAR(Controller + ECR_OFFSET);
|
||
#if (1 == PARCHIP_ECR_ARBITRATOR)
|
||
#else
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_PS2);
|
||
#endif
|
||
//
|
||
// Event 47
|
||
//
|
||
Extension->CurrentEvent = 47;
|
||
dcr |= DCR_NOT_INIT;
|
||
StoreControl (Controller, dcr);
|
||
|
||
//
|
||
// Wait for Event 49
|
||
//
|
||
Extension->CurrentEvent = 49;
|
||
KeQueryTickCount(&Start);
|
||
while (TRUE) {
|
||
|
||
KeQueryTickCount(&End);
|
||
|
||
dsr = GetStatus(Controller);
|
||
if (dsr & DSR_PERROR) {
|
||
break;
|
||
}
|
||
|
||
if ((End.QuadPart - Start.QuadPart) * KeQueryTimeIncrement() >
|
||
Wait35ms.QuadPart) {
|
||
|
||
dsr = GetStatus(Controller);
|
||
if (dsr & DSR_PERROR) {
|
||
break;
|
||
}
|
||
#if DVRH_BUS_RESET_ON_ERROR
|
||
BusReset(Controller+OFFSET_DCR); // Pass in the dcr address
|
||
#endif
|
||
// Restore the ecr register
|
||
if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
|
||
#if (1 == PARCHIP_ECR_ARBITRATOR)
|
||
#else
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
|
||
#endif
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
|
||
}
|
||
|
||
ParDump2(PARERRORS,("ParEcpReverseToForward: Failed to get State 49\r\n"));
|
||
return STATUS_IO_DEVICE_ERROR;
|
||
}
|
||
}
|
||
|
||
// restore the ecr register
|
||
if (Extension->HardwareCapabilities & PPT_ECP_PRESENT) {
|
||
#if (1 == PARCHIP_ECR_ARBITRATOR)
|
||
#else
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, DEFAULT_ECR_COMPATIBILITY);
|
||
#endif
|
||
WRITE_PORT_UCHAR(Controller + ECR_OFFSET, ecr);
|
||
}
|
||
|
||
Extension->CurrentPhase = PHASE_FORWARD_IDLE;
|
||
return STATUS_SUCCESS;
|
||
}
|