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