Source code of Windows XP (NT5)
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

/*++
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;
}