1284comm.c

来自「WinCE 3.0 BSP, 包含Inter SA1110, Intel_815」· C语言 代码 · 共 768 行 · 第 1/2 页

C
768
字号
#endif

// The following values are used during nibble mode read opeations.
#define NM_CONTROL_MASK         0xF0    // 1111 0000
#define NM_INT_MASK             0x60    // 0110 0000
#define NM_INTERRUPT            0x40    // 0100 0000
#define NM_HOSTBUSY             0x02    // 0000 0010
#define NM_INIT                 0x04    // 0000 0100


#define NM_PTRCLK_MASK          0x40    // 0100 0000
#define NM_PTRCLK_HI            0x40    // 0100 0000
#define NM_PTRCLK_LO            0x00    // 0000 0000

//---------------------------------------------------------------------------
BYTE
AssembleNibbles
(
    BYTE bLoNib,
    BYTE bHiNib
)
// PURPOSE
//  Assemble nibbles into a byte.
//
// ASSUMPTIONS & ASSERTIONS
//  Status bits and nibble bits are mapped as follow,
//      x--- ----: Busy          : bit 3, 7
//      --x- ----: PError   : bit 2, 6
//      ---x ----: Select   : bit 1, 5
//      ---- x---: nFault   : bit 0, 4
//
// INTERNAL STRUCTURES
//
// UNRESOLVED ISSUES
//
// RETURNS
//  a byte data.
//---------------------------------------------------------------------------
{
#if x86
   _asm {
        push ax
        mov  al, bLoNib
        rcl  al, 1
        jc   lo_set
        or   ax, 0x80
        jmp  lo_nib
   lo_set:
        and  ax, 0x7F
   lo_nib:
        shr  al, 4

        mov  ah, bHiNib
        rcl  ah, 1
        jc   hi_set
        or   ax, 0x8000
        jmp  hi_nib
   hi_set:
        and  ax, 0x7fff
   hi_nib:
        and  ah, 0xF0
        or   al, ah
        mov  bHiNib, al
        pop  ax
   }
#else
     unsigned int uLowNib, uHiNib;
     uLowNib= (unsigned int)bLoNib;
     uHiNib= (unsigned int)bHiNib;
     uLowNib<<=1;
     if (uLowNib & 0x100) {
          uLowNib&=0x0000007f;
     } else
          uLowNib|=0x00000080;
     uLowNib>>=4;
     uHiNib<<=1;
     if (uHiNib & 0x100) {
          uHiNib&=0x0000007f;
     } else
          uHiNib|=0x00000080;
     uHiNib&=0x000000f0;
     uHiNib|=uLowNib;
     bHiNib= (BYTE)uHiNib;
#endif
   DEBUGMSG(ZONE_MAXIO,(TEXT("[AssembleNibbles] byte = %Xh\r\n"),bHiNib));
   return (bHiNib);
}
//---------------------------------------------------------------------------
BOOL
NibbleRead
(
    ULONG             ulBase,
    char*             lpInBuffer,
    DWORD             dwInBufferSize,
    DWORD*            lpdwBytesReceived
)
// PURPOSE
//  Read a block of data from the parallel port.
//
// ASSUMPTIONS & ASSERTIONS
//  Data will be read using P1284 Nibble mode protocol.  The basic method is:
//  1)current phase is reverse idle,
//      Watch for nDataAvail low
//      Raise HostBusy high
//  2)current phase is host busy data avail
//      Drop HostBusy
//      Watch for  PtrClk
//      Latch Nibble 0 (Data bits 0-3)
//      Raise HostBusy
//      Watch for PtrClk
//      Drop HostBusy
//      Watch for PtrClk
//      Latch Nibble 1 (Data bits 4-7)
//      Raise HostBusy
//
//  Data will be read until the read buffer is full, there is a time out
//  on PtrClk, or the peripheral does not assert nDataAvail.
//  A timeout occurs if the host does not see PtrClk drop
//  within T(l) + T(p) after HostBusy is droped.  Currently T(l) is
//  defiend to be 35 ms MAX, and T(p) is defined to be .5 us MIN.
//  MAX for T(p) is undefinned, and will be passed as a parameter to P1284LPT.
//       Data is read from status port.
//
// INTERNAL STRUCTURES
//
// UNRESOLVED ISSUES
//
// RETURNS
//  TRUE: if some or all data are read
//  FALSE: if no data read
//---------------------------------------------------------------------------
{
    DWORD dwBytesRead = 0L;
    BYTE  bLoRawNibble, bHiRawNibble;
    BYTE  bData, bOldDCR;
    ULONG uDataPort, uStatusPort, uControlPort;

    // Initialize the LPT Port variables
    uDataPort = ulBase;
    uStatusPort = uDataPort + 1;
    uControlPort = uDataPort + 2;

    if (ChecknFault(uStatusPort))
    {
        DEBUGMSG(ZONE_ERROR,(TEXT("[NibbleRead] data not available.\r\n")));
        *lpdwBytesReceived = 0;  // No data, not error.
        return (FALSE);
    }

    // Check current phase via HostBusy
    // We can be in Idle phase or HBDA
    bOldDCR = READ_PORT_UCHAR((PUCHAR)uControlPort);
    if (bOldDCR & NM_HOSTBUSY)
    {
        DEBUGMSG(ZONE_IO,(TEXT("[NibbleRead] reverse idle.\r\n")));
        // now in reverse idle phase
        //verify interrupt, state 19
        //respond to raise HostBusy high (state 20) enter HBDA
        //be carefule for PS/2 Type3 machine, avoid to touch AutoStrobe (b7)
        bOldDCR &= NM_CONTROL_MASK;
        WRITE_PORT_UCHAR((PUCHAR)uControlPort, (BYTE)(bOldDCR | NM_INIT));

        //wait PE low & nAck Hi for 35ms
        if (!CheckPort(uStatusPort,NM_INT_MASK, NM_INTERRUPT, P1284_MS))
        {
            *lpdwBytesReceived = 0;
            return (FALSE);
        }
        DEBUGMSG(ZONE_IO,(TEXT("[NibbleRead] host busy data available and interrupt received.\r\n")));
    }
    else
    {
        //be carefule for PS/2 Type3 machine, avoid to touch AutoStrobe (b7)
        bOldDCR &= NM_CONTROL_MASK;
    }
    // Read until we fill the input buffer, time-out, or have no data
    // available
    DEBUGMSG(ZONE_IO,(TEXT("[NibbleRead] read data into %Xh\r\n"),lpInBuffer));
    do
    {
        // Data is available and peripheral is ready to send data,
        // so drop HostBusy
        // do not modify other bits except HostBusy, we may overried high byte on PS/2 machine
        WRITE_PORT_UCHAR((PUCHAR)uControlPort, (BYTE)(bOldDCR | NM_INIT | NM_HOSTBUSY));

        // wait PtrClk go low          //0x40          //0x00
        if (!CheckPort(uStatusPort,NM_PTRCLK_MASK, NM_PTRCLK_LO, P1284_MS))
        {
               DEBUGMSG(ZONE_IO,(TEXT("[NibbleRead] Time-out waiting for PtrClk to go LO first Nibble\r\n")));
            *lpdwBytesReceived = dwBytesRead;
            return (TRUE);
        }
        // Latch first nibble, bits <0:3>
        bLoRawNibble = READ_PORT_UCHAR((PUCHAR)uStatusPort);

        // Raise HostBusy
        WRITE_PORT_UCHAR((PUCHAR)uControlPort, (BYTE)(bOldDCR | NM_INIT));

        // Wait PtrClk go Hi             //0x40         //0x40
        if (!CheckPort(uStatusPort,NM_PTRCLK_MASK, NM_PTRCLK_HI, P1284_MS))
        {
            DEBUGMSG(ZONE_IO,(TEXT("[NibbleRead] Time-out waiting for PtrClk to go HI first Nibble\r\n")));
            *lpdwBytesReceived = dwBytesRead;
            return (TRUE);
        }

        // Ready to get the Second Nibble.  Drop HostBusy again
        WRITE_PORT_UCHAR((PUCHAR)uControlPort, (BYTE)(bOldDCR | NM_INIT | NM_HOSTBUSY));

        // Wait PtrClk go low
        if (!CheckPort(uStatusPort,NM_PTRCLK_MASK, NM_PTRCLK_LO, P1284_MS))
        {
               DEBUGMSG(ZONE_IO,(TEXT("[NibbleRead] Time-out waiting for PtrClk to go LO on Second Nibble\r\n")));
            *lpdwBytesReceived = dwBytesRead;
            return (TRUE);
        }
        // Latch second nibble
        bHiRawNibble = READ_PORT_UCHAR((PUCHAR)uStatusPort);

        // Raise HostBusy
        WRITE_PORT_UCHAR((PUCHAR)uControlPort, (BYTE)(bOldDCR | NM_INIT));

        // Assemble the received, encoded nibble, into a data byte,
        // store it in the output array, and update the counters.
        bData = AssembleNibbles (bLoRawNibble, bHiRawNibble);
        *lpInBuffer++ = bData;
        dwBytesRead ++;

        // Wait PtrClk go Hi             //0x40         //0x40
        if (!CheckPort(uStatusPort,NM_PTRCLK_MASK, NM_PTRCLK_HI, P1284_MS))
        {
            *lpdwBytesReceived = dwBytesRead;
            return (TRUE);
        }

        // check nDataAvail, if high no more data
        if (ChecknFault(uStatusPort))
        {
            DEBUGMSG(ZONE_IO,(TEXT("[NibbleRead] data not available.\r\n")));
            *lpdwBytesReceived = dwBytesRead;
            return (TRUE);
        }
    }
    while(dwBytesRead < dwInBufferSize);
    // if we get here, we filled the input buffer, se we can just return.
    *lpdwBytesReceived = dwBytesRead;
    DEBUGMSG(ZONE_IO,(TEXT("[NibbleRead] read #EAX bytes\r\n"),dwBytesRead));
    return (TRUE);
}

BOOL
WaitTransfer
(
    PPortInformation    PortObj
)
{
    LONG lStartTick;

    if (PortObj->bFrdProtocol == ID_ECP)
    {
        lStartTick = GetTickCount();
        do
        {
            if (PortObj->blInTransfer == FALSE)
                return (TRUE);            
        } while ((GetTickCount() - lStartTick) < P1284_MS);

        PortObj->pPortData.dwLastError = PortObj->pPortData.dwCommError;
        PortObj->pPortData.dwCommError = CE_PTO;
        return (FALSE);
    }

    return(TRUE);
}

BOOL
ResetECP
(
    PPortInformation  PortObj
)
// PURPOSE
//
//  Attempts to reset both host and peripheral ECP hardware to its default state.
//
// ASSUMPTIONS & ASSERTIONS
//
// INTERNAL STRUCTURES
//
// UNRESOLVED ISSUES
//
// RETURNS
//  TRUE - ECP device is reset
//---------------------------------------------------------------------------
{
    unsigned   uDCR_reg, uECR_reg;

    // Initialize the LPT Port variables
    uDCR_reg = PortObj->ulBase + ECP_DCR_Reg;
    uECR_reg = PortObj->ulBase + ECP_ECR_Reg;
                                          
    // Set host ECP to compatibility mode to clear FIFO and counter
    // now probably in forward or reverse channel
    WRITE_PORT_UCHAR((PUCHAR)uECR_reg, ECP_STD_MODE);

    /*
    // Reset DMA channel, clear Tx and Rx and counters
    if (PortObj->pDDS->DDS_bufferID == DMA_SCATTER_LOCK)
        VDMAD_Scatter_Unlock(PortObj->pExtDDS);
    */

    //PortObj->dwDmaXferCnt = 0;
    //PortObj->pDDS->DDS_bufferID = 0;

    PortObj->pPortData.QOutCount = 0;
    PortObj->pPortData.QOutGet = 0;
    PortObj->pPortData.QInCount = 0;
    PortObj->pPortData.QInPut = 0;

    // Terminate IEEE 1284 high speed mode back to compatibility mode,
    // then toggle nSelectIn Lo to reset peripheral device
    if (WaitTransfer(PortObj))
        TerminateChannel(PortObj);
    else
        return (FALSE);
      

    DEBUGMSG(ZONE_CLOSE,(TEXT("[ResetECP] reset printer, set back to compatible mode\r\n")));

    WRITE_PORT_UCHAR((PUCHAR)uDCR_reg, ECP_RESET_HW);   //0xCC
    WRITE_PORT_UCHAR((PUCHAR)uDCR_reg, (BYTE)(ECP_RESET_HW & NINIT_LOW)); // drop Init
    WRITE_PORT_UCHAR((PUCHAR)uDCR_reg, ECP_RESET_HW);                     // pull Init

    return (TRUE);
}

//---------------------------------------------------------------------------
void
ResetPort
(
    PPortInformation  PortObj
)
// PURPOSE
//
//  Attempts to reset peripheral LPT hardware to its default state.
//
// ASSUMPTIONS & ASSERTIONS
//  1)toggle nInit(Reset) to peripheral to reset the interface.
//  2)PC-compatible printer requires at least 50us pulse width of nInit
//  3)9us is taken on a Gateway2000 66v by most printers.
//  4)0x0c-0x08-0x0c would be safer to IBM ps/2.
//
// INTERNAL STRUCTURES
//
// UNRESOLVED ISSUES
//
// RETURNS
//  TRUE - LPT device is reset
//---------------------------------------------------------------------------
{
    unsigned   uControlPort;
    BYTE       bData;
    
    uControlPort = PortObj->ulBase + 2;

    //be carefule for PS/2 Type3 machine, avoid to touch AutoStrobe (b7)
    bData = (BYTE)(READ_PORT_UCHAR((PUCHAR)uControlPort) & CONTROL_CLEAR_MASK);    //0x40
    WRITE_PORT_UCHAR((PUCHAR)uControlPort, (BYTE)(bData | 0x0c));

    // wait at most 1/3 sec to reset
    WRITE_PORT_UCHAR((PUCHAR)uControlPort, (BYTE)(bData | 0x08));
    lStartTick = GetTickCount();
    
    do
    {
        ;
    }
    while ((LONG)(GetTickCount() - lStartTick) < 300);

    WRITE_PORT_UCHAR((PUCHAR)uControlPort, (BYTE)(bData | 0x0c));
    CheckPrinterStatus(PortObj, PortObj->ulBase+1); 
    PortObj->bCurrentPhase = FORWARD_IDLE;
    return;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?