/*++ 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 PPDO_EXTENSION Pdx ) /*++ Routine Description: This routine determines whether or not byte mode is suported by trying to negotiate when asked. Arguments: Pdx - The device extension. Return Value: BOOLEAN. --*/ { NTSTATUS Status; if (Pdx->BadProtocolModes & BYTE_BIDIR) { DD((PCE)Pdx,DDT,"ParIsByteSupported - BAD PROTOCOL\n"); return FALSE; } if (!(Pdx->HardwareCapabilities & PPT_BYTE_PRESENT)) { DD((PCE)Pdx,DDT,"ParIsByteSupported - NO\n"); return FALSE; } if (Pdx->ProtocolModesSupported & BYTE_BIDIR) { DD((PCE)Pdx,DDT,"ParIsByteSupported - Already Checked - YES\n"); return TRUE; } // Must use Byte Enter and Terminate for this test. // Internel state machines will fail otherwise. --dvrh Status = ParEnterByteMode (Pdx, FALSE); ParTerminateByteMode (Pdx); if (NT_SUCCESS(Status)) { DD((PCE)Pdx,DDT,"ParIsByteSupported - SUCCESS\n"); Pdx->ProtocolModesSupported |= BYTE_BIDIR; return TRUE; } DD((PCE)Pdx,DDT,"ParIsByteSupported - UNSUCCESSFUL\n"); return FALSE; } NTSTATUS ParEnterByteMode( IN PPDO_EXTENSION Pdx, 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; // Make sure Byte mode Harware is still there Status = Pdx->TrySetChipMode( Pdx->PortContext, ECR_BYTE_PIO_MODE ); if( NT_SUCCESS(Status) ) { if ( SAFE_MODE == Pdx->ModeSafety ) { if( DeviceIdRequest ) { // RMT - not sure if we want to support non-nibble 1284 ID query Status = IeeeEnter1284Mode( Pdx, BYTE_EXTENSIBILITY | DEVICE_ID_REQ ); } else { Status = IeeeEnter1284Mode( Pdx, BYTE_EXTENSIBILITY ); } } else { // UNSAFE_MODE Pdx->Connected = TRUE; } } if (NT_SUCCESS(Status)) { P5SetPhase( Pdx, PHASE_REVERSE_IDLE ); Pdx->IsIeeeTerminateOk = TRUE; } else { ParTerminateByteMode ( Pdx ); P5SetPhase( Pdx, PHASE_UNKNOWN ); Pdx->IsIeeeTerminateOk = FALSE; } DD((PCE)Pdx,DDT,"ParEnterByteMode - exit w/Status=%x\n",Status); return Status; } VOID ParTerminateByteMode( 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. --*/ { if ( Pdx->ModeSafety == SAFE_MODE ) { IeeeTerminate1284Mode( Pdx ); } else { Pdx->Connected = FALSE; } Pdx->ClearChipMode( Pdx->PortContext, ECR_BYTE_PIO_MODE ); DD((PCE)Pdx,DDT,"ParTerminateByteMode - exit\n"); } NTSTATUS ParByteModeRead( IN PPDO_EXTENSION Pdx, 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: 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; NTSTATUS Status = STATUS_SUCCESS; PUCHAR lpsBufPtr = (PUCHAR)Buffer; ULONG i; UCHAR dsr, dcr; UCHAR HDReady, HDAck, HDFinished; Controller = Pdx->Controller; // Read Byte according to 1284 spec. DD((PCE)Pdx,DDT,"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( Pdx->CurrentPhase ) { case PHASE_REVERSE_IDLE: // 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; P5SetPhase( Pdx, PHASE_UNKNOWN ); DD((PCE)Pdx,DDE,"ParByteModeRead - Failed State 7 - dcr=%x\n",dcr); } goto ByteReadExit; } else { // Data is available, go to Reverse Transfer Phase P5SetPhase( Pdx, PHASE_REVERSE_XFER); // Go to Reverse XFER phase goto PhaseReverseXfer; } } PhaseReverseXfer: case PHASE_REVERSE_XFER: 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; DD((PCE)Pdx,DDE,"ParByteModeRead - Failed State 9 - dcr=%x\n",dcr); P5SetPhase( Pdx, PHASE_UNKNOWN ); goto ByteReadExit; } // Read the Byte P5ReadPortBufferUchar( 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; DD((PCE)Pdx,DDE,"ParByteModeRead - Failed State 11 - dcr=%x\n",dcr); P5SetPhase( Pdx, 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 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; dsr = GetStatus(Controller); // DON'T FALL THRU THIS ONE break; default: Status = STATUS_IO_DEVICE_ERROR; P5SetPhase( Pdx, PHASE_UNKNOWN ); DD((PCE)Pdx,DDE,"ParByteModeRead:Failed State 9: Unknown Phase - dcr=%x\n",dcr); goto ByteReadExit; } // end switch ByteReadExit: if( Pdx->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); DD((PCE)Pdx,DDT,"ParByteModeRead - exit, status=%x, bytes read=%d\n", Status, *BytesTransferred); Pdx->log.ByteReadCount += *BytesTransferred; return Status; }