/////////////////////////////////////////////////////////////////////////////// // // Microsoft Research Singularity // // Copyright (c) Microsoft Corporation. All rights reserved. // // HalKdUartIop348.cpp: UART serial transport for IOP348 // // Note: Kernel Only // #include "hal.h" #include "halkd.h" // // Debugger Debugging // #define KDDBG if (0) kdprintf #define KDDBG2 if (0) kdprintf // // Status Constants for reading data from comport // #define CP_GET_SUCCESS 0 #define CP_GET_NODATA 1 #define CP_GET_ERROR 2 #define IOP348_UART1_BASE 0xffd82300 #define IOP348_UART2_BASE 0xffd82340 ///////////////////////////////////////////////////////////////// Serial Port. // #define IOP348_CLOCK_RATE 2083375 #define IOP348_CONTROL_PADCONF_UART1_TX (0x17c) #define IOP348_CONTROL_PADCONF_UART1_CTS (0x180) #define IOP348_CONTROL_PADCONF_UART2_TX (0x178) #define IOP348_CONTROL_PADCONF_UART2_CTS (0x174) // Define COM Port registers. #define COM_DAT 0x00 #define COM_DLL 0x00 // Divisor Latch (LSB). #define COM_IEN 0x01 // Interrupt enable register #define COM_DLM 0x01 // Divisor Latch (MSB). #define COM_FCR 0x02 // FIFO Control Register. #define COM_LCR 0x03 // Line Control Register. #define COM_MCR 0x04 // Modem Control Register. #define COM_LSR 0x05 // Line Status Register. #define COM_MSR 0x06 // Modem Status Register. #define COM_SCR 0x07 // Scratch Register. #define IOP348_UART_MDR1 0x8 #define IOP348_UART_IER 0x1 #define IOP348_UART_EFR 0x2 // Define bits in the Interrupt enable register #define IEN_UNIT_ENABLE 0x40 // Define bits in the FIFO Control Register (FCR). #define FCR_ENABLE 0x01 #define FCR_CLEAR_RECEIVE 0x02 #define FCR_CLEAR_TRANSMIT 0x04 // Define bits in the Line Control Register (LCR). #define LCR_DATA_SIZE 0x03 #define LCR_DLAB 0x80 // Define bits in the Modem Control Register (MCR). #define MCR_DATA_TERMINAL_READY 0x01 #define MCR_REQUEST_TO_SEND 0x02 #define MCR_OUT1 0x04 #define MCR_OUT2 0x08 #define MCR_LOOPBACK 0x10 #define MCR_INITIALIZE (MCR_DATA_TERMINAL_READY | MCR_REQUEST_TO_SEND) // Define bits in the Line Status Register (LSR). #define LSR_DATA_AVAILABLE 0x01 #define LSR_OVERRUN_ERROR 0x02 #define LSR_PARITY_ERROR 0x04 #define LSR_FRAMING_ERROR 0x08 #define LSR_BREAK_SIGNAL 0x10 #define LSR_THR_EMPTY 0x20 #define LSR_THR_LINE_IDLE 0x40 // Defined bits in the Modem Status Register (MSR). #define MSR_DELTA_CLEAR_TO_SEND 0x01 #define MSR_DELTA_DATA_SET_READY 0x02 #define MSR_DELTA_RING_INDICATOR 0x04 #define MSR_DELTA_CARRIER_DETECT 0x08 #define MSR_CLEAR_TO_SEND 0x10 #define MSR_DATA_SET_READY 0x20 #define MSR_RING_INDICATOR 0x40 #define MSR_CARRIER_DETECT 0x80 // // Communication functions. // static const uint32 BaudRate = 115200; static uint32 *uartBase = 0; ////////////////////////////////////////////////// Serial Port Input & Output. // static inline void WriteReg8(volatile void * addr, uint8 value) { ((volatile uint8 *)addr)[0] = value; } static inline uint8 ReadReg8(volatile void * addr) { return ((volatile uint8 *)addr)[0]; } static void UartSetBaudRate(uint32 * BaseAddress, uint32 BaudRate) { UINT32 Divisor = 18; // IOP348_CLOCK_RATE / BaudRate; // Disable UART WriteReg8(BaseAddress + IOP348_UART_MDR1, 0x7); // Set register configuration mode B WriteReg8(BaseAddress + COM_LCR, 0xBF); // Save enhanced mode UINT8 Enhanced = ReadReg8(BaseAddress + IOP348_UART_EFR); WriteReg8(BaseAddress + IOP348_UART_EFR, Enhanced | (1 << 4)); // switch to operational mode WriteReg8(BaseAddress + COM_LCR, 0); // clear sleep mode WriteReg8(BaseAddress + IOP348_UART_IER, 0); // Set register configuration mode B WriteReg8(BaseAddress + COM_LCR, 0xBF); // Write the divisor value to DLL and DLM. WriteReg8(BaseAddress + COM_DLM, (UINT8)((Divisor >> 8) & 0xff)); WriteReg8(BaseAddress + COM_DLL, (UINT8)(Divisor & 0xff)); // Restore enhanced mode WriteReg8(BaseAddress + IOP348_UART_EFR, Enhanced); // Reset the Line Control Register. WriteReg8(BaseAddress + COM_LCR, LCR_DATA_SIZE); // Enable UART WriteReg8(BaseAddress + IOP348_UART_MDR1, 0); } bool KdpSerialInit(Class_Microsoft_Singularity_Hal_Platform *nbi) { if (nbi->DebugBasePort < 0x100) { return false; } uartBase = (uint32 *)nbi->DebugBasePort; // Set the default baudrate. UartSetBaudRate(uartBase, BaudRate); // Set DLAB to zero. DLAB controls the meaning of the first two // registers. When zero, the first register is used for all byte transfer // and the second register controls device interrupts. // WriteReg8(uartBase + COM_LCR, ReadReg8(uartBase + COM_LCR) & ~LCR_DLAB); // Disable device interrupts. This implementation will handle state // transitions by request only. WriteReg8(uartBase + COM_IEN, 0); // Reset and disable the FIFO queue. // N.B. FIFO will be reenabled before returning from this routine. // WriteReg8(uartBase + COM_FCR, FCR_CLEAR_TRANSMIT | FCR_CLEAR_RECEIVE); // Configure the Modem Control Register. Disabled device interrupts, // turn off loopback. // WriteReg8(uartBase + COM_MCR, ReadReg8(uartBase + COM_MCR) & MCR_INITIALIZE); // Initialize the Modem Control Register. Indicate to the device that // we are able to send and receive data. // WriteReg8(uartBase + COM_MCR, MCR_INITIALIZE); // Enable the FIFO queues. WriteReg8(uartBase + COM_FCR, FCR_ENABLE); // Enable the UART by enabling the UUE bit WriteReg8(uartBase + COM_IEN, IEN_UNIT_ENABLE); return true; } // // Define wait timeout value. // #define TIMEOUT_COUNT 30 * 1024 // #define TIMEOUT_COUNT 1024 * 200 //#define TIMEOUT_COUNT 15 KDP_STATUS KdpSerialGetByte(OUT PUCHAR Input, BOOL WaitForByte) { UINT8 lsr; UINT8 value; UINT32 limitcount = WaitForByte ? TIMEOUT_COUNT : 1; UINT8 msr; msr = ReadReg8(uartBase + COM_MSR); while (limitcount != 0) { limitcount--; lsr = ReadReg8(uartBase + COM_LSR); if (lsr & LSR_DATA_AVAILABLE) { value = ReadReg8(uartBase + COM_DAT); *Input = (UINT8)(value & 0xff); return KDP_PACKET_RECEIVED; } } return KDP_PACKET_TIMEOUT; } void KdpSerialPutByte(IN UCHAR Output) { // Loop until the device is ready for output while ((ReadReg8(uartBase + COM_LSR) & LSR_THR_EMPTY) == 0) { } // The transmitter regiser is clear and can be written to. WriteReg8(uartBase + COM_DAT, Output); } // End of File.