File: /usr/src/linux/arch/ppc/xmon/xmon.c
1 /*
2 * BK Id: SCCS/s.xmon.c 1.14 06/28/01 15:50:17 paulus
3 */
4 /*
5 * Routines providing a simple monitor for use on the PowerMac.
6 *
7 * Copyright (C) 1996 Paul Mackerras.
8 */
9 #include <linux/config.h>
10 #include <linux/errno.h>
11 #include <linux/sched.h>
12 #include <linux/smp.h>
13 #include <asm/ptrace.h>
14 #include <asm/string.h>
15 #include <asm/prom.h>
16 #include <asm/bitops.h>
17 #include "nonstdio.h"
18 #include "privinst.h"
19
20 #define scanhex xmon_scanhex
21 #define skipbl xmon_skipbl
22
23 #ifdef CONFIG_SMP
24 static unsigned long cpus_in_xmon = 0;
25 static unsigned long got_xmon = 0;
26 static volatile int take_xmon = -1;
27 #endif /* CONFIG_SMP */
28
29 static unsigned adrs;
30 static int size = 1;
31 static unsigned ndump = 64;
32 static unsigned nidump = 16;
33 static unsigned ncsum = 4096;
34 static int termch;
35
36 static u_int bus_error_jmp[100];
37 #define setjmp xmon_setjmp
38 #define longjmp xmon_longjmp
39
40 /* Breakpoint stuff */
41 struct bpt {
42 unsigned address;
43 unsigned instr;
44 unsigned count;
45 unsigned char enabled;
46 };
47
48 #define NBPTS 16
49 static struct bpt bpts[NBPTS];
50 static struct bpt dabr;
51 static struct bpt iabr;
52 static unsigned bpinstr = 0x7fe00008; /* trap */
53
54 /* Prototypes */
55 extern void (*debugger_fault_handler)(struct pt_regs *);
56 static int cmds(struct pt_regs *);
57 static int mread(unsigned, void *, int);
58 static int mwrite(unsigned, void *, int);
59 static void handle_fault(struct pt_regs *);
60 static void byterev(unsigned char *, int);
61 static void memex(void);
62 static int bsesc(void);
63 static void dump(void);
64 static void prdump(unsigned, int);
65 #ifdef __MWERKS__
66 static void prndump(unsigned, int);
67 static int nvreadb(unsigned);
68 #endif
69 static int ppc_inst_dump(unsigned, int);
70 void print_address(unsigned);
71 static int getsp(void);
72 static void dump_hash_table(void);
73 static void backtrace(struct pt_regs *);
74 static void excprint(struct pt_regs *);
75 static void prregs(struct pt_regs *);
76 static void memops(int);
77 static void memlocate(void);
78 static void memzcan(void);
79 static void memdiffs(unsigned char *, unsigned char *, unsigned, unsigned);
80 int skipbl(void);
81 int scanhex(unsigned *valp);
82 static void scannl(void);
83 static int hexdigit(int);
84 void getstring(char *, int);
85 static void flush_input(void);
86 static int inchar(void);
87 static void take_input(char *);
88 /* static void openforth(void); */
89 static unsigned read_spr(int);
90 static void write_spr(int, unsigned);
91 static void super_regs(void);
92 static void print_sysmap(void);
93 static void remove_bpts(void);
94 static void insert_bpts(void);
95 static struct bpt *at_breakpoint(unsigned pc);
96 static void bpt_cmds(void);
97 static void cacheflush(void);
98 #ifdef CONFIG_SMP
99 static void cpu_cmd(void);
100 #endif /* CONFIG_SMP */
101 #if 0 /* Makes compile with -Wall */
102 static char *pretty_print_addr(unsigned long addr);
103 static char *lookup_name(unsigned long addr);
104 #endif
105 static void csum(void);
106
107 extern int print_insn_big_powerpc(FILE *, unsigned long, unsigned);
108 extern void printf(const char *fmt, ...);
109 extern int putchar(int ch);
110 extern int setjmp(u_int *);
111 extern void longjmp(u_int *, int);
112
113 extern void xmon_enter(void);
114 extern void xmon_leave(void);
115
116 #define GETWORD(v) (((v)[0] << 24) + ((v)[1] << 16) + ((v)[2] << 8) + (v)[3])
117
118 #define isxdigit(c) (('0' <= (c) && (c) <= '9') \
119 || ('a' <= (c) && (c) <= 'f') \
120 || ('A' <= (c) && (c) <= 'F'))
121 #define isalnum(c) (('0' <= (c) && (c) <= '9') \
122 || ('a' <= (c) && (c) <= 'z') \
123 || ('A' <= (c) && (c) <= 'Z'))
124
125 static char *help_string = "\
126 Commands:\n\
127 d dump bytes\n\
128 di dump instructions\n\
129 df dump float values\n\
130 dd dump double values\n\
131 e print exception information\n\
132 h dump hash table\n\
133 m examine/change memory\n\
134 mm move a block of memory\n\
135 ms set a block of memory\n\
136 md compare two blocks of memory\n\
137 M print System.map\n\
138 r print registers\n\
139 S print special registers\n\
140 t print backtrace\n\
141 x exit monitor\n\
142 ";
143
144 static int xmon_trace[NR_CPUS];
145 #define SSTEP 1 /* stepping because of 's' command */
146 #define BRSTEP 2 /* stepping over breakpoint */
147
148 static struct pt_regs *xmon_regs[NR_CPUS];
149
150 void
151 xmon(struct pt_regs *excp)
152 {
153 struct pt_regs regs;
154 int msr, cmd;
155
156 if (excp == NULL) {
157 asm volatile ("stw 0,0(%0)\n\
158 lwz 0,0(1)\n\
159 stw 0,4(%0)\n\
160 stmw 2,8(%0)" : : "b" (®s));
161 regs.nip = regs.link = ((unsigned long *)regs.gpr[1])[1];
162 regs.msr = get_msr();
163 regs.ctr = get_ctr();
164 regs.xer = get_xer();
165 regs.ccr = get_cr();
166 regs.trap = 0;
167 excp = ®s;
168 }
169
170 msr = get_msr();
171 set_msr(msr & ~0x8000); /* disable interrupts */
172 xmon_regs[smp_processor_id()] = excp;
173 xmon_enter();
174 excprint(excp);
175 #ifdef CONFIG_SMP
176 if (test_and_set_bit(smp_processor_id(), &cpus_in_xmon))
177 for (;;)
178 ;
179 while (test_and_set_bit(0, &got_xmon)) {
180 if (take_xmon == smp_processor_id()) {
181 take_xmon = -1;
182 break;
183 }
184 }
185 /*
186 * XXX: breakpoints are removed while any cpu is in xmon
187 */
188 #endif /* CONFIG_SMP */
189 remove_bpts();
190 cmd = cmds(excp);
191 if (cmd == 's') {
192 xmon_trace[smp_processor_id()] = SSTEP;
193 excp->msr |= 0x400;
194 } else if (at_breakpoint(excp->nip)) {
195 xmon_trace[smp_processor_id()] = BRSTEP;
196 excp->msr |= 0x400;
197 } else {
198 xmon_trace[smp_processor_id()] = 0;
199 insert_bpts();
200 }
201 xmon_leave();
202 xmon_regs[smp_processor_id()] = 0;
203 #ifdef CONFIG_SMP
204 clear_bit(0, &got_xmon);
205 clear_bit(smp_processor_id(), &cpus_in_xmon);
206 #endif /* CONFIG_SMP */
207 set_msr(msr); /* restore interrupt enable */
208 }
209
210 void
211 xmon_irq(int irq, void *d, struct pt_regs *regs)
212 {
213 unsigned long flags;
214 __save_flags(flags);
215 __cli();
216 printf("Keyboard interrupt\n");
217 xmon(regs);
218 __restore_flags(flags);
219 }
220
221 int
222 xmon_bpt(struct pt_regs *regs)
223 {
224 struct bpt *bp;
225
226 bp = at_breakpoint(regs->nip);
227 if (!bp)
228 return 0;
229 if (bp->count) {
230 --bp->count;
231 remove_bpts();
232 excprint(regs);
233 xmon_trace[smp_processor_id()] = BRSTEP;
234 regs->msr |= 0x400;
235 } else {
236 xmon(regs);
237 }
238 return 1;
239 }
240
241 int
242 xmon_sstep(struct pt_regs *regs)
243 {
244 if (!xmon_trace[smp_processor_id()])
245 return 0;
246 if (xmon_trace[smp_processor_id()] == BRSTEP) {
247 xmon_trace[smp_processor_id()] = 0;
248 insert_bpts();
249 } else {
250 xmon(regs);
251 }
252 return 1;
253 }
254
255 int
256 xmon_dabr_match(struct pt_regs *regs)
257 {
258 if (dabr.enabled && dabr.count) {
259 --dabr.count;
260 remove_bpts();
261 excprint(regs);
262 xmon_trace[smp_processor_id()] = BRSTEP;
263 regs->msr |= 0x400;
264 } else {
265 dabr.instr = regs->nip;
266 xmon(regs);
267 }
268 return 1;
269 }
270
271 int
272 xmon_iabr_match(struct pt_regs *regs)
273 {
274 if (iabr.enabled && iabr.count) {
275 --iabr.count;
276 remove_bpts();
277 excprint(regs);
278 xmon_trace[smp_processor_id()] = BRSTEP;
279 regs->msr |= 0x400;
280 } else {
281 xmon(regs);
282 }
283 return 1;
284 }
285
286 static struct bpt *
287 at_breakpoint(unsigned pc)
288 {
289 int i;
290 struct bpt *bp;
291
292 if (dabr.enabled && pc == dabr.instr)
293 return &dabr;
294 if (iabr.enabled && pc == iabr.address)
295 return &iabr;
296 bp = bpts;
297 for (i = 0; i < NBPTS; ++i, ++bp)
298 if (bp->enabled && pc == bp->address)
299 return bp;
300 return 0;
301 }
302
303 static void
304 insert_bpts()
305 {
306 int i;
307 struct bpt *bp;
308
309 bp = bpts;
310 for (i = 0; i < NBPTS; ++i, ++bp) {
311 if (!bp->enabled)
312 continue;
313 if (mread(bp->address, &bp->instr, 4) != 4
314 || mwrite(bp->address, &bpinstr, 4) != 4) {
315 printf("Couldn't insert breakpoint at %x, disabling\n",
316 bp->address);
317 bp->enabled = 0;
318 }
319 store_inst((void *) bp->address);
320 }
321 #if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
322 if (dabr.enabled)
323 set_dabr(dabr.address);
324 if (iabr.enabled)
325 set_iabr(iabr.address);
326 #endif
327 }
328
329 static void
330 remove_bpts()
331 {
332 int i;
333 struct bpt *bp;
334 unsigned instr;
335
336 #if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
337 set_dabr(0);
338 set_iabr(0);
339 #endif
340 bp = bpts;
341 for (i = 0; i < NBPTS; ++i, ++bp) {
342 if (!bp->enabled)
343 continue;
344 if (mread(bp->address, &instr, 4) == 4
345 && instr == bpinstr
346 && mwrite(bp->address, &bp->instr, 4) != 4)
347 printf("Couldn't remove breakpoint at %x\n",
348 bp->address);
349 store_inst((void *) bp->address);
350 }
351 }
352
353 static char *last_cmd;
354
355 /* Command interpreting routine */
356 static int
357 cmds(struct pt_regs *excp)
358 {
359 int cmd;
360
361 last_cmd = NULL;
362 for(;;) {
363 #ifdef CONFIG_SMP
364 printf("%d:", smp_processor_id());
365 #endif /* CONFIG_SMP */
366 printf("mon> ");
367 fflush(stdout);
368 flush_input();
369 termch = 0;
370 cmd = skipbl();
371 if( cmd == '\n' ) {
372 if (last_cmd == NULL)
373 continue;
374 take_input(last_cmd);
375 last_cmd = NULL;
376 cmd = inchar();
377 }
378 switch (cmd) {
379 case 'm':
380 cmd = inchar();
381 switch (cmd) {
382 case 'm':
383 case 's':
384 case 'd':
385 memops(cmd);
386 break;
387 case 'l':
388 memlocate();
389 break;
390 case 'z':
391 memzcan();
392 break;
393 default:
394 termch = cmd;
395 memex();
396 }
397 break;
398 case 'd':
399 dump();
400 break;
401 case 'r':
402 if (excp != NULL)
403 prregs(excp); /* print regs */
404 break;
405 case 'e':
406 if (excp == NULL)
407 printf("No exception information\n");
408 else
409 excprint(excp);
410 break;
411 case 'M':
412 print_sysmap();
413 break;
414 case 'S':
415 super_regs();
416 break;
417 case 't':
418 backtrace(excp);
419 break;
420 case 'f':
421 cacheflush();
422 break;
423 case 'h':
424 dump_hash_table();
425 break;
426 case 's':
427 case 'x':
428 case EOF:
429 return cmd;
430 case '?':
431 printf(help_string);
432 break;
433 default:
434 printf("Unrecognized command: ");
435 if( ' ' < cmd && cmd <= '~' )
436 putchar(cmd);
437 else
438 printf("\\x%x", cmd);
439 printf(" (type ? for help)\n");
440 break;
441 case 'b':
442 bpt_cmds();
443 break;
444 case 'C':
445 csum();
446 break;
447 #ifdef CONFIG_SMP
448 case 'c':
449 cpu_cmd();
450 break;
451 #endif /* CONFIG_SMP */
452 }
453 }
454 }
455
456 #ifdef CONFIG_SMP
457 static void cpu_cmd(void)
458 {
459 unsigned cpu;
460 int timeout;
461 int cmd;
462
463 cmd = inchar();
464 if (cmd == 'i') {
465 /* interrupt other cpu(s) */
466 cpu = MSG_ALL_BUT_SELF;
467 scanhex(&cpu);
468 smp_send_xmon_break(cpu);
469 return;
470 }
471 termch = cmd;
472 if (!scanhex(&cpu)) {
473 /* print cpus waiting or in xmon */
474 printf("cpus stopped:");
475 for (cpu = 0; cpu < NR_CPUS; ++cpu) {
476 if (test_bit(cpu, &cpus_in_xmon)) {
477 printf(" %d", cpu);
478 if (cpu == smp_processor_id())
479 printf("*", cpu);
480 }
481 }
482 printf("\n");
483 return;
484 }
485 /* try to switch to cpu specified */
486 take_xmon = cpu;
487 timeout = 10000000;
488 while (take_xmon >= 0) {
489 if (--timeout == 0) {
490 /* yes there's a race here */
491 take_xmon = -1;
492 printf("cpu %u didn't take control\n", cpu);
493 return;
494 }
495 }
496 /* now have to wait to be given control back */
497 while (test_and_set_bit(0, &got_xmon)) {
498 if (take_xmon == smp_processor_id()) {
499 take_xmon = -1;
500 break;
501 }
502 }
503 }
504 #endif /* CONFIG_SMP */
505
506 static unsigned short fcstab[256] = {
507 0x0000, 0x1189, 0x2312, 0x329b, 0x4624, 0x57ad, 0x6536, 0x74bf,
508 0x8c48, 0x9dc1, 0xaf5a, 0xbed3, 0xca6c, 0xdbe5, 0xe97e, 0xf8f7,
509 0x1081, 0x0108, 0x3393, 0x221a, 0x56a5, 0x472c, 0x75b7, 0x643e,
510 0x9cc9, 0x8d40, 0xbfdb, 0xae52, 0xdaed, 0xcb64, 0xf9ff, 0xe876,
511 0x2102, 0x308b, 0x0210, 0x1399, 0x6726, 0x76af, 0x4434, 0x55bd,
512 0xad4a, 0xbcc3, 0x8e58, 0x9fd1, 0xeb6e, 0xfae7, 0xc87c, 0xd9f5,
513 0x3183, 0x200a, 0x1291, 0x0318, 0x77a7, 0x662e, 0x54b5, 0x453c,
514 0xbdcb, 0xac42, 0x9ed9, 0x8f50, 0xfbef, 0xea66, 0xd8fd, 0xc974,
515 0x4204, 0x538d, 0x6116, 0x709f, 0x0420, 0x15a9, 0x2732, 0x36bb,
516 0xce4c, 0xdfc5, 0xed5e, 0xfcd7, 0x8868, 0x99e1, 0xab7a, 0xbaf3,
517 0x5285, 0x430c, 0x7197, 0x601e, 0x14a1, 0x0528, 0x37b3, 0x263a,
518 0xdecd, 0xcf44, 0xfddf, 0xec56, 0x98e9, 0x8960, 0xbbfb, 0xaa72,
519 0x6306, 0x728f, 0x4014, 0x519d, 0x2522, 0x34ab, 0x0630, 0x17b9,
520 0xef4e, 0xfec7, 0xcc5c, 0xddd5, 0xa96a, 0xb8e3, 0x8a78, 0x9bf1,
521 0x7387, 0x620e, 0x5095, 0x411c, 0x35a3, 0x242a, 0x16b1, 0x0738,
522 0xffcf, 0xee46, 0xdcdd, 0xcd54, 0xb9eb, 0xa862, 0x9af9, 0x8b70,
523 0x8408, 0x9581, 0xa71a, 0xb693, 0xc22c, 0xd3a5, 0xe13e, 0xf0b7,
524 0x0840, 0x19c9, 0x2b52, 0x3adb, 0x4e64, 0x5fed, 0x6d76, 0x7cff,
525 0x9489, 0x8500, 0xb79b, 0xa612, 0xd2ad, 0xc324, 0xf1bf, 0xe036,
526 0x18c1, 0x0948, 0x3bd3, 0x2a5a, 0x5ee5, 0x4f6c, 0x7df7, 0x6c7e,
527 0xa50a, 0xb483, 0x8618, 0x9791, 0xe32e, 0xf2a7, 0xc03c, 0xd1b5,
528 0x2942, 0x38cb, 0x0a50, 0x1bd9, 0x6f66, 0x7eef, 0x4c74, 0x5dfd,
529 0xb58b, 0xa402, 0x9699, 0x8710, 0xf3af, 0xe226, 0xd0bd, 0xc134,
530 0x39c3, 0x284a, 0x1ad1, 0x0b58, 0x7fe7, 0x6e6e, 0x5cf5, 0x4d7c,
531 0xc60c, 0xd785, 0xe51e, 0xf497, 0x8028, 0x91a1, 0xa33a, 0xb2b3,
532 0x4a44, 0x5bcd, 0x6956, 0x78df, 0x0c60, 0x1de9, 0x2f72, 0x3efb,
533 0xd68d, 0xc704, 0xf59f, 0xe416, 0x90a9, 0x8120, 0xb3bb, 0xa232,
534 0x5ac5, 0x4b4c, 0x79d7, 0x685e, 0x1ce1, 0x0d68, 0x3ff3, 0x2e7a,
535 0xe70e, 0xf687, 0xc41c, 0xd595, 0xa12a, 0xb0a3, 0x8238, 0x93b1,
536 0x6b46, 0x7acf, 0x4854, 0x59dd, 0x2d62, 0x3ceb, 0x0e70, 0x1ff9,
537 0xf78f, 0xe606, 0xd49d, 0xc514, 0xb1ab, 0xa022, 0x92b9, 0x8330,
538 0x7bc7, 0x6a4e, 0x58d5, 0x495c, 0x3de3, 0x2c6a, 0x1ef1, 0x0f78
539 };
540
541 #define FCS(fcs, c) (((fcs) >> 8) ^ fcstab[((fcs) ^ (c)) & 0xff])
542
543 static void
544 csum(void)
545 {
546 unsigned int i;
547 unsigned short fcs;
548 unsigned char v;
549
550 scanhex(&adrs);
551 scanhex(&ncsum);
552 fcs = 0xffff;
553 for (i = 0; i < ncsum; ++i) {
554 if (mread(adrs+i, &v, 1) == 0) {
555 printf("csum stopped at %x\n", adrs+i);
556 break;
557 }
558 fcs = FCS(fcs, v);
559 }
560 printf("%x\n", fcs);
561 }
562
563 static void
564 bpt_cmds(void)
565 {
566 int cmd;
567 unsigned a;
568 int mode, i;
569 struct bpt *bp;
570
571 cmd = inchar();
572 switch (cmd) {
573 #if !defined(CONFIG_8xx) && !defined(CONFIG_POWER4)
574 case 'd':
575 mode = 7;
576 cmd = inchar();
577 if (cmd == 'r')
578 mode = 5;
579 else if (cmd == 'w')
580 mode = 6;
581 else
582 termch = cmd;
583 dabr.address = 0;
584 dabr.count = 0;
585 dabr.enabled = scanhex(&dabr.address);
586 scanhex(&dabr.count);
587 if (dabr.enabled)
588 dabr.address = (dabr.address & ~7) | mode;
589 break;
590 case 'i':
591 iabr.address = 0;
592 iabr.count = 0;
593 iabr.enabled = scanhex(&iabr.address);
594 if (iabr.enabled)
595 iabr.address |= 3;
596 scanhex(&iabr.count);
597 break;
598 #endif
599 case 'c':
600 if (!scanhex(&a)) {
601 /* clear all breakpoints */
602 for (i = 0; i < NBPTS; ++i)
603 bpts[i].enabled = 0;
604 iabr.enabled = 0;
605 dabr.enabled = 0;
606 printf("All breakpoints cleared\n");
607 } else {
608 bp = at_breakpoint(a);
609 if (bp == 0) {
610 printf("No breakpoint at %x\n", a);
611 } else {
612 bp->enabled = 0;
613 }
614 }
615 break;
616 default:
617 termch = cmd;
618 if (!scanhex(&a)) {
619 /* print all breakpoints */
620 printf("type address count\n");
621 if (dabr.enabled) {
622 printf("data %.8x %8x [", dabr.address & ~7,
623 dabr.count);
624 if (dabr.address & 1)
625 printf("r");
626 if (dabr.address & 2)
627 printf("w");
628 printf("]\n");
629 }
630 if (iabr.enabled)
631 printf("inst %.8x %8x\n", iabr.address & ~3,
632 iabr.count);
633 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
634 if (bp->enabled)
635 printf("trap %.8x %8x\n", bp->address,
636 bp->count);
637 break;
638 }
639 bp = at_breakpoint(a);
640 if (bp == 0) {
641 for (bp = bpts; bp < &bpts[NBPTS]; ++bp)
642 if (!bp->enabled)
643 break;
644 if (bp >= &bpts[NBPTS]) {
645 printf("Sorry, no free breakpoints\n");
646 break;
647 }
648 }
649 bp->enabled = 1;
650 bp->address = a;
651 bp->count = 0;
652 scanhex(&bp->count);
653 break;
654 }
655 }
656
657 static void
658 backtrace(struct pt_regs *excp)
659 {
660 unsigned sp;
661 unsigned stack[2];
662 struct pt_regs regs;
663 extern char ret_from_intercept, ret_from_syscall_1, ret_from_syscall_2;
664 extern char do_signal_ret, ret_from_except;
665
666 printf("backtrace:\n");
667
668 if (excp != NULL)
669 sp = excp->gpr[1];
670 else
671 sp = getsp();
672 scanhex(&sp);
673 scannl();
674 for (; sp != 0; sp = stack[0]) {
675 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
676 break;
677 printf("%x ", stack[1]);
678 if (stack[1] == (unsigned) &ret_from_intercept
679 || stack[1] == (unsigned) &ret_from_except
680 || stack[1] == (unsigned) &ret_from_syscall_1
681 || stack[1] == (unsigned) &ret_from_syscall_2
682 || stack[1] == (unsigned) &do_signal_ret) {
683 if (mread(sp+16, ®s, sizeof(regs)) != sizeof(regs))
684 break;
685 printf("\nexception:%x [%x] %x ", regs.trap, sp+16,
686 regs.nip);
687 sp = regs.gpr[1];
688 if (mread(sp, stack, sizeof(stack)) != sizeof(stack))
689 break;
690 }
691 }
692 printf("\n");
693 }
694
695 int
696 getsp()
697 {
698 int x;
699
700 asm("mr %0,1" : "=r" (x) :);
701 return x;
702 }
703
704 void
705 excprint(struct pt_regs *fp)
706 {
707 #ifdef CONFIG_SMP
708 printf("cpu %d: ", smp_processor_id());
709 #endif /* CONFIG_SMP */
710 printf("vector: %x at pc = %x",
711 fp->trap, fp->nip);
712 printf(", lr = %x, msr = %x, sp = %x [%x]\n",
713 fp->link, fp->msr, fp->gpr[1], fp);
714 if (fp->trap == 0x300 || fp->trap == 0x600)
715 printf("dar = %x, dsisr = %x\n", fp->dar, fp->dsisr);
716 if (current)
717 printf("current = %x, pid = %d, comm = %s\n",
718 current, current->pid, current->comm);
719 }
720
721 void
722 prregs(struct pt_regs *fp)
723 {
724 int n;
725 unsigned base;
726
727 if (scanhex(&base))
728 fp = (struct pt_regs *) base;
729 for (n = 0; n < 32; ++n)
730 printf("R%.2d = %.8x%s", n, fp->gpr[n],
731 (n & 3) == 3? "\n": " ");
732 printf("pc = %.8x msr = %.8x lr = %.8x cr = %.8x\n",
733 fp->nip, fp->msr, fp->link, fp->ccr);
734 printf("ctr = %.8x xer = %.8x trap = %4x\n",
735 fp->ctr, fp->xer, fp->trap);
736 }
737
738 void
739 cacheflush(void)
740 {
741 int cmd;
742 unsigned nflush;
743
744 cmd = inchar();
745 if (cmd != 'i')
746 termch = cmd;
747 scanhex(&adrs);
748 if (termch != '\n')
749 termch = 0;
750 nflush = 1;
751 scanhex(&nflush);
752 nflush = (nflush + 31) / 32;
753 if (cmd != 'i') {
754 for (; nflush > 0; --nflush, adrs += 0x20)
755 cflush((void *) adrs);
756 } else {
757 for (; nflush > 0; --nflush, adrs += 0x20)
758 cinval((void *) adrs);
759 }
760 }
761
762 unsigned int
763 read_spr(int n)
764 {
765 unsigned int instrs[2];
766 int (*code)(void);
767
768 instrs[0] = 0x7c6002a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
769 instrs[1] = 0x4e800020;
770 store_inst(instrs);
771 store_inst(instrs+1);
772 code = (int (*)(void)) instrs;
773 return code();
774 }
775
776 void
777 write_spr(int n, unsigned int val)
778 {
779 unsigned int instrs[2];
780 int (*code)(unsigned int);
781
782 instrs[0] = 0x7c6003a6 + ((n & 0x1F) << 16) + ((n & 0x3e0) << 6);
783 instrs[1] = 0x4e800020;
784 store_inst(instrs);
785 store_inst(instrs+1);
786 code = (int (*)(unsigned int)) instrs;
787 code(val);
788 }
789
790 static unsigned int regno;
791 extern char exc_prolog;
792 extern char dec_exc;
793
794 void
795 print_sysmap(void)
796 {
797 extern char *sysmap;
798 if ( sysmap )
799 printf("System.map: \n%s", sysmap);
800 else
801 printf("No System.map\n");
802 }
803
804 void
805 super_regs()
806 {
807 int i, cmd;
808 unsigned val;
809
810 cmd = skipbl();
811 if (cmd == '\n') {
812 printf("msr = %x, pvr = %x\n", get_msr(), get_pvr());
813 printf("sprg0-3 = %x %x %x %x\n", get_sprg0(), get_sprg1(),
814 get_sprg2(), get_sprg3());
815 printf("srr0 = %x, srr1 = %x\n", get_srr0(), get_srr1());
816 printf("sr0-15 =");
817 for (i = 0; i < 16; ++i)
818 printf(" %x", get_sr(i));
819 printf("\n");
820 asm("mr %0,1" : "=r" (i) :);
821 printf("sp = %x ", i);
822 asm("mr %0,2" : "=r" (i) :);
823 printf("toc = %x\n", i);
824 return;
825 }
826
827 scanhex(®no);
828 switch (cmd) {
829 case 'w':
830 val = read_spr(regno);
831 scanhex(&val);
832 write_spr(regno, val);
833 /* fall through */
834 case 'r':
835 printf("spr %x = %x\n", regno, read_spr(regno));
836 break;
837 case 's':
838 val = get_sr(regno);
839 scanhex(&val);
840 set_sr(regno, val);
841 break;
842 case 'm':
843 val = get_msr();
844 scanhex(&val);
845 set_msr(val);
846 break;
847 }
848 scannl();
849 }
850
851 #if 0
852 static void
853 openforth()
854 {
855 int c;
856 char *p;
857 char cmd[1024];
858 int args[5];
859 extern int (*prom_entry)(int *);
860
861 p = cmd;
862 c = skipbl();
863 while (c != '\n') {
864 *p++ = c;
865 c = inchar();
866 }
867 *p = 0;
868 args[0] = (int) "interpret";
869 args[1] = 1;
870 args[2] = 1;
871 args[3] = (int) cmd;
872 (*prom_entry)(args);
873 printf("\n");
874 if (args[4] != 0)
875 printf("error %x\n", args[4]);
876 }
877 #endif
878
879 #ifndef CONFIG_PPC64BRIDGE
880 static void
881 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
882 {
883 extern void *Hash;
884 extern unsigned long Hash_size;
885 unsigned *htab = Hash;
886 unsigned hsize = Hash_size;
887 unsigned v, hmask, va, last_va;
888 int found, last_found, i;
889 unsigned *hg, w1, last_w2, last_va0;
890
891 last_found = 0;
892 hmask = hsize / 64 - 1;
893 va = start;
894 start = (start >> 12) & 0xffff;
895 end = (end >> 12) & 0xffff;
896 for (v = start; v < end; ++v) {
897 found = 0;
898 hg = htab + (((v ^ seg) & hmask) * 16);
899 w1 = 0x80000000 | (seg << 7) | (v >> 10);
900 for (i = 0; i < 8; ++i, hg += 2) {
901 if (*hg == w1) {
902 found = 1;
903 break;
904 }
905 }
906 if (!found) {
907 w1 ^= 0x40;
908 hg = htab + ((~(v ^ seg) & hmask) * 16);
909 for (i = 0; i < 8; ++i, hg += 2) {
910 if (*hg == w1) {
911 found = 1;
912 break;
913 }
914 }
915 }
916 if (!(last_found && found && (hg[1] & ~0x180) == last_w2 + 4096)) {
917 if (last_found) {
918 if (last_va != last_va0)
919 printf(" ... %x", last_va);
920 printf("\n");
921 }
922 if (found) {
923 printf("%x to %x", va, hg[1]);
924 last_va0 = va;
925 }
926 last_found = found;
927 }
928 if (found) {
929 last_w2 = hg[1] & ~0x180;
930 last_va = va;
931 }
932 va += 4096;
933 }
934 if (last_found)
935 printf(" ... %x\n", last_va);
936 }
937
938 #else /* CONFIG_PPC64BRIDGE */
939 static void
940 dump_hash_table_seg(unsigned seg, unsigned start, unsigned end)
941 {
942 extern void *Hash;
943 extern unsigned long Hash_size;
944 unsigned *htab = Hash;
945 unsigned hsize = Hash_size;
946 unsigned v, hmask, va, last_va;
947 int found, last_found, i;
948 unsigned *hg, w1, last_w2, last_va0;
949
950 last_found = 0;
951 hmask = hsize / 128 - 1;
952 va = start;
953 start = (start >> 12) & 0xffff;
954 end = (end >> 12) & 0xffff;
955 for (v = start; v < end; ++v) {
956 found = 0;
957 hg = htab + (((v ^ seg) & hmask) * 32);
958 w1 = 1 | (seg << 12) | ((v & 0xf800) >> 4);
959 for (i = 0; i < 8; ++i, hg += 4) {
960 if (hg[1] == w1) {
961 found = 1;
962 break;
963 }
964 }
965 if (!found) {
966 w1 ^= 2;
967 hg = htab + ((~(v ^ seg) & hmask) * 32);
968 for (i = 0; i < 8; ++i, hg += 4) {
969 if (hg[1] == w1) {
970 found = 1;
971 break;
972 }
973 }
974 }
975 if (!(last_found && found && (hg[3] & ~0x180) == last_w2 + 4096)) {
976 if (last_found) {
977 if (last_va != last_va0)
978 printf(" ... %x", last_va);
979 printf("\n");
980 }
981 if (found) {
982 printf("%x to %x", va, hg[3]);
983 last_va0 = va;
984 }
985 last_found = found;
986 }
987 if (found) {
988 last_w2 = hg[3] & ~0x180;
989 last_va = va;
990 }
991 va += 4096;
992 }
993 if (last_found)
994 printf(" ... %x\n", last_va);
995 }
996 #endif /* CONFIG_PPC64BRIDGE */
997
998 static unsigned hash_ctx;
999 static unsigned hash_start;
1000 static unsigned hash_end;
1001
1002 static void
1003 dump_hash_table()
1004 {
1005 int seg;
1006 unsigned seg_start, seg_end;
1007
1008 hash_ctx = 0;
1009 hash_start = 0;
1010 hash_end = 0xfffff000;
1011 scanhex(&hash_ctx);
1012 scanhex(&hash_start);
1013 scanhex(&hash_end);
1014 printf("Mappings for context %x\n", hash_ctx);
1015 seg_start = hash_start;
1016 for (seg = hash_start >> 28; seg <= hash_end >> 28; ++seg) {
1017 seg_end = (seg << 28) | 0x0ffff000;
1018 if (seg_end > hash_end)
1019 seg_end = hash_end;
1020 dump_hash_table_seg((hash_ctx << 4) + (seg * 0x111),
1021 seg_start, seg_end);
1022 seg_start = seg_end + 0x1000;
1023 }
1024 }
1025
1026 /*
1027 * Stuff for reading and writing memory safely
1028 */
1029 extern inline void sync(void)
1030 {
1031 asm volatile("sync; isync");
1032 }
1033
1034 extern inline void __delay(unsigned int loops)
1035 {
1036 if (loops != 0)
1037 __asm__ __volatile__("mtctr %0; 1: bdnz 1b" : :
1038 "r" (loops) : "ctr");
1039 }
1040
1041 int
1042 mread(unsigned adrs, void *buf, int size)
1043 {
1044 volatile int n;
1045 char *p, *q;
1046
1047 n = 0;
1048 if( setjmp(bus_error_jmp) == 0 ){
1049 debugger_fault_handler = handle_fault;
1050 sync();
1051 p = (char *) adrs;
1052 q = (char *) buf;
1053 switch (size) {
1054 case 2: *(short *)q = *(short *)p; break;
1055 case 4: *(int *)q = *(int *)p; break;
1056 default:
1057 for( ; n < size; ++n ) {
1058 *q++ = *p++;
1059 sync();
1060 }
1061 }
1062 sync();
1063 /* wait a little while to see if we get a machine check */
1064 __delay(200);
1065 n = size;
1066 }
1067 debugger_fault_handler = 0;
1068 return n;
1069 }
1070
1071 int
1072 mwrite(unsigned adrs, void *buf, int size)
1073 {
1074 volatile int n;
1075 char *p, *q;
1076
1077 n = 0;
1078 if( setjmp(bus_error_jmp) == 0 ){
1079 debugger_fault_handler = handle_fault;
1080 sync();
1081 p = (char *) adrs;
1082 q = (char *) buf;
1083 switch (size) {
1084 case 2: *(short *)p = *(short *)q; break;
1085 case 4: *(int *)p = *(int *)q; break;
1086 default:
1087 for( ; n < size; ++n ) {
1088 *p++ = *q++;
1089 sync();
1090 }
1091 }
1092 sync();
1093 n = size;
1094 } else {
1095 printf("*** Error writing address %x\n", adrs + n);
1096 }
1097 debugger_fault_handler = 0;
1098 return n;
1099 }
1100
1101 static int fault_type;
1102 static char *fault_chars[] = { "--", "**", "##" };
1103
1104 static void
1105 handle_fault(struct pt_regs *regs)
1106 {
1107 fault_type = regs->trap == 0x200? 0: regs->trap == 0x300? 1: 2;
1108 longjmp(bus_error_jmp, 1);
1109 }
1110
1111 #define SWAP(a, b, t) ((t) = (a), (a) = (b), (b) = (t))
1112
1113 void
1114 byterev(unsigned char *val, int size)
1115 {
1116 int t;
1117
1118 switch (size) {
1119 case 2:
1120 SWAP(val[0], val[1], t);
1121 break;
1122 case 4:
1123 SWAP(val[0], val[3], t);
1124 SWAP(val[1], val[2], t);
1125 break;
1126 }
1127 }
1128
1129 static int brev;
1130 static int mnoread;
1131
1132 void
1133 memex()
1134 {
1135 int cmd, inc, i, nslash;
1136 unsigned n;
1137 unsigned char val[4];
1138
1139 last_cmd = "m\n";
1140 scanhex(&adrs);
1141 while ((cmd = skipbl()) != '\n') {
1142 switch( cmd ){
1143 case 'b': size = 1; break;
1144 case 'w': size = 2; break;
1145 case 'l': size = 4; break;
1146 case 'r': brev = !brev; break;
1147 case 'n': mnoread = 1; break;
1148 case '.': mnoread = 0; break;
1149 }
1150 }
1151 if( size <= 0 )
1152 size = 1;
1153 else if( size > 4 )
1154 size = 4;
1155 for(;;){
1156 if (!mnoread)
1157 n = mread(adrs, val, size);
1158 printf("%.8x%c", adrs, brev? 'r': ' ');
1159 if (!mnoread) {
1160 if (brev)
1161 byterev(val, size);
1162 putchar(' ');
1163 for (i = 0; i < n; ++i)
1164 printf("%.2x", val[i]);
1165 for (; i < size; ++i)
1166 printf("%s", fault_chars[fault_type]);
1167 }
1168 putchar(' ');
1169 inc = size;
1170 nslash = 0;
1171 for(;;){
1172 if( scanhex(&n) ){
1173 for (i = 0; i < size; ++i)
1174 val[i] = n >> (i * 8);
1175 if (!brev)
1176 byterev(val, size);
1177 mwrite(adrs, val, size);
1178 inc = size;
1179 }
1180 cmd = skipbl();
1181 if (cmd == '\n')
1182 break;
1183 inc = 0;
1184 switch (cmd) {
1185 case '\'':
1186 for(;;){
1187 n = inchar();
1188 if( n == '\\' )
1189 n = bsesc();
1190 else if( n == '\'' )
1191 break;
1192 for (i = 0; i < size; ++i)
1193 val[i] = n >> (i * 8);
1194 if (!brev)
1195 byterev(val, size);
1196 mwrite(adrs, val, size);
1197 adrs += size;
1198 }
1199 adrs -= size;
1200 inc = size;
1201 break;
1202 case ',':
1203 adrs += size;
1204 break;
1205 case '.':
1206 mnoread = 0;
1207 break;
1208 case ';':
1209 break;
1210 case 'x':
1211 case EOF:
1212 scannl();
1213 return;
1214 case 'b':
1215 case 'v':
1216 size = 1;
1217 break;
1218 case 'w':
1219 size = 2;
1220 break;
1221 case 'l':
1222 size = 4;
1223 break;
1224 case '^':
1225 adrs -= size;
1226 break;
1227 break;
1228 case '/':
1229 if (nslash > 0)
1230 adrs -= 1 << nslash;
1231 else
1232 nslash = 0;
1233 nslash += 4;
1234 adrs += 1 << nslash;
1235 break;
1236 case '\\':
1237 if (nslash < 0)
1238 adrs += 1 << -nslash;
1239 else
1240 nslash = 0;
1241 nslash -= 4;
1242 adrs -= 1 << -nslash;
1243 break;
1244 case 'm':
1245 scanhex(&adrs);
1246 break;
1247 case 'n':
1248 mnoread = 1;
1249 break;
1250 case 'r':
1251 brev = !brev;
1252 break;
1253 case '<':
1254 n = size;
1255 scanhex(&n);
1256 adrs -= n;
1257 break;
1258 case '>':
1259 n = size;
1260 scanhex(&n);
1261 adrs += n;
1262 break;
1263 }
1264 }
1265 adrs += inc;
1266 }
1267 }
1268
1269 int
1270 bsesc()
1271 {
1272 int c;
1273
1274 c = inchar();
1275 switch( c ){
1276 case 'n': c = '\n'; break;
1277 case 'r': c = '\r'; break;
1278 case 'b': c = '\b'; break;
1279 case 't': c = '\t'; break;
1280 }
1281 return c;
1282 }
1283
1284 void
1285 dump()
1286 {
1287 int c;
1288
1289 c = inchar();
1290 if ((isxdigit(c) && c != 'f' && c != 'd') || c == '\n')
1291 termch = c;
1292 scanhex(&adrs);
1293 if( termch != '\n')
1294 termch = 0;
1295 if( c == 'i' ){
1296 scanhex(&nidump);
1297 if( nidump == 0 )
1298 nidump = 16;
1299 adrs += ppc_inst_dump(adrs, nidump);
1300 last_cmd = "di\n";
1301 } else {
1302 scanhex(&ndump);
1303 if( ndump == 0 )
1304 ndump = 64;
1305 prdump(adrs, ndump);
1306 adrs += ndump;
1307 last_cmd = "d\n";
1308 }
1309 }
1310
1311 void
1312 prdump(unsigned adrs, int ndump)
1313 {
1314 register int n, m, c, r, nr;
1315 unsigned char temp[16];
1316
1317 for( n = ndump; n > 0; ){
1318 printf("%.8x", adrs);
1319 putchar(' ');
1320 r = n < 16? n: 16;
1321 nr = mread(adrs, temp, r);
1322 adrs += nr;
1323 for( m = 0; m < r; ++m ){
1324 putchar((m & 3) == 0 && m > 0? '.': ' ');
1325 if( m < nr )
1326 printf("%.2x", temp[m]);
1327 else
1328 printf("%s", fault_chars[fault_type]);
1329 }
1330 for(; m < 16; ++m )
1331 printf(" ");
1332 printf(" |");
1333 for( m = 0; m < r; ++m ){
1334 if( m < nr ){
1335 c = temp[m];
1336 putchar(' ' <= c && c <= '~'? c: '.');
1337 } else
1338 putchar(' ');
1339 }
1340 n -= r;
1341 for(; m < 16; ++m )
1342 putchar(' ');
1343 printf("|\n");
1344 if( nr < r )
1345 break;
1346 }
1347 }
1348
1349 int
1350 ppc_inst_dump(unsigned adr, int count)
1351 {
1352 int nr, dotted;
1353 unsigned first_adr;
1354 unsigned long inst, last_inst;
1355 unsigned char val[4];
1356
1357 dotted = 0;
1358 for (first_adr = adr; count > 0; --count, adr += 4){
1359 nr = mread(adr, val, 4);
1360 if( nr == 0 ){
1361 const char *x = fault_chars[fault_type];
1362 printf("%.8x %s%s%s%s\n", adr, x, x, x, x);
1363 break;
1364 }
1365 inst = GETWORD(val);
1366 if (adr > first_adr && inst == last_inst) {
1367 if (!dotted) {
1368 printf(" ...\n");
1369 dotted = 1;
1370 }
1371 continue;
1372 }
1373 dotted = 0;
1374 last_inst = inst;
1375 printf("%.8x ", adr);
1376 printf("%.8x\t", inst);
1377 print_insn_big_powerpc(stdout, inst, adr); /* always returns 4 */
1378 printf("\n");
1379 }
1380 return adr - first_adr;
1381 }
1382
1383 void
1384 print_address(addr)
1385 unsigned addr;
1386 {
1387 printf("0x%x", addr);
1388 }
1389
1390 /*
1391 * Memory operations - move, set, print differences
1392 */
1393 static unsigned mdest; /* destination address */
1394 static unsigned msrc; /* source address */
1395 static unsigned mval; /* byte value to set memory to */
1396 static unsigned mcount; /* # bytes to affect */
1397 static unsigned mdiffs; /* max # differences to print */
1398
1399 void
1400 memops(int cmd)
1401 {
1402 scanhex(&mdest);
1403 if( termch != '\n' )
1404 termch = 0;
1405 scanhex(cmd == 's'? &mval: &msrc);
1406 if( termch != '\n' )
1407 termch = 0;
1408 scanhex(&mcount);
1409 switch( cmd ){
1410 case 'm':
1411 memmove((void *)mdest, (void *)msrc, mcount);
1412 break;
1413 case 's':
1414 memset((void *)mdest, mval, mcount);
1415 break;
1416 case 'd':
1417 if( termch != '\n' )
1418 termch = 0;
1419 scanhex(&mdiffs);
1420 memdiffs((unsigned char *)mdest, (unsigned char *)msrc, mcount, mdiffs);
1421 break;
1422 }
1423 }
1424
1425 void
1426 memdiffs(unsigned char *p1, unsigned char *p2, unsigned nb, unsigned maxpr)
1427 {
1428 unsigned n, prt;
1429
1430 prt = 0;
1431 for( n = nb; n > 0; --n )
1432 if( *p1++ != *p2++ )
1433 if( ++prt <= maxpr )
1434 printf("%.8x %.2x # %.8x %.2x\n", (unsigned)p1 - 1,
1435 p1[-1], (unsigned)p2 - 1, p2[-1]);
1436 if( prt > maxpr )
1437 printf("Total of %d differences\n", prt);
1438 }
1439
1440 static unsigned mend;
1441 static unsigned mask;
1442
1443 void
1444 memlocate()
1445 {
1446 unsigned a, n;
1447 unsigned char val[4];
1448
1449 last_cmd = "ml";
1450 scanhex(&mdest);
1451 if (termch != '\n') {
1452 termch = 0;
1453 scanhex(&mend);
1454 if (termch != '\n') {
1455 termch = 0;
1456 scanhex(&mval);
1457 mask = ~0;
1458 if (termch != '\n') termch = 0;
1459 scanhex(&mask);
1460 }
1461 }
1462 n = 0;
1463 for (a = mdest; a < mend; a += 4) {
1464 if (mread(a, val, 4) == 4
1465 && ((GETWORD(val) ^ mval) & mask) == 0) {
1466 printf("%.8x: %.8x\n", a, GETWORD(val));
1467 if (++n >= 10)
1468 break;
1469 }
1470 }
1471 }
1472
1473 static unsigned mskip = 0x1000;
1474 static unsigned mlim = 0xffffffff;
1475
1476 void
1477 memzcan()
1478 {
1479 unsigned char v;
1480 unsigned a;
1481 int ok, ook;
1482
1483 scanhex(&mdest);
1484 if (termch != '\n') termch = 0;
1485 scanhex(&mskip);
1486 if (termch != '\n') termch = 0;
1487 scanhex(&mlim);
1488 ook = 0;
1489 for (a = mdest; a < mlim; a += mskip) {
1490 ok = mread(a, &v, 1);
1491 if (ok && !ook) {
1492 printf("%.8x .. ", a);
1493 fflush(stdout);
1494 } else if (!ok && ook)
1495 printf("%.8x\n", a - mskip);
1496 ook = ok;
1497 if (a + mskip < a)
1498 break;
1499 }
1500 if (ook)
1501 printf("%.8x\n", a - mskip);
1502 }
1503
1504 /* Input scanning routines */
1505 int
1506 skipbl()
1507 {
1508 int c;
1509
1510 if( termch != 0 ){
1511 c = termch;
1512 termch = 0;
1513 } else
1514 c = inchar();
1515 while( c == ' ' || c == '\t' )
1516 c = inchar();
1517 return c;
1518 }
1519
1520 #define N_PTREGS 44
1521 static char *regnames[N_PTREGS] = {
1522 "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
1523 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15",
1524 "r16", "r17", "r18", "r19", "r20", "r21", "r22", "r23",
1525 "r24", "r25", "r26", "r27", "r28", "r29", "r30", "r31",
1526 "pc", "msr", "or3", "ctr", "lr", "xer", "ccr", "mq",
1527 "trap", "dar", "dsisr", "res"
1528 };
1529
1530 int
1531 scanhex(vp)
1532 unsigned *vp;
1533 {
1534 int c, d;
1535 unsigned v;
1536
1537 c = skipbl();
1538 if (c == '%') {
1539 /* parse register name */
1540 char regname[8];
1541 int i;
1542
1543 for (i = 0; i < sizeof(regname) - 1; ++i) {
1544 c = inchar();
1545 if (!isalnum(c)) {
1546 termch = c;
1547 break;
1548 }
1549 regname[i] = c;
1550 }
1551 regname[i] = 0;
1552 for (i = 0; i < N_PTREGS; ++i) {
1553 if (strcmp(regnames[i], regname) == 0) {
1554 unsigned *rp = (unsigned *)
1555 xmon_regs[smp_processor_id()];
1556 if (rp == NULL) {
1557 printf("regs not available\n");
1558 return 0;
1559 }
1560 *vp = rp[i];
1561 return 1;
1562 }
1563 }
1564 printf("invalid register name '%%%s'\n", regname);
1565 return 0;
1566 }
1567
1568 d = hexdigit(c);
1569 if( d == EOF ){
1570 termch = c;
1571 return 0;
1572 }
1573 v = 0;
1574 do {
1575 v = (v << 4) + d;
1576 c = inchar();
1577 d = hexdigit(c);
1578 } while( d != EOF );
1579 termch = c;
1580 *vp = v;
1581 return 1;
1582 }
1583
1584 void
1585 scannl()
1586 {
1587 int c;
1588
1589 c = termch;
1590 termch = 0;
1591 while( c != '\n' )
1592 c = inchar();
1593 }
1594
1595 int
1596 hexdigit(c)
1597 {
1598 if( '0' <= c && c <= '9' )
1599 return c - '0';
1600 if( 'A' <= c && c <= 'F' )
1601 return c - ('A' - 10);
1602 if( 'a' <= c && c <= 'f' )
1603 return c - ('a' - 10);
1604 return EOF;
1605 }
1606
1607 void
1608 getstring(char *s, int size)
1609 {
1610 int c;
1611
1612 c = skipbl();
1613 do {
1614 if( size > 1 ){
1615 *s++ = c;
1616 --size;
1617 }
1618 c = inchar();
1619 } while( c != ' ' && c != '\t' && c != '\n' );
1620 termch = c;
1621 *s = 0;
1622 }
1623
1624 static char line[256];
1625 static char *lineptr;
1626
1627 void
1628 flush_input()
1629 {
1630 lineptr = NULL;
1631 }
1632
1633 int
1634 inchar()
1635 {
1636 if (lineptr == NULL || *lineptr == 0) {
1637 if (fgets(line, sizeof(line), stdin) == NULL) {
1638 lineptr = NULL;
1639 return EOF;
1640 }
1641 lineptr = line;
1642 }
1643 return *lineptr++;
1644 }
1645
1646 void
1647 take_input(str)
1648 char *str;
1649 {
1650 lineptr = str;
1651 }
1652
1653 #if 0 /* Makes compile with -Wall */
1654 static char *pretty_print_addr(unsigned long addr)
1655 {
1656 printf("%08x", addr);
1657 if ( lookup_name(addr) )
1658 printf(" %s", lookup_name(addr) );
1659 return NULL;
1660 }
1661 #endif
1662
1663 #if 0 /* Makes compile with -Wall */
1664 static char *lookup_name(unsigned long addr)
1665 {
1666 extern char *sysmap;
1667 extern unsigned long sysmap_size;
1668 char *c = sysmap;
1669 unsigned long cmp;
1670 if ( !sysmap || !sysmap_size )
1671 return NULL;
1672 return NULL;
1673 #if 0
1674 cmp = simple_strtoul(c, &c, 8);
1675 /* XXX crap, we don't want the whole of the rest of the map - paulus */
1676 strcpy( last, strsep( &c, "\n"));
1677 while ( c < (sysmap+sysmap_size) )
1678 {
1679 cmp = simple_strtoul(c, &c, 8);
1680 if ( cmp < addr )
1681 break;
1682 strcpy( last, strsep( &c, "\n"));
1683 }
1684 return last;
1685 #endif
1686 }
1687 #endif
1688