/*++ Copyright (c) 1991 Microsoft Corporation Copyright (c) 1992 Silicon Graphics, Inc. Module Name: s3port.c Abstract: This module implements the code that provides communication between the kernel debugger on SGI's Indigo system and the host system. Author: David N. Cutler (davec) 28-Apr-1991 Kevin Meier (o-kevinm) 20-Jan-1992 Environment: Kernel mode Revision History: --*/ #include "halp.h" #define HEADER_FILE #include "kxmips.h" // BUGBUG put these in a header file!!! // Defines from sgikbmou.h for the z8530 // #define DBGPORT_BASE 0xbfb80d10 #define DBGPORT_CTRL DBGPORT_BASE #define DBGPORT_DATA (DBGPORT_BASE+4) #define RR0_TX_EMPTY 0x04 /* Tx buffer empty */ #define RR0_RX_CHR 0x01 /* Rx character available */ #define RR1_FRAMING_ERR 0x40 /* framing error */ #define RR1_RX_ORUN_ERR 0x20 /* Rx overrun */ #define RR1_PARITY_ERR 0x10 /* parity error */ #define WR0_RST_ERR 0x30 /* reset error (bits in RR1) */ #define RR1 1 /* Rx condition status/residue codes */ #define WR12 12 #define WR13 13 #define WR14 14 #define WR14_BRG_ENBL 0x01 #define Z8530_DELAY KeStallExecutionProcessor(1) #define BRATE 19200 #define CLK_SPEED 3672000 #define CLK_FACTOR 16 #define WR_CNTRL(p, r, v) {Z8530_DELAY; \ WRITE_REGISTER_ULONG((p), (ULONG)(r)); \ Z8530_DELAY; \ WRITE_REGISTER_ULONG((p), (ULONG)(v));} #define TIMEOUT_COUNT 1024*512 // // BUGBUG For now, the kernel debugger will use this variable to // port to the debugger port it is using. // PUCHAR KdComPortInUse = NULL; BOOLEAN KdPortInitialize ( PDEBUG_PARAMETERS DebugParameters, PLOADER_PARAMETER_BLOCK LoaderBlock, BOOLEAN Initialize ) { ULONG baud = (CLK_SPEED + BRATE * CLK_FACTOR) / (BRATE * CLK_FACTOR * 2) - 2; // // If the debugger is not being enabled, then return. There is no // need to capture any parameters. // if (Initialize == FALSE) { return(TRUE); } // // BUGBUG For now, simply save the physical base of the // uart being used for debugging. The serial driver will // use this to prevent itself from using the UART. // KdComPortInUse = (PUCHAR)DBGPORT_CTRL; // The prom has already initialized the port, simply set the baud // rate to 19200. // WR_CNTRL(DBGPORT_CTRL, WR14, 0x00) WR_CNTRL(DBGPORT_CTRL, WR12, baud & 0xff) WR_CNTRL(DBGPORT_CTRL, WR13, (baud >> 8) & 0xff) WR_CNTRL(DBGPORT_CTRL, WR14, WR14_BRG_ENBL) return TRUE; } ULONG HalpGetByte ( IN PCHAR Input, IN BOOLEAN Wait ) /*++ Routine Description: This routine gets a byte from the serial port used by the kernel debugger. Arguments: Input - Supplies a pointer to a variable that receives the input data byte. Wait - Supplies a boolean value that detemines whether a timeout is applied to the input operation. Return Value: CP_GET_SUCCESS is returned if a byte is successfully read from the kernel debugger line. CP_GET_ERROR is returned if an error is encountered during reading. CP_GET_NODATA is returned if timeout occurs. --*/ { ULONG TimeoutCount; // // Attempt to read a byte from the debugger port until a byte is // available or until a timeout occurs. // TimeoutCount = Wait ? TIMEOUT_COUNT : 1; do { TimeoutCount -= 1; // // Wait until data is available in the receive buffer. // KeStallExecutionProcessor(1); if (!(READ_REGISTER_ULONG(DBGPORT_CTRL) & RR0_RX_CHR)) continue; // // Read input byte and store in callers buffer. // WRITE_REGISTER_ULONG(DBGPORT_CTRL, RR1); if((READ_REGISTER_ULONG(DBGPORT_CTRL) & (RR1_RX_ORUN_ERR | RR1_FRAMING_ERR | RR1_PARITY_ERR))) { WRITE_REGISTER_ULONG(DBGPORT_CTRL, WR0_RST_ERR); return CP_GET_ERROR; } else { *Input = (UCHAR)(READ_REGISTER_ULONG(DBGPORT_DATA)); } return CP_GET_SUCCESS; } while(TimeoutCount != 0); return CP_GET_NODATA; } ULONG KdPortGetByte ( OUT PUCHAR Input ) /*++ Routine Description: This routine gets a byte from the serial port used by the kernel debugger. N.B. It is assumed that the IRQL has been raised to the highest level, and necessary multiprocessor synchronization has been performed before this routine is called. Arguments: Input - Supplies a pointer to a variable that receives the input data byte. Return Value: CP_GET_SUCCESS is returned if a byte is successfully read from the kernel debugger line. CP_GET_ERROR is returned if an error is encountered during reading. CP_GET_NODATA is returned if timeout occurs. --*/ { return HalpGetByte(Input, TRUE); } ULONG KdPortPollByte ( OUT PUCHAR Input ) /*++ Routine Description: This routine gets a byte from the serial port used by the kernel debugger iff a byte is available. N.B. It is assumed that the IRQL has been raised to the highest level, and necessary multiprocessor synchronization has been performed before this routine is called. Arguments: Input - Supplies a pointer to a variable that receives the input data byte. Return Value: CP_GET_SUCCESS is returned if a byte is successfully read from the kernel debugger line. CP_GET_ERROR is returned if an error encountered during reading. CP_GET_NODATA is returned if timeout occurs. --*/ { ULONG Status; // // Save port status, map the serial controller, get byte from the // debugger port is one is avaliable, restore port status, unmap // the serial controller, and return the operation status. // KdPortSave(); Status = HalpGetByte(Input, FALSE); KdPortRestore(); return Status; } VOID KdPortPutByte (IN UCHAR Output) { // Wait for the transmit buffer to empty, and write the char. // while(!(READ_REGISTER_ULONG(DBGPORT_CTRL) & RR0_TX_EMPTY)) ; // empty WRITE_REGISTER_ULONG(DBGPORT_DATA,(ULONG)Output); return; } VOID KdPortRestore (VOID) { return; } VOID KdPortSave (VOID) { return; } #ifdef DBG VOID SgiPortPuts(IN PCHAR pString) { for(; *pString; KdPortPutByte((UCHAR)*pString), ++pString ); } #endif