📄 mdd.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:
mdd.c
Abstract:
This file contains the parallel mdd (model device driver) code.
Functions:
LPT_Init
LPT_Open
LPT_Close
LPT_Deinit
LPT_Read
LPT_Write
LPT_Seek
LPT_PowerUp
LPT_PowerDown
LPT_IOControl
ParallelDllEntry
Notes:
--*/
#include <windows.h>
#include <ceddk.h>
#include <types.h>
#include <memory.h>
#include <nkintr.h>
#include <pegdpar.h>
#include "parpriv.h"
#include "pardbg.h"
#include "1284comm.h"
#include "tmtick.h"
#include "comdef.h"
#include "1284neg.h"
#include "lptio.h"
/****************************************************************************
* Modification done by Maneesh Gupta
*
* Included platform.h & cc.h
****************************************************************************/
#include "cc.h"
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
/* Debug Zones.
*/
#ifdef DEBUG
#define DBG_INIT 0x0001
#define DBG_OPEN 0x0002
#define DBG_READ 0x0004
#define DBG_WRITE 0x0008
#define DBG_CLOSE 0x0010
#define DBG_IOCTL 0x0020
#define DBG_THREAD 0x0040
#define DBG_EVENTS 0x0080
#define DBG_CRITSEC 0x0100
#define DBG_IO 0x0200
#define DBG_MAXIO 0x0400
#define DBG_UNUSED2 0x0800
#define DBG_ALLOC 0x1000
#define DBG_FUNCTION 0x2000
#define DBG_WARNING 0x4000
#define DBG_ERROR 0x8000
DBGPARAM dpCurSettings = {
TEXT("Parallel"), {
TEXT("Init"),TEXT("Open"),TEXT("Read"),TEXT("Write"),
TEXT("Close"),TEXT("Ioctl"),TEXT("Thread"),TEXT("Events"),
TEXT("CritSec"),TEXT("IO"),TEXT("MaxIO"),TEXT("Unused2"),
TEXT("Alloc"),TEXT("Function"),TEXT("Warning"),TEXT("Error") },
DBG_WARNING | DBG_ERROR
};
#endif
#define swapbyte(wA) (WORD)(((wA>>8) & 0x00FF) | (wA<<8))
/****************************************************************************
* Modification done by Maneesh Gupta
*
* Changes for ASPEN / BIGSUR
*
* 1. The base address is hard coded instead of reading from the
* registry. This is because the Companion Chip is present at a constant
* location. There is no need to read the base address from registry.
*
* 2. On HD64465, the parallel port registers are present at alternate
* bye addresses while on normal PC they are present at consecutive
* addresses.
* So all the register offsets get multiplied by two.
*
* So For ASPEN platform, a new global variable dwPrinterRegMultiplier is
* introduced. This would be set to 2, to take care of the above mentioned
* fact
* Multiplier used to access the printer registers.
****************************************************************************/
unsigned dwPrinterRegMultiplier;
unsigned VirtualAddress(unsigned StartAddress, unsigned Length);
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
// Define some internally used functions
BOOL LPT_Close(PPortInformation pPortObj);
BOOL LPT_Deinit(PPortInformation pPortObj);
int Get_DJ400_Dev_Status(unsigned long port_base, unsigned char *buffer);
/*
@doc INTERNAL
@func BOOL | ParallelDllEntry | Process attach/detach api.
*
@rdesc The return is a BOOL, representing success (TRUE) or failure (FALSE).
*/
BOOL
ParallelDllEntry(
HINSTANCE hinstDll, /*@parm Instance pointer. */
DWORD dwReason, /*@parm Reason routine is called. */
LPVOID lpReserved /*@parm system parameter. */
)
{
DEBUGMSG(ZONE_IO,(TEXT("ParallelDllEntry: entry\r\n")));
if ( dwReason == DLL_PROCESS_ATTACH ) {
DEBUGREGISTER(hinstDll);
DEBUGMSG (ZONE_INIT, (TEXT("parallel port process attach\r\n")));
}
if ( dwReason == DLL_PROCESS_DETACH ) {
DEBUGMSG (ZONE_INIT, (TEXT("parallel port process detach called\r\n")));
}
return TRUE;
}
// ****************************************************************
//
// @doc EXTERNAL
// @func HANDLE | LPT_INIT | Parallel device initialization.
//
// @parm ULONG | Identifier | Port identifier. The device loader
// passes in the registry key that contains information
// about the active device.
//
// @remark This routine is called at device load time in order
// to perform any initialization. Typically the init
// routine does as little as possible, postponing memory
// allocation and device power-on to Open time.
//
// @rdesc Returns a pointer to the serial head which is passed into
// the LPT_OPEN and LPT_DEINIT entry points as a device handle.
//
PPortInformation
LPT_Init(
ULONG Identifier
)
{
PPortInformation pPortObj;
DEBUGMSG(ZONE_IO,(TEXT("[LPT_Init]: entry.\r\n")));
//allocate new data buffer
pPortObj = (PPortInformation)LocalAlloc(LPTR,(ULONG)sizeof(PortInformation));
if (!pPortObj) {
DEBUGMSG(ZONE_ERROR,(TEXT("[LPT_Init]: ERROR: Unable to allocate PortInformation buffer.\r\n")));
return 0;
}
memset(pPortObj,0,sizeof(PortInformation)); //Initial to zero
return pPortObj;
}
// Miscellaneous internal routines.
PUCHAR
static
Par_InternalMapRegisterAddresses(
ULONG HWAddress,
ULONG Size
)
{
PUCHAR ioPortBase;
ULONG inIoSpace = 1;
PHYSICAL_ADDRESS ioPhysicalBase = { HWAddress, 0 };
DEBUGMSG(ZONE_FUNCTION,
(TEXT("Par_InternalMapRegisterAddresses : HalTranslateBusAddress\r\n")));
if (HalTranslateBusAddress(Isa, 0, ioPhysicalBase, &inIoSpace,
&ioPhysicalBase))
{
DEBUGMSG(ZONE_INIT,
(TEXT("Par_InternalMapRegisterAddresses : HalTranslateBusAddress - OK\r\n")));
if (!inIoSpace)
{
DEBUGMSG(ZONE_INIT,
(TEXT("Par_InternalMapRegisterAddresses : ! IO Space\r\n")));
if ((ioPortBase = (PUCHAR)MmMapIoSpace(ioPhysicalBase,
Size, FALSE)) == NULL)
{
// We may as well not continue
DEBUGMSG(ZONE_INIT | ZONE_ERROR,
(TEXT("Error mapping I/O Ports\r\n")));
return(NULL);
}
}
else
{
DEBUGMSG(ZONE_INIT,
(TEXT("Par_InternalMapRegisterAddresses : IO Space\r\n")));
ioPortBase = (PUCHAR)ioPhysicalBase.LowPart;
}
}
else
{
DEBUGMSG(ZONE_INIT | ZONE_ERROR,
(TEXT("Error translating I/O Ports.\r\n")));
return(NULL);
}
DEBUGMSG(ZONE_FUNCTION,
(TEXT("Par_InternalMapRegisterAddresses : %d\r\n"),
ioPortBase ));
return ioPortBase;
}
//
// Function to get the I/O port range from the registry
//
// NOTE: lpRegPath is assumed to be under HKEY_LOCAL_MACHINE
//
// Returns ERROR_SUCCESS on success or a Win32 error code on failure
//
DWORD
GetRegistryConfig(
LPWSTR lpRegPath,
DWORD * lpdwIoBase,
DWORD * lpdwIoLen
)
{
HKEY hConfig;
DWORD dwData;
DWORD dwSize;
DWORD dwType;
DWORD dwRet;
*lpdwIoBase= LPT_DEFAULT_IOBASE; // setup to default values
*lpdwIoLen= LPT_DEFAULT_IOLEN;
dwRet = RegOpenKeyEx(
HKEY_LOCAL_MACHINE,
lpRegPath,
0,
0,
&hConfig);
if (dwRet != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT,
(TEXT("PARALLEL:GetRegistryConfig RegOpenKeyEx(%s) failed %d\r\n"),
lpRegPath, dwRet));
return dwRet;
}
dwSize = sizeof(DWORD);
dwRet = RegQueryValueEx(
hConfig,
IOBASE_VALUE_NAME,
0,
&dwType,
(PUCHAR)&dwData,
&dwSize);
if (dwRet != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT,
(TEXT("PARALLEL:GetRegistryConfig RegQueryValueEx(%s) failed %d\r\n"),
IOBASE_VALUE_NAME, dwRet));
goto grc_fail;
}
*lpdwIoBase = dwData;
dwSize = sizeof(DWORD);
dwRet = RegQueryValueEx(
hConfig,
IOLEN_VALUE_NAME,
0,
&dwType,
(PUCHAR)&dwData,
&dwSize);
if (dwRet != ERROR_SUCCESS) {
DEBUGMSG(ZONE_INIT,
(TEXT("PCMCIA:GetRegistryConfig RegQueryValueEx(%s) failed %d\r\n"),
IOLEN_VALUE_NAME, dwRet));
goto grc_fail;
}
*lpdwIoLen = dwData;
return ERROR_SUCCESS;
grc_fail:
RegCloseKey(hConfig);
return dwRet;
} // GetRegistryConfig
/*
@doc EXTERNAL
@func HANDLE | LPT_Open | Parallel port driver initialization.
* Description: This routine must be called by the user to open the
* parallel device. The HANDLE returned must be used by the application in
* all subsequent calls to the parallel driver. This routine starts the thread
* which handles the parallel events.
* Exported to users.
*
@rdesc This routine returns a HANDLE representing the device.
*/
PPortInformation
LPT_Open(
PPortInformation pPortObj, // @parm Handle returned by LPT_Init.
DWORD AccessCode, // @parm access code.
DWORD ShareMode // @parm share mode - Not used in this driver.
)
{
char *Name;
DWORD IoBase;
DWORD IoLen;
DWORD dwRet;
DEBUGMSG(ZONE_IO,(TEXT("[LPT_Open]: entry\r\n")));
Name= LPT_DEFAULT_NAME;
/****************************************************************************
* Modification done by Maneesh Gupta
*
* For Aspen, do a Virtual Allocation here, instead of reading
* any data from the registry.
*
****************************************************************************/
if ((dwRet = GetRegistryConfig(PARALLEL_DRIVER_KEY, &IoBase, &IoLen))
!= ERROR_SUCCESS) {
DEBUGMSG(ZONE_IO,
(TEXT("LPT_Open GetRegistryConfig failed %d\r\n"),
dwRet));
return NULL;
}
// IoBase = CC_PAR_BASE_REG;
// IoLen = 12;
if(!(IoBase = VirtualAddress(IoBase, IoLen))) {
ERRORMSG(1, (TEXT("Could not Allocate VirtualAddress (0x%x) to Parallel Base Register.\r\n"), IoBase));
dwRet=0; //Just toremove a compiler warning
return NULL;
}
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
DEBUGMSG(ZONE_IO,(TEXT("[LPT_Open]: Portname = %a IoBase= %Xh IoLen= %d\r\n"),Name,IoBase,IoLen));
pPortObj->ulBase = IoBase;
memcpy(pPortObj->Name, Name, 4);
pPortObj->dwPortSharing = 0;
pPortObj->blPortOpen = FALSE;
pPortObj->pPortData.LossByte = 0;
pPortObj->dwPortSharing |= PORT_IN_USE;
pPortObj->wHost = HOST_NO_ECP;
pPortObj->bCurrentMode = LPT_MODE;
pPortObj->bCurrentPhase = FORWARD_IDLE;
pPortObj->bFrdProtocol = ID_LPT;
pPortObj->pPortData.PDLength = (WORD)sizeof(PortData);
pPortObj->pPortData.PDVersion = 0x100;
pPortObj->hOEvent = 0;
pPortObj->hIEvent = 0;
pPortObj->blInTransfer = FALSE;
// turn off all notification marks
pPortObj->dwNotifyFlags = 0;
pPortObj->TxLO = 0xFFFFFFFF;
pPortObj->RxHI = 0xFFFFFFFF;
/****************************************************************************
* Modification done by Maneesh Gupta
*
* Assignment of dwPrinterRegMultiplier for Different platform.
****************************************************************************/
dwPrinterRegMultiplier = 2;
/****************************************************************************
* End of Modification done by Maneesh Gupta
****************************************************************************/
// Init CommTimeouts.
pPortObj->CommTimeouts.ReadIntervalTimeout = READ_TIMEOUT;
pPortObj->CommTimeouts.ReadTotalTimeoutMultiplier =
READ_TIMEOUT_MULTIPLIER;
pPortObj->CommTimeouts.ReadTotalTimeoutConstant =
READ_TIMEOUT_CONSTANT;
pPortObj->CommTimeouts.WriteTotalTimeoutMultiplier= WRITE_TIMEOUT_MULTIPLIER;
pPortObj->CommTimeouts.WriteTotalTimeoutConstant = WRITE_TIMEOUT_CONSTANT;
// Negotiate w/o requesting device ID string
DEBUGMSG(ZONE_IO,(TEXT("[LPT_Open]: Calling NegotiateChannel...\r\n")));
NegotiateChannel(pPortObj,FALSE);
if (pPortObj->bCurrentMode == NIBBLE_MODE)
{
DEBUGMSG(ZONE_IO,(TEXT("[LPT_Open]: In NIBBLE_MODE calling TerminateChannel...\r\n")));
// If we are in nibble mode return to the forward direction
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -