439 lines
13 KiB
C
439 lines
13 KiB
C
/*++
|
||
|
||
Copyright (C) Microsoft Corporation, 1993 - 1999
|
||
|
||
Module Name:
|
||
|
||
Byte.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the code to do byte mode reads.
|
||
|
||
Author:
|
||
|
||
Don Redford 30-Aug-1998
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History :
|
||
|
||
--*/
|
||
|
||
#include "pch.h"
|
||
|
||
BOOLEAN
|
||
ParIsByteSupported(
|
||
IN PDEVICE_EXTENSION Extension
|
||
);
|
||
|
||
NTSTATUS
|
||
ParEnterByteMode(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN BOOLEAN DeviceIdRequest
|
||
);
|
||
|
||
VOID
|
||
ParTerminateByteMode(
|
||
IN PDEVICE_EXTENSION Extension
|
||
);
|
||
|
||
NTSTATUS
|
||
ParByteModeRead(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN PVOID Buffer,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG BytesTransferred
|
||
);
|
||
|
||
|
||
BOOLEAN
|
||
ParIsByteSupported(
|
||
IN PDEVICE_EXTENSION Extension
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine determines whether or not byte mode is suported
|
||
by trying to negotiate when asked.
|
||
|
||
Arguments:
|
||
|
||
Extension - The device extension.
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
|
||
ParDump2(PARINFO, ("ParIsByteSupported: Start\n"));
|
||
|
||
if (Extension->BadProtocolModes & BYTE_BIDIR) {
|
||
ParDump2(PARINFO, ("ParIsByteSupported: BAD PROTOCOL Leaving\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
if (!(Extension->HardwareCapabilities & PPT_BYTE_PRESENT)) {
|
||
ParDump2(PARINFO, ("ParIsByteSupported: NO Leaving\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
if (Extension->ProtocolModesSupported & BYTE_BIDIR) {
|
||
ParDump2(PARINFO, ("ParIsByteSupported: Already Checked YES Leaving\n"));
|
||
return TRUE;
|
||
}
|
||
|
||
// Must use Byte Enter and Terminate for this test.
|
||
// Internel state machines will fail otherwise. --dvrh
|
||
Status = ParEnterByteMode (Extension, FALSE);
|
||
ParTerminateByteMode (Extension);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
ParDump2(PARINFO, ("ParIsByteSupported: SUCCESS Leaving\n"));
|
||
Extension->ProtocolModesSupported |= BYTE_BIDIR;
|
||
return TRUE;
|
||
}
|
||
|
||
ParDump2(PARINFO, ("ParIsByteSupported: UNSUCCESSFUL Leaving\n"));
|
||
return FALSE;
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEnterByteMode(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN BOOLEAN DeviceIdRequest
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine performs 1284 negotiation with the peripheral to the
|
||
byte 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;
|
||
|
||
ParDump2(PARINFO, ("ParEnterByteMode: Start\n"));
|
||
// Make sure Byte mode Harware is still there
|
||
Status = Extension->TrySetChipMode( Extension->PortContext, ECR_BYTE_PIO_MODE );
|
||
|
||
|
||
if ( NT_SUCCESS(Status) ) {
|
||
if ( Extension->ModeSafety == SAFE_MODE ) {
|
||
ParDump2(PARINFO, ("ParEnterByteMode: In SAFE_MODE doing IEEE Negotiation\n"));
|
||
if ( DeviceIdRequest ) {
|
||
Status = IeeeEnter1284Mode (Extension, BYTE_EXTENSIBILITY | DEVICE_ID_REQ);
|
||
} else {
|
||
Status = IeeeEnter1284Mode (Extension, BYTE_EXTENSIBILITY);
|
||
}
|
||
} else {
|
||
ParDump2(PARINFO, ("ParEnterByteMode: In UNSAFE_MODE.\n"));
|
||
Extension->Connected = TRUE;
|
||
}
|
||
}
|
||
|
||
// dvdr
|
||
if (NT_SUCCESS(Status)) {
|
||
ParDump2(PARINFO, ("ParEnterByteMode: IeeeEnter1284Mode returned success\n"));
|
||
Extension->CurrentPhase = PHASE_REVERSE_IDLE;
|
||
Extension->IsIeeeTerminateOk = TRUE;
|
||
} else {
|
||
ParDump2(PARINFO, ("ParEnterByteMode: IeeeEnter1284Mode returned unsuccessful\n"));
|
||
ParTerminateByteMode ( Extension );
|
||
Extension->CurrentPhase = PHASE_UNKNOWN;
|
||
Extension->IsIeeeTerminateOk = FALSE;
|
||
}
|
||
|
||
ParDump2(PARINFO, ("ParEnterByteMode: Leaving with Status : %x \n", Status));
|
||
|
||
return Status;
|
||
}
|
||
|
||
VOID
|
||
ParTerminateByteMode(
|
||
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.
|
||
|
||
--*/
|
||
|
||
{
|
||
ParDump2(PARINFO, ("ParTerminateByteMode: Enter.\n"));
|
||
if ( Extension->ModeSafety == SAFE_MODE ) {
|
||
IeeeTerminate1284Mode (Extension);
|
||
} else {
|
||
ParDump2(PARINFO, ("ParTerminateByteMode: In UNSAFE_MODE.\n"));
|
||
Extension->Connected = FALSE;
|
||
}
|
||
Extension->ClearChipMode( Extension->PortContext, ECR_BYTE_PIO_MODE );
|
||
ParDump2(PARINFO, ("ParTerminateByteMode: Exit.\n"));
|
||
}
|
||
|
||
NTSTATUS
|
||
ParByteModeRead(
|
||
IN PDEVICE_EXTENSION Extension,
|
||
IN PVOID Buffer,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG BytesTransferred
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine performs a 1284 byte mode read 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;
|
||
NTSTATUS Status = STATUS_SUCCESS;
|
||
PUCHAR lpsBufPtr = (PUCHAR)Buffer;
|
||
ULONG i;
|
||
UCHAR dsr, dcr;
|
||
UCHAR HDReady, HDAck, HDFinished;
|
||
|
||
Controller = Extension->Controller;
|
||
|
||
// Read Byte according to 1284 spec.
|
||
ParDump2(PARENTRY,("ParByteModeRead: Start\n"));
|
||
|
||
dcr = GetControl (Controller);
|
||
|
||
// Set Direction to be in reverse
|
||
dcr |= DCR_DIRECTION;
|
||
StoreControl (Controller, dcr);
|
||
|
||
HDReady = SET_DCR( ACTIVE, INACTIVE, ACTIVE, INACTIVE, INACTIVE, ACTIVE );
|
||
HDAck = SET_DCR( ACTIVE, INACTIVE, ACTIVE, INACTIVE, ACTIVE, INACTIVE );
|
||
HDFinished = SET_DCR( ACTIVE, INACTIVE, ACTIVE, INACTIVE, ACTIVE, ACTIVE );
|
||
|
||
switch (Extension->CurrentPhase) {
|
||
|
||
case PHASE_REVERSE_IDLE:
|
||
|
||
ParDump2(PARINFO,("ParByteModeRead: PHASE_REVERSE_IDLE\n"));
|
||
// Check to see if the peripheral has indicated Interrupt Phase and if so,
|
||
// get us ready to reverse transfer.
|
||
|
||
for (;;) {
|
||
|
||
// See if data is available (looking for state 7)
|
||
dsr = GetStatus(Controller);
|
||
|
||
if (dsr & DSR_NOT_DATA_AVAIL) {
|
||
|
||
// Data is NOT available - do nothing
|
||
// The device doesn't report any data, it still looks like it is
|
||
// in ReverseIdle. Just to make sure it hasn't powered off or somehow
|
||
// jumped out of Byte mode, test also for AckDataReq high and XFlag low
|
||
// and nDataAvaul high.
|
||
if( (dsr & DSR_BYTE_VALIDATION) != DSR_BYTE_TEST_RESULT ) {
|
||
|
||
Status = STATUS_IO_DEVICE_ERROR;
|
||
Extension->CurrentPhase = PHASE_UNKNOWN;
|
||
|
||
ParDump2(PARERRORS, ("ParByteModeRead:Failed State 7: Controller %x dcr %x\n",
|
||
Controller, dcr));
|
||
}
|
||
goto ByteReadExit;
|
||
|
||
} else {
|
||
|
||
// Data is available, go to Reverse Transfer Phase
|
||
Extension->CurrentPhase = PHASE_REVERSE_XFER ;
|
||
// Go to Reverse XFER phase
|
||
goto PhaseReverseXfer;
|
||
}
|
||
|
||
}
|
||
|
||
PhaseReverseXfer:
|
||
|
||
case PHASE_REVERSE_XFER:
|
||
|
||
ParDump2(PARINFO,("ParByteModeRead:PHASE_REVERSE_XFER\n"));
|
||
|
||
for (i = 0; i < BufferSize; i++) {
|
||
|
||
// Host enters state 7
|
||
StoreControl (Controller, HDReady);
|
||
|
||
// =============== Periph State 9 ===============8
|
||
// PeriphAck/PtrBusy = Don't Care
|
||
// PeriphClk/PtrClk = low (signals state 9)
|
||
// nAckReverse/AckDataReq = Don't Care
|
||
// XFlag = Don't Care
|
||
// nPeriphReq/nDataAvail = Don't Care
|
||
if (!CHECK_DSR(Controller,
|
||
DONT_CARE, INACTIVE, DONT_CARE,
|
||
DONT_CARE, DONT_CARE,
|
||
IEEE_MAXTIME_TL)) {
|
||
// Time out.
|
||
// Bad things happened - timed out on this state,
|
||
// Mark Status as bad and let our mgr kill current mode.
|
||
Status = STATUS_IO_DEVICE_ERROR;
|
||
|
||
ParDump2(PARERRORS, ("ParByteModeRead:Failed State 9: Controller %x dcr %x\n",
|
||
Controller, dcr));
|
||
Extension->CurrentPhase = PHASE_UNKNOWN;
|
||
goto ByteReadExit;
|
||
}
|
||
|
||
// Read the Byte
|
||
READ_PORT_BUFFER_UCHAR( Controller, lpsBufPtr++, (ULONG)0x01 );
|
||
|
||
// Set host lines to indicate state 10.
|
||
StoreControl (Controller, HDAck);
|
||
|
||
// =============== Periph State 11 ===============8
|
||
// PeriphAck/PtrBusy = Don't Care
|
||
// PeriphClk/PtrClk = High (signals state 11)
|
||
// nAckReverse/AckDataReq = Don't Care
|
||
// XFlag = Don't Care
|
||
// nPeriphReq/nDataAvail = Don't Care
|
||
if (!CHECK_DSR(Controller,
|
||
DONT_CARE, ACTIVE, DONT_CARE,
|
||
DONT_CARE, DONT_CARE,
|
||
IEEE_MAXTIME_TL)) {
|
||
// Time out.
|
||
// Bad things happened - timed out on this state,
|
||
// Mark Status as bad and let our mgr kill current mode.
|
||
Status = STATUS_IO_DEVICE_ERROR;
|
||
|
||
// Extension->IeeeTerminateIsOk = TRUE;
|
||
ParDump2(PARERRORS, ("ParByteModeRead:Failed State 11: Controller %x dcr %x\n",
|
||
Controller, dcr));
|
||
Extension->CurrentPhase = PHASE_UNKNOWN;
|
||
goto ByteReadExit;
|
||
}
|
||
|
||
|
||
// Set host lines to indicate state 16.
|
||
StoreControl (Controller, HDFinished);
|
||
|
||
// At this point, we've either received the number of bytes we
|
||
// were looking for, or the peripheral has no more data to
|
||
// send, or there was an error of some sort (of course, in the
|
||
// error case we shouldn't get to this comment). Set the
|
||
// phase to indicate reverse idle if no data available or
|
||
// reverse data transfer if there's some waiting for us
|
||
// to get next time.
|
||
|
||
dsr = GetStatus(Controller);
|
||
|
||
if (dsr & DSR_NOT_DATA_AVAIL) {
|
||
|
||
// Data is NOT available - go to Reverse Idle
|
||
// Really we are going to HBDNA, but if we set
|
||
// current phase to reverse idle, the next time
|
||
// we get into this function all we have to do
|
||
// is set hostbusy low to indicate idle and
|
||
// we have infinite time to do that.
|
||
// Break out of the loop so we don't try to read
|
||
// data that isn't there.
|
||
// NOTE - this is a successful case even if we
|
||
// didn't read all that the caller requested
|
||
Extension->CurrentPhase = PHASE_REVERSE_IDLE ;
|
||
i++; // account for this last byte transferred
|
||
break;
|
||
|
||
} else {
|
||
// Data is available, go to (remain in ) Reverse Transfer Phase
|
||
Extension->CurrentPhase = PHASE_REVERSE_XFER ;
|
||
}
|
||
|
||
} // end for i loop
|
||
|
||
*BytesTransferred = i;
|
||
|
||
dsr = GetStatus(Controller);
|
||
|
||
// DON'T FALL THRU THIS ONE
|
||
break;
|
||
|
||
default:
|
||
|
||
Status = STATUS_IO_DEVICE_ERROR;
|
||
Extension->CurrentPhase = PHASE_UNKNOWN ;
|
||
|
||
ParDump2(PARERRORS, ("ParByteModeRead:Failed State 9: Unknown Phase. Controller %x dcr %x\n",
|
||
Controller, dcr));
|
||
ParDump2(PARERRORS, ( "ParByteModeRead: You're hosed man.\n" ));
|
||
ParDump2(PARERRORS, ( "ParByteModeRead: If you are here, you've got a bug somewhere else.\n" ));
|
||
ParDump2(PARERRORS, ( "ParByteModeRead: Go fix it!\n" ));
|
||
goto ByteReadExit;
|
||
break;
|
||
} // end switch
|
||
|
||
ByteReadExit:
|
||
|
||
ParDump2(PARINFO,("ParByteModeRead:PHASE_REVERSE_IDLE\n"));
|
||
|
||
if( Extension->CurrentPhase == PHASE_REVERSE_IDLE ) {
|
||
// Host enters state 7 - officially in Reverse Idle now
|
||
dcr |= DCR_NOT_HOST_BUSY;
|
||
|
||
StoreControl (Controller, dcr);
|
||
}
|
||
|
||
// Set Direction to be in forward
|
||
dcr &= ~DCR_DIRECTION;
|
||
StoreControl (Controller, dcr);
|
||
|
||
ParDump2(PAREXIT,("ParByteModeRead:End [%d] bytes read = %d\n",
|
||
NT_SUCCESS(Status), *BytesTransferred));
|
||
Extension->log.ByteReadCount += *BytesTransferred;
|
||
return Status;
|
||
}
|
||
|