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.
672 lines
22 KiB
672 lines
22 KiB
/*++
|
|
|
|
Copyright (C) Microsoft Corporation, 1993 - 1999
|
|
|
|
Module Name:
|
|
|
|
nibble.c
|
|
|
|
Abstract:
|
|
|
|
This module contains the code to do nibble mode reads.
|
|
|
|
Author:
|
|
|
|
Anthony V. Ercolano 1-Aug-1992
|
|
Norbert P. Kusters 22-Oct-1993
|
|
|
|
Environment:
|
|
|
|
Kernel mode
|
|
|
|
Revision History :
|
|
|
|
--*/
|
|
|
|
#include "pch.h"
|
|
|
|
BOOLEAN
|
|
ParIsNibbleSupported(
|
|
IN PPDO_EXTENSION Pdx
|
|
);
|
|
|
|
BOOLEAN
|
|
ParIsChannelizedNibbleSupported(
|
|
IN PPDO_EXTENSION Pdx
|
|
);
|
|
|
|
NTSTATUS
|
|
ParEnterNibbleMode(
|
|
IN PPDO_EXTENSION Pdx,
|
|
IN BOOLEAN DeviceIdRequest
|
|
);
|
|
|
|
NTSTATUS
|
|
ParEnterChannelizedNibbleMode(
|
|
IN PPDO_EXTENSION Pdx,
|
|
IN BOOLEAN DeviceIdRequest
|
|
);
|
|
|
|
VOID
|
|
ParTerminateNibbleMode(
|
|
IN PPDO_EXTENSION Pdx
|
|
);
|
|
|
|
NTSTATUS
|
|
ParNibbleModeRead(
|
|
IN PPDO_EXTENSION Pdx,
|
|
IN PVOID Buffer,
|
|
IN ULONG BufferSize,
|
|
OUT PULONG BytesTransferred
|
|
);
|
|
|
|
|
|
BOOLEAN
|
|
ParIsNibbleSupported(
|
|
IN PPDO_EXTENSION Pdx
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine determines whether or not nibble mode is suported
|
|
by trying to negotiate when asked.
|
|
|
|
Arguments:
|
|
|
|
Pdx - The device extension.
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
if (Pdx->BadProtocolModes & NIBBLE) {
|
|
DD((PCE)Pdx,DDT,"ParIsNibbleSupported: BAD PROTOCOL Leaving\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (Pdx->ProtocolModesSupported & NIBBLE) {
|
|
DD((PCE)Pdx,DDT,"ParIsNibbleSupported: Already Checked YES Leaving\n");
|
|
return TRUE;
|
|
}
|
|
|
|
Status = ParEnterNibbleMode (Pdx, FALSE);
|
|
ParTerminateNibbleMode (Pdx);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
DD((PCE)Pdx,DDT,"ParIsNibbleSupported: SUCCESS Leaving\n");
|
|
Pdx->ProtocolModesSupported |= NIBBLE;
|
|
return TRUE;
|
|
}
|
|
|
|
DD((PCE)Pdx,DDT,"ParIsNibbleSupported: UNSUCCESSFUL Leaving\n");
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
BOOLEAN
|
|
ParIsChannelizedNibbleSupported(
|
|
IN PPDO_EXTENSION Pdx
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine determines whether or not channelized nibble mode is suported (1284.3)
|
|
by trying to negotiate when asked.
|
|
|
|
Arguments:
|
|
|
|
Pdx - The device extension.
|
|
|
|
Return Value:
|
|
|
|
BOOLEAN.
|
|
|
|
--*/
|
|
|
|
{
|
|
|
|
NTSTATUS Status;
|
|
|
|
if (Pdx->BadProtocolModes & CHANNEL_NIBBLE) {
|
|
DD((PCE)Pdx,DDT,"ParIsChannelizedNibbleSupported: BAD PROTOCOL Leaving\n");
|
|
return FALSE;
|
|
}
|
|
|
|
if (Pdx->ProtocolModesSupported & CHANNEL_NIBBLE) {
|
|
DD((PCE)Pdx,DDT,"ParIsChannelizedNibbleSupported: Already Checked YES Leaving\n");
|
|
return TRUE;
|
|
}
|
|
|
|
Status = ParEnterChannelizedNibbleMode (Pdx, FALSE);
|
|
ParTerminateNibbleMode (Pdx);
|
|
|
|
if (NT_SUCCESS(Status)) {
|
|
DD((PCE)Pdx,DDT,"ParIsChannelizedNibbleSupported: SUCCESS Leaving\n");
|
|
Pdx->ProtocolModesSupported |= CHANNEL_NIBBLE;
|
|
return TRUE;
|
|
}
|
|
|
|
DD((PCE)Pdx,DDT,"ParIsChannelizedNibbleSupported: UNSUCCESSFUL Leaving\n");
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
NTSTATUS
|
|
ParEnterNibbleMode(
|
|
IN PPDO_EXTENSION Pdx,
|
|
IN BOOLEAN DeviceIdRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine performs 1284 negotiation with the peripheral to the
|
|
nibble 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,"ParEnterNibbleMode: Start\n");
|
|
|
|
if ( Pdx->ModeSafety == SAFE_MODE ) {
|
|
if (DeviceIdRequest) {
|
|
Status = IeeeEnter1284Mode (Pdx, NIBBLE_EXTENSIBILITY | DEVICE_ID_REQ);
|
|
} else {
|
|
Status = IeeeEnter1284Mode (Pdx, NIBBLE_EXTENSIBILITY);
|
|
}
|
|
} else {
|
|
DD((PCE)Pdx,DDT,"ParEnterNibbleMode: In UNSAFE_MODE.\n");
|
|
Pdx->Connected = TRUE;
|
|
}
|
|
|
|
// dvdr
|
|
if (NT_SUCCESS(Status)) {
|
|
DD((PCE)Pdx,DDT,"ParEnterNibbleMode: IeeeEnter1284Mode returned success\n");
|
|
Pdx->CurrentEvent = 6;
|
|
P5SetPhase( Pdx, PHASE_NEGOTIATION );
|
|
Pdx->IsIeeeTerminateOk = TRUE;
|
|
} else {
|
|
DD((PCE)Pdx,DDT,"ParEnterNibbleMode: IeeeEnter1284Mode returned unsuccessful\n");
|
|
ParTerminateNibbleMode ( Pdx );
|
|
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
|
Pdx->IsIeeeTerminateOk = FALSE;
|
|
}
|
|
|
|
DD((PCE)Pdx,DDT,"ParEnterNibbleMode: Leaving with Status : %x \n", Status);
|
|
|
|
return Status;
|
|
}
|
|
|
|
NTSTATUS
|
|
ParEnterChannelizedNibbleMode(
|
|
IN PPDO_EXTENSION Pdx,
|
|
IN BOOLEAN DeviceIdRequest
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine performs 1284 negotiation with the peripheral to the
|
|
nibble 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,"ParEnterChannelizedNibbleMode: Start\n");
|
|
|
|
if ( Pdx->ModeSafety == SAFE_MODE ) {
|
|
if (DeviceIdRequest) {
|
|
Status = IeeeEnter1284Mode (Pdx, CHANNELIZED_EXTENSIBILITY | DEVICE_ID_REQ);
|
|
} else {
|
|
Status = IeeeEnter1284Mode (Pdx, CHANNELIZED_EXTENSIBILITY);
|
|
}
|
|
} else {
|
|
DD((PCE)Pdx,DDT,"ParEnterChannelizedNibbleMode: In UNSAFE_MODE.\n");
|
|
Pdx->Connected = TRUE;
|
|
}
|
|
|
|
// dvdr
|
|
if (NT_SUCCESS(Status)) {
|
|
DD((PCE)Pdx,DDT,"ParEnterChannelizedNibbleMode: IeeeEnter1284Mode returned success\n");
|
|
Pdx->CurrentEvent = 6;
|
|
P5SetPhase( Pdx, PHASE_NEGOTIATION );
|
|
Pdx->IsIeeeTerminateOk = TRUE;
|
|
} else {
|
|
DD((PCE)Pdx,DDT,"ParEnterChannelizedNibbleMode: IeeeEnter1284Mode returned unsuccessful\n");
|
|
ParTerminateNibbleMode ( Pdx );
|
|
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
|
Pdx->IsIeeeTerminateOk = FALSE;
|
|
}
|
|
|
|
DD((PCE)Pdx,DDT,"ParEnterChannelizedNibbleMode: Leaving with Status : %x \n", Status);
|
|
return Status;
|
|
}
|
|
|
|
VOID
|
|
ParTerminateNibbleMode(
|
|
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.
|
|
|
|
--*/
|
|
|
|
{
|
|
DD((PCE)Pdx,DDT,"ParTerminateNibbleMode: Enter.\n");
|
|
if ( Pdx->ModeSafety == SAFE_MODE ) {
|
|
IeeeTerminate1284Mode (Pdx);
|
|
} else {
|
|
DD((PCE)Pdx,DDT,"ParTerminateNibbleMode: In UNSAFE_MODE.\n");
|
|
Pdx->Connected = FALSE;
|
|
}
|
|
DD((PCE)Pdx,DDT,"ParTerminateNibbleMode: Exit.\n");
|
|
}
|
|
|
|
NTSTATUS
|
|
ParNibbleModeRead(
|
|
IN PPDO_EXTENSION Pdx,
|
|
IN PVOID Buffer,
|
|
IN ULONG BufferSize,
|
|
OUT PULONG BytesTransferred
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This routine performs a 1284 nibble 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;
|
|
PUCHAR wPortDCR;
|
|
PUCHAR wPortDSR;
|
|
NTSTATUS Status = STATUS_SUCCESS;
|
|
PUCHAR p = (PUCHAR)Buffer;
|
|
UCHAR dsr, dcr;
|
|
UCHAR nibble[2];
|
|
ULONG i, j;
|
|
|
|
Controller = Pdx->Controller;
|
|
wPortDCR = Controller + OFFSET_DCR;
|
|
wPortDSR = Controller + OFFSET_DSR;
|
|
|
|
// Read nibbles according to 1284 spec.
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead - enter\n");
|
|
|
|
dcr = P5ReadPortUchar(wPortDCR);
|
|
|
|
switch (Pdx->CurrentPhase) {
|
|
|
|
case PHASE_NEGOTIATION:
|
|
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead - case PHASE_NEGOTIATION\n");
|
|
|
|
// Starting in state 6 - where do we go from here?
|
|
// To Reverse Idle or Reverse Data Transfer Phase depending if
|
|
// data is available.
|
|
|
|
dsr = P5ReadPortUchar(wPortDSR);
|
|
|
|
// =============== Periph State 6 ===============8
|
|
// PeriphAck/PtrBusy = Don't Care
|
|
// PeriphClk/PtrClk = Don't Care (should be high
|
|
// and the nego. proc already
|
|
// checked this)
|
|
// nAckReverse/AckDataReq = Don't Care (should be high)
|
|
// XFlag = Don't Care (should be low)
|
|
// nPeriphReq/nDataAvail = High/Low (line status determines
|
|
// which state we move to)
|
|
Pdx->CurrentEvent = 6;
|
|
#if (0 == DVRH_USE_NIBBLE_MACROS)
|
|
if (dsr & DSR_NOT_DATA_AVAIL)
|
|
#else
|
|
if (TEST_DSR(dsr, DONT_CARE, DONT_CARE, DONT_CARE, DONT_CARE, ACTIVE ))
|
|
#endif
|
|
{
|
|
// Data is NOT available - go to Reverse Idle
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead - now in PHASE_REVERSE_IDLE\n");
|
|
// Host enters state 7 - officially in Reverse Idle now
|
|
|
|
// Must stall for at least .5 microseconds before this state.
|
|
KeStallExecutionProcessor(1);
|
|
|
|
/* =============== Host State 7 Nibble Reverse Idle ===============8
|
|
DIR = Don't Care
|
|
IRQEN = Don't Care
|
|
1284/SelectIn = High
|
|
nReverseReq/ (ECP only)= Don't Care
|
|
HostAck/HostBusy = Low (signals State 7)
|
|
HostClk/nStrobe = High
|
|
============================================================ */
|
|
Pdx->CurrentEvent = 7;
|
|
#if (0 == DVRH_USE_NIBBLE_MACROS)
|
|
dcr |= DCR_NOT_HOST_BUSY;
|
|
#else
|
|
dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE, INACTIVE, ACTIVE);
|
|
#endif
|
|
P5WritePortUchar(wPortDCR, dcr);
|
|
|
|
P5SetPhase( Pdx, PHASE_REVERSE_IDLE );
|
|
// FALL THRU TO reverse idle
|
|
} else {
|
|
|
|
// Data is available, go to Reverse Transfer Phase
|
|
P5SetPhase( Pdx, PHASE_REVERSE_XFER );
|
|
// DO NOT fall thru
|
|
goto PhaseReverseXfer; // please save me from my sins!
|
|
}
|
|
|
|
|
|
case PHASE_REVERSE_IDLE:
|
|
|
|
// Check to see if the peripheral has indicated Interrupt Phase and if so,
|
|
// get us ready to reverse transfer.
|
|
|
|
// See if data is available (looking for state 19)
|
|
dsr = P5ReadPortUchar(Controller + OFFSET_DSR);
|
|
|
|
if (!(dsr & DSR_NOT_DATA_AVAIL)) {
|
|
|
|
dcr = P5ReadPortUchar(wPortDCR);
|
|
// =========== Host State 20 Interrupt Phase ===========8
|
|
// DIR = Don't Care
|
|
// IRQEN = Don't Care
|
|
// 1284/SelectIn = High
|
|
// nReverseReq/ (ECP only) = Don't Care
|
|
// HostAck/HostBusy = High (Signals state 20)
|
|
// HostClk/nStrobe = High
|
|
//
|
|
// Data is available, get us to Reverse Transfer Phase
|
|
Pdx->CurrentEvent = 20;
|
|
dcr = UPDATE_DCR(dcr, DONT_CARE, DONT_CARE, ACTIVE, DONT_CARE, ACTIVE, ACTIVE);
|
|
P5WritePortUchar(wPortDCR, dcr);
|
|
|
|
// =============== Periph State 21 HBDA ===============8
|
|
// PeriphAck/PtrBusy = Don't Care
|
|
// PeriphClk/PtrClk = Don't Care (should be high)
|
|
// nAckReverse/AckDataReq = low (signals state 21)
|
|
// XFlag = Don't Care (should be low)
|
|
// nPeriphReq/nDataAvail = Don't Care (should be low)
|
|
Pdx->CurrentEvent = 21;
|
|
if (CHECK_DSR(Controller,
|
|
DONT_CARE, DONT_CARE, INACTIVE,
|
|
DONT_CARE, DONT_CARE,
|
|
IEEE_MAXTIME_TL)) {
|
|
|
|
// Got state 21
|
|
// Let's jump to Reverse Xfer and get the data
|
|
P5SetPhase( Pdx, PHASE_REVERSE_XFER );
|
|
goto PhaseReverseXfer;
|
|
|
|
} else {
|
|
|
|
// Timeout on state 21
|
|
Pdx->IsIeeeTerminateOk = TRUE;
|
|
Status = STATUS_IO_DEVICE_ERROR;
|
|
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead - Failed State 21: Controller %x dcr %x\n", Controller, dcr);
|
|
// NOTE: Don't ASSERT Here. An Assert here can bite you if you are in
|
|
// Nibble Rev and you device is off/offline.
|
|
// dvrh 2/25/97
|
|
goto NibbleReadExit;
|
|
}
|
|
|
|
} else {
|
|
|
|
// 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 Nibble mode, test also for AckDataReq high and XFlag low
|
|
// and nDataAvaul high.
|
|
Pdx->CurrentEvent = 18;
|
|
dsr = P5ReadPortUchar(Controller + OFFSET_DSR);
|
|
if(( dsr & DSR_NIBBLE_VALIDATION )== DSR_NIBBLE_TEST_RESULT ) {
|
|
|
|
P5SetPhase( Pdx, PHASE_REVERSE_IDLE );
|
|
|
|
} else {
|
|
#if DVRH_BUS_RESET_ON_ERROR
|
|
BusReset(wPortDCR); // Pass in the dcr address
|
|
#endif
|
|
// Appears we failed state 19.
|
|
Pdx->IsIeeeTerminateOk = TRUE;
|
|
Status = STATUS_IO_DEVICE_ERROR;
|
|
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead - Failed State 19: Controller %x dcr %x\n", Controller, dcr);
|
|
}
|
|
goto NibbleReadExit;
|
|
|
|
}
|
|
|
|
PhaseReverseXfer:
|
|
|
|
case PHASE_REVERSE_XFER:
|
|
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead - case PHASE_REVERSE_IDLE\n");
|
|
|
|
for (i = 0; i < BufferSize; i++) {
|
|
|
|
for (j = 0; j < 2; j++) {
|
|
|
|
// Host enters state 7 or 12 depending if nibble 1 or 2
|
|
// StoreControl (Controller, HDReady);
|
|
dcr |= DCR_NOT_HOST_BUSY;
|
|
P5WritePortUchar(wPortDCR, dcr);
|
|
|
|
// =============== Periph State 9 ===============8
|
|
// PeriphAck/PtrBusy = Don't Care (Bit 3 of Nibble)
|
|
// PeriphClk/PtrClk = low (signals state 9)
|
|
// nAckReverse/AckDataReq = Don't Care (Bit 2 of Nibble)
|
|
// XFlag = Don't Care (Bit 1 of Nibble)
|
|
// nPeriphReq/nDataAvail = Don't Care (Bit 0 of Nibble)
|
|
Pdx->CurrentEvent = 9;
|
|
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.
|
|
|
|
Pdx->IsIeeeTerminateOk = FALSE;
|
|
Status = STATUS_IO_DEVICE_ERROR;
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead - Failed State 9: Controller %x dcr %x\n", Controller, dcr);
|
|
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
|
goto NibbleReadExit;
|
|
}
|
|
|
|
// Read Nibble
|
|
nibble[j] = P5ReadPortUchar(wPortDSR);
|
|
|
|
/* ============== Host State 10 Nibble Read ===============8
|
|
DIR = Don't Care
|
|
IRQEN = Don't Care
|
|
1284/SelectIn = High
|
|
HostAck/HostBusy = High (signals State 10)
|
|
HostClk/nStrobe = High
|
|
============================================================ */
|
|
Pdx->CurrentEvent = 10;
|
|
dcr &= ~DCR_NOT_HOST_BUSY;
|
|
P5WritePortUchar(wPortDCR, dcr);
|
|
|
|
// =============== Periph State 11 ===============8
|
|
// PeriphAck/PtrBusy = Don't Care (Bit 3 of Nibble)
|
|
// PeriphClk/PtrClk = High (signals state 11)
|
|
// nAckReverse/AckDataReq = Don't Care (Bit 2 of Nibble)
|
|
// XFlag = Don't Care (Bit 1 of Nibble)
|
|
// nPeriphReq/nDataAvail = Don't Care (Bit 0 of Nibble)
|
|
Pdx->CurrentEvent = 11;
|
|
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;
|
|
Pdx->IsIeeeTerminateOk = FALSE;
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead - Failed State 11: Controller %x dcr %x\n", Controller, dcr);
|
|
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
|
goto NibbleReadExit;
|
|
}
|
|
}
|
|
|
|
// Read two nibbles - make them into one byte.
|
|
|
|
p[i] = (((nibble[0]&0x38)>>3)&0x07) | ((nibble[0]&0x80) ? 0x00 : 0x08);
|
|
p[i] |= (((nibble[1]&0x38)<<1)&0x70) | ((nibble[1]&0x80) ? 0x00 : 0x80);
|
|
|
|
// RMT - put this back in if needed - DD((PCE)Pdx,DDT,"ParNibbleModeRead:%x:%c\n", p[i], p[i]);
|
|
|
|
// 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 = P5ReadPortUchar(wPortDSR);
|
|
|
|
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;
|
|
// DON'T FALL THRU THIS ONE
|
|
break;
|
|
|
|
default:
|
|
// I'm gonna mark this as false. There is not a correct answer here.
|
|
// The peripheral and the host are out of sync. I'm gonna reset myself
|
|
// and the peripheral.
|
|
Pdx->IsIeeeTerminateOk = FALSE;
|
|
Status = STATUS_IO_DEVICE_ERROR;
|
|
P5SetPhase( Pdx, PHASE_UNKNOWN );
|
|
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead - Failed State 9: Unknown Phase. Controller %x dcr %x\n", Controller, dcr);
|
|
DD((PCE)Pdx,DDT, "ParNibbleModeRead: You're hosed man.\n" );
|
|
DD((PCE)Pdx,DDT, "ParNibbleModeRead: If you are here, you've got a bug somewhere else.\n" );
|
|
DD((PCE)Pdx,DDT, "ParNibbleModeRead: Go fix it!\n" );
|
|
goto NibbleReadExit;
|
|
break;
|
|
} // end switch
|
|
|
|
NibbleReadExit:
|
|
|
|
if( Pdx->CurrentPhase == PHASE_REVERSE_IDLE ) {
|
|
// Host enters state 7 - officially in Reverse Idle now
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead - PHASE_REVERSE_IDLE\n");
|
|
dcr |= DCR_NOT_HOST_BUSY;
|
|
P5WritePortUchar (wPortDCR, dcr);
|
|
}
|
|
|
|
DD((PCE)Pdx,DDT,"ParNibbleModeRead:End [%d] bytes read = %d\n", NT_SUCCESS(Status), *BytesTransferred);
|
|
Pdx->log.NibbleReadCount += *BytesTransferred;
|
|
|
|
#if 1 == DBG_SHOW_BYTES
|
|
if( DbgShowBytes ) {
|
|
if( NT_SUCCESS( Status ) && (*BytesTransferred > 0) ) {
|
|
const ULONG maxBytes = 32;
|
|
ULONG i;
|
|
PUCHAR bytePtr = (PUCHAR)Buffer;
|
|
DbgPrint("n: ");
|
|
for( i=0 ; (i < *BytesTransferred) && (i < maxBytes ) ; ++i ) {
|
|
DbgPrint("%02x ",*bytePtr++);
|
|
}
|
|
if( *BytesTransferred > maxBytes ) {
|
|
DbgPrint("... ");
|
|
}
|
|
DbgPrint("zz\n");
|
|
}
|
|
}
|
|
#endif
|
|
|
|
return Status;
|
|
}
|
|
|