1 |
/**************************************************************************** |
2 |
/* F i l e D a t a |
3 |
/* |
4 |
/* Module : BootStrap |
5 |
/* C.I. No. : |
6 |
/* $Revision: 1.2 $ |
7 |
/* $Date: 2003/08/22 07:49:03 $ |
8 |
/* Belonging to : |
9 |
/* : |
10 |
/* $RCSfile: mon.c,v $ |
11 |
/* Program Type : |
12 |
/* Sub-modules : |
13 |
/* |
14 |
/**************************************************************************** |
15 |
/* S W D e v e l o p m e n t E n v i r o n m e n t |
16 |
/* |
17 |
/* Host system : |
18 |
/* SW Compiler : |
19 |
/* $Author: sebastiani $ |
20 |
/* : |
21 |
/**************************************************************************** |
22 |
/* U p d a t i n g |
23 |
/* |
24 |
/* $Log: mon.c,v $ |
25 |
/* Revision 1.2 2003/08/22 07:49:03 sebastiani |
26 |
/* write the magic number (usefull to undestand the log start) |
27 |
/* |
28 |
/* Revision 1.1.1.1 2003/08/04 09:40:21 sebastiani |
29 |
/* Imported sources laben rel. 19.06.2003 integrated with pam2 |
30 |
/* |
31 |
/* Revision 1.5 2002/07/25 09:24:46 zulia |
32 |
/* FM PROM - Configurated version |
33 |
/* |
34 |
/* Revision 1.4 2002/07/16 07:13:32 zulia |
35 |
/* setup for 24MHz |
36 |
/* Copy the eeprom in ram at boot |
37 |
/* |
38 |
/* Revision 1.3 2002/05/09 08:16:34 zulia |
39 |
/* * acceptance release |
40 |
/* |
41 |
/* |
42 |
/*****************************************************************************/ |
43 |
|
44 |
|
45 |
/**************************************************************************** |
46 |
|
47 |
THIS SOFTWARE IS NOT COPYRIGHTED |
48 |
|
49 |
HP offers the following for use in the public domain. HP makes no |
50 |
warranty with regard to the software or it's performance and the |
51 |
user accepts the software "AS IS" with all faults. |
52 |
|
53 |
HP DISCLAIMS ANY WARRANTIES, EXPRESS OR IMPLIED, WITH REGARD |
54 |
TO THIS SOFTWARE INCLUDING BUT NOT LIMITED TO THE WARRANTIES |
55 |
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
56 |
|
57 |
****************************************************************************/ |
58 |
|
59 |
/**************************************************************************** |
60 |
* Header: remcom.c,v 1.34 91/03/09 12:29:49 glenne Exp $ |
61 |
* |
62 |
* Module name: remcom.c $ |
63 |
* Revision: 1.34 $ |
64 |
* Date: 91/03/09 12:29:49 $ |
65 |
* Contributor: Lake Stevens Instrument Division$ |
66 |
* |
67 |
* Description: low level support for gdb debugger. $ |
68 |
* |
69 |
* Considerations: only works on target hardware $ |
70 |
* |
71 |
* Written by: Glenn Engel $ |
72 |
* ModuleState: Experimental $ |
73 |
* |
74 |
* NOTES: See Below $ |
75 |
* |
76 |
* Modified for SPARC by Stu Grossman, Cygnus Support. |
77 |
* |
78 |
* Further modified by Jiri Gaisler, ESA/ESTEC, to work as |
79 |
* an embedded monitor for ERC32 targets. |
80 |
* |
81 |
* |
82 |
* @ 19200 |
83 |
* |
84 |
************* |
85 |
* |
86 |
* The following gdb commands are supported: |
87 |
* |
88 |
* command function Return value |
89 |
* |
90 |
* g return the value of the CPU registers hex data or ENN |
91 |
* G set the value of the CPU registers OK or ENN |
92 |
* |
93 |
* mAA..AA,LLLL Read LLLL bytes at address AA..AA hex data or ENN |
94 |
* MAA..AA,LLLL: Write LLLL bytes at address AA.AA OK or ENN |
95 |
* |
96 |
* c Resume at current address SNN ( signal NN) |
97 |
* cAA..AA Continue at address AA..AA SNN |
98 |
* |
99 |
* s Step one instruction SNN |
100 |
* sAA..AA Step one instruction from AA..AA SNN |
101 |
* |
102 |
* k kill |
103 |
* |
104 |
* ? What was the last sigval ? SNN (signal NN) |
105 |
* |
106 |
* bBB..BB Set baud rate to BB..BB OK or BNN, then sets |
107 |
* baud rate |
108 |
* |
109 |
* All commands and responses are sent with a packet which includes a |
110 |
* checksum. A packet consists of |
111 |
* |
112 |
* $<packet info>#<checksum>. |
113 |
* |
114 |
* where |
115 |
* <packet info> :: <characters representing the command or response> |
116 |
* <checksum> :: < two hex digits computed as modulo 256 sum of <packetinfo>> |
117 |
* |
118 |
* When a packet is received, it is first acknowledged with either '+' or '-'. |
119 |
* '+' indicates a successful transfer. '-' indicates a failed transfer. |
120 |
* |
121 |
* Example: |
122 |
* |
123 |
* Host: Reply: |
124 |
* $m0,10#2a +$00010203040506070809101112131415#42 |
125 |
* |
126 |
****************************************************************************/ |
127 |
|
128 |
#include <string.h> |
129 |
#include <signal.h> |
130 |
#include <src/BootStrap/Boot/la695e.h> |
131 |
|
132 |
/*============== Macros for asynchronous interrupts enable/disable =========*/ |
133 |
/* |
134 |
* Standard nop |
135 |
*/ |
136 |
|
137 |
#define nop() \ |
138 |
do { \ |
139 |
asm volatile ( "nop" ); \ |
140 |
} while ( 0 ) |
141 |
|
142 |
|
143 |
#define SPARC_PSR_PIL_MASK 0x00000F00 /* bits 8 - 11 */ |
144 |
|
145 |
/* |
146 |
* Get and set the PSR |
147 |
*/ |
148 |
|
149 |
#define sparc_get_psr( _psr ) \ |
150 |
do { \ |
151 |
(_psr) = 0; \ |
152 |
asm volatile( "rd %%psr, %0" : "=r" (_psr) : "0" (_psr) ); \ |
153 |
} while ( 0 ) |
154 |
|
155 |
#define sparc_set_psr( _psr ) \ |
156 |
do { \ |
157 |
asm volatile ( "mov %0, %%psr " : "=r" ((_psr)) : "0" ((_psr)) ); \ |
158 |
nop(); \ |
159 |
nop(); \ |
160 |
nop(); \ |
161 |
} while ( 0 ) |
162 |
|
163 |
#define sparc_disable_interrupts( _level ) \ |
164 |
do { \ |
165 |
register unsigned int _newlevel; \ |
166 |
\ |
167 |
sparc_get_psr( _level ); \ |
168 |
(_newlevel) = (_level) | SPARC_PSR_PIL_MASK; \ |
169 |
sparc_set_psr( _newlevel ); \ |
170 |
} while ( 0 ) |
171 |
|
172 |
#define sparc_enable_interrupts( _level ) \ |
173 |
do { \ |
174 |
unsigned int _tmp; \ |
175 |
\ |
176 |
sparc_get_psr( _tmp ); \ |
177 |
_tmp &= ~SPARC_PSR_PIL_MASK; \ |
178 |
_tmp |= (_level) & SPARC_PSR_PIL_MASK; \ |
179 |
sparc_set_psr( _tmp ); \ |
180 |
} while ( 0 ) |
181 |
|
182 |
|
183 |
/*===== Constant for routine to copy the application program into EEPROM ======*/ |
184 |
|
185 |
typedef unsigned char UBYTE; |
186 |
typedef unsigned int UINT; |
187 |
|
188 |
#define PD_RAM_ADDR_START RAM_START_EXE |
189 |
#define PD_EEPROM_ADDR_START EEPROM_START_EXE |
190 |
#define PD_EEPROM_LENGHT EEPROM_LEN_EXE |
191 |
#define PD_EEPROM_PAGE 0x200 /* EEPROM page Lenght 128 words 32bit */ |
192 |
#define PD_EEPROM_PAGE_W 0x80 /* EEPROM page Lenght 128 word */ |
193 |
#define PD_EEPROM_LAST_PAGE (PD_EEPROM_LENGHT - PD_EEPROM_PAGE) |
194 |
#define WAIT_FOR_20ms 0x19700 /* at 24 MHz */ |
195 |
|
196 |
#define CD_EEPROM_WRITE_ENABLE (*(unsigned short* )0x10000310 =0x0020) |
197 |
#define CD_EEPROM_WRITE_DISABLE (*(unsigned short* )0x10000310 =0x0120) |
198 |
|
199 |
#define word (unsigned int *) |
200 |
#define MEC_REG_BASE_ADDR 0x01f80000 |
201 |
#define CRIMEA_REG_BASE_ADDR 0x10000000 |
202 |
unsigned int *MEM_CONF_REG = word (MEC_REG_BASE_ADDR + 0x10); |
203 |
unsigned int *IO_CONF_REG = word (MEC_REG_BASE_ADDR + 0x14); |
204 |
unsigned int *CONFIG_LOW = word (CRIMEA_REG_BASE_ADDR + 0x310); |
205 |
unsigned int *EE_WAIT = word (CRIMEA_REG_BASE_ADDR + 0x340); |
206 |
|
207 |
#ifdef LEON |
208 |
#define START_ADDR 0x40000000 |
209 |
#else |
210 |
#define START_ADDR 0x2000000 |
211 |
#endif |
212 |
|
213 |
const char version[] = " rdbmon v1.0 by LABEN SpA - Starting monitor\n\n\r"; |
214 |
const char loadprg[] = " rdbmon v1.0 by LABEN SpA - Loading application\n\n\r"; |
215 |
const char copyprg[] = " rdbmon v1.0 by LABEN SpA - Loading application into EEPROM\n\n\r"; |
216 |
const char debugprg[] = " rdbmon v1.0 by LABEN SpA - Loading application into RAM\n\n\r"; |
217 |
const char startprg[] = " rdbmon v1.0 by LABEN SpA - Starting application\n\n\r"; |
218 |
|
219 |
extern int aux; |
220 |
|
221 |
/* ^^^^^^^^^^^^ p r o t o t y p e s ^^^^^^^^^^^^ */ |
222 |
unsigned short PD_ifcrcComp (unsigned char* adrs, unsigned short Crc); |
223 |
void PD_ifCopyRamToEEprom (UINT* Source, UINT* Dest, UINT Len); |
224 |
void PD_ifLoad (void); |
225 |
void PD_ifLoadFromEeprom (void); |
226 |
|
227 |
|
228 |
/*=========================================================================*/ |
229 |
/*============================== START CODE ===============================*/ |
230 |
|
231 |
void exceptionHandler(ex_num,ex_add,tbr) |
232 |
unsigned char ex_num; |
233 |
unsigned int *ex_add,tbr; |
234 |
{ |
235 |
unsigned int *t_add; |
236 |
|
237 |
t_add = (unsigned int *) ((tbr & ~0x0fff) | ((unsigned int) ex_num << 4)); |
238 |
*t_add = 0xA010000F; /* or %o7,%g0,%l0 */ |
239 |
t_add++; |
240 |
*t_add = (0x40000000 | (((unsigned int) (ex_add-t_add)) )); /* call _ex_add */ |
241 |
t_add++; |
242 |
*t_add = 0x9E100010; /* or %l0,%g0,%o7 */ |
243 |
} |
244 |
|
245 |
void flush_i_cache() |
246 |
{ |
247 |
/* asm("flush"); */ |
248 |
} |
249 |
|
250 |
unsigned char getDebugChar() |
251 |
{ |
252 |
char c; |
253 |
|
254 |
read(3,&c,1); |
255 |
return(c); |
256 |
} |
257 |
|
258 |
int putDebugChar(c) |
259 |
unsigned char c; |
260 |
{ |
261 |
return(write(4,&c,1)); |
262 |
} |
263 |
|
264 |
void puts(s) |
265 |
char *s; |
266 |
{ |
267 |
while (*s) { |
268 |
write(1,s,1); |
269 |
s++; |
270 |
} |
271 |
} |
272 |
|
273 |
/************************************************************************/ |
274 |
/* BUFMAX defines the maximum number of characters in inbound/outbound buffers*/ |
275 |
/* at least NUMREGBYTES*2 are needed for register packets */ |
276 |
#define BUFMAX 2048 |
277 |
|
278 |
static int initialized = 0; /* !0 means we've been initialized */ |
279 |
|
280 |
static void set_mem_fault_trap(); |
281 |
|
282 |
static const char hexchars[]="0123456789abcdef"; |
283 |
|
284 |
#define NUMREGS 72 |
285 |
|
286 |
/* Number of bytes of registers. */ |
287 |
#define NUMREGBYTES (NUMREGS * 4) |
288 |
enum regnames { G0, G1, G2, G3, G4, G5, G6, G7, |
289 |
O0, O1, O2, O3, O4, O5, SP, O7, |
290 |
L0, L1, L2, L3, L4, L5, L6, L7, |
291 |
I0, I1, I2, I3, I4, I5, FP, I7, |
292 |
|
293 |
F0, F1, F2, F3, F4, F5, F6, F7, |
294 |
F8, F9, F10, F11, F12, F13, F14, F15, |
295 |
F16, F17, F18, F19, F20, F21, F22, F23, |
296 |
F24, F25, F26, F27, F28, F29, F30, F31, |
297 |
Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR }; |
298 |
|
299 |
/*************************** ASSEMBLY CODE MACROS *************************/ |
300 |
/* */ |
301 |
|
302 |
extern void trap128(), systrap(), trap_low(); |
303 |
unsigned int trapstack; |
304 |
|
305 |
asm(" |
306 |
|
307 |
.data |
308 |
.align 4 |
309 |
|
310 |
in_trap_handler: |
311 |
.word 0 |
312 |
tctrl: |
313 |
.word 0 |
314 |
.word 0 |
315 |
|
316 |
|
317 |
! This function is called when any SPARC trap (except window overflow or |
318 |
! underflow) occurs. It makes sure that the invalid register window is still |
319 |
! available before jumping into C code. It will also restore the world if you |
320 |
! return from handle_exception. |
321 |
|
322 |
"); |
323 |
|
324 |
#ifdef LEON |
325 |
asm(" |
326 |
.text |
327 |
|
328 |
.globl _trap_low |
329 |
_trap_low: |
330 |
|
331 |
.align 4 |
332 |
set 0x80000000, %l3 ! stop timers |
333 |
ld [%l3 + 0x48], %l4 |
334 |
set tctrl, %l5 |
335 |
st %g0, [%l3 + 0x48] |
336 |
st %l4, [%l5] |
337 |
ld [%l3 + 0x58], %l4 |
338 |
st %g0, [%l3 + 0x58] |
339 |
st %l4, [%l5+4] |
340 |
"); |
341 |
#else |
342 |
asm(" |
343 |
.text |
344 |
|
345 |
.globl _trap_low |
346 |
_trap_low: |
347 |
|
348 |
set 0x01f80000, %l3 ! stop timers |
349 |
st %g0, [%l3 + 0x98] |
350 |
"); |
351 |
#endif |
352 |
asm(" |
353 |
.text |
354 |
|
355 |
mov %psr, %l0 |
356 |
mov %wim, %l3 |
357 |
|
358 |
srl %l3, %l0, %l4 ! wim >> cwp |
359 |
cmp %l4, 1 |
360 |
bne window_fine ! Branch if not in the invalid window |
361 |
nop |
362 |
|
363 |
! Handle window overflow |
364 |
|
365 |
mov %g1, %l4 ! Save g1, we use it to hold the wim |
366 |
srl %l3, 1, %g1 ! Rotate wim right |
367 |
sll %l3, 8-1, %l5 |
368 |
or %l5, %g1, %g1 |
369 |
|
370 |
save %g0, %g0, %g0 ! Slip into next window |
371 |
mov %g1, %wim ! Install the new wim |
372 |
|
373 |
std %l0, [%sp + 0 * 4] ! save L & I registers |
374 |
std %l2, [%sp + 2 * 4] |
375 |
std %l4, [%sp + 4 * 4] |
376 |
std %l6, [%sp + 6 * 4] |
377 |
|
378 |
std %i0, [%sp + 8 * 4] |
379 |
std %i2, [%sp + 10 * 4] |
380 |
std %i4, [%sp + 12 * 4] |
381 |
std %i6, [%sp + 14 * 4] |
382 |
|
383 |
restore ! Go back to trap window. |
384 |
mov %l4, %g1 ! Restore %g1 |
385 |
|
386 |
window_fine: |
387 |
sethi %hi(in_trap_handler), %l4 |
388 |
ld [%lo(in_trap_handler) + %l4], %l5 |
389 |
tst %l5 |
390 |
bg recursive_trap |
391 |
inc %l5 |
392 |
|
393 |
set _trapstack, %sp ! Switch to trap stack |
394 |
ld [%sp], %sp |
395 |
|
396 |
recursive_trap: |
397 |
st %l5, [%lo(in_trap_handler) + %l4] |
398 |
sub %sp,(16+1+6+1+72)*4,%sp ! Make room for input & locals |
399 |
! + hidden arg + arg spill |
400 |
! + doubleword alignment |
401 |
! + registers[72] local var |
402 |
|
403 |
std %g0, [%sp + (24 + 0) * 4] ! registers[Gx] |
404 |
std %g2, [%sp + (24 + 2) * 4] |
405 |
std %g4, [%sp + (24 + 4) * 4] |
406 |
std %g6, [%sp + (24 + 6) * 4] |
407 |
|
408 |
std %i0, [%sp + (24 + 8) * 4] ! registers[Ox] |
409 |
std %i2, [%sp + (24 + 10) * 4] |
410 |
std %i4, [%sp + (24 + 12) * 4] |
411 |
std %i6, [%sp + (24 + 14) * 4] |
412 |
mov %y, %l4 |
413 |
mov %tbr, %l5 |
414 |
st %l4, [%sp + (24 + 64) * 4] ! Y |
415 |
st %l0, [%sp + (24 + 65) * 4] ! PSR |
416 |
st %l3, [%sp + (24 + 66) * 4] ! WIM |
417 |
st %l5, [%sp + (24 + 67) * 4] ! TBR |
418 |
st %l1, [%sp + (24 + 68) * 4] ! PC |
419 |
st %l2, [%sp + (24 + 69) * 4] ! NPC |
420 |
|
421 |
! F0->F31 if FPU enabled |
422 |
srl %l0, 12, %l4 |
423 |
andcc %l4, 1, %g0 |
424 |
be 1f |
425 |
nop |
426 |
std %f0, [%sp + (24 + 32) * 4] |
427 |
std %f2, [%sp + (24 + 34) * 4] |
428 |
std %f4, [%sp + (24 + 36) * 4] |
429 |
std %f6, [%sp + (24 + 38) * 4] |
430 |
std %f8, [%sp + (24 + 40) * 4] |
431 |
std %f10, [%sp + (24 + 42) * 4] |
432 |
std %f12, [%sp + (24 + 44) * 4] |
433 |
std %f14, [%sp + (24 + 46) * 4] |
434 |
std %f16, [%sp + (24 + 48) * 4] |
435 |
std %f18, [%sp + (24 + 50) * 4] |
436 |
std %f20, [%sp + (24 + 52) * 4] |
437 |
std %f22, [%sp + (24 + 54) * 4] |
438 |
std %f24, [%sp + (24 + 56) * 4] |
439 |
std %f26, [%sp + (24 + 58) * 4] |
440 |
std %f28, [%sp + (24 + 60) * 4] |
441 |
std %f30, [%sp + (24 + 62) * 4] |
442 |
st %fsr, [%sp + (24 + 70) * 4] ! FSR |
443 |
! CPSR not impl |
444 |
|
445 |
1: |
446 |
or %l0, 0xf20, %l4 |
447 |
mov %l4, %psr ! Turn on traps, disable interrupts |
448 |
|
449 |
call _handle_exception |
450 |
add %sp, 24 * 4, %o0 ! Pass address of registers |
451 |
|
452 |
! Reload all of the registers that aren't on the stack |
453 |
|
454 |
ld [%sp + (24 + 1) * 4], %g1 ! registers[Gx] |
455 |
ldd [%sp + (24 + 2) * 4], %g2 |
456 |
ldd [%sp + (24 + 4) * 4], %g4 |
457 |
ldd [%sp + (24 + 6) * 4], %g6 |
458 |
|
459 |
ldd [%sp + (24 + 8) * 4], %i0 ! registers[Ox] |
460 |
ldd [%sp + (24 + 10) * 4], %i2 |
461 |
ldd [%sp + (24 + 12) * 4], %i4 |
462 |
ldd [%sp + (24 + 14) * 4], %i6 |
463 |
|
464 |
|
465 |
ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR |
466 |
srl %l1, 12, %l1 |
467 |
andcc %l1, 1, %g0 |
468 |
be 1f |
469 |
nop |
470 |
ldd [%sp + (24 + 32) * 4], %f0 ! F0->F31 |
471 |
ldd [%sp + (24 + 34) * 4], %f2 |
472 |
ldd [%sp + (24 + 36) * 4], %f4 |
473 |
ldd [%sp + (24 + 38) * 4], %f6 |
474 |
ldd [%sp + (24 + 40) * 4], %f8 |
475 |
ldd [%sp + (24 + 42) * 4], %f10 |
476 |
ldd [%sp + (24 + 44) * 4], %f12 |
477 |
ldd [%sp + (24 + 46) * 4], %f14 |
478 |
ldd [%sp + (24 + 48) * 4], %f16 |
479 |
ldd [%sp + (24 + 50) * 4], %f18 |
480 |
ldd [%sp + (24 + 52) * 4], %f20 |
481 |
ldd [%sp + (24 + 54) * 4], %f22 |
482 |
ldd [%sp + (24 + 56) * 4], %f24 |
483 |
ldd [%sp + (24 + 58) * 4], %f26 |
484 |
ldd [%sp + (24 + 60) * 4], %f28 |
485 |
ldd [%sp + (24 + 62) * 4], %f30 |
486 |
ld [%sp + (24 + 70) * 4], %fsr |
487 |
1: |
488 |
ldd [%sp + (24 + 64) * 4], %l0 ! Y & PSR |
489 |
ldd [%sp + (24 + 68) * 4], %l2 ! PC & NPC |
490 |
|
491 |
restore ! Ensure that previous window is valid |
492 |
save %g0, %g0, %g0 ! by causing a window_underflow trap |
493 |
|
494 |
mov %l0, %y |
495 |
mov %l1, %psr ! Make sure that traps are disabled |
496 |
! for rett |
497 |
nop; nop; nop |
498 |
|
499 |
sethi %hi(in_trap_handler), %l4 |
500 |
ld [%lo(in_trap_handler) + %l4], %l5 |
501 |
dec %l5 |
502 |
st %l5, [%lo(in_trap_handler) + %l4] |
503 |
"); |
504 |
|
505 |
#ifdef LEON |
506 |
asm(" |
507 |
.text |
508 |
|
509 |
set tctrl, %l5 |
510 |
ld [%l5], %l4 |
511 |
set 0x80000000, %l6 ! start timers |
512 |
st %l4, [%l6 + 0x48] |
513 |
ld [%l5 + 0x4], %l4 |
514 |
st %l4, [%l6 + 0x58] |
515 |
set 4, %l4 |
516 |
st %l4, [%l6 + 0x9C] |
517 |
ld [%l6 + 0x90], %l5 |
518 |
or %l5, %l4, %l5 |
519 |
st %l5, [%l6 + 0x90] |
520 |
"); |
521 |
|
522 |
#else |
523 |
asm(" |
524 |
.text |
525 |
|
526 |
mov %tbr, %l4 |
527 |
andn %l4, 0x0fff, %l4 |
528 |
or %l4, 0x07c0, %l4 |
529 |
ld [%l4], %l4 |
530 |
and %l4, 0x0505, %l4 ! Start timers |
531 |
set 0x01f80000, %l5 |
532 |
st %l4, [%l5 + 0x98] |
533 |
"); |
534 |
|
535 |
#endif |
536 |
|
537 |
asm(" |
538 |
.text |
539 |
|
540 |
jmpl %l2, %g0 ! Restore old PC |
541 |
rett %l3 ! Restore old nPC |
542 |
|
543 |
! handle sys traps |
544 |
|
545 |
.globl _systrap |
546 |
_systrap: |
547 |
mov %psr, %l0 |
548 |
subcc %g1, 1, %g0 |
549 |
be _trap_low |
550 |
mov %l0, %psr |
551 |
nop |
552 |
ba _trap128 |
553 |
nop |
554 |
.data |
555 |
.globl _trap128 |
556 |
_trap128: |
557 |
.word 0,0,0,0 |
558 |
.text |
559 |
|
560 |
"); |
561 |
|
562 |
/* Convert ch from a hex digit to an int */ |
563 |
|
564 |
static int |
565 |
hex(ch) |
566 |
unsigned char ch; |
567 |
{ |
568 |
if (ch >= 'a' && ch <= 'f') |
569 |
return ch-'a'+10; |
570 |
if (ch >= '0' && ch <= '9') |
571 |
return ch-'0'; |
572 |
if (ch >= 'A' && ch <= 'F') |
573 |
return ch-'A'+10; |
574 |
return -1; |
575 |
} |
576 |
|
577 |
/* scan for the sequence $<data>#<checksum> */ |
578 |
|
579 |
static void |
580 |
getpacket(buffer) |
581 |
char *buffer; |
582 |
{ |
583 |
unsigned char checksum; |
584 |
unsigned char xmitcsum; |
585 |
int i; |
586 |
int count; |
587 |
unsigned char ch; |
588 |
|
589 |
do |
590 |
{ |
591 |
/* wait around for the start character, ignore all other characters */ |
592 |
while ((ch = getDebugChar()) != '$') ; |
593 |
|
594 |
checksum = 0; |
595 |
xmitcsum = -1; |
596 |
|
597 |
count = 0; |
598 |
|
599 |
/* now, read until a # or end of buffer is found */ |
600 |
while (count < BUFMAX) |
601 |
{ |
602 |
ch = getDebugChar(); |
603 |
if (ch == '#') |
604 |
break; |
605 |
checksum = checksum + ch; |
606 |
buffer[count] = ch; |
607 |
count = count + 1; |
608 |
} |
609 |
|
610 |
if (count >= BUFMAX) |
611 |
continue; |
612 |
|
613 |
buffer[count] = 0; |
614 |
|
615 |
if (ch == '#') |
616 |
{ |
617 |
xmitcsum = hex(getDebugChar()) << 4; |
618 |
xmitcsum |= hex(getDebugChar()); |
619 |
#if 0 |
620 |
/* Humans shouldn't have to figure out checksums to type to it. */ |
621 |
putDebugChar ('+'); |
622 |
return; |
623 |
#endif |
624 |
if (checksum != xmitcsum) |
625 |
putDebugChar('-'); /* failed checksum */ |
626 |
else |
627 |
{ |
628 |
putDebugChar('+'); /* successful transfer */ |
629 |
/* if a sequence char is present, reply the sequence ID */ |
630 |
if (buffer[2] == ':') |
631 |
{ |
632 |
putDebugChar(buffer[0]); |
633 |
putDebugChar(buffer[1]); |
634 |
/* remove sequence chars from buffer */ |
635 |
count = strlen(buffer); |
636 |
for (i=3; i <= count; i++) |
637 |
buffer[i-3] = buffer[i]; |
638 |
} |
639 |
} |
640 |
} |
641 |
} |
642 |
while (checksum != xmitcsum); |
643 |
} |
644 |
|
645 |
/* send the packet in buffer. */ |
646 |
|
647 |
static void |
648 |
putpacket(buffer) |
649 |
unsigned char *buffer; |
650 |
{ |
651 |
unsigned char checksum; |
652 |
int count; |
653 |
unsigned char ch; |
654 |
|
655 |
/* $<packet info>#<checksum>. */ |
656 |
do |
657 |
{ |
658 |
putDebugChar('$'); |
659 |
checksum = 0; |
660 |
count = 0; |
661 |
|
662 |
while (ch = buffer[count]) |
663 |
{ |
664 |
if (! putDebugChar(ch)) |
665 |
return; |
666 |
checksum += ch; |
667 |
count += 1; |
668 |
} |
669 |
|
670 |
putDebugChar('#'); |
671 |
putDebugChar(hexchars[checksum >> 4]); |
672 |
putDebugChar(hexchars[checksum & 0xf]); |
673 |
|
674 |
} |
675 |
while (getDebugChar() != '+'); |
676 |
} |
677 |
|
678 |
static char remcomInBuffer[BUFMAX]; |
679 |
static char remcomOutBuffer[BUFMAX]; |
680 |
|
681 |
/* Indicate to caller of mem2hex or hex2mem that there has been an |
682 |
error. */ |
683 |
static volatile int mem_err = 0; |
684 |
|
685 |
/* Convert the memory pointed to by mem into hex, placing result in buf. |
686 |
* Return a pointer to the last char put in buf (null), in case of mem fault, |
687 |
* return 0. |
688 |
* If MAY_FAULT is non-zero, then we will handle memory faults by returning |
689 |
* a 0, else treat a fault like any other fault in the stub. |
690 |
*/ |
691 |
|
692 |
static unsigned char * |
693 |
mem2hex(mem, buf, count, may_fault) |
694 |
unsigned char *mem; |
695 |
unsigned char *buf; |
696 |
int count; |
697 |
int may_fault; |
698 |
{ |
699 |
unsigned char ch; |
700 |
|
701 |
set_mem_fault_trap(may_fault); |
702 |
|
703 |
while (count-- > 0) |
704 |
{ |
705 |
ch = *mem++; |
706 |
if (mem_err) { |
707 |
set_mem_fault_trap(0); |
708 |
return 0; |
709 |
} |
710 |
*buf++ = hexchars[ch >> 4]; |
711 |
*buf++ = hexchars[ch & 0xf]; |
712 |
} |
713 |
|
714 |
*buf = 0; |
715 |
|
716 |
set_mem_fault_trap(0); |
717 |
|
718 |
return buf; |
719 |
} |
720 |
|
721 |
static unsigned char * |
722 |
memw2hex(mem, buf, count, may_fault) |
723 |
unsigned char *mem; |
724 |
unsigned char *buf; |
725 |
int count; |
726 |
int may_fault; |
727 |
{ |
728 |
unsigned char ch; |
729 |
unsigned int memw, *memp; |
730 |
int i, first, last; |
731 |
|
732 |
if (!(((int) mem) & 3) && !(count & 3)) { |
733 |
set_mem_fault_trap(may_fault); |
734 |
|
735 |
memp = (int *) mem; |
736 |
while (count > 0) |
737 |
{ |
738 |
memw = *memp++; |
739 |
if (mem_err) { |
740 |
set_mem_fault_trap(0); |
741 |
return 0; |
742 |
} |
743 |
for (i=28; i>=0; i-=4) { |
744 |
ch = (memw >> i) & 0xf; |
745 |
*buf++ = hexchars[ch]; |
746 |
} |
747 |
count -= 4; |
748 |
} |
749 |
|
750 |
*buf = 0; |
751 |
|
752 |
set_mem_fault_trap(0); |
753 |
return buf; |
754 |
|
755 |
} else return(mem2hex(mem, buf, count, may_fault)); |
756 |
} |
757 |
|
758 |
/* convert the hex array pointed to by buf into binary to be placed in mem |
759 |
* return a pointer to the character AFTER the last byte written */ |
760 |
|
761 |
static char * |
762 |
hex2mem(buf, mem, count, may_fault) |
763 |
unsigned char *buf; |
764 |
unsigned char *mem; |
765 |
int count; |
766 |
int may_fault; |
767 |
{ |
768 |
int i; |
769 |
unsigned char ch; |
770 |
unsigned int memw; |
771 |
|
772 |
set_mem_fault_trap(may_fault); |
773 |
|
774 |
if ((count == 4) && ((((int) mem) & 3) == 0)) { |
775 |
memw = hex(*buf++); |
776 |
for (i=0; i<7; i++) { |
777 |
memw <<= 4; |
778 |
memw |= hex(*buf++); |
779 |
} |
780 |
*((int *)mem) = memw; |
781 |
dummy(memw); |
782 |
if (mem_err) { |
783 |
set_mem_fault_trap(0); |
784 |
return 0; |
785 |
} |
786 |
} else for (i=0; i<count; i++) |
787 |
{ |
788 |
ch = hex(*buf++) << 4; |
789 |
ch |= hex(*buf++); |
790 |
*mem++ = ch; |
791 |
dummy(ch); |
792 |
if (mem_err) { |
793 |
set_mem_fault_trap(0); |
794 |
return 0; |
795 |
} |
796 |
} |
797 |
|
798 |
set_mem_fault_trap(0); |
799 |
|
800 |
return mem; |
801 |
} |
802 |
|
803 |
dummy(memw) /* needed to avoid some gcc optimisations */ |
804 |
int memw; |
805 |
{} |
806 |
|
807 |
/* This table contains the mapping between SPARC hardware trap types, and |
808 |
signals, which are primarily what GDB understands. It also indicates |
809 |
which hardware traps we need to commandeer when initializing the stub. */ |
810 |
|
811 |
static struct hard_trap_info |
812 |
{ |
813 |
unsigned char tt; /* Trap type code for SPARClite */ |
814 |
unsigned char signo; /* Signal that we map this trap into */ |
815 |
} hard_trap_info[] = { |
816 |
{1, SIGSEGV}, /* instruction access error */ |
817 |
{2, SIGILL}, /* illegal instruction */ |
818 |
{3, SIGILL}, /* privileged instruction */ |
819 |
{4, SIGEMT}, /* fp disabled */ |
820 |
{36, SIGEMT}, /* cp disabled */ |
821 |
{7, SIGBUS}, /* mem address not aligned */ |
822 |
{9, SIGSEGV}, /* data access exception */ |
823 |
{10, SIGEMT}, /* tag overflow */ |
824 |
#ifdef LEON |
825 |
{0x12, SIGINT}, /* IRQ 2, UART B (used for host interrupt)*/ |
826 |
#else |
827 |
{0x15, SIGINT}, /* IRQ 5, UART B (used for host interrupt)*/ |
828 |
#endif |
829 |
/* {128, SIGSYS}, /* ta 0 - systrap used for exit */ |
830 |
{128+1, SIGTRAP}, /* ta 1 - normal breakpoint instruction */ |
831 |
{128+16, SIGHUP}, /* user define ta 16 - initialise */ |
832 |
{0, 0} /* Must be last */ |
833 |
}; |
834 |
|
835 |
/* Set up exception handlers for tracing and breakpoints */ |
836 |
|
837 |
void |
838 |
set_debug_traps() |
839 |
{ |
840 |
struct hard_trap_info *ht; |
841 |
|
842 |
for (ht = hard_trap_info; ht->tt; ht++) |
843 |
exceptionHandler(ht->tt, trap_low, rdtbr()); |
844 |
|
845 |
/* In case GDB is started before us, ack any packets (presumably |
846 |
"$?#xx") sitting there. */ |
847 |
|
848 |
putDebugChar ('+'); |
849 |
|
850 |
initialized = 1; |
851 |
} |
852 |
|
853 |
asm (" |
854 |
! Trap handler for memory errors. This just sets mem_err to be non-zero. It |
855 |
! assumes that %l1 is non-zero. This should be safe, as it is doubtful that |
856 |
! 0 would ever contain code that could mem fault. This routine will skip |
857 |
! past the faulting instruction after setting mem_err. |
858 |
|
859 |
.text |
860 |
.align 4 |
861 |
|
862 |
_fltr_set_mem_err: |
863 |
sethi %hi(_mem_err), %l0 |
864 |
st %l1, [%l0 + %lo(_mem_err)] |
865 |
jmpl %l2, %g0 |
866 |
rett %l2+4 |
867 |
"); |
868 |
|
869 |
static void |
870 |
set_mem_fault_trap(enable) |
871 |
int enable; |
872 |
{ |
873 |
extern void fltr_set_mem_err(); |
874 |
mem_err = 0; |
875 |
|
876 |
if (enable) |
877 |
exceptionHandler(9, fltr_set_mem_err,rdtbr()); |
878 |
else |
879 |
exceptionHandler(9, trap_low,rdtbr()); |
880 |
} |
881 |
|
882 |
/* Convert the SPARC hardware trap type code to a unix signal number. */ |
883 |
|
884 |
static int |
885 |
computeSignal(tt) |
886 |
int tt; |
887 |
{ |
888 |
struct hard_trap_info *ht; |
889 |
|
890 |
for (ht = hard_trap_info; ht->tt && ht->signo; ht++) |
891 |
if (ht->tt == tt) |
892 |
return ht->signo; |
893 |
|
894 |
return SIGHUP; /* default for things we don't know about */ |
895 |
} |
896 |
|
897 |
/* |
898 |
* While we find nice hex chars, build an int. |
899 |
* Return number of chars processed. |
900 |
*/ |
901 |
|
902 |
static int |
903 |
hexToInt(char **ptr, int *intValue) |
904 |
{ |
905 |
int numChars = 0; |
906 |
int hexValue; |
907 |
|
908 |
*intValue = 0; |
909 |
|
910 |
while (**ptr) |
911 |
{ |
912 |
hexValue = hex(**ptr); |
913 |
if (hexValue < 0) |
914 |
break; |
915 |
|
916 |
*intValue = (*intValue << 4) | hexValue; |
917 |
numChars ++; |
918 |
|
919 |
(*ptr)++; |
920 |
} |
921 |
|
922 |
return (numChars); |
923 |
} |
924 |
|
925 |
/* |
926 |
* This function does all command procesing for interfacing to gdb. It |
927 |
* returns 1 if you should skip the instruction at the trap address, 0 |
928 |
* otherwise. |
929 |
*/ |
930 |
|
931 |
extern int text_start; |
932 |
|
933 |
static void |
934 |
handle_exception (registers) |
935 |
unsigned long *registers; |
936 |
{ |
937 |
int tt; /* Trap type */ |
938 |
int sigval; |
939 |
int addr; |
940 |
int length; |
941 |
int i; |
942 |
int ustat; |
943 |
char *ptr, resp; |
944 |
unsigned long *sp; |
945 |
static unsigned long userfp; |
946 |
static unsigned long usersp; |
947 |
static unsigned long freq; |
948 |
struct hard_trap_info *ht; |
949 |
#ifdef LEON |
950 |
volatile unsigned int *leon = (unsigned int *) 0x80000000; |
951 |
#else |
952 |
volatile unsigned int *mec = (unsigned int *) 0x01f80000; |
953 |
#endif |
954 |
unsigned long *newsp, psr; |
955 |
int *t128new, *t128org; |
956 |
|
957 |
/* First, we must force all of the windows to be spilled out */ |
958 |
|
959 |
asm(" |
960 |
save %sp, -64, %sp |
961 |
save %sp, -64, %sp |
962 |
save %sp, -64, %sp |
963 |
save %sp, -64, %sp |
964 |
save %sp, -64, %sp |
965 |
save %sp, -64, %sp |
966 |
save %sp, -64, %sp |
967 |
save %sp, -64, %sp |
968 |
restore |
969 |
restore |
970 |
restore |
971 |
restore |
972 |
restore |
973 |
restore |
974 |
restore |
975 |
restore |
976 |
"); |
977 |
|
978 |
|
979 |
sp = (unsigned long *)registers[SP]; |
980 |
|
981 |
tt = (registers[TBR] >> 4) & 0xff; |
982 |
|
983 |
sigval = computeSignal(tt); |
984 |
ptr = remcomOutBuffer; |
985 |
|
986 |
switch (tt) { |
987 |
#ifdef LEON |
988 |
case 0x12: /* UART B interrupt, used to break into running app */ |
989 |
/* If no data arrived just continue (TX empty irq) */ |
990 |
ustat = leon[0x84/4]; |
991 |
leon[0x84/4] = 0; /* clear any pending errors */ |
992 |
if ((ustat & 0x1) == 0) { |
993 |
return; |
994 |
} |
995 |
#else |
996 |
case 0x15: /* UART B interrupt, used to break into running app */ |
997 |
/* If no data arrived just continue (TX empty irq) */ |
998 |
ustat = mec[0xE8/4]; |
999 |
if ((ustat & 0x710000) == 0) { |
1000 |
return; |
1001 |
} |
1002 |
/* Report that we stopped with signal = 0 */ |
1003 |
if (mec[0xE8/4] & 0x700000) { /* Clear UART B if errors */ |
1004 |
mec[0xE8/4] = 0x800000; |
1005 |
mec[0] = mec[0]; /* Re-program baudrate */ |
1006 |
putDebugChar('-'); /* Initiate retransmitt */ |
1007 |
} |
1008 |
#endif |
1009 |
remcomOutBuffer[0] = 'S'; |
1010 |
remcomOutBuffer[1] = hexchars[sigval >> 4]; |
1011 |
remcomOutBuffer[2] = hexchars[sigval & 0xf]; |
1012 |
remcomOutBuffer[3] = 0; |
1013 |
putpacket(remcomOutBuffer); |
1014 |
break; |
1015 |
case 0x03: /* privileged instruction */ |
1016 |
for (ht = hard_trap_info; ht->tt; ht++) |
1017 |
exceptionHandler(ht->tt, trap_low, registers[G1]); |
1018 |
t128new = (int *) trap128; |
1019 |
t128org = (int *) registers[G1]; |
1020 |
t128new[0] = t128org[512]; t128new[1] = t128org[513]; |
1021 |
t128new[2] = t128org[514]; t128new[3] = t128org[515]; |
1022 |
exceptionHandler(128, systrap, registers[G1]); |
1023 |
registers[PSR] |= 0x40; |
1024 |
*((int *)(registers[G1] + 0x7e0)) = freq; /* pass freq to app */ |
1025 |
return; |
1026 |
break; |
1027 |
case (128 + 16) : /* Initialise */ |
1028 |
registers[PC] = START_ADDR; |
1029 |
registers[NPC] = registers[PC] + 4; |
1030 |
registers[PSR] &= ~0x40; |
1031 |
userfp = sp[14] = (rdtbr() & ~0x0fff) - 16; /* FP = user stack */ |
1032 |
usersp = registers[SP] = sp[14] - 96*4; |
1033 |
freq = *((int *)((rdtbr() & ~0x0fff) + 0x7e0)); /* get current freq */ |
1034 |
sp[7] = 0; |
1035 |
sigval = 0; |
1036 |
resp = 'W'; |
1037 |
*ptr++ = resp; |
1038 |
*ptr++ = hexchars[(registers[O0] >> 4) & 0xf]; |
1039 |
*ptr++ = hexchars[registers[O0] & 0xf]; |
1040 |
*ptr++ = 0; |
1041 |
putpacket(remcomOutBuffer); |
1042 |
break; |
1043 |
case 128: |
1044 |
switch (registers[G1]) { |
1045 |
case (1) : /* exit() */ |
1046 |
resp = 'W'; |
1047 |
*ptr++ = resp; |
1048 |
*ptr++ = hexchars[(registers[O0] >> 4) & 0xf]; |
1049 |
*ptr++ = hexchars[registers[O0] & 0xf]; |
1050 |
*ptr++ = 0; |
1051 |
/* |
1052 |
registers[PC] = 0x2000000; |
1053 |
registers[NPC] = registers[PC] + 4; |
1054 |
registers[PSR] &= ~0x40; |
1055 |
sp[14] = userfp; |
1056 |
registers[SP] = usersp; |
1057 |
*/ |
1058 |
break; |
1059 |
case (4) : /* write(fd, buf, size) */ |
1060 |
resp = 'O'; |
1061 |
*ptr++ = resp; |
1062 |
for (i=0;i<registers[O2];i++) |
1063 |
*ptr++ = *((char *) (registers[O1]+i)); |
1064 |
*ptr++ = 0; |
1065 |
putpacket(remcomOutBuffer); |
1066 |
registers[PC] = registers[NPC]; |
1067 |
registers[NPC] += 4; |
1068 |
registers[O0] = registers[O2]; |
1069 |
return; |
1070 |
default: /* Not supported systraps */ |
1071 |
resp = 'W'; |
1072 |
*ptr++ = resp; |
1073 |
*ptr++ = hexchars[(registers[O0] >> 4) & 0xf]; |
1074 |
*ptr++ = hexchars[registers[O0] & 0xf]; |
1075 |
*ptr++ = 0; |
1076 |
break; |
1077 |
} |
1078 |
|
1079 |
|
1080 |
putpacket(remcomOutBuffer); |
1081 |
break; |
1082 |
|
1083 |
default: |
1084 |
/* reply to host that an exception has occurred */ |
1085 |
|
1086 |
ptr = remcomOutBuffer; |
1087 |
|
1088 |
*ptr++ = 'T'; |
1089 |
*ptr++ = hexchars[sigval >> 4]; |
1090 |
*ptr++ = hexchars[sigval & 0xf]; |
1091 |
|
1092 |
*ptr++ = hexchars[PC >> 4]; |
1093 |
*ptr++ = hexchars[PC & 0xf]; |
1094 |
*ptr++ = ':'; |
1095 |
ptr = mem2hex((char *)®isters[PC], ptr, 4, 0); |
1096 |
*ptr++ = ';'; |
1097 |
|
1098 |
*ptr++ = hexchars[FP >> 4]; |
1099 |
*ptr++ = hexchars[FP & 0xf]; |
1100 |
*ptr++ = ':'; |
1101 |
ptr = mem2hex(sp + 8 + 6, ptr, 4, 0); /* FP */ |
1102 |
*ptr++ = ';'; |
1103 |
|
1104 |
*ptr++ = hexchars[SP >> 4]; |
1105 |
*ptr++ = hexchars[SP & 0xf]; |
1106 |
*ptr++ = ':'; |
1107 |
ptr = mem2hex((char *)&sp, ptr, 4, 0); |
1108 |
*ptr++ = ';'; |
1109 |
|
1110 |
*ptr++ = hexchars[NPC >> 4]; |
1111 |
*ptr++ = hexchars[NPC & 0xf]; |
1112 |
*ptr++ = ':'; |
1113 |
ptr = mem2hex((char *)®isters[NPC], ptr, 4, 0); |
1114 |
*ptr++ = ';'; |
1115 |
|
1116 |
*ptr++ = hexchars[O7 >> 4]; |
1117 |
*ptr++ = hexchars[O7 & 0xf]; |
1118 |
*ptr++ = ':'; |
1119 |
ptr = mem2hex((char *)®isters[O7], ptr, 4, 0); |
1120 |
*ptr++ = ';'; |
1121 |
|
1122 |
*ptr++ = 0; |
1123 |
|
1124 |
putpacket(remcomOutBuffer); |
1125 |
|
1126 |
} |
1127 |
|
1128 |
|
1129 |
while (1) { |
1130 |
remcomOutBuffer[0] = 0; |
1131 |
|
1132 |
getpacket(remcomInBuffer); |
1133 |
switch (remcomInBuffer[0]) { |
1134 |
case '?': /* Status */ |
1135 |
remcomOutBuffer[0] = 'S'; |
1136 |
remcomOutBuffer[1] = hexchars[sigval >> 4]; |
1137 |
remcomOutBuffer[2] = hexchars[sigval & 0xf]; |
1138 |
remcomOutBuffer[3] = 0; |
1139 |
break; |
1140 |
|
1141 |
case 'd': /* toggle debug flag */ |
1142 |
break; |
1143 |
|
1144 |
case 'g': /* return the value of the CPU registers */ |
1145 |
ptr = remcomOutBuffer; |
1146 |
ptr = mem2hex((char *)registers, ptr, 16 * 4, 0); /* G & O regs */ |
1147 |
ptr = mem2hex(sp + 0, ptr, 16 * 4, 0); /* L & I regs */ |
1148 |
ptr = mem2hex((char *)®isters[F0], ptr, 32 * 4, 0);/* FLOAT */ |
1149 |
/* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ |
1150 |
mem2hex((char *)®isters[Y], ptr, 8 * 4, 0); |
1151 |
break; |
1152 |
case 'G': /* set the value of the CPU registers - return OK */ |
1153 |
|
1154 |
psr = registers[PSR]; |
1155 |
|
1156 |
ptr = &remcomInBuffer[1]; |
1157 |
hex2mem(ptr, (char *)registers, 16 * 4, 0); /* G & O regs */ |
1158 |
hex2mem(ptr + 16 * 4 * 2, sp + 0, 16 * 4, 0); /* L & I regs */ |
1159 |
hex2mem(ptr + 32 * 4 * 2, (char *)®isters[F0], 32 * 4, 0); /* Floating point */ |
1160 |
hex2mem(ptr + 64 * 4 * 2, (char *)®isters[Y], |
1161 |
8 * 4, 0); /* Y, PSR, WIM, TBR, PC, NPC, FPSR, CPSR */ |
1162 |
|
1163 |
/* See if the stack pointer has moved. If so, then copy the saved |
1164 |
locals and ins to the new location. This keeps the window |
1165 |
overflow and underflow routines happy. */ |
1166 |
|
1167 |
newsp = (unsigned long *)registers[SP]; |
1168 |
if (sp != newsp) |
1169 |
sp = memcpy(newsp, sp, 16 * 4); |
1170 |
|
1171 |
/* Don't allow CWP to be modified. */ |
1172 |
|
1173 |
if (psr != registers[PSR]) |
1174 |
registers[PSR] = (psr & 0x1f) | (registers[PSR] & ~0x1f); |
1175 |
|
1176 |
strcpy(remcomOutBuffer,"OK"); |
1177 |
break; |
1178 |
case 'm': /* mAA..AA,LLLL Read LLLL bytes at address AA..AA */ |
1179 |
/* Try to read %x,%x. */ |
1180 |
|
1181 |
ptr = &remcomInBuffer[1]; |
1182 |
if (hexToInt(&ptr, &addr) && *ptr++ == ',' |
1183 |
&& hexToInt(&ptr, &length)) |
1184 |
{ |
1185 |
if (memw2hex((char *)addr, remcomOutBuffer, length, 1)) break; |
1186 |
strcpy (remcomOutBuffer, "E03"); |
1187 |
} else |
1188 |
strcpy(remcomOutBuffer,"E01"); |
1189 |
break; |
1190 |
|
1191 |
case 'M': /* MAA..AA,LLLL: Write LLLL bytes at address AA.AA return OK */ |
1192 |
/* Try to read '%x,%x:'. */ |
1193 |
|
1194 |
ptr = &remcomInBuffer[1]; |
1195 |
if (hexToInt(&ptr, &addr) && *ptr++ == ',' |
1196 |
&& hexToInt(&ptr, &length) && *ptr++ == ':') |
1197 |
{ |
1198 |
if (hex2mem(ptr, (char *)addr, length, 1)) |
1199 |
strcpy(remcomOutBuffer, "OK"); |
1200 |
else |
1201 |
strcpy(remcomOutBuffer, "E03"); |
1202 |
} else |
1203 |
strcpy(remcomOutBuffer, "E02"); |
1204 |
break; |
1205 |
|
1206 |
case 'c': /* cAA..AA Continue at address AA..AA(optional) */ |
1207 |
/* try to read optional parameter, pc unchanged if no parm */ |
1208 |
|
1209 |
if (*((unsigned int*)0x23f7ffc)==0x210553) |
1210 |
{ |
1211 |
puts(copyprg); |
1212 |
PD_ifLoad(); |
1213 |
*((unsigned int*)0x23f7ffc)=0x00; |
1214 |
} |
1215 |
ptr = &remcomInBuffer[1]; |
1216 |
if (hexToInt(&ptr, &addr)) |
1217 |
{ |
1218 |
registers[PC] = addr; |
1219 |
registers[NPC] = addr + 4; |
1220 |
} |
1221 |
if (registers[PC] == START_ADDR) |
1222 |
{ |
1223 |
registers[PSR] &= ~0x40; |
1224 |
for (ht = hard_trap_info; ht->tt; ht++) |
1225 |
exceptionHandler(ht->tt, trap_low, rdtbr()); |
1226 |
sp[14] = userfp; |
1227 |
sp[7] = START_ADDR; |
1228 |
registers[SP] = usersp; |
1229 |
} |
1230 |
|
1231 |
#ifdef LEON |
1232 |
leon[0x9c/4] = 4; /* clear uart b irq */ |
1233 |
#else |
1234 |
mec[0x50/4] = 0x20; |
1235 |
mec[0x4C/4] &= ~0x20; |
1236 |
#endif |
1237 |
|
1238 |
/* Need to flush the instruction cache here, as we may have deposited a |
1239 |
breakpoint, and the icache probably has no way of knowing that a data ref to |
1240 |
some location may have changed something that is in the instruction cache. |
1241 |
*/ |
1242 |
|
1243 |
flush_i_cache(); |
1244 |
return; |
1245 |
|
1246 |
/* kill the program */ |
1247 |
case 'k' : /* do nothing */ |
1248 |
sigval = 0; |
1249 |
registers[PC] = START_ADDR; |
1250 |
registers[NPC] = registers[PC] + 4; |
1251 |
registers[PSR] &= ~0x40; |
1252 |
registers[FP] = userfp; |
1253 |
registers[SP] = usersp; |
1254 |
sp[7] = 0; |
1255 |
|
1256 |
break; |
1257 |
|
1258 |
case 'r': /* Reset */ |
1259 |
|
1260 |
asm(" |
1261 |
call 0; |
1262 |
nop; |
1263 |
"); |
1264 |
break; |
1265 |
|
1266 |
#if 0 |
1267 |
Disabled until we can unscrew this properly |
1268 |
|
1269 |
case 'b': /* bBB... Set baud rate to BB... */ |
1270 |
int baudrate; |
1271 |
extern void set_timer_3(); |
1272 |
|
1273 |
ptr = &remcomInBuffer[1]; |
1274 |
if (!hexToInt(&ptr, &baudrate)) |
1275 |
{ |
1276 |
strcpy(remcomOutBuffer,"B01"); |
1277 |
break; |
1278 |
} |
1279 |
|
1280 |
/* Convert baud rate to uart clock divider */ |
1281 |
switch (baudrate) |
1282 |
{ |
1283 |
case 38400: |
1284 |
baudrate = 16; |
1285 |
break; |
1286 |
case 19200: |
1287 |
baudrate = 33; |
1288 |
break; |
1289 |
case 9600: |
1290 |
baudrate = 65; |
1291 |
break; |
1292 |
default: |
1293 |
strcpy(remcomOutBuffer,"B02"); |
1294 |
goto x1; |
1295 |
} |
1296 |
|
1297 |
putpacket("OK"); /* Ack before changing speed */ |
1298 |
set_timer_3(baudrate); /* Set it */ |
1299 |
x1: break; |
1300 |
#endif |
1301 |
} /* switch */ |
1302 |
|
1303 |
/* reply to the request */ |
1304 |
putpacket(remcomOutBuffer); |
1305 |
} |
1306 |
} |
1307 |
|
1308 |
/*****************************************************************************/ |
1309 |
/* @Function: PD_ifLoad */ |
1310 |
/* @Purpose : */ |
1311 |
/* This function copies the application program into EEPROM device. */ |
1312 |
/* The number of bytes copied and the CRC are written into last but one and */ |
1313 |
/* last word location. */ |
1314 |
/* */ |
1315 |
/* @@ */ |
1316 |
/* @Parameter Name @Mode @Description */ |
1317 |
/* @@ */ |
1318 |
/*****************************************************************************/ |
1319 |
void PD_ifLoad(void) |
1320 |
{ |
1321 |
unsigned short crc; |
1322 |
UINT* pEE; |
1323 |
UBYTE* pR; |
1324 |
UBYTE ch; |
1325 |
unsigned int i,c,cntWord; |
1326 |
UINT temp; |
1327 |
UBYTE* pRam; |
1328 |
unsigned int level; |
1329 |
|
1330 |
/* Disable asynchronous interrupts */ |
1331 |
sparc_disable_interrupts(level); |
1332 |
|
1333 |
*MEM_CONF_REG |=0x6000; /* EDAC/parity enabled */ |
1334 |
*IO_CONF_REG =0x1f; /* Enable CRIMEA Register access */ |
1335 |
*EE_WAIT =0x500; /* Read/write EEPROM 5 wait state SW (+1HW)*/ |
1336 |
|
1337 |
CD_EEPROM_WRITE_ENABLE; |
1338 |
|
1339 |
pR =(UBYTE *)(PD_RAM_ADDR_START); |
1340 |
pEE =(UINT *)(PD_EEPROM_ADDR_START); |
1341 |
/* Copy program application into EEPROM (0x80000 Kbytes) */ |
1342 |
for (i=0, crc=0xffff; i< PD_EEPROM_LENGHT; i +=512, pEE +=128, pR +=512) |
1343 |
{ |
1344 |
/* Into EEPROM last page do not count the last 8 byte */ |
1345 |
/* of CRC (room for EEPROM lenght and CRC) */ |
1346 |
cntWord =512; |
1347 |
if (i==PD_EEPROM_LAST_PAGE) |
1348 |
{ |
1349 |
cntWord =504; |
1350 |
} |
1351 |
|
1352 |
for (c=0; c<cntWord; c++) |
1353 |
{ |
1354 |
crc =PD_ifcrcComp(pR+c,crc); |
1355 |
} |
1356 |
/* Write specified number of words into EEPROM */ |
1357 |
PD_ifCopyRamToEEprom((UINT*)pR,pEE,PD_EEPROM_PAGE_W); |
1358 |
} |
1359 |
|
1360 |
/* Write number of bytes copied into EEPROM */ |
1361 |
*((UINT*)(PD_EEPROM_ADDR_START + PD_EEPROM_LENGHT - 8)) =PD_EEPROM_LENGHT; |
1362 |
/* Write CRC */ |
1363 |
*((UINT*)(PD_EEPROM_ADDR_START + PD_EEPROM_LENGHT - 4)) =crc; |
1364 |
|
1365 |
/* Waiting for internal EEPROM writing */ |
1366 |
for (c=0; c<= WAIT_FOR_20ms ;c++); |
1367 |
|
1368 |
|
1369 |
/* Disable EEPROM writing by programming CRIMEA register */ |
1370 |
CD_EEPROM_WRITE_DISABLE; |
1371 |
|
1372 |
pEE =(UINT*)(PD_EEPROM_ADDR_START); |
1373 |
for (i=0, crc=0xffff; i< PD_EEPROM_LENGHT-8; i +=4,pEE++ ) |
1374 |
{ |
1375 |
temp =*pEE; |
1376 |
ch =(UBYTE)((temp>>24) & 0x000000ff); |
1377 |
crc =PD_ifcrcComp(&ch,crc); |
1378 |
ch =(UBYTE)((temp>>16) & 0x000000ff); |
1379 |
crc =PD_ifcrcComp(&ch,crc); |
1380 |
ch =(UBYTE)((temp>>8) & 0x000000ff); |
1381 |
crc =PD_ifcrcComp(&ch,crc); |
1382 |
ch =(UBYTE)(temp & 0x000000ff); |
1383 |
crc =PD_ifcrcComp(&ch,crc); |
1384 |
} |
1385 |
if (crc == *((unsigned int*)(PD_EEPROM_ADDR_START + PD_EEPROM_LENGHT - 4)) ) |
1386 |
{ |
1387 |
puts("\n\rThe EEPROM copy is OK\n\r"); |
1388 |
} |
1389 |
else |
1390 |
{ |
1391 |
puts("\n\rThe EEPROM copy is FAILED\n\r"); |
1392 |
} |
1393 |
/* Enable asynchronous interrupts */ |
1394 |
sparc_enable_interrupts(level); |
1395 |
} |
1396 |
|
1397 |
|
1398 |
/*****************************************************************************/ |
1399 |
/* @Function: PD_ifcrcComp */ |
1400 |
/* @Purpose : */ |
1401 |
/* This function calculates the CRC. */ |
1402 |
/* */ |
1403 |
/* @@ */ |
1404 |
/* @Parameter Name @Mode @Description */ |
1405 |
/* @@ */ |
1406 |
/*****************************************************************************/ |
1407 |
unsigned short PD_ifcrcComp (unsigned char* adrs, unsigned short Crc) |
1408 |
{ |
1409 |
unsigned int Crc16Value; |
1410 |
|
1411 |
Crc16Value =Crc; |
1412 |
// Calculating the CRC16 by using a LookUp table |
1413 |
Crc16Value = (unsigned int)(Crc16Value << 8) ^ |
1414 |
(unsigned int)(Crc_lookup[ (unsigned int) ( ((Crc16Value >> |
1415 |
8) & 0xFF) ^ *adrs) ]); |
1416 |
return ((unsigned short)Crc16Value); |
1417 |
|
1418 |
} |
1419 |
|
1420 |
/*****************************************************************************/ |
1421 |
/* @Function: PD_ifCopyRamToEEprom */ |
1422 |
/* @Purpose : */ |
1423 |
/* This function writes a specified number of words from a source buffer */ |
1424 |
/* a source buffer to an EEPROM memory address. The number of written words */ |
1425 |
/* into the EEPROM must not exceed the page boundary. At the end of the */ |
1426 |
/* writing procedure the task is suspended for 10 milliseconds. */ |
1427 |
/* */ |
1428 |
/* @@ */ |
1429 |
/* @Parameter Name @Mode @Description */ |
1430 |
/* Dest IN write destination address */ |
1431 |
/* Source IN read source address */ |
1432 |
/* Len IN number of words (32 bit) to be written */ |
1433 |
/* @@ */ |
1434 |
/*****************************************************************************/ |
1435 |
void PD_ifCopyRamToEEprom(UINT* Source, UINT* Dest, UINT Len) |
1436 |
{ |
1437 |
unsigned int c; |
1438 |
|
1439 |
/* Move data from source to destination */ |
1440 |
for (c=0 ; c<Len; c++, Source++,Dest++) |
1441 |
{ |
1442 |
*Dest =*Source; |
1443 |
} |
1444 |
|
1445 |
/* Waiting for internal EEPROM writing */ |
1446 |
for (c=0; c<= WAIT_FOR_20ms; c++); |
1447 |
} |
1448 |
|
1449 |
/*****************************************************************************/ |
1450 |
/* @Function: PD_ifCopyRamToEEprom */ |
1451 |
/* @Purpose : */ |
1452 |
/* This function writes */ |
1453 |
/* */ |
1454 |
/* @@ */ |
1455 |
/* @Parameter Name @Mode @Description */ |
1456 |
/* @@ */ |
1457 |
/*****************************************************************************/ |
1458 |
void PD_ifLoadFromEeprom(void) |
1459 |
{ |
1460 |
unsigned int level; |
1461 |
UINT* pEE; |
1462 |
UINT* pR; |
1463 |
UINT len; |
1464 |
UINT i; |
1465 |
|
1466 |
pR = (UINT *)(PD_RAM_ADDR_START); |
1467 |
pEE = (UINT *)(PD_EEPROM_ADDR_START); |
1468 |
len = (PD_EEPROM_LENGHT-8) >> 2; |
1469 |
|
1470 |
/* Disable asynchronous interrupts */ |
1471 |
sparc_disable_interrupts(level); |
1472 |
|
1473 |
/* copy EEPROM to RAM */ |
1474 |
i = 0; |
1475 |
while (i < len) { |
1476 |
*pR++ = *pEE++; |
1477 |
i++; |
1478 |
} |
1479 |
|
1480 |
/* Enable asynchronous interrupts */ |
1481 |
sparc_enable_interrupts(level); |
1482 |
} |
1483 |
|
1484 |
|
1485 |
/* This function will generate a breakpoint exception. It is used at the |
1486 |
beginning of a program to sync up with a debugger and can be used |
1487 |
otherwise as a quick means to stop program execution and "break" into |
1488 |
the debugger. */ |
1489 |
|
1490 |
main() |
1491 |
{ |
1492 |
volatile unsigned int *mec = (unsigned int *) 0x1f80000; |
1493 |
|
1494 |
mec[0x20 / 4] = 0; |
1495 |
mec[0x24 / 4] = 0; |
1496 |
mec[0x14 / 4] =0x0000001f; |
1497 |
|
1498 |
puts(version); |
1499 |
puts(debugprg); |
1500 |
|
1501 |
/* write the magic number FAFEDEFA in order to start loggin properly by |
1502 |
the analizer */ |
1503 |
putchar(0xFA); |
1504 |
putchar(0xFE); |
1505 |
putchar(0xDE); |
1506 |
putchar(0xFA); |
1507 |
|
1508 |
PD_ifLoadFromEeprom(); |
1509 |
|
1510 |
set_debug_traps(); |
1511 |
asm(" |
1512 |
|
1513 |
set _trapstack, %o0 |
1514 |
sub %sp, 32, %o1 |
1515 |
andn %o1, 0x0f, %o1 |
1516 |
st %o1, [%o0] |
1517 |
|
1518 |
.globl _syncinst |
1519 |
|
1520 |
_syncinst: ta 16 |
1521 |
nop |
1522 |
"); |
1523 |
|
1524 |
} |
1525 |
|
1526 |
|
1527 |
|
1528 |
|
1529 |
|
1530 |
|
1531 |
|
1532 |
|
1533 |
|
1534 |
|
1535 |
|
1536 |
|
1537 |
|
1538 |
|
1539 |
|
1540 |
|
1541 |
|
1542 |
|
1543 |
|
1544 |
|