390 lines
11 KiB
C
390 lines
11 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 PPDO_EXTENSION Pdx
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine determines whether or not byte mode is suported
|
||
by trying to negotiate when asked.
|
||
|
||
Arguments:
|
||
|
||
Pdx - The device extension.
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN.
|
||
|
||
--*/
|
||
{
|
||
NTSTATUS Status;
|
||
|
||
if (Pdx->BadProtocolModes & BYTE_BIDIR) {
|
||
DD((PCE)Pdx,DDT,"ParIsByteSupported - BAD PROTOCOL\n");
|
||
return FALSE;
|
||
}
|
||
|
||
if (!(Pdx->HardwareCapabilities & PPT_BYTE_PRESENT)) {
|
||
DD((PCE)Pdx,DDT,"ParIsByteSupported - NO\n");
|
||
return FALSE;
|
||
}
|
||
|
||
if (Pdx->ProtocolModesSupported & BYTE_BIDIR) {
|
||
DD((PCE)Pdx,DDT,"ParIsByteSupported - Already Checked - YES\n");
|
||
return TRUE;
|
||
}
|
||
|
||
// Must use Byte Enter and Terminate for this test.
|
||
// Internel state machines will fail otherwise. --dvrh
|
||
Status = ParEnterByteMode (Pdx, FALSE);
|
||
ParTerminateByteMode (Pdx);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
DD((PCE)Pdx,DDT,"ParIsByteSupported - SUCCESS\n");
|
||
Pdx->ProtocolModesSupported |= BYTE_BIDIR;
|
||
return TRUE;
|
||
}
|
||
|
||
DD((PCE)Pdx,DDT,"ParIsByteSupported - UNSUCCESSFUL\n");
|
||
return FALSE;
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEnterByteMode(
|
||
IN PPDO_EXTENSION Pdx,
|
||
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;
|
||
|
||
// Make sure Byte mode Harware is still there
|
||
Status = Pdx->TrySetChipMode( Pdx->PortContext, ECR_BYTE_PIO_MODE );
|
||
|
||
if( NT_SUCCESS(Status) ) {
|
||
|
||
if ( SAFE_MODE == Pdx->ModeSafety ) {
|
||
|
||
if( DeviceIdRequest ) {
|
||
// RMT - not sure if we want to support non-nibble 1284 ID query
|
||
Status = IeeeEnter1284Mode( Pdx, BYTE_EXTENSIBILITY | DEVICE_ID_REQ );
|
||
} else {
|
||
Status = IeeeEnter1284Mode( Pdx, BYTE_EXTENSIBILITY );
|
||
}
|
||
|
||
} else {
|
||
// UNSAFE_MODE
|
||
Pdx->Connected = TRUE;
|
||
}
|
||
|
||
}
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
|
||
P5SetPhase( Pdx, PHASE_REVERSE_IDLE );
|
||
Pdx->IsIeeeTerminateOk = TRUE;
|
||
|
||
} else {
|
||
|
||
ParTerminateByteMode ( Pdx );
|
||
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
||
Pdx->IsIeeeTerminateOk = FALSE;
|
||
}
|
||
|
||
DD((PCE)Pdx,DDT,"ParEnterByteMode - exit w/Status=%x\n",Status);
|
||
|
||
return Status;
|
||
}
|
||
|
||
VOID
|
||
ParTerminateByteMode(
|
||
IN PPDO_EXTENSION Pdx
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine terminates the interface back to compatibility mode.
|
||
|
||
Arguments:
|
||
|
||
Controller - Supplies the parallel port's controller address.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
if ( Pdx->ModeSafety == SAFE_MODE ) {
|
||
|
||
IeeeTerminate1284Mode( Pdx );
|
||
|
||
} else {
|
||
|
||
Pdx->Connected = FALSE;
|
||
|
||
}
|
||
|
||
Pdx->ClearChipMode( Pdx->PortContext, ECR_BYTE_PIO_MODE );
|
||
|
||
DD((PCE)Pdx,DDT,"ParTerminateByteMode - exit\n");
|
||
}
|
||
|
||
NTSTATUS
|
||
ParByteModeRead(
|
||
IN PPDO_EXTENSION Pdx,
|
||
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:
|
||
|
||
Pdx - 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 = Pdx->Controller;
|
||
|
||
// Read Byte according to 1284 spec.
|
||
DD((PCE)Pdx,DDT,"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( Pdx->CurrentPhase ) {
|
||
|
||
case PHASE_REVERSE_IDLE:
|
||
|
||
// 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;
|
||
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
||
|
||
DD((PCE)Pdx,DDE,"ParByteModeRead - Failed State 7 - dcr=%x\n",dcr);
|
||
}
|
||
goto ByteReadExit;
|
||
|
||
} else {
|
||
|
||
// Data is available, go to Reverse Transfer Phase
|
||
P5SetPhase( Pdx, PHASE_REVERSE_XFER);
|
||
// Go to Reverse XFER phase
|
||
goto PhaseReverseXfer;
|
||
}
|
||
|
||
}
|
||
|
||
PhaseReverseXfer:
|
||
|
||
case PHASE_REVERSE_XFER:
|
||
|
||
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;
|
||
|
||
DD((PCE)Pdx,DDE,"ParByteModeRead - Failed State 9 - dcr=%x\n",dcr);
|
||
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
||
goto ByteReadExit;
|
||
}
|
||
|
||
// Read the Byte
|
||
P5ReadPortBufferUchar( 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;
|
||
|
||
DD((PCE)Pdx,DDE,"ParByteModeRead - Failed State 11 - dcr=%x\n",dcr);
|
||
P5SetPhase( Pdx, 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
|
||
P5SetPhase( Pdx, PHASE_REVERSE_IDLE );
|
||
i++; // account for this last byte transferred
|
||
break;
|
||
|
||
} else {
|
||
// Data is available, go to (remain in ) Reverse Transfer Phase
|
||
P5SetPhase( Pdx, 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;
|
||
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
||
|
||
DD((PCE)Pdx,DDE,"ParByteModeRead:Failed State 9: Unknown Phase - dcr=%x\n",dcr);
|
||
goto ByteReadExit;
|
||
|
||
} // end switch
|
||
|
||
ByteReadExit:
|
||
|
||
if( Pdx->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);
|
||
|
||
DD((PCE)Pdx,DDT,"ParByteModeRead - exit, status=%x, bytes read=%d\n", Status, *BytesTransferred);
|
||
Pdx->log.ByteReadCount += *BytesTransferred;
|
||
return Status;
|
||
}
|
||
|