📄 1284comm.c
字号:
{
// all other modes, expect (x,1,x,1,x) (nibble w/ ID)
if (CheckPort(uStatusPort, P_STATE5_MASK, P_STATE5_VALUE, P1284_MS))
return (PD_SUCCESS);
}
DEBUGMSG(ZONE_ERROR,(TEXT("[P1284Negotiate] Timeout at E5/E6 read\r\n")));
// Terminate FAILed negotiation, inverted Boolean
if (bExtenByte == NIBBLE_MODE)
P1284Terminate(ulBase, FALSE);
else
P1284Terminate(ulBase, TRUE);
// return (PD_UNSUPPORTED);
return (PD_NOTP1284);
}
// 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 %c\r\n"),bHiNib, 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 * dwPrinterRegMultiplier;
uControlPort = uDataPort + 2 * dwPrinterRegMultiplier;
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);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -