📄 ccser_pdd.c
字号:
/*
Copyright(c) 1998,1999 SIC/Hitachi,Ltd.
Module Name:
CCSer_pdd.c
Revision History:
26th April 1999 Released
*/
#include <windows.h>
#include <types.h>
#include <memory.h>
#include <serhw.h>
#include <ser16550.h>
#include <hw16550.h>
#include <serdbg.h>
#include <nkintr.h>
#include "ser_pdd.h"
//#include "mobytel.h"
#include "cc.h"
//#include "shx.h"
#include "macros.h"
extern DWORD dwHD64465Base;
// #define DBGMSG
#define DBGMSG NKDbgPrintfW
#define BAUD_TABLE_SIZE 23
static const
PAIRS BaudPairs[BAUD_TABLE_SIZE] = {
{50, 2307},
{75, 1538},
{110, 1049},
{135, 858},
{150, 769},
{300, 384},
{600, 192},
{1200, 96},
{1800, 64},
{2000, 58},
{2400, 48},
{3600, 32},
{4800, 24},
{7200, 16},
{9600, 12},
{12800, 9},
{14400, 8},
{19200, 6},
{23040, 5},
{28800, 4},
{38400, 3},
{57600, 2},
{115200, 1}
};
static const LOOKUP_TBL BaudTable = {BAUD_TABLE_SIZE, (PAIRS *) BaudPairs};
/*
UCHAR READ_PORT_UCHAR(PUCHAR port)
{
UCHAR bTemp;
bTemp =(UCHAR) *(volatile unsigned short *)port;
return bTemp;
}
VOID WRITE_PORT_UCHAR(PUCHAR port, UCHAR value)
{
// DEBUGMSG (DBG_PORT_ACCESS, (TEXT("Setting Port @ 0x%X to 0x%X\r\n"), port, value));
*(volatile unsigned short *)port = (unsigned short)value;
}
*/
// Miscellaneous internal routines.
PUCHAR
static
CCSer_InternalMapRegisterAddresses(
ULONG HWAddress,
ULONG Size
)
{
PUCHAR ioPortBase;
DEBUGMSG(ZONE_FUNCTION,
(TEXT("+CCSer_InternalMapRegisterAddresses: adr=0x%x len=0x%x\r\n"),
HWAddress, Size));
ioPortBase = VirtualAlloc(0, Size, MEM_RESERVE, PAGE_NOACCESS);
if ( ioPortBase == NULL )
{
ERRORMSG(1, (TEXT("CCSer_InternalMapRegisterAddresses: VirtualAlloc failed!\r\n")));
}
else if ( !VirtualCopy((PVOID)ioPortBase, (PVOID)HWAddress, Size, PAGE_READWRITE|PAGE_NOCACHE) )
{
ERRORMSG(1, (TEXT("CCSer_InternalMapRegisterAddresses: VirtualCopy failed!\r\n")));
VirtualFree( (PVOID)ioPortBase, 0, MEM_RELEASE );
ioPortBase = 0;
}
DEBUGMSG(ZONE_FUNCTION,
(TEXT("-CCSer_InternalMapRegisterAddresses: mapped at 0x%x\r\n"),
ioPortBase ));
return ioPortBase;
}
static
BOOL
CCSerSetIRBaudRate(
PSER_INFO pHWHead,
ULONG baud // @parm UINT16 what is the baud rate
)
{
DEBUGMSG (ZONE_INIT, (TEXT("Serial set IR Baud %d\r\n"),
baud));
return TRUE;
}
/*
* NOTE : The caller should have set pHWHead->fIRMode. It is not
* set here, since power on/off may need to temporarily disable
* the intefaces without actually overwriting the current recorded
* mode.
*/
static
void
CCSerSetOutputMode(
PSER_INFO pHWHead,
BOOL UseIR, // @parm BOOL Should we use IR interface
BOOL Use9Pin // @parm BOOL Should we use Wire interface
)
{
// TODO - here you need to set the interface to either IR mode
// or normal serial. Note that it is possible for both BOOls to
// be false (i.e. power down), but never for both to be TRUE.
}
/*
@doc OEM
@func PVOID | CCSerInit | Initializes device identified by argument.
* This routine sets information controlled by the user
* such as Line control and baud rate. It can also initialize events and
* interrupts, thereby indirectly managing initializing hardware buffers.
* Exported only to driver, called only once per process.
*
@rdesc The return value is a PVOID to be passed back into the HW
dependent layer when HW functions are called.
*/
static
PVOID
CCSerInit(
ULONG Identifier, // @parm Device identifier.
PVOID pMddHead // @parm First argument to mdd callbacks.
)
{
PSER_INFO pHWHead;
// Note on defaults. While the PC typcially considers COM1 to be at
// 3F8, irq4 and COM2 to be 2F8, irq3, NKPC uses COM1 internally for the
// debugger. So, when NK tells me to start "COM1" it really means the
// first one that's available, which is what the PC calls COM2. Confused?
// The end result is that COM1 on NK is what the PC considers to be COM2.
// But wait, there's more. On a Puzzle, the debugger is on COM2 and the
// COM1 for NK is ACTUALLY COM1. So PCs need 2F8 for their port base
// and Puzzles need 3F8.
const UINT cDefaultCom1PortBase = 0x2F8;
const UINT cDefaultComPortRange = 8;
// Allocate for our main data structure and one of it's fields.
pHWHead = (PSER_INFO)LocalAlloc( LMEM_ZEROINIT|LMEM_FIXED ,
sizeof(SER_INFO) );
if (!pHWHead)
goto ALLOCFAILED;
// This call will map the address space for the 16550 UART.
pHWHead->pBaseAddress = CCSer_InternalMapRegisterAddresses(
(dwHD64465Base + HD64465_UART_OFFSET), 0x400);
pHWHead->pMddHead = pMddHead;
pHWHead->cOpenCount = 0;
// Set up our Comm Properties data
pHWHead->CommProp.wPacketLength = 0xffff;
pHWHead->CommProp.wPacketVersion = 0xffff;
pHWHead->CommProp.dwServiceMask = SP_SERIALCOMM;
pHWHead->CommProp.dwReserved1 = 0;
pHWHead->CommProp.dwMaxTxQueue = 16;
pHWHead->CommProp.dwMaxRxQueue = 16;
pHWHead->CommProp.dwMaxBaud = BAUD_115200;
pHWHead->CommProp.dwProvSubType = PST_RS232;
pHWHead->CommProp.dwProvCapabilities =
PCF_DTRDSR | PCF_RLSD | PCF_RTSCTS |
PCF_SETXCHAR |
PCF_INTTIMEOUTS |
PCF_PARITY_CHECK |
PCF_SPECIALCHARS |
PCF_TOTALTIMEOUTS |
PCF_XONXOFF;
pHWHead->CommProp.dwSettableBaud =
BAUD_075 | BAUD_110 | BAUD_150 | BAUD_300 | BAUD_600 |
BAUD_1200 | BAUD_1800 | BAUD_2400 | BAUD_4800 |
BAUD_7200 | BAUD_9600 | BAUD_14400 |
BAUD_19200 | BAUD_38400 | BAUD_56K | BAUD_128K |
BAUD_115200 | BAUD_57600 | BAUD_USER;
pHWHead->CommProp.dwSettableParams =
SP_BAUD | SP_DATABITS | SP_HANDSHAKING | SP_PARITY |
SP_PARITY_CHECK | SP_RLSD | SP_STOPBITS;
pHWHead->CommProp.wSettableData =
DATABITS_5 | DATABITS_6 | DATABITS_7 | DATABITS_8;
pHWHead->CommProp.wSettableStopParity =
STOPBITS_10 | STOPBITS_20 |
PARITY_NONE | PARITY_ODD | PARITY_EVEN | PARITY_SPACE |
PARITY_MARK;
// Init 16550 info, register stride is 1
DEBUGMSG (ZONE_INIT, (TEXT("CCSerInit - Init 16550 data\r\n")));
SL_Init( pHWHead, pHWHead->pBaseAddress, CC_16550_REG_STRIDE,
EvaluateEventFlag, pMddHead, (PLOOKUP_TBL)&BaudTable);
DEBUGMSG (ZONE_INIT,
(TEXT("CCSerInit - Disabling UART Power\r\n")));
pHWHead->fIRMode = FALSE; // Select wired by default
CCSerSetOutputMode(pHWHead, FALSE, FALSE );
return pHWHead;
ALLOCFAILED:
if ( pHWHead->pBaseAddress )
VirtualFree(pHWHead->pBaseAddress, 0, MEM_RELEASE);
LocalFree(pHWHead);
return NULL;
}
/*
@doc OEM
@func ULONG | CCSerClose | This routine closes the device identified by the PVOID returned by CCSerInit.
* Not exported to users, only to driver.
*
@rdesc The return value is 0.
*/
static
ULONG
CCSerClose(
PVOID pHead // @parm PVOID returned by CCSerInit.
)
{
PSER_INFO pHWHead = (PSER_INFO)pHead;
ULONG uTries;
DEBUGMSG (ZONE_CLOSE,(TEXT("+CCSerClose\r\n")));
if( pHWHead->cOpenCount )
{
DEBUGMSG (ZONE_CLOSE,
(TEXT("CCSerClose, closing device\r\n")));
pHWHead->cOpenCount--;
// while we are still transmitting, sleep.
uTries = 0;
while ( (uTries++ < 100) &&
!(pHWHead->ser16550.LSR & SERIAL_LSR_TEMT) )
{
DEBUGMSG (ZONE_CLOSE,
(TEXT("CCSerClose, TX in progress, LSR 0x%X\r\n"),
pHWHead->ser16550.LSR));
Sleep(10);
}
// When the device is closed, we power it down.
DEBUGMSG (ZONE_CLOSE,
(TEXT("CCSerClose - Powering down UART\r\n")));
pHWHead->fIRMode = FALSE;
CCSerSetOutputMode(pHWHead, FALSE, FALSE );
}
DEBUGMSG (ZONE_CLOSE,(TEXT("-CCSerClose\r\n")));
return 0;
}
/*
@doc OEM
@func PVOID | CCSerDeinit | Deinitializes device identified by argument.
* This routine frees any memory allocated by CCSerInit.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -