xref: /illumos-gate/usr/src/cmd/mdb/common/kmdb/kmdb_promif.c (revision c7d88479a7c0629cf06e34280d67c35d84331a5e)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License (the "License").
6  * You may not use this file except in compliance with the License.
7  *
8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9  * or http://www.opensolaris.org/os/licensing.
10  * See the License for the specific language governing permissions
11  * and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL HEADER in each
14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15  * If applicable, add the following below this CDDL HEADER, with the
16  * fields enclosed by brackets "[]" replaced with your own identifying
17  * information: Portions Copyright [yyyy] [name of copyright owner]
18  *
19  * CDDL HEADER END
20  */
21 
22 /*
23  * Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <sys/types.h>
30 #include <sys/termios.h>
31 #include <sys/promif.h>
32 #include <unistd.h>
33 #include <string.h>
34 #include <stdlib.h>
35 
36 #include <kmdb/kmdb_promif_impl.h>
37 #include <kmdb/kmdb_kdi.h>
38 #include <kmdb/kmdb_dpi.h>
39 #include <mdb/mdb_debug.h>
40 #include <mdb/mdb_err.h>
41 #include <mdb/mdb_frame.h>
42 #include <mdb/mdb_string.h>
43 #include <mdb/mdb.h>
44 
45 #define	KMDB_PROM_DEF_CONS_MODE	"9600,n,1,-,-"
46 
47 #define	KMDB_PROM_READBUF_SIZE	1024
48 
49 static char kmdb_prom_readbuf[KMDB_PROM_READBUF_SIZE];
50 static int kmdb_prom_readbuf_head;
51 static int kmdb_prom_readbuf_tail;
52 
53 ssize_t
54 kmdb_prom_polled_read(caddr_t buf, size_t len)
55 {
56 	uintptr_t arg = (uintptr_t)mdb.m_pio->cons_polledio_argument;
57 	uintptr_t ischar = (uintptr_t)mdb.m_pio->cons_polledio_ischar;
58 	int nread = 0;
59 	int c;
60 
61 	while ((ischar == NULL || kmdb_dpi_call(ischar, 1, &arg)) &&
62 	    nread < len) {
63 		c = kmdb_dpi_call((uintptr_t)mdb.m_pio->cons_polledio_getchar,
64 		    1, &arg);
65 
66 		*buf++ = (char)c;
67 		nread++;
68 	}
69 
70 	return (nread);
71 }
72 
73 ssize_t
74 kmdb_prom_polled_write(caddr_t buf, size_t len)
75 {
76 	uintptr_t args[2];
77 	int i;
78 
79 	args[0] = (uintptr_t)mdb.m_pio->cons_polledio_argument;
80 
81 	for (i = 0; i < len; i++) {
82 		args[1] = *buf++;
83 		(void) kmdb_dpi_call(
84 		    (uintptr_t)mdb.m_pio->cons_polledio_putchar, 2, args);
85 	}
86 
87 	return (len);
88 }
89 
90 static ssize_t
91 kmdb_prom_reader(caddr_t buf, size_t len)
92 {
93 	int nread = 0;
94 	int c;
95 
96 	if (mdb.m_pio != NULL && mdb.m_pio->cons_polledio_getchar != NULL)
97 		return (kmdb_prom_polled_read(buf, len));
98 
99 	while (nread < len && (c = prom_mayget()) != -1) {
100 		*buf++ = (char)c;
101 		nread++;
102 	}
103 
104 	return (nread);
105 }
106 
107 static ssize_t
108 kmdb_prom_writer(caddr_t buf, size_t len)
109 {
110 	if (mdb.m_pio != NULL && mdb.m_pio->cons_polledio_putchar != NULL)
111 		return (kmdb_prom_polled_write(buf, len));
112 
113 	return (kmdb_prom_obp_writer(buf, len));
114 }
115 
116 /*
117  * Due to the nature of kmdb, we don't have signals.  This prevents us from
118  * receiving asynchronous notification when the user would like to abort
119  * active dcmds.  Whereas mdb can simply declare a SIGINT handler, we must
120  * occasionally poll the input stream, looking for pending ^C characters.  To
121  * give the illusion of asynchronous interrupt delivery, this polling is
122  * triggered from several commonly-used functions, such as kmdb_prom_write,
123  * kmdb_prom_read, and the *read and *write target ops.  When an interrupt
124  * check is triggered, we read through pending input, looking for interrupt
125  * characters.  If we find one, we deliver it.
126  *
127  * OBP doesn't have an "unget" facility.  Any character read for interrupt
128  * checking is gone forever, unless we save it.  Loss of these characters
129  * would prevent us from supporting typeahead.  We like typeahead, so we're
130  * going to save characters gathered during interrupt checking.  As with
131  * ungetc(3c), however, we can only store a finite number of characters in
132  * our typeahead buffer.  Characters read beyond that will be silently dropped
133  * after they undergo interrupt processing.
134  *
135  * The typeahead facility is implemented as a ring buffer, stored in
136  * kmdb_prom_readbuf, and has the following interfaces:
137  *
138  *   kmdb_prom_drain_readbuf - Given a buffer and a length, copy that many bytes
139  *    into the passed buffer.  This routine will not attempt to refill the ring
140  *    buffer.  The number of bytes actually copied will be returned.
141  *
142  *   kmdb_prom_fill_readbuf - Attempt to refill the ring buffer from the input
143  *    stream.  The `lossy' argument governs the action taken if the available
144  *    input will overflow the available space in the ring buffer.  If the lossy
145  *    argument is set, available input will be exhausted.  Characters that will
146  *    not fit in the ring buffer will be discarded after interrupt processing.
147  *    If this routine is invoked in lossless mode (i.e. the lossy flag is not
148  *    set), input will be read only until the buffer is full.
149  *
150  * kmdb_prom_* routines may call drain and fill directly.  Callers outside of
151  * the kmdb promif subsystem must use kmdb_prom_check_interrupt, which will
152  * invoke fill in lossy mode.
153  */
154 size_t
155 kmdb_prom_drain_readbuf(void *buf, size_t len)
156 {
157 	size_t n, tailread;
158 
159 	/*
160 	 * If head > tail, life is easy - we can simply read as much as we need
161 	 * in one gulp.
162 	 */
163 	if (kmdb_prom_readbuf_head > kmdb_prom_readbuf_tail) {
164 		n = MIN(kmdb_prom_readbuf_head - kmdb_prom_readbuf_tail, len);
165 		bcopy(kmdb_prom_readbuf + kmdb_prom_readbuf_tail, buf, n);
166 		kmdb_prom_readbuf_tail += n;
167 		return (n);
168 
169 	} else if (kmdb_prom_readbuf_head == kmdb_prom_readbuf_tail) {
170 		return (0);
171 	}
172 
173 	/*
174 	 * The consumable slots wrap around zero (there are slots from tail to
175 	 * zero, and from zero to head).  We have to read them in two parts.
176 	 */
177 	n = MIN(KMDB_PROM_READBUF_SIZE - kmdb_prom_readbuf_tail, len);
178 	bcopy(kmdb_prom_readbuf + kmdb_prom_readbuf_tail, buf, n);
179 	kmdb_prom_readbuf_tail = (kmdb_prom_readbuf_tail + n) %
180 	    KMDB_PROM_READBUF_SIZE;
181 
182 	if (n == len) {
183 		/*
184 		 * We filled the passed buffer from the first part, so there's
185 		 * no need to read the second.
186 		 */
187 		return (n);
188 	} else {
189 		tailread = n;
190 	}
191 
192 	n = MIN(kmdb_prom_readbuf_head, len - tailread);
193 	buf = (void *)((uintptr_t)buf + tailread);
194 	bcopy(kmdb_prom_readbuf, buf, n);
195 
196 	kmdb_prom_readbuf_tail = (kmdb_prom_readbuf_tail + n) %
197 	    KMDB_PROM_READBUF_SIZE;
198 
199 	return (tailread + n);
200 }
201 
202 static void
203 check_int(char *buf, size_t len)
204 {
205 	int i;
206 
207 	for (i = 0; i < len; i++) {
208 		if (buf[i] == ('c' & 037)) {
209 			kmdb_prom_readbuf_tail = kmdb_prom_readbuf_head;
210 			if (mdb.m_intr == 0)
211 				longjmp(mdb.m_frame->f_pcb, MDB_ERR_SIGINT);
212 			else
213 				mdb.m_pend++;
214 		}
215 	}
216 }
217 
218 void
219 kmdb_prom_fill_readbuf(int lossy)
220 {
221 	int oldhead, left, n;
222 
223 	/*
224 	 * Calculate the number of slots left before we wrap around to the
225 	 * beginning again.
226 	 */
227 	left = KMDB_PROM_READBUF_SIZE - kmdb_prom_readbuf_head;
228 	if (kmdb_prom_readbuf_tail == 0)
229 		left--;
230 
231 	if (kmdb_prom_readbuf_head == kmdb_prom_readbuf_tail ||
232 	    (kmdb_prom_readbuf_head > kmdb_prom_readbuf_tail && left > 0)) {
233 		/*
234 		 * head > tail, so we have to read in two parts - the slots
235 		 * from head until we wrap back around to zero, and the ones
236 		 * from zero to tail.  We handle the first part here, and let
237 		 * the common code handle the second.
238 		 */
239 		if ((n = kmdb_prom_reader(kmdb_prom_readbuf +
240 		    kmdb_prom_readbuf_head, left)) <= 0)
241 			return;
242 
243 		oldhead = kmdb_prom_readbuf_head;
244 		kmdb_prom_readbuf_head = (kmdb_prom_readbuf_head + n) %
245 		    KMDB_PROM_READBUF_SIZE;
246 
247 		check_int(kmdb_prom_readbuf + oldhead, n);
248 
249 		if (n != left)
250 			return;
251 	}
252 
253 	left = kmdb_prom_readbuf_tail - kmdb_prom_readbuf_head - 1;
254 	if (left > 0) {
255 		if ((n = kmdb_prom_reader(kmdb_prom_readbuf +
256 		    kmdb_prom_readbuf_head, left)) <= 0)
257 			return;
258 
259 		oldhead = kmdb_prom_readbuf_head;
260 		kmdb_prom_readbuf_head = (kmdb_prom_readbuf_head + n) %
261 		    KMDB_PROM_READBUF_SIZE;
262 
263 		check_int(kmdb_prom_readbuf + oldhead, n);
264 
265 		if (n != left)
266 			return;
267 	}
268 
269 	if (lossy) {
270 		char c;
271 
272 		while (kmdb_prom_reader(&c, 1) == 1)
273 			check_int(&c, 1);
274 	}
275 }
276 
277 void
278 kmdb_prom_check_interrupt(void)
279 {
280 	kmdb_prom_fill_readbuf(1);
281 }
282 
283 /*
284  * OBP reads are always non-blocking.  If there are characters available,
285  * we'll return as many as we can.  If nothing is available, we'll spin
286  * until one shows up.
287  */
288 ssize_t
289 kmdb_prom_read(void *buf, size_t len, struct termios *tio)
290 {
291 	size_t totread = 0;
292 	size_t thisread;
293 	char *c = (char *)buf;
294 
295 	for (;;) {
296 		kmdb_prom_fill_readbuf(0);
297 		thisread = kmdb_prom_drain_readbuf(c, len);
298 		len -= thisread;
299 		totread += thisread;
300 		c += thisread;
301 
302 		/* wait until something shows up */
303 		if (totread == 0)
304 			continue;
305 
306 		/*
307 		 * We're done if we've exhausted available input or if we've
308 		 * filled the provided buffer.
309 		 */
310 		if (len == 0 || thisread == 0)
311 			break;
312 	}
313 
314 	if (tio->c_iflag & ICRNL) {
315 		char *cbuf = buf;
316 		int i;
317 
318 		for (i = 0; i < totread; i++) {
319 			if (cbuf[i] == '\r')
320 				cbuf[i] = '\n';
321 		}
322 	}
323 
324 	if (tio->c_lflag & ECHO)
325 		(void) kmdb_prom_write(buf, totread, tio);
326 
327 	return (totread);
328 }
329 
330 /*ARGSUSED*/
331 ssize_t
332 kmdb_prom_write(const void *bufp, size_t len, struct termios *tio)
333 {
334 	caddr_t buf = (caddr_t)bufp;
335 	size_t left = len;
336 	char *nl = "\r\n";
337 	char *c;
338 
339 	kmdb_prom_check_interrupt();
340 
341 	if (!(tio->c_oflag & ONLCR))
342 		return (kmdb_prom_writer(buf, left));
343 
344 	/* translate every \n into \r\n */
345 	while ((c = strnchr(buf, '\n', left)) != NULL) {
346 		if (c != buf) {
347 			size_t sz = (size_t)(c - buf);
348 			(void) kmdb_prom_writer(buf, sz);
349 			left -= sz;
350 		}
351 
352 		buf = c + 1;
353 		left--;
354 
355 		(void) kmdb_prom_writer(nl, 2);
356 	}
357 
358 	if (*buf != '\0')
359 		(void) kmdb_prom_writer(buf, left);
360 
361 	return (len);
362 }
363 
364 static char *
365 kmdb_get_ttyio_mode(kmdb_auxv_t *kav, char *devname)
366 {
367 	char *modepname, *modepval;
368 
369 	modepname = mdb_alloc(strlen(devname) + 5 + 1, UM_SLEEP);
370 	strcpy(modepname, devname);
371 	strcat(modepname, "-mode");
372 
373 	modepval = kmdb_prom_get_ddi_prop(kav, modepname);
374 
375 	strfree(modepname);
376 
377 	return (modepval);
378 }
379 
380 static int
381 termios_setispeed(struct termios *tip, speed_t s)
382 {
383 	if (s > (2 * CBAUD + 1))
384 		return (-1);
385 
386 	if ((s << IBSHIFT) > CIBAUD) {
387 		tip->c_cflag |= CIBAUDEXT;
388 		s -= ((CIBAUD >> IBSHIFT) + 1);
389 	} else
390 		tip->c_cflag &= ~CIBAUDEXT;
391 
392 	tip->c_cflag = (tip->c_cflag & ~CIBAUD) | ((s << IBSHIFT) & CIBAUD);
393 
394 	return (0);
395 }
396 
397 static int
398 termios_setospeed(struct termios *tip, speed_t s)
399 {
400 	if (s > (2 * CBAUD + 1))
401 		return (-1);
402 
403 	if (s > CBAUD) {
404 		tip->c_cflag |= CBAUDEXT;
405 		s -= (CBAUD + 1);
406 	} else
407 		tip->c_cflag &= ~CBAUDEXT;
408 
409 	tip->c_cflag = (tip->c_cflag & ~CBAUD) | (s & CBAUD);
410 
411 	return (0);
412 }
413 
414 static int
415 kmdb_parse_mode(const char *mode, struct termios *tip, int in)
416 {
417 	static const uint_t baudmap[] = {
418 		0, 50, 75, 110, 134, 150, 200, 300, 600, 1200,
419 		1800, 2400, 4800, 9600, 19200, 38400, 57600,
420 		76800, 115200, 153600, 230400, 307200, 460800
421 	};
422 	static const uint_t bitsmap[] = { CS6, CS6, CS7, CS8 };
423 	char *m = strdup(mode);
424 	char *w;
425 	int rc = -1;
426 	speed_t speed;
427 	int baud, i;
428 
429 	/*
430 	 * termios supports different baud rates and flow control types for
431 	 * input and output, but it requires character width, parity, and stop
432 	 * bits to be equal in input and output.  obp allows them to be
433 	 * different, but we're going to (silently) assume that nobody will use
434 	 * it that way.
435 	 */
436 
437 	/* baud rate - see baudmap above */
438 	if ((w = strtok(m, ",")) == NULL)
439 		goto parse_mode_bail;
440 
441 	baud = strtol(w, NULL, 10);
442 	speed = 0;
443 	for (i = 0; i < sizeof (baudmap) / sizeof (baudmap[0]); i++) {
444 		if (baudmap[i] == baud) {
445 			speed = i;
446 			break;
447 		}
448 	}
449 	if (speed == 0)
450 		goto parse_mode_bail;
451 
452 	if (in == 1)
453 		(void) termios_setispeed(tip, speed);
454 	else
455 		(void) termios_setospeed(tip, speed);
456 
457 	/* character width (bits) - 5, 6, 7, or 8 */
458 	if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 || *w < '5' ||
459 	    *w > '8')
460 		goto parse_mode_bail;
461 	tip->c_cflag = (tip->c_cflag & ~CSIZE) | bitsmap[*w - '5'];
462 
463 	/* parity - `n' (none), `e' (even), or `o' (odd) */
464 	if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 ||
465 	    strchr("neo", *w) == NULL)
466 		goto parse_mode_bail;
467 
468 	tip->c_cflag = (tip->c_cflag & ~(PARENB|PARODD));
469 	switch (*w) {
470 	case 'n':
471 		/* nothing */
472 		break;
473 	case 'e':
474 		tip->c_cflag |= PARENB;
475 		break;
476 	case 'o':
477 		tip->c_cflag |= PARENB|PARODD;
478 		break;
479 	}
480 
481 	/*
482 	 * stop bits - 1, or 2.  obp can, in theory, support 1.5 bits,
483 	 * but we can't.  how many angels can dance on half of a bit?
484 	 */
485 	if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 || *w < '1' ||
486 	    *w > '2')
487 		goto parse_mode_bail;
488 
489 	if (*w == '1')
490 		tip->c_cflag &= ~CSTOPB;
491 	else
492 		tip->c_cflag |= CSTOPB;
493 
494 	/* flow control - `-' (none), `h' (h/w), or `s' (s/w - XON/XOFF) */
495 	if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 ||
496 	    strchr("-hs", *w) == NULL)
497 		goto parse_mode_bail;
498 
499 	tip->c_cflag &= ~(CRTSXOFF|CRTSCTS);
500 	tip->c_iflag &= ~(IXON|IXANY|IXOFF);
501 
502 	switch (*w) {
503 	case 'h':
504 		tip->c_cflag |= (in == 1 ? CRTSXOFF : CRTSCTS);
505 		break;
506 
507 	case 's':
508 		tip->c_iflag |= (in == 1 ? IXOFF : IXON);
509 		break;
510 	}
511 
512 	rc = 0;
513 
514 parse_mode_bail:
515 	strfree(m);
516 
517 	return (rc);
518 }
519 
520 #ifdef __sparc
521 #define	ATTACHED_TERM_TYPE	"sun"
522 #else
523 #define	ATTACHED_TERM_TYPE	"sun-color"
524 #endif
525 
526 static void
527 kmdb_prom_term_init(kmdb_auxv_t *kav, kmdb_promif_t *pif)
528 {
529 	const char ccs[NCCS] = { 0x03, 0x1c, 0x08, 0x15, 0x04, 0x00, 0x00,
530 	    0x00, 0x11, 0x13, 0x1a, 0x19, 0x12, 0x0f, 0x17, 0x16 };
531 	char *conin = NULL, *conout = NULL;
532 
533 	if (kmdb_prom_stdout_is_framebuffer(kav))
534 		pif->pif_oterm = ATTACHED_TERM_TYPE;
535 
536 	bzero(&pif->pif_tios, sizeof (struct termios));
537 
538 	/* output device characteristics */
539 	if ((conout = kmdb_prom_get_ddi_prop(kav, "output-device")) ==
540 	    NULL || strcmp(conout, "screen") == 0) {
541 		(void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
542 		    &pif->pif_tios, 0);
543 	} else if (*conout == '/') {
544 		/*
545 		 * We're not going to be able to get characteristics for a
546 		 * device that's specified as a path, so don't even try.
547 		 * Conveniently, this allows us to avoid chattering on
548 		 * Serengetis.
549 		 */
550 		(void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
551 		    &pif->pif_tios, 0);
552 	} else {
553 		char *mode = kmdb_get_ttyio_mode(kav, conout);
554 
555 #ifdef __sparc
556 		/*
557 		 * Some platforms (Starfire) define a value of `ttya' for
558 		 * output-device, but neglect to provide a specific property
559 		 * with the characteristics.  We'll provide a default value.
560 		 */
561 		if (mode == NULL && strcmp(conout, "ttya") == 0) {
562 			(void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
563 			    &pif->pif_tios, 0);
564 		} else
565 #endif
566 		{
567 			if (mode == NULL || kmdb_parse_mode(mode,
568 			    &pif->pif_tios, 0) < 0) {
569 				/*
570 				 * Either we couldn't retrieve the
571 				 * characteristics for this console, or they
572 				 * weren't parseable.  The console hasn't been
573 				 * set up yet, so we can't warn.  We'll have to
574 				 * silently fall back to the default
575 				 * characteristics.
576 				 */
577 				(void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
578 				    &pif->pif_tios, 0);
579 			}
580 		}
581 
582 		if (mode != NULL)
583 			kmdb_prom_free_ddi_prop(mode);
584 	}
585 
586 	/* input device characteristics */
587 	if ((conin = kmdb_prom_get_ddi_prop(kav, "input-device")) == NULL ||
588 	    strcmp(conin, "keyboard") == 0) {
589 		(void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
590 		    &pif->pif_tios, 1);
591 	} else if (*conin == '/') {
592 		/* See similar case in output-device above */
593 		(void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
594 		    &pif->pif_tios, 1);
595 	} else {
596 		char *mode = kmdb_get_ttyio_mode(kav, conin);
597 
598 #ifdef __sparc
599 		/*
600 		 * Some platforms (Starfire) define a value of `ttya' for
601 		 * input-device, but neglect to provide a specific property
602 		 * with the characteristics.  We'll provide a default value.
603 		 */
604 		if (mode == NULL && strcmp(conin, "ttya") == 0) {
605 			(void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
606 			    &pif->pif_tios, 1);
607 		} else
608 #endif
609 		{
610 			if (mode == NULL || kmdb_parse_mode(mode,
611 			    &pif->pif_tios, 1) < 0) {
612 				/*
613 				 * Either we couldn't retrieve the
614 				 * characteristics for this console, or they
615 				 * weren't parseable.  The console hasn't been
616 				 * set up yet, so we can't warn.  We'll have to
617 				 * silently fall back to the default
618 				 * characteristics.
619 				 */
620 				(void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE,
621 				    &pif->pif_tios, 1);
622 			}
623 		}
624 
625 		if (mode != NULL)
626 			kmdb_prom_free_ddi_prop(mode);
627 	}
628 
629 	/* various characteristics of the prom read/write interface */
630 	pif->pif_tios.c_iflag |= ICRNL;
631 	pif->pif_tios.c_lflag |= ECHO;
632 	bcopy(ccs, &pif->pif_tios.c_cc, sizeof (ccs));
633 
634 	if (conin != NULL)
635 		kmdb_prom_free_ddi_prop(conin);
636 	if (conout != NULL)
637 		kmdb_prom_free_ddi_prop(conout);
638 }
639 
640 char *
641 kmdb_prom_term_type(void)
642 {
643 	return (mdb.m_promif->pif_oterm);
644 }
645 
646 int
647 kmdb_prom_term_ctl(int req, void *arg)
648 {
649 	switch (req) {
650 	case TCGETS: {
651 		struct termios *ti = arg;
652 		bcopy(&mdb.m_promif->pif_tios, ti, sizeof (struct termios));
653 		return (0);
654 	}
655 	case TIOCGWINSZ:
656 		/*
657 		 * When kmdb is used over a serial console, we have no idea how
658 		 * large the terminal window is.  When we're invoked on a local
659 		 * console, however, we do, and need to share that information
660 		 * with the debugger in order to contradict potentially
661 		 * incorrect sizing information retrieved from the terminfo
662 		 * database.  One specific case where this happens is with the
663 		 * Intel console, which is 80x25.  The terminfo entry for
664 		 * sun-color -- the default terminal type for local Intel
665 		 * consoles -- was cloned from sun, which has a height of 34
666 		 * rows.
667 		 */
668 		if (mdb.m_promif->pif_oterm != NULL) {
669 			struct winsize *wsz = arg;
670 			wsz->ws_row = KMDB_PIF_WINSIZE_ROWS;
671 			wsz->ws_col = KMDB_PIF_WINSIZE_COLS;
672 			wsz->ws_xpixel = wsz->ws_ypixel = 0;
673 			return (0);
674 		}
675 
676 		return (set_errno(ENOTSUP));
677 	default:
678 		return (set_errno(EINVAL));
679 	}
680 }
681 
682 int
683 kmdb_prom_vtop(uintptr_t virt, physaddr_t *pap)
684 {
685 	physaddr_t pa;
686 	int rc = kmdb_kdi_vtop(virt, &pa);
687 
688 #ifdef	__sparc
689 	if (rc < 0 && errno == EAGAIN)
690 		rc = kmdb_prom_translate_virt(virt, &pa);
691 #endif
692 
693 	if (rc == 0 && pap != NULL)
694 		*pap = pa;
695 
696 	return (rc);
697 }
698 
699 void
700 kmdb_prom_debugger_entry(void)
701 {
702 	/*
703 	 * While kmdb_prom_debugger_entry and kmdb_prom_debugger_exit are not
704 	 * guaranteed to be called an identical number of times (an intentional
705 	 * debugger fault will cause an additional entry call without a matching
706 	 * exit call), we must ensure that the polled I/O entry and exit calls
707 	 * match.
708 	 */
709 	if (mdb.m_pio == NULL) {
710 		mdb.m_pio = kmdb_kdi_get_polled_io();
711 
712 		if (mdb.m_pio != NULL &&
713 		    mdb.m_pio->cons_polledio_enter != NULL) {
714 			(void) kmdb_dpi_call(
715 			    (uintptr_t)mdb.m_pio->cons_polledio_enter, 1,
716 			    (uintptr_t *)&mdb.m_pio->cons_polledio_argument);
717 		}
718 	}
719 }
720 
721 void
722 kmdb_prom_debugger_exit(void)
723 {
724 	if (mdb.m_pio != NULL && mdb.m_pio->cons_polledio_exit != NULL) {
725 		(void) kmdb_dpi_call((uintptr_t)mdb.m_pio->cons_polledio_exit,
726 		    1, (uintptr_t *)&mdb.m_pio->cons_polledio_argument);
727 	}
728 
729 	mdb.m_pio = NULL;
730 }
731 
732 #ifdef DEBUG
733 /*
734  * The prom_* files use ASSERT, which is #defined as assfail().
735  * We need to redirect that to our assert function.
736  */
737 int
738 kmdb_prom_assfail(const char *assertion, const char *file, int line)
739 {
740 	(void) mdb_dassert(assertion, file, line);
741 	/*NOTREACHED*/
742 	return (0);
743 }
744 #endif
745 
746 /*
747  * Begin the initialization of the debugger/PROM interface.  Initialization is
748  * performed in two steps due to interlocking dependencies between promif and
749  * both the memory allocator and mdb_create.  The first phase is performed
750  * before either of the others have been initialized, and thus must neither
751  * attempt to allocate memory nor access/write to `mdb'.
752  */
753 void
754 kmdb_prom_init_begin(char *pgmname, kmdb_auxv_t *kav)
755 {
756 	prom_init(pgmname, kav->kav_romp);
757 
758 	/* Initialize the interrupt ring buffer */
759 	kmdb_prom_readbuf_head = kmdb_prom_readbuf_tail;
760 
761 #if defined(__i386) || defined(__amd64)
762 	kmdb_sysp = kav->kav_romp;
763 #endif
764 }
765 
766 /*
767  * Conclude the initialization of the debugger/PROM interface.  Memory
768  * allocation and the global `mdb' object are now available.
769  */
770 void
771 kmdb_prom_init_finish(kmdb_auxv_t *kav)
772 {
773 	mdb.m_promif = mdb_zalloc(sizeof (kmdb_promif_t), UM_SLEEP);
774 	kmdb_prom_term_init(kav, mdb.m_promif);
775 }
776