/* * Mach Operating System * Copyright (c) 1991,1990 Carnegie Mellon University * All Rights Reserved. * * Permission to use, copy, modify and distribute this software and its * documentation is hereby granted, provided that both the copyright * notice and this permission notice appear in all copies of the * software, derivative works or modified versions, and any portions * thereof, and that both notices appear in supporting documentation. * * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. * * Carnegie Mellon requests users of this software to return to * * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU * School of Computer Science * Carnegie Mellon University * Pittsburgh PA 15213-3890 * * any improvements or extensions that they make and grant Carnegie the * rights to redistribute these changes. * * $FreeBSD: src/sys/ddb/db_output.c,v 1.26 1999/08/28 00:41:09 peter Exp $ */ /* * Author: David B. Golub, Carnegie Mellon University * Date: 7/90 */ /* * Printf and character output for debugger. */ #include #include #include #include #include #include #include #include #include /* * Character output - tracks position in line. * To do this correctly, we should know how wide * the output device is - then we could zero * the line position when the output device wraps * around to the start of the next line. * * Instead, we count the number of spaces printed * since the last printing character so that we * don't print trailing spaces. This avoids most * of the wraparounds. */ static int db_output_position = 0; /* output column */ static int db_last_non_space = 0; /* last non-space character */ db_expr_t db_tab_stop_width = 8; /* how wide are tab stops? */ #define NEXT_TAB(i) rounddown((i) + db_tab_stop_width, db_tab_stop_width) db_expr_t db_max_width = 79; /* output line width */ static void db_putchar (int c, void *arg); /* * Force pending whitespace. */ void db_force_whitespace(void) { int last_print, next_tab; last_print = db_last_non_space; while (last_print < db_output_position) { next_tab = NEXT_TAB(last_print); if (next_tab <= db_output_position) { while (last_print < next_tab) { /* DON'T send a tab!!! */ cnputc(' '); last_print++; } } else { cnputc(' '); last_print++; } } db_last_non_space = db_output_position; } /* * Output character. Buffer whitespace. * * Parameters: * arg: character to output */ static void db_putchar(int c, void *arg) { /* * If not in the debugger, output data to both the console and * the message buffer. */ if (!db_active) { if (c == '\r' || c == '\n' || c == '\t' || isprint(c)) { kprintf("%c", c); } else { kprintf("?"); } if (!db_active) return; if (c == '\r' || c == '\n') db_check_interrupt(); return; } crit_enter_hard(); if (c > ' ' && c <= '~') { /* * Printing character. * If we have spaces to print, print them first. * Use tabs if possible. */ db_force_whitespace(); cnputc(c); db_output_position++; db_last_non_space = db_output_position; } else if (c == '\n') { /* Newline */ cnputc(c); db_output_position = 0; db_last_non_space = 0; db_check_interrupt(); } else if (c == '\r') { /* Return */ cnputc(c); db_output_position = 0; db_last_non_space = 0; db_check_interrupt(); } else if (c == '\t') { /* assume tabs every 8 positions */ db_output_position = NEXT_TAB(db_output_position); } else if (c == ' ') { /* space */ db_output_position++; } else if (c == '\007') { /* bell */ cnputc(c); } /* other characters are assumed non-printing */ crit_exit_hard(); } /* * Return output position */ int db_print_position(void) { return (db_output_position); } /* * Printing * * NOTE: We bypass subr_prf's cons_spin here by using our own putchar * function. */ void db_printf(const char *fmt, ...) { __va_list listp; __va_start(listp, fmt); kvcprintf (fmt, db_putchar, NULL, listp); __va_end(listp); /* DELAY(100000);*/ } void db_vprintf(const char *fmt, __va_list va) { kvcprintf (fmt, db_putchar, NULL, va); /* DELAY(100000);*/ } int db_indent; void db_iprintf(const char *fmt,...) { int i; __va_list listp; for (i = db_indent; i >= 8; i -= 8) db_printf("\t"); while (--i >= 0) db_printf(" "); __va_start(listp, fmt); kvcprintf (fmt, db_putchar, NULL, listp); __va_end(listp); } /* * End line if too long. */ void db_end_line(int field_width) { if (db_output_position + field_width > db_max_width) db_printf("\n"); } /* * Simple pager */ int db_more(int *nl) { ++*nl; if (*nl == 20) { int c; db_printf("--More--"); c = cngetc(); db_printf("\r"); /* * A whole screenfull or just one line? */ switch (c) { case '\n': /* just one line */ *nl = 19; break; case ' ': *nl = 0; /* another screenfull */ break; default: /* exit */ db_printf("\n"); return(-1); } } return(0); } /* * Replacement for old '%r' kprintf format. */ void db_format_radix(char *buf, size_t bufsiz, quad_t val, int altflag) { const char *fmt; if (db_radix == 16) { db_format_hex(buf, bufsiz, val, altflag); return; } if (db_radix == 8) fmt = altflag ? "-%#qo" : "-%qo"; else fmt = altflag ? "-%#qu" : "-%qu"; if (val < 0) val = -val; else ++fmt; ksnprintf(buf, bufsiz, fmt, val); } /* * Replacement for old '%z' kprintf format. */ void db_format_hex(char *buf, size_t bufsiz, quad_t val, int altflag) { /* Only use alternate form if val is nonzero. */ const char *fmt = (altflag && val) ? "-%#qx" : "-%qx"; if (val < 0) val = -val; else ++fmt; ksnprintf(buf, bufsiz, fmt, val); } /* #define TEMPORARY_DEBUGGING */ #ifdef TEMPORARY_DEBUGGING /* * Temporary Debugging, only turned on manually by kernel hackers trying * to debug extremely low level code. Adjust PCHAR_ as required. */ static void PCHAR_(int, void * __unused); void kprintf0(const char *fmt, ...) { __va_list ap; __va_start(ap, fmt); kvcprintf(fmt, PCHAR_, NULL, ap); __va_end(ap); } static void PCHAR_(int c, void *dummy __unused) { const int COMC_TXWAIT = 0x40000; const int COMPORT = 0x2f8; /* 0x3f8 COM1, 0x2f8 COM2 */ const int LSR_TXRDY = 0x20; const int BAUD = 115200; const int com_lsr = 5; const int com_data = 0; int wait; static int setbaud; if (setbaud == 0) { setbaud = 1; outb(COMPORT+3, 0x83); /* DLAB + 8N1 */ outb(COMPORT+0, (115200 / BAUD) & 0xFF); outb(COMPORT+1, (115200 / BAUD) >> 8); outb(COMPORT+3, 0x03); /* 8N1 */ outb(COMPORT+4, 0x03); /* RTS+DTR */ outb(COMPORT+2, 0x01); /* FIFO_ENABLE */ } for (wait = COMC_TXWAIT; wait > 0; wait--) { if (inb(COMPORT + com_lsr) & LSR_TXRDY) { outb(COMPORT + com_data, (u_char)c); break; } } } #endif