📄 nibble.c
字号:
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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -