scoutos / prex-0.9.0 / bsp / drv / dev / base / kd.c @ 03e9c04a
History | View | Annotate | Download (13.9 KB)
1 |
/*-
|
---|---|
2 |
* Copyright (c) 2008-2009, Kohsuke Ohtani
|
3 |
* All rights reserved.
|
4 |
*
|
5 |
* Redistribution and use in source and binary forms, with or without
|
6 |
* modification, are permitted provided that the following conditions
|
7 |
* are met:
|
8 |
* 1. Redistributions of source code must retain the above copyright
|
9 |
* notice, this list of conditions and the following disclaimer.
|
10 |
* 2. Redistributions in binary form must reproduce the above copyright
|
11 |
* notice, this list of conditions and the following disclaimer in the
|
12 |
* documentation and/or other materials provided with the distribution.
|
13 |
* 3. Neither the name of the author nor the names of any co-contributors
|
14 |
* may be used to endorse or promote products derived from this software
|
15 |
* without specific prior written permission.
|
16 |
*
|
17 |
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
18 |
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
19 |
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
20 |
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
21 |
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
22 |
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
23 |
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
24 |
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
25 |
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
26 |
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
27 |
* SUCH DAMAGE.
|
28 |
*/
|
29 |
|
30 |
/*
|
31 |
* kd.c - kernel debugger.
|
32 |
*/
|
33 |
|
34 |
#include <driver.h> |
35 |
#include <sys/sysinfo.h> |
36 |
#include <sys/power.h> |
37 |
#include <sys/dbgctl.h> |
38 |
#include <sys/endian.h> |
39 |
|
40 |
#include <devctl.h> |
41 |
#include <cons.h> |
42 |
#include <pm.h> |
43 |
|
44 |
#define ARGMAX 32 |
45 |
|
46 |
static void kd_abort(void); |
47 |
|
48 |
static int kd_null(int, char **); |
49 |
static int kd_help(int, char **); |
50 |
static int kd_continue(int, char **); |
51 |
static int kd_reboot(int, char **); |
52 |
static int kd_mstat(int, char **); |
53 |
static int kd_thread(int, char **); |
54 |
static int kd_task(int, char **); |
55 |
static int kd_vm(int, char **); |
56 |
static int kd_device(int, char **); |
57 |
static int kd_driver(int, char **); |
58 |
static int kd_irq(int, char **); |
59 |
static int kd_trap(int, char **); |
60 |
static int kd_devstat(int, char **); |
61 |
static int kd_trace(int, char **); |
62 |
static int kd_examine(int, char **); |
63 |
static int kd_write(int, char **); |
64 |
|
65 |
struct cmd_entry {
|
66 |
const char *cmd; |
67 |
int (*func)(int, char **); |
68 |
const char *usage; |
69 |
}; |
70 |
|
71 |
static const struct cmd_entry cmd_table[] = { |
72 |
{ "help" ,kd_help ,"This help" }, |
73 |
{ "continue" ,kd_continue ,"Continue execution [c]" }, |
74 |
{ "reboot" ,kd_reboot ,"Reboot system" }, |
75 |
{ "mstat" ,kd_mstat ,"Display memory usage" }, |
76 |
{ "thread" ,kd_thread ,"Display thread information" }, |
77 |
{ "task" ,kd_task ,"Display task information" }, |
78 |
{ "vm" ,kd_vm ,"Dump all VM segments" }, |
79 |
{ "device" ,kd_device ,"Display list of devices" }, |
80 |
{ "driver" ,kd_driver ,"Display list of drivers" }, |
81 |
{ "irq" ,kd_irq ,"Display interrupt information" }, |
82 |
{ "trap" ,kd_trap ,"Dump current trap frame" }, |
83 |
{ "devstat" ,kd_devstat ,"Dump all device state" }, |
84 |
{ "trace" ,kd_trace ,"Set trace flag for task" }, |
85 |
{ "examine" ,kd_examine ,"Examine data (x [/fmt] [addr])" }, |
86 |
{ "write" ,kd_write ,"Write data (w [/size] addr val)" }, |
87 |
/* command alias section */
|
88 |
{ "?" ,kd_help ,NULL }, |
89 |
{ "x" ,kd_examine ,NULL }, |
90 |
{ "w" ,kd_write ,NULL }, |
91 |
{ "c" ,kd_continue ,NULL }, |
92 |
{ NULL ,kd_null ,NULL }, |
93 |
}; |
94 |
|
95 |
/*
|
96 |
* Errors
|
97 |
*/
|
98 |
#define KERR_SYNTAX 1 |
99 |
#define KERR_TOOMANY 2 |
100 |
#define KERR_INVAL 3 |
101 |
#define KERR_BADADDR 4 |
102 |
#define KERR_NOFUNC 5 |
103 |
#define KERR_NOMEM 6 |
104 |
|
105 |
static const char *kd_errname[] = { |
106 |
"",
|
107 |
"Syntax error",
|
108 |
"Too many arguments",
|
109 |
"Invalid argument",
|
110 |
"No physical memory",
|
111 |
"Function not supported",
|
112 |
"Out of memory",
|
113 |
}; |
114 |
|
115 |
#define KERR_MAX (int)(sizeof(kd_errname) / sizeof(char *)) |
116 |
|
117 |
|
118 |
static dpc_t kd_dpc; /* dpc for debugger */ |
119 |
|
120 |
static struct abort_ops kd_abort_ops = { |
121 |
/* abort */ kd_abort,
|
122 |
}; |
123 |
|
124 |
static int |
125 |
kd_null(int argc, char **argv) |
126 |
{ |
127 |
return 0; |
128 |
} |
129 |
|
130 |
static void |
131 |
kd_error(int id)
|
132 |
{ |
133 |
|
134 |
if (id < KERR_MAX)
|
135 |
printf("%s\n", kd_errname[id]);
|
136 |
} |
137 |
|
138 |
/*
|
139 |
* Get taks id from its name.
|
140 |
*/
|
141 |
static task_t
|
142 |
kd_lookup_task(char *name)
|
143 |
{ |
144 |
struct taskinfo ti;
|
145 |
task_t task = TASK_NULL; |
146 |
int rc;
|
147 |
|
148 |
rc = 0;
|
149 |
ti.cookie = 0;
|
150 |
do {
|
151 |
rc = sysinfo(INFO_TASK, &ti); |
152 |
if (!rc && !strncmp(ti.taskname, name, MAXTASKNAME)) {
|
153 |
task = ti.id; |
154 |
} |
155 |
} while (rc == 0); |
156 |
return task;
|
157 |
} |
158 |
|
159 |
|
160 |
static int |
161 |
kd_help(int argc, char **argv) |
162 |
{ |
163 |
int i = 0; |
164 |
|
165 |
while (cmd_table[i].cmd != NULL) { |
166 |
if (cmd_table[i].usage)
|
167 |
printf(" %10s -- %s.\n", cmd_table[i].cmd,
|
168 |
cmd_table[i].usage); |
169 |
i++; |
170 |
} |
171 |
printf("\nuse `-?` to find out more about each command.\n");
|
172 |
return 0; |
173 |
} |
174 |
|
175 |
static int |
176 |
kd_continue(int argc, char **argv) |
177 |
{ |
178 |
|
179 |
return -1; |
180 |
} |
181 |
|
182 |
static int |
183 |
kd_reboot(int argc, char **argv) |
184 |
{ |
185 |
|
186 |
#ifdef CONFIG_PM
|
187 |
pm_set_power(PWR_REBOOT); |
188 |
#else
|
189 |
machine_powerdown(PWR_REBOOT); |
190 |
#endif
|
191 |
return 0; |
192 |
} |
193 |
|
194 |
static int |
195 |
kd_mstat(int argc, char **argv) |
196 |
{ |
197 |
struct meminfo info;
|
198 |
|
199 |
/* Get memory information from kernel. */
|
200 |
sysinfo(INFO_MEMORY, &info); |
201 |
|
202 |
printf("Memory usage:\n");
|
203 |
printf(" Used :%8ld KB\n", (info.total - info.free) / 1024); |
204 |
printf(" Free :%8ld KB\n", info.free / 1024); |
205 |
printf(" Total :%8ld KB\n", info.total / 1024); |
206 |
printf(" Bootdisk :%8ld KB\n", info.bootdisk / 1024); |
207 |
return 0; |
208 |
} |
209 |
|
210 |
static int |
211 |
kd_thread(int argc, char **argv) |
212 |
{ |
213 |
const char state[][4] = \ |
214 |
{ "RUN", "SLP", "SUS", "S&S", "EXT" }; |
215 |
const char pol[][5] = { "FIFO", "RR " }; |
216 |
struct threadinfo ti;
|
217 |
int rc;
|
218 |
|
219 |
printf("Thread list:\n");
|
220 |
printf(" thread task stat pol pri base time "
|
221 |
"suscnt sleep event\n");
|
222 |
printf(" -------- ------------ ---- ---- --- ---- -------- "
|
223 |
"------ ------------\n");
|
224 |
|
225 |
rc = 0;
|
226 |
ti.cookie = 0;
|
227 |
do {
|
228 |
/* Get thread information from kernel. */
|
229 |
rc = sysinfo(INFO_THREAD, &ti); |
230 |
if (!rc) {
|
231 |
printf(" %08lx %12s %s%c %s %3d %3d %8d %6d %s\n",
|
232 |
ti.id, ti.taskname, state[ti.state], |
233 |
ti.active ? '*' : ' ', |
234 |
pol[ti.policy], ti.priority, ti.basepri, |
235 |
ti.time, ti.suscnt, ti.slpevt); |
236 |
} |
237 |
} while (rc == 0); |
238 |
|
239 |
return 0; |
240 |
} |
241 |
|
242 |
static int |
243 |
kd_task(int argc, char **argv) |
244 |
{ |
245 |
struct taskinfo ti;
|
246 |
int rc;
|
247 |
|
248 |
printf("Task list:\n");
|
249 |
printf(" task name nthreads flags suscnt capability vmsize\n");
|
250 |
printf(" --------- -------- -------- -------- ------ ---------- --------\n");
|
251 |
|
252 |
rc = 0;
|
253 |
ti.cookie = 0;
|
254 |
do {
|
255 |
/* Get task information from kernel. */
|
256 |
rc = sysinfo(INFO_TASK, &ti); |
257 |
if (!rc) {
|
258 |
printf(" %08lx%c %8s %8d %08x %6d %08x %8d\n",
|
259 |
ti.id, ti.active ? '*' : ' ', ti.taskname, |
260 |
ti.nthreads, ti.flags, ti.suscnt, |
261 |
ti.capability, ti.vmsize); |
262 |
} |
263 |
} while (rc == 0); |
264 |
|
265 |
return 0; |
266 |
} |
267 |
|
268 |
static void |
269 |
kd_vm_region(task_t task) |
270 |
{ |
271 |
struct vminfo vi;
|
272 |
char flags[6]; |
273 |
int rc;
|
274 |
|
275 |
printf(" virtual physical size flags\n");
|
276 |
printf(" -------- -------- -------- -----\n");
|
277 |
|
278 |
rc = 0;
|
279 |
vi.cookie = 0;
|
280 |
do {
|
281 |
/* Get task information from kernel. */
|
282 |
vi.task = task; |
283 |
rc = sysinfo(INFO_VM, &vi); |
284 |
if (!rc) {
|
285 |
if (vi.flags != VF_FREE) {
|
286 |
strlcpy(flags, "-----", sizeof(flags)); |
287 |
if (vi.flags & VF_READ)
|
288 |
flags[0] = 'R'; |
289 |
if (vi.flags & VF_WRITE)
|
290 |
flags[1] = 'W'; |
291 |
if (vi.flags & VF_EXEC)
|
292 |
flags[2] = 'E'; |
293 |
if (vi.flags & VF_SHARED)
|
294 |
flags[3] = 'S'; |
295 |
if (vi.flags & VF_MAPPED)
|
296 |
flags[4] = 'M'; |
297 |
printf(" %08lx %08lx %8x %s\n",
|
298 |
(long)vi.virt, (long)vi.phys, |
299 |
vi.size, flags); |
300 |
} |
301 |
} |
302 |
} while (rc == 0); |
303 |
} |
304 |
|
305 |
static int |
306 |
kd_vm(int argc, char **argv) |
307 |
{ |
308 |
struct taskinfo ti;
|
309 |
int rc;
|
310 |
|
311 |
printf("VM information:\n");
|
312 |
|
313 |
rc = 0;
|
314 |
ti.cookie = 0;
|
315 |
do {
|
316 |
/* Get task information from kernel. */
|
317 |
rc = sysinfo(INFO_TASK, &ti); |
318 |
if (!rc) {
|
319 |
if (ti.vmsize != 0) { |
320 |
printf("\ntask=%08lx name=%s total=%dK bytes\n",
|
321 |
ti.id, ti.taskname, ti.vmsize / 1024);
|
322 |
kd_vm_region(ti.id); |
323 |
} |
324 |
} |
325 |
} while (rc == 0); |
326 |
|
327 |
return 0; |
328 |
} |
329 |
|
330 |
static int |
331 |
kd_device(int argc, char **argv) |
332 |
{ |
333 |
struct devinfo di;
|
334 |
char flags[6]; |
335 |
int rc;
|
336 |
|
337 |
printf("Device list:\n");
|
338 |
printf(" device name flags\n");
|
339 |
printf(" -------- ------------ -----\n");
|
340 |
|
341 |
rc = 0;
|
342 |
di.cookie = 0;
|
343 |
do {
|
344 |
/* Get device information from kernel. */
|
345 |
rc = sysinfo(INFO_DEVICE, &di); |
346 |
if (!rc) {
|
347 |
strlcpy(flags, "-----", sizeof(flags)); |
348 |
if (di.flags & D_CHR)
|
349 |
flags[0] = 'C'; |
350 |
if (di.flags & D_BLK)
|
351 |
flags[1] = 'B'; |
352 |
if (di.flags & D_REM)
|
353 |
flags[2] = 'R'; |
354 |
if (di.flags & D_PROT)
|
355 |
flags[3] = 'P'; |
356 |
if (di.flags & D_TTY)
|
357 |
flags[4] = 'T'; |
358 |
|
359 |
printf(" %08lx %12s %s\n", di.id, di.name, flags);
|
360 |
} |
361 |
} while (rc == 0); |
362 |
|
363 |
return 0; |
364 |
} |
365 |
|
366 |
static int |
367 |
kd_driver(int argc, char **argv) |
368 |
{ |
369 |
|
370 |
driver_dump(); |
371 |
return 0; |
372 |
} |
373 |
|
374 |
static int |
375 |
kd_irq(int argc, char **argv) |
376 |
{ |
377 |
struct irqinfo ii;
|
378 |
int rc;
|
379 |
|
380 |
printf("Interrupt table:\n");
|
381 |
printf(" vector count pending IST pri thread\n");
|
382 |
printf(" ------ -------- ----------- --- --------\n");
|
383 |
|
384 |
rc = 0;
|
385 |
ii.cookie = 0;
|
386 |
do {
|
387 |
rc = sysinfo(INFO_IRQ, &ii); |
388 |
if (!rc) {
|
389 |
printf(" %4d %8d %8d %3d %08lx\n",
|
390 |
ii.vector, ii.count, ii.istreq, |
391 |
ii.priority, (long)ii.thread);
|
392 |
} |
393 |
} while (rc == 0); |
394 |
|
395 |
return 0; |
396 |
} |
397 |
|
398 |
static int |
399 |
kd_trap(int argc, char **argv) |
400 |
{ |
401 |
|
402 |
printf("Trap frame:\n");
|
403 |
|
404 |
dbgctl(DBGC_DUMPTRAP, NULL);
|
405 |
return 0; |
406 |
} |
407 |
|
408 |
static int |
409 |
kd_devstat(int argc, char **argv) |
410 |
{ |
411 |
|
412 |
printf("Device state:\n");
|
413 |
|
414 |
device_broadcast(DEVCTL_DBG_DEVSTAT, NULL, 1); |
415 |
return 0; |
416 |
} |
417 |
|
418 |
static int |
419 |
kd_trace(int argc, char **argv) |
420 |
{ |
421 |
task_t task; |
422 |
|
423 |
if (argc != 2 || !strncmp(argv[1], "-?", 2)) { |
424 |
printf("usage: trace taskname\n");
|
425 |
return 0; |
426 |
} |
427 |
|
428 |
task = kd_lookup_task(argv[1]);
|
429 |
if (task == TASK_NULL)
|
430 |
return KERR_INVAL;
|
431 |
|
432 |
printf("Toggle trace flag: %s (%08lx)\n", argv[1], (long)task); |
433 |
dbgctl(DBGC_TRACE, (void *)task);
|
434 |
|
435 |
return 0; |
436 |
} |
437 |
|
438 |
static int |
439 |
kd_examine(int argc, char **argv) |
440 |
{ |
441 |
char *p;
|
442 |
u_char *kp; |
443 |
static u_long len = 16; |
444 |
static u_long cnt;
|
445 |
static vaddr_t addr;
|
446 |
static int size = 4; |
447 |
static char fmt = '*'; |
448 |
|
449 |
p = argv[1];
|
450 |
switch (argc) {
|
451 |
case 1: |
452 |
/* Use previous address and format */
|
453 |
p = NULL;
|
454 |
break;
|
455 |
case 2: |
456 |
p = argv[1];
|
457 |
len = 16;
|
458 |
break;
|
459 |
case 3: |
460 |
if (*p != '/') |
461 |
return KERR_INVAL;
|
462 |
p++; |
463 |
switch (*p) {
|
464 |
case 'c': |
465 |
case 'b': |
466 |
case 'h': |
467 |
case 'w': |
468 |
fmt = *p; |
469 |
p++; |
470 |
break;
|
471 |
} |
472 |
len = strtoul(p, NULL, 16); |
473 |
if (len == ULONG_MAX)
|
474 |
return KERR_INVAL;
|
475 |
p = argv[2];
|
476 |
break;
|
477 |
default:
|
478 |
return KERR_SYNTAX;
|
479 |
} |
480 |
if (p != NULL) { |
481 |
addr = strtoul(p, NULL, 16); |
482 |
if (addr == ULONG_MAX)
|
483 |
return KERR_INVAL;
|
484 |
} |
485 |
|
486 |
if ((kp = kmem_map((void *)addr, (size_t)len)) == NULL) |
487 |
return KERR_BADADDR;
|
488 |
|
489 |
for (cnt = 0; cnt < len;) { |
490 |
if ((cnt % 16) == 0) |
491 |
printf("\n%08lx: ", (long)addr); |
492 |
|
493 |
switch (fmt) {
|
494 |
case 'c': |
495 |
printf("%c", *kp);
|
496 |
size = 1;
|
497 |
break;
|
498 |
case 'b': |
499 |
printf("%02x ", *kp);
|
500 |
size = 1;
|
501 |
break;
|
502 |
case 'h': |
503 |
printf("%04x ", *(u_short *)kp);
|
504 |
size = 2;
|
505 |
break;
|
506 |
case 'w': |
507 |
default:
|
508 |
printf("%08lx ", *(u_long *)kp);
|
509 |
size = 4;
|
510 |
break;
|
511 |
} |
512 |
addr += size; |
513 |
kp += size; |
514 |
cnt += size; |
515 |
} |
516 |
return 0; |
517 |
} |
518 |
|
519 |
static int |
520 |
kd_write(int argc, char **argv) |
521 |
{ |
522 |
vaddr_t addr; |
523 |
int size = 4; |
524 |
u_char *kp; |
525 |
char *p, *pa, *pv;
|
526 |
u_long val; |
527 |
int i;
|
528 |
|
529 |
if (argc < 3) |
530 |
return KERR_INVAL;
|
531 |
|
532 |
pa = argv[1];
|
533 |
pv = argv[2];
|
534 |
|
535 |
if (argc == 4) { |
536 |
p = argv[1];
|
537 |
if (*p != '/') |
538 |
return KERR_INVAL;
|
539 |
p++; |
540 |
switch (*p) {
|
541 |
case 'b': |
542 |
size = 1;
|
543 |
break;
|
544 |
case 'h': |
545 |
size = 2;
|
546 |
break;
|
547 |
case 'w': |
548 |
size = 4;
|
549 |
break;
|
550 |
default:
|
551 |
return KERR_INVAL;
|
552 |
} |
553 |
pa = argv[2];
|
554 |
pv = argv[3];
|
555 |
} |
556 |
addr = strtoul(pa, NULL, 16); |
557 |
if (addr == ULONG_MAX)
|
558 |
return KERR_INVAL;
|
559 |
|
560 |
val = strtoul(pv, NULL, 16); |
561 |
if (val == ULONG_MAX)
|
562 |
return KERR_INVAL;
|
563 |
|
564 |
if ((kp = kmem_map((void *)addr, (size_t)size)) == NULL) |
565 |
return KERR_BADADDR;
|
566 |
|
567 |
#if BYTE_ORDER == LITTLE_ENDIAN
|
568 |
for (i = 0; i < size; i++) { |
569 |
#else /* BYTE_ORDER == BIG_ENDIAN */ |
570 |
for (i = size; i-- > 0;) { |
571 |
#endif /* BYTE_ORDER */ |
572 |
/* FIXME: need to check alignment... */
|
573 |
*(char *)((char *)addr + i) = (char)(val & 0xff); |
574 |
val >>= 8;
|
575 |
} |
576 |
|
577 |
return 0; |
578 |
} |
579 |
|
580 |
static int |
581 |
kd_dispatch(int argc, char **argv) |
582 |
{ |
583 |
int i = 0; |
584 |
int error = 0; |
585 |
|
586 |
while (cmd_table[i].cmd != NULL) { |
587 |
if (!strncmp(argv[0], cmd_table[i].cmd, LINE_MAX)) { |
588 |
error = (cmd_table[i].func)(argc, argv); |
589 |
break;
|
590 |
} |
591 |
i++; |
592 |
} |
593 |
if (cmd_table[i].cmd == NULL) |
594 |
error = KERR_SYNTAX; |
595 |
|
596 |
if (error > 0 && error <= KERR_MAX) |
597 |
kd_error(error); |
598 |
|
599 |
if (error == -1) |
600 |
return -1; |
601 |
return 0; |
602 |
} |
603 |
|
604 |
static int |
605 |
kd_parse_line(char *line)
|
606 |
{ |
607 |
static char *args[ARGMAX]; |
608 |
char *p, *word = NULL; |
609 |
int argc = 0; |
610 |
int rc = 0; |
611 |
|
612 |
if (line[0] != ' ' && line[0] != '\t') |
613 |
word = line; |
614 |
|
615 |
p = line; |
616 |
while (*p) {
|
617 |
if (word == NULL) { |
618 |
/* Skip white space. */
|
619 |
if (*p != ' ' && *p != '\t') |
620 |
word = p; |
621 |
} else {
|
622 |
if (*p == ' ' || *p == '\t') { |
623 |
*p = '\0';
|
624 |
args[argc++] = word; |
625 |
word = NULL;
|
626 |
if (argc >= ARGMAX - 1) { |
627 |
kd_error(KERR_TOOMANY); |
628 |
return 0; |
629 |
} |
630 |
} |
631 |
} |
632 |
p++; |
633 |
} |
634 |
if (word)
|
635 |
args[argc++] = word; |
636 |
args[argc] = NULL;
|
637 |
|
638 |
if (argc) {
|
639 |
if (kd_dispatch(argc, args))
|
640 |
rc = 1;
|
641 |
} |
642 |
return rc;
|
643 |
} |
644 |
|
645 |
static void |
646 |
kd_read_line(char *line)
|
647 |
{ |
648 |
int c, pos = 0; |
649 |
char *p = line;
|
650 |
|
651 |
for (;;) {
|
652 |
c = cons_getc(); |
653 |
|
654 |
switch(c) {
|
655 |
case '\n': |
656 |
case '\r': |
657 |
*p = '\0';
|
658 |
printf("\n");
|
659 |
return;
|
660 |
case '\b': |
661 |
case 127: |
662 |
if (pos > 0) { |
663 |
*p = '\0';
|
664 |
p--; |
665 |
pos--; |
666 |
printf("\b");
|
667 |
printf(" ");
|
668 |
printf("\b");
|
669 |
} |
670 |
break;
|
671 |
default:
|
672 |
*p = (char)c;
|
673 |
p++; |
674 |
pos++; |
675 |
if (pos > LINE_MAX) {
|
676 |
*p = '\0';
|
677 |
return;
|
678 |
} |
679 |
printf("%c", c);
|
680 |
break;
|
681 |
} |
682 |
} |
683 |
} |
684 |
|
685 |
void
|
686 |
kd_invoke(void *arg)
|
687 |
{ |
688 |
static char line[LINE_MAX]; |
689 |
int s;
|
690 |
|
691 |
printf("\n-------------------------------\n");
|
692 |
printf(" Entering debugger.\n");
|
693 |
printf(" Type 'help' to list commands.\n");
|
694 |
printf("-------------------------------\n");
|
695 |
|
696 |
s = spl0(); |
697 |
|
698 |
/* Set input device to polling mode. */
|
699 |
cons_pollc(1);
|
700 |
|
701 |
for (;;) {
|
702 |
printf("\n[kd] ");
|
703 |
kd_read_line(line); |
704 |
if (kd_parse_line(line))
|
705 |
break;
|
706 |
} |
707 |
cons_pollc(0);
|
708 |
splx(s); |
709 |
} |
710 |
|
711 |
/*
|
712 |
* User can enter kd by pressing ctrl+k key at any time.
|
713 |
*/
|
714 |
void
|
715 |
kd_enter(void)
|
716 |
{ |
717 |
|
718 |
/* Call back in DPC level */
|
719 |
sched_dpc(&kd_dpc, &kd_invoke, NULL);
|
720 |
} |
721 |
|
722 |
/*
|
723 |
* Callback handler for abort.
|
724 |
*/
|
725 |
void
|
726 |
kd_abort(void)
|
727 |
{ |
728 |
|
729 |
kd_invoke(NULL);
|
730 |
} |
731 |
|
732 |
void
|
733 |
kd_init(void)
|
734 |
{ |
735 |
|
736 |
/*
|
737 |
* Install abort handler to catch assert & panic events.
|
738 |
*/
|
739 |
dbgctl(DBGC_SETABORT, &kd_abort_ops); |
740 |
} |