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