320 lines
7.8 KiB
C
320 lines
7.8 KiB
C
/*++
|
||
|
||
Copyright (C) Microsoft Corporation, 1993 - 1999
|
||
|
||
Module Name:
|
||
|
||
epp.c
|
||
|
||
Abstract:
|
||
|
||
This module contains the code to perform all Hardware EPP related tasks.
|
||
|
||
Author:
|
||
|
||
Don Redford - July 30, 1998
|
||
|
||
Environment:
|
||
|
||
Kernel mode
|
||
|
||
Revision History :
|
||
|
||
--*/
|
||
|
||
#include "pch.h"
|
||
|
||
|
||
BOOLEAN
|
||
ParIsEppHwSupported(
|
||
IN PPDO_EXTENSION Pdx
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine determines whether or not HW EPP mode is suported
|
||
for either direction by negotiating when asked.
|
||
|
||
Arguments:
|
||
|
||
Pdx - The device extension.
|
||
|
||
Return Value:
|
||
|
||
BOOLEAN.
|
||
|
||
--*/
|
||
|
||
{
|
||
|
||
NTSTATUS Status;
|
||
|
||
DD((PCE)Pdx,DDT,"ParIsEppHwWriteSupported: Entering\n");
|
||
|
||
// Check to see if the hardware is capable
|
||
if (!(Pdx->HardwareCapabilities & PPT_EPP_PRESENT)) {
|
||
DD((PCE)Pdx,DDT,"ParIsEppHwWriteSupported: Hardware Not Supported Leaving\n");
|
||
return FALSE;
|
||
}
|
||
|
||
if (Pdx->BadProtocolModes & EPP_HW) {
|
||
DD((PCE)Pdx,DDT,"ParIsEppHwWriteSupported: Bad Protocol Not Supported Leaving\n");
|
||
return FALSE;
|
||
}
|
||
|
||
if (Pdx->ProtocolModesSupported & EPP_HW) {
|
||
DD((PCE)Pdx,DDT,"ParIsEppHwWriteSupported: Already Checked Supported Leaving\n");
|
||
return TRUE;
|
||
}
|
||
|
||
// Must use HWEPP Enter and Terminate for this test.
|
||
// Internel state machines will fail otherwise. --dvrh
|
||
Status = ParEnterEppHwMode (Pdx, FALSE);
|
||
ParTerminateEppHwMode (Pdx);
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
DD((PCE)Pdx,DDT,"ParIsEppHwWriteSupported: Negotiated Supported Leaving\n");
|
||
Pdx->ProtocolModesSupported |= EPP_HW;
|
||
return TRUE;
|
||
}
|
||
|
||
DD((PCE)Pdx,DDT,"ParIsEppHwWriteSupported: Not Negotiated Not Supported Leaving\n");
|
||
return FALSE;
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEnterEppHwMode(
|
||
IN PPDO_EXTENSION Pdx,
|
||
IN BOOLEAN DeviceIdRequest
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine performs 1284 negotiation with the peripheral to the
|
||
EPP 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;
|
||
|
||
DD((PCE)Pdx,DDT,"ParEnterEppHwMode: Entering\n");
|
||
|
||
if ( Pdx->ModeSafety == SAFE_MODE ) {
|
||
if (DeviceIdRequest) {
|
||
DD((PCE)Pdx,DDT,"ParEnterEppHwMode: Calling IeeeEnter1284Mode with DEVICE_ID_REQUEST\n");
|
||
Status = IeeeEnter1284Mode (Pdx, EPP_EXTENSIBILITY | DEVICE_ID_REQ);
|
||
} else {
|
||
DD((PCE)Pdx,DDT,"ParEnterEppHwMode: Calling IeeeEnter1284Mode\n");
|
||
Status = IeeeEnter1284Mode (Pdx, EPP_EXTENSIBILITY);
|
||
}
|
||
} else {
|
||
DD((PCE)Pdx,DDT,"ParEnterEppHwMode: In UNSAFE_MODE.\n");
|
||
Pdx->Connected = TRUE;
|
||
}
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
Status = Pdx->TrySetChipMode ( Pdx->PortContext, ECR_EPP_PIO_MODE );
|
||
|
||
if (NT_SUCCESS(Status)) {
|
||
DD((PCE)Pdx,DDT,"ParEnterEppHwMode: IeeeEnter1284Mode returned success\n");
|
||
P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
|
||
Pdx->IsIeeeTerminateOk = TRUE;
|
||
} else {
|
||
DD((PCE)Pdx,DDT,"ParEnterEppHwMode: TrySetChipMode returned unsuccessful\n");
|
||
ParTerminateEppHwMode ( Pdx );
|
||
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
||
Pdx->IsIeeeTerminateOk = FALSE;
|
||
}
|
||
} else {
|
||
DD((PCE)Pdx,DDT,"ParEnterEppHwMode: IeeeEnter1284Mode returned unsuccessful\n");
|
||
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
||
Pdx->IsIeeeTerminateOk = FALSE;
|
||
}
|
||
|
||
DD((PCE)Pdx,DDT,"ParEnterEppHwMode: Leaving with Status : %x \n", Status);
|
||
|
||
return Status;
|
||
}
|
||
|
||
VOID
|
||
ParTerminateEppHwMode(
|
||
IN PPDO_EXTENSION Pdx
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine terminates the interface back to compatibility mode.
|
||
|
||
Arguments:
|
||
|
||
Pdx - The Device Extension which has the parallel port's controller address.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
|
||
{
|
||
DD((PCE)Pdx,DDT,"ParTerminateEppMode: Entering\n");
|
||
Pdx->ClearChipMode( Pdx->PortContext, ECR_EPP_PIO_MODE );
|
||
if ( Pdx->ModeSafety == SAFE_MODE ) {
|
||
IeeeTerminate1284Mode ( Pdx );
|
||
} else {
|
||
DD((PCE)Pdx,DDT,"ParTerminateEppMode: In UNSAFE_MODE.\n");
|
||
Pdx->Connected = FALSE;
|
||
}
|
||
DD((PCE)Pdx,DDT,"ParTerminateEppMode: Leaving\n");
|
||
return;
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEppHwWrite(
|
||
IN PPDO_EXTENSION Pdx,
|
||
IN PVOID Buffer,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG BytesTransferred
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Writes data to the peripheral using the EPP using Hardware flow control.
|
||
|
||
Arguments:
|
||
|
||
Pdx - Supplies the device extension.
|
||
|
||
Buffer - Supplies the buffer to write from.
|
||
|
||
BufferSize - Supplies the number of bytes in the buffer.
|
||
|
||
BytesTransferred - Returns the number of bytes transferred.
|
||
|
||
Return Value:
|
||
|
||
None.
|
||
|
||
--*/
|
||
{
|
||
PUCHAR wPortEPP;
|
||
PUCHAR pBuffer;
|
||
ULONG ulongSize = 0; // represents how many ULONG's we are transfering if enabled
|
||
|
||
DD((PCE)Pdx,DDT,"ParEppHwWrite: Entering\n");
|
||
|
||
wPortEPP = Pdx->Controller + EPP_OFFSET;
|
||
pBuffer = Buffer;
|
||
|
||
P5SetPhase( Pdx, PHASE_FORWARD_XFER );
|
||
|
||
// Check to see if hardware supports 32 bit reads and writes
|
||
if ( Pdx->HardwareCapabilities & PPT_EPP_32_PRESENT ) {
|
||
if ( !(BufferSize % 4) )
|
||
ulongSize = BufferSize >> 2;
|
||
}
|
||
|
||
// ulongSize != 0 so EPP 32 bit is enabled and Buffersize / 4
|
||
if ( ulongSize ) {
|
||
WRITE_PORT_BUFFER_ULONG( (PULONG)wPortEPP,
|
||
(PULONG)pBuffer,
|
||
ulongSize );
|
||
} else {
|
||
P5WritePortBufferUchar( wPortEPP,
|
||
(PUCHAR)pBuffer,
|
||
BufferSize );
|
||
}
|
||
|
||
P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
|
||
|
||
*BytesTransferred = BufferSize;
|
||
|
||
DD((PCE)Pdx,DDT,"ParEppHwWrite: Leaving with %i Bytes Transferred\n", BufferSize);
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|
||
|
||
NTSTATUS
|
||
ParEppHwRead(
|
||
IN PPDO_EXTENSION Pdx,
|
||
IN PVOID Buffer,
|
||
IN ULONG BufferSize,
|
||
OUT PULONG BytesTransferred
|
||
)
|
||
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
This routine performs a 1284 EPP mode read under software control
|
||
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 wPortEPP;
|
||
PUCHAR pBuffer;
|
||
ULONG ulongSize = 0; // represents how many ULONG's we are transfering if enabled
|
||
|
||
DD((PCE)Pdx,DDT,"ParEppHwRead: Entering\n");
|
||
|
||
wPortEPP = Pdx->Controller + EPP_OFFSET;
|
||
pBuffer = Buffer;
|
||
P5SetPhase( Pdx, PHASE_REVERSE_XFER );
|
||
|
||
// Check to see if hardware supports 32 bit reads and writes
|
||
if ( Pdx->HardwareCapabilities & PPT_EPP_32_PRESENT ) {
|
||
if ( !(BufferSize % 4) )
|
||
ulongSize = BufferSize >> 2;
|
||
}
|
||
|
||
// ulongSize != 0 so EPP 32 bit is enabled and Buffersize / 4
|
||
if ( ulongSize ) {
|
||
READ_PORT_BUFFER_ULONG( (PULONG)wPortEPP,
|
||
(PULONG)pBuffer,
|
||
ulongSize );
|
||
} else {
|
||
P5ReadPortBufferUchar( wPortEPP,
|
||
(PUCHAR)pBuffer,
|
||
BufferSize );
|
||
}
|
||
|
||
P5SetPhase( Pdx, PHASE_FORWARD_IDLE );
|
||
*BytesTransferred = BufferSize;
|
||
|
||
DD((PCE)Pdx,DDT,"ParEppHwRead: Leaving with %i Bytes Transferred\n", BufferSize);
|
||
|
||
return STATUS_SUCCESS;
|
||
}
|