1 /* 2 * Mach Operating System 3 * Copyright (c) 1991,1990 Carnegie Mellon University 4 * All Rights Reserved. 5 * 6 * Permission to use, copy, modify and distribute this software and its 7 * documentation is hereby granted, provided that both the copyright 8 * notice and this permission notice appear in all copies of the 9 * software, derivative works or modified versions, and any portions 10 * thereof, and that both notices appear in supporting documentation. 11 * 12 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS 13 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR 14 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE. 15 * 16 * Carnegie Mellon requests users of this software to return to 17 * 18 * Software Distribution Coordinator or Software.Distribution@CS.CMU.EDU 19 * School of Computer Science 20 * Carnegie Mellon University 21 * Pittsburgh PA 15213-3890 22 * 23 * any improvements or extensions that they make and grant Carnegie the 24 * rights to redistribute these changes. 25 * 26 * $FreeBSD: src/sys/ddb/db_output.c,v 1.26 1999/08/28 00:41:09 peter Exp $ 27 */ 28 29 /* 30 * Author: David B. Golub, Carnegie Mellon University 31 * Date: 7/90 32 */ 33 34 /* 35 * Printf and character output for debugger. 36 */ 37 38 #include <sys/param.h> 39 #include <sys/systm.h> 40 #include <sys/cons.h> 41 #include <sys/ctype.h> 42 #include <sys/thread2.h> 43 #include <sys/spinlock2.h> 44 45 #include <machine/stdarg.h> 46 47 #include <ddb/ddb.h> 48 #include <ddb/db_output.h> 49 50 /* 51 * Character output - tracks position in line. 52 * To do this correctly, we should know how wide 53 * the output device is - then we could zero 54 * the line position when the output device wraps 55 * around to the start of the next line. 56 * 57 * Instead, we count the number of spaces printed 58 * since the last printing character so that we 59 * don't print trailing spaces. This avoids most 60 * of the wraparounds. 61 */ 62 static int db_output_position = 0; /* output column */ 63 static int db_last_non_space = 0; /* last non-space character */ 64 db_expr_t db_tab_stop_width = 8; /* how wide are tab stops? */ 65 #define NEXT_TAB(i) \ 66 ((((i) + db_tab_stop_width) / db_tab_stop_width) * db_tab_stop_width) 67 db_expr_t db_max_width = 79; /* output line width */ 68 69 static void db_putchar (int c, void *arg); 70 71 /* 72 * Force pending whitespace. 73 */ 74 void 75 db_force_whitespace(void) 76 { 77 int last_print, next_tab; 78 79 last_print = db_last_non_space; 80 while (last_print < db_output_position) { 81 next_tab = NEXT_TAB(last_print); 82 if (next_tab <= db_output_position) { 83 while (last_print < next_tab) { /* DON'T send a tab!!! */ 84 cnputc(' '); 85 last_print++; 86 } 87 } 88 else { 89 cnputc(' '); 90 last_print++; 91 } 92 } 93 db_last_non_space = db_output_position; 94 } 95 96 /* 97 * Output character. Buffer whitespace. 98 * 99 * Parameters: 100 * arg: character to output 101 */ 102 static void 103 db_putchar(int c, void *arg) 104 { 105 /* 106 * If not in the debugger, output data to both the console and 107 * the message buffer. 108 */ 109 if (!db_active) { 110 if (c == '\r' || c == '\n' || c == '\t' || 111 isprint(c)) { 112 kprintf("%c", c); 113 } else { 114 kprintf("?"); 115 } 116 if (!db_active) 117 return; 118 if (c == '\r' || c == '\n') 119 db_check_interrupt(); 120 return; 121 } 122 123 crit_enter_hard(); 124 125 if (c > ' ' && c <= '~') { 126 /* 127 * Printing character. 128 * If we have spaces to print, print them first. 129 * Use tabs if possible. 130 */ 131 db_force_whitespace(); 132 cnputc(c); 133 db_output_position++; 134 db_last_non_space = db_output_position; 135 } 136 else if (c == '\n') { 137 /* Newline */ 138 cnputc(c); 139 db_output_position = 0; 140 db_last_non_space = 0; 141 db_check_interrupt(); 142 } 143 else if (c == '\r') { 144 /* Return */ 145 cnputc(c); 146 db_output_position = 0; 147 db_last_non_space = 0; 148 db_check_interrupt(); 149 } 150 else if (c == '\t') { 151 /* assume tabs every 8 positions */ 152 db_output_position = NEXT_TAB(db_output_position); 153 } 154 else if (c == ' ') { 155 /* space */ 156 db_output_position++; 157 } 158 else if (c == '\007') { 159 /* bell */ 160 cnputc(c); 161 } 162 /* other characters are assumed non-printing */ 163 crit_exit_hard(); 164 } 165 166 /* 167 * Return output position 168 */ 169 int 170 db_print_position(void) 171 { 172 return (db_output_position); 173 } 174 175 /* 176 * Printing 177 * 178 * NOTE: We bypass subr_prf's cons_spin here by using our own putchar 179 * function. 180 */ 181 void 182 db_printf(const char *fmt, ...) 183 { 184 __va_list listp; 185 186 __va_start(listp, fmt); 187 kvcprintf (fmt, db_putchar, NULL, db_radix, listp); 188 __va_end(listp); 189 /* DELAY(100000);*/ 190 } 191 192 void 193 db_vprintf(const char *fmt, __va_list va) 194 { 195 kvcprintf (fmt, db_putchar, NULL, db_radix, va); 196 /* DELAY(100000);*/ 197 } 198 199 int db_indent; 200 201 void 202 db_iprintf(const char *fmt,...) 203 { 204 int i; 205 __va_list listp; 206 207 for (i = db_indent; i >= 8; i -= 8) 208 db_printf("\t"); 209 while (--i >= 0) 210 db_printf(" "); 211 __va_start(listp, fmt); 212 kvcprintf (fmt, db_putchar, NULL, db_radix, listp); 213 __va_end(listp); 214 } 215 216 /* 217 * End line if too long. 218 */ 219 void 220 db_end_line(int field_width) 221 { 222 if (db_output_position + field_width > db_max_width) 223 db_printf("\n"); 224 } 225 226 /* 227 * Simple pager 228 */ 229 int 230 db_more(int *nl) 231 { 232 ++*nl; 233 if (*nl == 20) { 234 int c; 235 236 db_printf("--More--"); 237 c = cngetc(); 238 db_printf("\r"); 239 /* 240 * A whole screenfull or just one line? 241 */ 242 switch (c) { 243 case '\n': /* just one line */ 244 *nl = 19; 245 break; 246 case ' ': 247 *nl = 0; /* another screenfull */ 248 break; 249 default: /* exit */ 250 db_printf("\n"); 251 return(-1); 252 } 253 } 254 return(0); 255 } 256 257 /* 258 * Replacement for old '%z' kprintf format. 259 */ 260 void 261 db_format_hex(char *buf, size_t bufsiz, quad_t val, int altflag) 262 { 263 /* Only use alternate form if val is nonzero. */ 264 const char *fmt = (altflag && val) ? "-%#qx" : "-%qx"; 265 266 if (val < 0) 267 val = -val; 268 else 269 ++fmt; 270 271 ksnprintf(buf, bufsiz, fmt, val); 272 } 273 274 /* #define TEMPORARY_DEBUGGING */ 275 #ifdef TEMPORARY_DEBUGGING 276 277 /* 278 * Temporary Debugging, only turned on manually by kernel hackers trying 279 * to debug extremely low level code. Adjust PCHAR_ as required. 280 */ 281 static void PCHAR_(int, void * __unused); 282 283 void 284 kprintf0(const char *fmt, ...) 285 { 286 __va_list ap; 287 288 __va_start(ap, fmt); 289 kvcprintf(fmt, PCHAR_, NULL, 10, ap); 290 __va_end(ap); 291 } 292 293 static void 294 PCHAR_(int c, void *dummy __unused) 295 { 296 const int COMC_TXWAIT = 0x40000; 297 const int COMPORT = 0x2f8; /* 0x3f8 COM1, 0x2f8 COM2 */ 298 const int LSR_TXRDY = 0x20; 299 const int BAUD = 9600; 300 const int com_lsr = 5; 301 const int com_data = 0; 302 int wait; 303 static int setbaud; 304 305 if (setbaud == 0) { 306 setbaud = 1; 307 outb(COMPORT+3, 0x83); /* DLAB + 8N1 */ 308 outb(COMPORT+0, (115200 / BAUD) & 0xFF); 309 outb(COMPORT+1, (115200 / BAUD) >> 8); 310 outb(COMPORT+3, 0x03); /* 8N1 */ 311 outb(COMPORT+4, 0x03); /* RTS+DTR */ 312 outb(COMPORT+2, 0x01); /* FIFO_ENABLE */ 313 } 314 315 for (wait = COMC_TXWAIT; wait > 0; wait--) { 316 if (inb(COMPORT + com_lsr) & LSR_TXRDY) { 317 outb(COMPORT + com_data, (u_char)c); 318 break; 319 } 320 } 321 } 322 323 #endif 324