mirror of https://github.com/tongzx/nt5src
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
438 lines
13 KiB
438 lines
13 KiB
/*++
|
|
|
|
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;
|
|
}
|
|
|