singrdk/base/boot/SingLdrPc/blcom.cpp

376 lines
8.4 KiB
C++
Raw Normal View History

2008-11-17 18:29:00 -05:00
//++
//
// Copyright (c) Microsoft Corporation
//
// Module Name:
//
// blcom.cpp
//
// Abstract:
//
// This module implements COM port support for the boot loader.
//
//--
#include "bl.h"
#define COM1_ADDRESS 0x3F8
#define COM2_ADDRESS 0x2F8
#define COM3_ADDRESS 0x3E8
#define COM4_ADDRESS 0x2E8
const UINT16 BlComBasePort[COM_MAX_PORT + 1] = {
0,
COM1_ADDRESS,
COM2_ADDRESS,
COM3_ADDRESS,
COM4_ADDRESS
};
#define COM_DATA_REGISTER 0x0000
#define COM_INTERRUPT_ENABLE_REGISTER 0x0001
#define COM_INTERRUPT_IDENTIFICATION_REGISTER 0x0002
#define COM_FIFO_CONTROL_REGISTER 0x0002
#define COM_LINE_CONTROL_REGISTER 0x0003
#define COM_MODEM_CONTROL_REGISTER 0x0004
#define COM_LINE_STATUS_REGISTER 0x0005
#define COM_MODEM_STATUS_REGISTER 0x0006
#define COM_SCRATCH_REGISTER 0x0007
#define COM_DIVISOR_LATCH_REGISTER_LOW 0x0000
#define COM_DIVISOR_LATCH_REGISTER_HIGH 0x0001
#define COM_CLOCK_RATE 0x1C200
#define COM_LINE_CONTROL_8BITS_1STOP 0x03
#define COM_LINE_CONTROL_DIVISOR_ACCESS 0x80
#define COM_MODEM_CONTROL_DATA_TERMINAL_READY 0x01
#define COM_MODEM_CONTROL_REQUEST_TO_SEND 0x02
#define COM_LINE_STATUS_DATA_READY 0x01
#define COM_LINE_STATUS_OVERRUN_ERROR 0x02
#define COM_LINE_STATUS_PARITY_ERROR 0x04
#define COM_LINE_STATUS_FRAMING_ERROR 0x08
#define COM_LINE_STATUS_SEND_BUFFER_EMPTY 0x20
BOOLEAN
BlComInitialize(
UINT8 PortNumber,
UINT32 BaudRate
)
//++
//
// Routine Description:
//
// This function initializes the specified COM port.
//
// Arguments:
//
// PortNumber - Supplies the number of the port to initialize.
//
// BaudRate - Supplies the baud rate.
//
// Return Value:
//
// TRUE, if initialization was successful.
// FALSE, otherwise.
//
//--
{
UINT16 Base;
UINT16 Divisor;
UINT8 Index;
UINT8 Status;
BLASSERT((PortNumber >= 1) && (PortNumber <= COM_MAX_PORT));
BLASSERT(BaudRate != 0);
BLASSERT(BaudRate <= COM_CLOCK_RATE);
BLASSERT((COM_CLOCK_RATE % BaudRate) == 0);
BLASSERT((COM_CLOCK_RATE / BaudRate) <= 0x10000);
Base = BlComBasePort[PortNumber];
BlRtlWritePort8(Base + COM_LINE_CONTROL_REGISTER, 0);
BlRtlWritePort8(Base + COM_INTERRUPT_ENABLE_REGISTER, 0);
BlRtlWritePort8(Base + COM_MODEM_CONTROL_REGISTER, COM_MODEM_CONTROL_DATA_TERMINAL_READY | COM_MODEM_CONTROL_REQUEST_TO_SEND);
Divisor = (UINT16) (COM_CLOCK_RATE / BaudRate);
BlRtlWritePort8(Base + COM_LINE_CONTROL_REGISTER, COM_LINE_CONTROL_DIVISOR_ACCESS);
BlRtlWritePort8(Base + COM_DIVISOR_LATCH_REGISTER_LOW, (UINT8) (Divisor & 0xFF));
BlRtlWritePort8(Base + COM_DIVISOR_LATCH_REGISTER_HIGH, (UINT8) (Divisor >> 8));
BlRtlWritePort8(Base + COM_LINE_CONTROL_REGISTER, COM_LINE_CONTROL_8BITS_1STOP);
Index = 0;
do {
BlRtlWritePort8(Base + COM_SCRATCH_REGISTER, Index);
if (BlRtlReadPort8(Base + COM_SCRATCH_REGISTER) != Index) {
return FALSE;
}
Index += 1;
} while (Index != 0);
Status = BlRtlReadPort8(Base + COM_LINE_STATUS_REGISTER);
if (Status == 0xFF) {
return FALSE;
}
#if COM_VERBOSE
if ((Status & COM_LINE_STATUS_OVERRUN_ERROR) != 0) {
BlVideoPrintf("COM%u: Overrun error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_PARITY_ERROR) != 0) {
BlVideoPrintf("COM%u: Parity error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_FRAMING_ERROR) != 0) {
BlVideoPrintf("COM%u: Framing error!\n", PortNumber);
}
#endif
return TRUE;
}
BOOLEAN
BlComSendByte(
UINT8 PortNumber,
UINT8 Byte
)
//++
//
// Routine Description:
//
// This function sends a byte to the specified COM port.
//
// Arguments:
//
// PortNumber - Supplies the number of the port to send to.
//
// Byte - Supplies the byte to send.
//
// Return Value:
//
// TRUE, if data was sent.
// FALSE, otherwise.
//
//--
{
UINT16 Base;
UINT8 Status;
BLASSERT((PortNumber >= 1) && (PortNumber <= COM_MAX_PORT));
Base = BlComBasePort[PortNumber];
do {
Status = BlRtlReadPort8(Base + COM_LINE_STATUS_REGISTER);
#if COM_VERBOSE
if ((Status & COM_LINE_STATUS_OVERRUN_ERROR) != 0) {
BlVideoPrintf("COM%u: Overrun error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_PARITY_ERROR) != 0) {
BlVideoPrintf("COM%u: Parity error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_FRAMING_ERROR) != 0) {
BlVideoPrintf("COM%u: Framing error!\n", PortNumber);
}
#endif
} while ((Status & COM_LINE_STATUS_SEND_BUFFER_EMPTY) == 0);
BlRtlWritePort8(Base + COM_DATA_REGISTER, Byte);
Status = BlRtlReadPort8(Base + COM_LINE_STATUS_REGISTER);
#if COM_VERBOSE
if ((Status & COM_LINE_STATUS_OVERRUN_ERROR) != 0) {
BlVideoPrintf("COM%u: Overrun error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_PARITY_ERROR) != 0) {
BlVideoPrintf("COM%u: Parity error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_FRAMING_ERROR) != 0) {
BlVideoPrintf("COM%u: Framing error!\n", PortNumber);
}
#endif
return TRUE;
}
BOOLEAN
BlComDataAvailable(
UINT8 PortNumber
)
//++
//
// Routine Description:
//
// This function checks if data is available at the specified COM port.
//
// Arguments:
//
// PortNumber - Supplies the number of the port to check.
//
// Return Value:
//
// TRUE, if data is available.
// FALSE, otherwise.
//
//--
{
UINT16 Base;
UINT8 Status;
BLASSERT((PortNumber >= 1) && (PortNumber <= COM_MAX_PORT));
Base = BlComBasePort[PortNumber];
Status = BlRtlReadPort8(Base + COM_LINE_STATUS_REGISTER);
#if COM_VERBOSE
if ((Status & COM_LINE_STATUS_OVERRUN_ERROR) != 0) {
BlVideoPrintf("COM%u: Overrun error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_PARITY_ERROR) != 0) {
BlVideoPrintf("COM%u: Parity error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_FRAMING_ERROR) != 0) {
BlVideoPrintf("COM%u: Framing error!\n", PortNumber);
}
#endif
return ((Status & COM_LINE_STATUS_DATA_READY) != 0);
}
UINT8
BlComReceiveByte(
UINT8 PortNumber
)
//++
//
// Routine Description:
//
// This function receives a byte from the specified COM port.
//
// Arguments:
//
// PortNumber - Supplies the number of the port to receive from.
//
// Return Value:
//
// Byte received from the specified COM port.
//
//--
{
UINT16 Base;
UINT8 Byte;
UINT8 Status;
BLASSERT((PortNumber >= 1) && (PortNumber <= COM_MAX_PORT));
Base = BlComBasePort[PortNumber];
BlRtlReadPort8(Base + COM_MODEM_STATUS_REGISTER);
do {
Status = BlRtlReadPort8(Base + COM_LINE_STATUS_REGISTER);
#if COM_VERBOSE
if ((Status & COM_LINE_STATUS_OVERRUN_ERROR) != 0) {
BlVideoPrintf("COM%u: Overrun error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_PARITY_ERROR) != 0) {
BlVideoPrintf("COM%u: Parity error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_FRAMING_ERROR) != 0) {
BlVideoPrintf("COM%u: Framing error!\n", PortNumber);
}
#endif
} while ((Status & COM_LINE_STATUS_DATA_READY) == 0);
Byte = BlRtlReadPort8(Base + COM_DATA_REGISTER);
Status = BlRtlReadPort8(Base + COM_LINE_STATUS_REGISTER);
#if COM_VERBOSE
if ((Status & COM_LINE_STATUS_OVERRUN_ERROR) != 0) {
BlVideoPrintf("COM%u: Overrun error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_PARITY_ERROR) != 0) {
BlVideoPrintf("COM%u: Parity error!\n", PortNumber);
}
if ((Status & COM_LINE_STATUS_FRAMING_ERROR) != 0) {
BlVideoPrintf("COM%u: Framing error!\n", PortNumber);
}
#endif
return Byte;
}