295 lines
6.3 KiB
C
295 lines
6.3 KiB
C
|
/*++
|
|||
|
|
|||
|
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
|