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