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;
|
|||
|
}
|
|||
|
|