159 lines
4.8 KiB
C++
159 lines
4.8 KiB
C++
//////////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Microsoft Research Singularity
|
|
//
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
//
|
|
// File: halkdcom.cpp: pc-compatible com port serial transport.
|
|
//
|
|
// Note: Kernel Only
|
|
//
|
|
|
|
#include "hal.h"
|
|
#include "halkd.h"
|
|
|
|
//
|
|
// Debugger Debugging
|
|
//
|
|
#define KDDBG if (0) kdprintf
|
|
#define KDDBG2 if (0) kdprintf
|
|
|
|
////////////////////////////////////////////////////////// COM PORT Constants.
|
|
//
|
|
#define COM1_PORT 0x03f8
|
|
#define COM2_PORT 0x02f8
|
|
#define COM3_PORT 0x03e8
|
|
#define COM4_PORT 0x02e8
|
|
|
|
#define COM_DAT 0x00
|
|
#define COM_IEN 0x01 // interrupt enable register
|
|
#define COM_FCR 0x02 // FIFO Control Register
|
|
#define COM_LCR 0x03 // line control registers
|
|
#define COM_MCR 0x04 // modem control reg
|
|
#define COM_LSR 0x05 // line status register
|
|
#define COM_MSR 0x06 // modem status register
|
|
#define COM_SCR 0x07 // scratch register
|
|
#define COM_DLL 0x00 // divisor latch least sig
|
|
#define COM_DLM 0x01 // divisor latch most sig
|
|
|
|
const UINT16 BaudRate = 1; // 115200 bps
|
|
|
|
#define COM_DATRDY 0x01
|
|
#define COM_OUTRDY 0x20
|
|
|
|
#define LC_DLAB 0x80
|
|
|
|
#define CLOCK_RATE 0x1C200 // USART clock rate
|
|
|
|
#define MC_DTRRTS 0x03 // Control bits to assert DTR and RTS
|
|
#define MS_DSRCTSCD 0xB0 // Status bits for DSR, CTS and CD
|
|
#define MS_CD 0x80
|
|
|
|
#define SERIAL_MCR_LOOP 0x10 // enables loopback testing mode
|
|
#define SERIAL_MCR_OUT1 0x04 // general purpose output.
|
|
#define SERIAL_MSR_CTS 0x10 // (complemented) state of clear to send (CTS).
|
|
#define SERIAL_MSR_DSR 0x20 // (complemented) state of data set ready (DSR).
|
|
#define SERIAL_MSR_RI 0x40 // (complemented) state of ring indicator (RI).
|
|
#define SERIAL_MSR_DCD 0x80 // (complemented) state of data carrier detect (DCD).
|
|
|
|
//
|
|
// Globals
|
|
//
|
|
static UINT16 KdBasePort = COM2_PORT;
|
|
|
|
////////////////////////////////////////////////// Serial Port Input & Output.
|
|
//
|
|
|
|
static UINT8 KdReadInt8(UINT16 port)
|
|
{
|
|
return __inbyte(port);
|
|
}
|
|
|
|
static void KdWriteInt8(UINT16 port, UINT8 value)
|
|
{
|
|
__outbyte(port, value);
|
|
}
|
|
|
|
bool KdpSerialInit(Class_Microsoft_Singularity_Hal_Platform *nbi)
|
|
// Initializes the communication port (baud rate, parity etc.)
|
|
{
|
|
KdBasePort = (UINT16)nbi->DebugBasePort;
|
|
if (KdBasePort < 0x100) {
|
|
KdBasePort = 0;
|
|
return false;
|
|
}
|
|
|
|
// turn off interrupts
|
|
KdWriteInt8(KdBasePort + COM_LCR, 0x00);
|
|
KdWriteInt8(KdBasePort + COM_IEN, 0x00);
|
|
|
|
// Turn on DTS/RTS
|
|
KdWriteInt8(KdBasePort + COM_MCR, MC_DTRRTS); // Needed for VirtualPC PIPE/Serial
|
|
|
|
// Turn on FIFO
|
|
//KdWriteInt8(KdBasePort + COM_FCR, 1);
|
|
|
|
// Set the baud rate
|
|
KdWriteInt8(KdBasePort + COM_LCR, LC_DLAB); // Divisor latch access bit
|
|
KdWriteInt8(KdBasePort + COM_DLM, (UINT8)(BaudRate >> 8));
|
|
KdWriteInt8(KdBasePort + COM_DLL, (UINT8)(BaudRate & 0xFF));
|
|
|
|
// initialize the LCR
|
|
KdWriteInt8(KdBasePort + COM_LCR, 0x03);
|
|
// 8 data bits, 1 stop bit, no parity, no break
|
|
|
|
// See if the 16450/16550 scratch register is available.
|
|
// If not, we'll assume the serial port doesn't really exist.
|
|
KdWriteInt8(KdBasePort + COM_SCR, 0xff);
|
|
UINT8 a1 = KdReadInt8(KdBasePort + COM_SCR);
|
|
KdWriteInt8(KdBasePort + COM_SCR, 0x00);
|
|
UINT8 a2 = KdReadInt8(KdBasePort + COM_SCR);
|
|
|
|
return (bool) ((a1 == (UINT8)0xff) && (a2 == (UINT8)0x00));
|
|
}
|
|
|
|
//
|
|
// Define wait timeout value.
|
|
//
|
|
#define TIMEOUT_COUNT 1024 * 1000
|
|
// #define TIMEOUT_COUNT 1024 * 200
|
|
//#define TIMEOUT_COUNT 15
|
|
|
|
KDP_STATUS KdpSerialGetByte(OUT PUCHAR Input, BOOL WaitForByte)
|
|
{
|
|
UCHAR lsr;
|
|
UCHAR value;
|
|
UINT32 limitcount = WaitForByte ? TIMEOUT_COUNT : 1;
|
|
|
|
UCHAR msr;
|
|
msr = KdReadInt8(KdBasePort + COM_MSR);
|
|
KDDBG2("MSR %02x\n", msr);
|
|
|
|
while (limitcount != 0) {
|
|
limitcount--;
|
|
|
|
lsr = KdReadInt8(KdBasePort + COM_LSR);
|
|
KDDBG2("LSR %02x\n", lsr);
|
|
if (lsr & COM_DATRDY) {
|
|
value = KdReadInt8(KdBasePort + COM_DAT);
|
|
*Input = value & 0xff;
|
|
return KDP_PACKET_RECEIVED;
|
|
}
|
|
}
|
|
return KDP_PACKET_TIMEOUT;
|
|
}
|
|
|
|
|
|
void KdpSerialPutByte(IN UCHAR Output)
|
|
{
|
|
// wait for the com port to be ready
|
|
while ((KdReadInt8( KdBasePort + COM_LSR ) & COM_OUTRDY) == 0) {
|
|
// nop;
|
|
}
|
|
|
|
// write a single char
|
|
KdWriteInt8(KdBasePort + COM_DAT, Output);
|
|
}
|
|
//
|
|
///////////////////////////////////////////////////////////////// End of File.
|