📄 1284neg.c
字号:
/*++
THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
PARTICULAR PURPOSE.
Copyright (c) 1995-1998 Microsoft Corporation
Module Name:
1284neg.c
Abstract:
P1284 protocol negotiation functions
DESCRIBED IN IEEE-1284 Standard Signaling Method
for a Bi-directional Parallel Peripheral
Interface for Personal Computer
Notes:
--*/
#include <windows.h>
#include <ceddk.h>
#include "pardbg.h"
#include "1284comm.h"
#include "tmtick.h"
#include "comdef.h"
#include "ecpreg.h"
#include "1284neg.h"
#include "lptio.h"
#define PD_UNSUPPORTED 0 /* Port is not supported */
//---------------------------------------------------------------------------
// ECP negotiation signals
//---------------------------------------------------------------------------
#define PE_STATE31_MASK 0xF0
#define PE_STATE31 0xF0
#define swapbyte(wA) (WORD)(((wA>>8) & 0x00FF) | (wA<<8))
// Multiplier used to access the printer registers.
extern unsigned dwPrinterRegMultiplier;
VOID
ReadIDString
(
PPortInformation PortObj
)
{
DWORD dwBytesRead;
WORD wTemp = 0x0000;
ULONG uDSR_reg;
DEBUGMSG(ZONE_MAXIO,(TEXT("[ReadIDStringl]: entry\r\n")));
uDSR_reg = PortObj->ulBase + 1 * dwPrinterRegMultiplier;
// fix for TI printer, wait 35ms for nDataAvail -- begin
if (!CheckPort(uDSR_reg, 0x08, 0x00, P1284_TL_MS)) {
DEBUGMSG(ZONE_MAXIO,(TEXT("[ReadIDStringl]: Failed CheckPort\r\n")));
return;
}
// fix for TI printer -- end
NibbleRead(PortObj->ulBase, (LPSTR)&wTemp, 2, &dwBytesRead);
wTemp = swapbyte(wTemp);
if (wTemp < 2) {
DEBUGMSG(ZONE_MAXIO,(TEXT("[ReadIDStringl]: Unable to read length bytes\r\n")));
return;
}
if (PortObj->pDeviceID.pdeviceID) {
LocalFree(PortObj->pDeviceID.pdeviceID);
PortObj->pDeviceID.pdeviceID=NULL;
}
PortObj->pDeviceID.pdeviceID = (LPSTR)LocalAlloc(LPTR, wTemp-1 );
if (PortObj->pDeviceID.pdeviceID) {
dwBytesRead=0;
NibbleRead(PortObj->ulBase, PortObj->pDeviceID.pdeviceID,
wTemp - 2, &dwBytesRead);
if (dwBytesRead>=(DWORD)wTemp - 2)
dwBytesRead=wTemp - 2;
PortObj->pDeviceID.pdeviceID[dwBytesRead]='\0';
DEBUGMSG(ZONE_MAXIO,(TEXT("[ReadIDStringl]: Length bytes=%d String=%a\r\nID="),wTemp,PortObj->pDeviceID.pdeviceID));
PortObj->pDeviceID.ulSize = dwBytesRead;
PortObj->pPortData.dwLastError = PortObj->pPortData.dwCommError;
PortObj->pPortData.dwCommError = 0;
}
TerminateChannel(PortObj);
return;
}
//---------------------------------------------------------------------------
BOOL
NegotiateChannel
(
PPortInformation PortObj,
BOOL bRequestDeviceID
)
// PURPOSE
// Attempts to start a negotiation session with an attached 1284 printer
// on a parallel port.
//
// ASSUMPTIONS & ASSERTIONS
// bRequestDeviceID is set to TRUE for requesting device ID string.
// Before return, the following fields of PortObj will be set:
// 1)bRevProtocol: reverse channel capability of device
// 2)bFrdProtocol : forward channel capability of device
// 3)bCurrentMode and bCurrentPhase : record of current status of hardware
// INTERNAL STRUCTURES
//
// UNRESOLVED ISSUES
//
// RETURNS
// 1)TRUE -> success
//---------------------------------------------------------------------------
{
BYTE bExtensibilityByte;
switch (PortObj->wHost)
{
case HOST_NO_ECP: //current mode: LPT mode or Nibble mode
{
DEBUGMSG(ZONE_IO,(TEXT("[NegotiateChannel]:Without ECP at host, find reverse protocol:\r\n")));
PortObj->bCurrentPhase = FORWARD_IDLE;
PortObj->bFrdProtocol = ID_LPT;
PortObj->pfnWrite = (PFN)LPT_WriteFewBytes;
bExtensibilityByte = (BYTE)((bRequestDeviceID) ?
(NIBBLE_MODE | PN_REQ_DEVID) :
NIBBLE_MODE);
if (PD_SUCCESS == Nibble_Connect(PortObj, bExtensibilityByte))
{
if (bRequestDeviceID)
{
ReadIDString(PortObj);
}
}
else
{
PortObj->bCurrentMode = LPT_MODE;
PortObj->bRevProtocol = ID_LPT;
} //nibble mode not supported
break;
}
}
return (TRUE);
}
//---------------------------------------------------------------------------
VOID
TerminateChannel
(
PPortInformation PortObj // -> PortInformation block
)
// PURPOSE
// Terminate a P1284 mode protocol and return to compatibility mode.
// Only the PortObj->bCurrentPhase and PortObj->bCurrentMode will be changed.
//
// ASSUMPTIONS & ASSERTIONS
// 1)If the current status is in ECP reverse mode, negotiate channel from
// reverse to forward before termination.
// 2)If any step during termination fails, drive control port to state 22
// (0xEC) to abort, returns TRUE.
//
// INTERNAL STRUCTURES
//
// UNRESOLVED ISSUES
//
// RETURNS
// 1)TRUE -> success
// 2)FALSE -> I/O pending
//---------------------------------------------------------------------------
{
DEBUGMSG(ZONE_MAXIO,(TEXT("[TerminateChannel]: entry\r\n")));
// not necessary to terminate if channel is in Compatibility mode already
if (PortObj->bCurrentMode == LPT_MODE)
return;
if ((PortObj->dwDevId != PN_REQ_DEVID) &&
(PortObj->bCurrentMode == NIBBLE_MODE))
{
// Terminiate Nibble mode (w/o device id)
P1284Terminate(PortObj->ulBase, TRUE);
}
else
{
// All other modes.
P1284Terminate(PortObj->ulBase, FALSE);
}
PortObj->bCurrentMode = LPT_MODE;
PortObj->bCurrentPhase = FORWARD_IDLE;
PortObj->dwDevId = 0;
PortObj->pPortData.dwLastError = PortObj->pPortData.dwCommError;
PortObj->pPortData.dwCommError = 0;
return;
}
//---------------------------------------------------------------------------
DWORD
Nibble_Connect
(
PPortInformation PortObj,
BYTE bExtenByte
)
// PURPOSE
// Negotiate channel to nibble mode. Stay at reverse idle phase to return.
//
// ASSUMPTIONS & ASSERTIONS
// 1) This code ASSUMES a ISA parallel port implementation.
// 2) current mode and phase are lpt/elpt mode, forward idle phase.
//
// INTERNAL STRUCTURES
//
// UNRESOLVED ISSUES
//
// RETURNS
// 1)PD_SUCCESS -> success
// 2)PD_NOTP1284
// 3)PD_UNSUPPORTED
//---------------------------------------------------------------------------
{
DWORD dwError;
ULONG uDCR_reg;
ULONG uDSR_reg;
DEBUGMSG(ZONE_IO,(TEXT("[Nibble_Connect]: entry\r\n")));
if (bExtenByte & PN_REQ_DEVID)
{
// We'll use this flag to determine the correct
// method for terminating from nibble mode.
PortObj->dwDevId = PN_REQ_DEVID;
}
if ((dwError = P1284Negotiate(PortObj->ulBase, bExtenByte)) != PD_SUCCESS)
{
PortObj->pPortData.dwLastError = PortObj->pPortData.dwCommError;
PortObj->pPortData.dwCommError = CE_MODE;
return (dwError);
}
DEBUGMSG(ZONE_IO,(TEXT("[Nibble_Connect]: Successfully negotiated into Nibble mode.\r\n")));
// Set the port status to reflect successful revese negotiation
PortObj->bCurrentMode = NIBBLE_MODE;
PortObj->bCurrentPhase = NB_REVERSE_IDLE; // Go into REV_IDLE state.
PortObj->bRevProtocol = ID_NIBBLE;
uDSR_reg = PortObj->ulBase + 1 * dwPrinterRegMultiplier;
if (!ChecknFault(uDSR_reg))
{
DEBUGMSG(ZONE_IO,(TEXT("[Nibble_Connect] data available.\r\n")));
PortObj->bCurrentPhase = NB_DATA_AVAILABLE;
}
else
{
DEBUGMSG(ZONE_IO,(TEXT("[Nibble_Connect] data not available.\r\n")));
//switch to reverse idle mode, drop HostBusy low to wait for interrupt
uDCR_reg = PortObj->ulBase + 2 * dwPrinterRegMultiplier;
//be carefule for PS/2 Type3 machine, avoid to touch AutoStrobe (b7)
WRITE_PORT_UCHAR((PUCHAR)uDCR_reg,(BYTE)(READ_PORT_UCHAR((PUCHAR)uDCR_reg) | NAUTOFD_LOW));
WRITE_PORT_UCHAR((PUCHAR)uDCR_reg,(BYTE)(READ_PORT_UCHAR((PUCHAR)uDCR_reg) | NAUTOFD_LOW));
PortObj->bCurrentPhase = NB_REVERSE_IDLE;
}
PortObj->pPortData.dwLastError = PortObj->pPortData.dwCommError;
PortObj->pPortData.dwCommError = 0;
return (PD_SUCCESS);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -