1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
|
/*++
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
|