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
kmdb_prom_getchar(int wait)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
kmdb_prom_polled_write(caddr_t buf,size_t len)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
kmdb_prom_reader(caddr_t buf,size_t len,int wait)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
kmdb_prom_writer(caddr_t buf,size_t len)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
kmdb_prom_drain_readbuf(void * buf,size_t len)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
check_int(char * buf,size_t len)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
kmdb_prom_fill_readbuf(int check_for_int,int wait)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
kmdb_prom_check_interrupt(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
kmdb_prom_read(void * buf,size_t len,struct termios * tio)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
kmdb_prom_write(const void * bufp,size_t len,struct termios * tio)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 *
kmdb_get_ttyio_mode(kmdb_auxv_t * kav,char * devname)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
termios_setispeed(struct termios * tip,speed_t s)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
termios_setospeed(struct termios * tip,speed_t s)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
kmdb_parse_mode(const char * mode,struct termios * tip,int in)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
kmdb_prom_term_init(kmdb_auxv_t * kav,kmdb_promif_t * pif)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 *
kmdb_prom_term_type(void)664 kmdb_prom_term_type(void)
665 {
666 return (mdb.m_promif->pif_oterm);
667 }
668
669 int
kmdb_prom_term_ctl(int req,void * arg)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
kmdb_prom_vtop(uintptr_t virt,physaddr_t * pap)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
kmdb_prom_debugger_entry(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
kmdb_prom_debugger_exit(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
kmdb_prom_assfail(const char * assertion,const char * file,int line)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
kmdb_prom_init_begin(char * pgmname,kmdb_auxv_t * kav)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
kmdb_prom_init_promif(char * pgmname,kmdb_auxv_t * kav)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
kmdb_prom_init_finish(kmdb_auxv_t * kav)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