17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5c7d88479Slq150181 * Common Development and Distribution License (the "License"). 6c7d88479Slq150181 * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 21de81e71eSTim Marsland 227c478bd9Sstevel@tonic-gate /* 23de81e71eSTim Marsland * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 247c478bd9Sstevel@tonic-gate * Use is subject to license terms. 257c478bd9Sstevel@tonic-gate */ 267c478bd9Sstevel@tonic-gate 277c478bd9Sstevel@tonic-gate #include <sys/types.h> 287c478bd9Sstevel@tonic-gate #include <sys/termios.h> 297c478bd9Sstevel@tonic-gate #include <sys/promif.h> 301ae08745Sheppo #ifdef sun4v 311ae08745Sheppo #include <sys/promif_impl.h> 321ae08745Sheppo #endif 337c478bd9Sstevel@tonic-gate #include <unistd.h> 347c478bd9Sstevel@tonic-gate #include <string.h> 357c478bd9Sstevel@tonic-gate #include <stdlib.h> 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate #include <kmdb/kmdb_promif_impl.h> 387c478bd9Sstevel@tonic-gate #include <kmdb/kmdb_kdi.h> 397c478bd9Sstevel@tonic-gate #include <kmdb/kmdb_dpi.h> 407c478bd9Sstevel@tonic-gate #include <mdb/mdb_debug.h> 417c478bd9Sstevel@tonic-gate #include <mdb/mdb_err.h> 427c478bd9Sstevel@tonic-gate #include <mdb/mdb_frame.h> 437c478bd9Sstevel@tonic-gate #include <mdb/mdb_string.h> 447c478bd9Sstevel@tonic-gate #include <mdb/mdb.h> 457c478bd9Sstevel@tonic-gate 467c478bd9Sstevel@tonic-gate #define KMDB_PROM_DEF_CONS_MODE "9600,n,1,-,-" 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate #define KMDB_PROM_READBUF_SIZE 1024 497c478bd9Sstevel@tonic-gate 507c478bd9Sstevel@tonic-gate static char kmdb_prom_readbuf[KMDB_PROM_READBUF_SIZE]; 517c478bd9Sstevel@tonic-gate static int kmdb_prom_readbuf_head; 527c478bd9Sstevel@tonic-gate static int kmdb_prom_readbuf_tail; 537c478bd9Sstevel@tonic-gate 54ae115bc7Smrj static int 55ae115bc7Smrj kmdb_prom_getchar(int wait) 567c478bd9Sstevel@tonic-gate { 57ae115bc7Smrj struct cons_polledio *pio = mdb.m_pio; 58ae115bc7Smrj uintptr_t ischar; 59ae115bc7Smrj uintptr_t getchar; 60ae115bc7Smrj uintptr_t arg; 61ae115bc7Smrj 62ae115bc7Smrj if (pio == NULL || pio->cons_polledio_getchar == NULL) { 637c478bd9Sstevel@tonic-gate int c; 64ae115bc7Smrj while ((c = prom_mayget()) == -1) { 65ae115bc7Smrj if (!wait) 66ae115bc7Smrj return (-1); 67ae115bc7Smrj } 68ae115bc7Smrj return (c); 697c478bd9Sstevel@tonic-gate } 707c478bd9Sstevel@tonic-gate 71ae115bc7Smrj ischar = (uintptr_t)pio->cons_polledio_ischar; 72ae115bc7Smrj getchar = (uintptr_t)pio->cons_polledio_getchar; 73ae115bc7Smrj arg = (uintptr_t)pio->cons_polledio_argument; 74ae115bc7Smrj 75ae115bc7Smrj if (!wait && ischar != NULL && !kmdb_dpi_call(ischar, 1, &arg)) 76ae115bc7Smrj return (-1); 77ae115bc7Smrj 78ae115bc7Smrj return ((int)kmdb_dpi_call(getchar, 1, &arg)); 797c478bd9Sstevel@tonic-gate } 807c478bd9Sstevel@tonic-gate 81c7bf3205Sjohnlev static ssize_t 827c478bd9Sstevel@tonic-gate kmdb_prom_polled_write(caddr_t buf, size_t len) 837c478bd9Sstevel@tonic-gate { 847c478bd9Sstevel@tonic-gate uintptr_t args[2]; 857c478bd9Sstevel@tonic-gate int i; 867c478bd9Sstevel@tonic-gate 877c478bd9Sstevel@tonic-gate args[0] = (uintptr_t)mdb.m_pio->cons_polledio_argument; 887c478bd9Sstevel@tonic-gate 897c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) { 907c478bd9Sstevel@tonic-gate args[1] = *buf++; 917c478bd9Sstevel@tonic-gate (void) kmdb_dpi_call( 927c478bd9Sstevel@tonic-gate (uintptr_t)mdb.m_pio->cons_polledio_putchar, 2, args); 937c478bd9Sstevel@tonic-gate } 947c478bd9Sstevel@tonic-gate 957c478bd9Sstevel@tonic-gate return (len); 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate static ssize_t 99ae115bc7Smrj kmdb_prom_reader(caddr_t buf, size_t len, int wait) 1007c478bd9Sstevel@tonic-gate { 1017c478bd9Sstevel@tonic-gate int nread = 0; 1027c478bd9Sstevel@tonic-gate int c; 1037c478bd9Sstevel@tonic-gate 104ae115bc7Smrj while (nread < len) { 105ae115bc7Smrj if ((c = kmdb_prom_getchar(wait)) == -1) 106ae115bc7Smrj break; 1077c478bd9Sstevel@tonic-gate 1087c478bd9Sstevel@tonic-gate *buf++ = (char)c; 1097c478bd9Sstevel@tonic-gate nread++; 110ae115bc7Smrj wait = 0; 1117c478bd9Sstevel@tonic-gate } 1127c478bd9Sstevel@tonic-gate 1137c478bd9Sstevel@tonic-gate return (nread); 1147c478bd9Sstevel@tonic-gate } 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate static ssize_t 1177c478bd9Sstevel@tonic-gate kmdb_prom_writer(caddr_t buf, size_t len) 1187c478bd9Sstevel@tonic-gate { 1197c478bd9Sstevel@tonic-gate if (mdb.m_pio != NULL && mdb.m_pio->cons_polledio_putchar != NULL) 1207c478bd9Sstevel@tonic-gate return (kmdb_prom_polled_write(buf, len)); 1217c478bd9Sstevel@tonic-gate 1227c478bd9Sstevel@tonic-gate return (kmdb_prom_obp_writer(buf, len)); 1237c478bd9Sstevel@tonic-gate } 1247c478bd9Sstevel@tonic-gate 1257c478bd9Sstevel@tonic-gate /* 1267c478bd9Sstevel@tonic-gate * Due to the nature of kmdb, we don't have signals. This prevents us from 127c7bf3205Sjohnlev * receiving asynchronous notification when the user would like to abort active 128c7bf3205Sjohnlev * dcmds. Whereas mdb can simply declare a SIGINT handler, we must 1297c478bd9Sstevel@tonic-gate * occasionally poll the input stream, looking for pending ^C characters. To 1307c478bd9Sstevel@tonic-gate * give the illusion of asynchronous interrupt delivery, this polling is 131c7bf3205Sjohnlev * triggered from several commonly-used functions, such as kmdb_prom_write and 132c7bf3205Sjohnlev * the *read and *write target ops. When an interrupt check is triggered, we 133c7bf3205Sjohnlev * read through pending input, looking for interrupt characters. If we find 134c7bf3205Sjohnlev * one, we deliver an interrupt immediately. 135c7bf3205Sjohnlev * 136c7bf3205Sjohnlev * In a read context, we can deliver the interrupt character directly back to 137c7bf3205Sjohnlev * the termio handler rather than raising an interrupt. 1387c478bd9Sstevel@tonic-gate * 1397c478bd9Sstevel@tonic-gate * OBP doesn't have an "unget" facility. Any character read for interrupt 1407c478bd9Sstevel@tonic-gate * checking is gone forever, unless we save it. Loss of these characters 1417c478bd9Sstevel@tonic-gate * would prevent us from supporting typeahead. We like typeahead, so we're 1427c478bd9Sstevel@tonic-gate * going to save characters gathered during interrupt checking. As with 1437c478bd9Sstevel@tonic-gate * ungetc(3c), however, we can only store a finite number of characters in 1447c478bd9Sstevel@tonic-gate * our typeahead buffer. Characters read beyond that will be silently dropped 1457c478bd9Sstevel@tonic-gate * after they undergo interrupt processing. 1467c478bd9Sstevel@tonic-gate * 1477c478bd9Sstevel@tonic-gate * The typeahead facility is implemented as a ring buffer, stored in 148c7bf3205Sjohnlev * kmdb_prom_readbuf. 1497c478bd9Sstevel@tonic-gate */ 150c7bf3205Sjohnlev static size_t 1517c478bd9Sstevel@tonic-gate kmdb_prom_drain_readbuf(void *buf, size_t len) 1527c478bd9Sstevel@tonic-gate { 1537c478bd9Sstevel@tonic-gate size_t n, tailread; 1547c478bd9Sstevel@tonic-gate 1557c478bd9Sstevel@tonic-gate /* 1567c478bd9Sstevel@tonic-gate * If head > tail, life is easy - we can simply read as much as we need 1577c478bd9Sstevel@tonic-gate * in one gulp. 1587c478bd9Sstevel@tonic-gate */ 1597c478bd9Sstevel@tonic-gate if (kmdb_prom_readbuf_head > kmdb_prom_readbuf_tail) { 1607c478bd9Sstevel@tonic-gate n = MIN(kmdb_prom_readbuf_head - kmdb_prom_readbuf_tail, len); 1617c478bd9Sstevel@tonic-gate bcopy(kmdb_prom_readbuf + kmdb_prom_readbuf_tail, buf, n); 1627c478bd9Sstevel@tonic-gate kmdb_prom_readbuf_tail += n; 1637c478bd9Sstevel@tonic-gate return (n); 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate } else if (kmdb_prom_readbuf_head == kmdb_prom_readbuf_tail) { 1667c478bd9Sstevel@tonic-gate return (0); 1677c478bd9Sstevel@tonic-gate } 1687c478bd9Sstevel@tonic-gate 1697c478bd9Sstevel@tonic-gate /* 1707c478bd9Sstevel@tonic-gate * The consumable slots wrap around zero (there are slots from tail to 1717c478bd9Sstevel@tonic-gate * zero, and from zero to head). We have to read them in two parts. 1727c478bd9Sstevel@tonic-gate */ 1737c478bd9Sstevel@tonic-gate n = MIN(KMDB_PROM_READBUF_SIZE - kmdb_prom_readbuf_tail, len); 1747c478bd9Sstevel@tonic-gate bcopy(kmdb_prom_readbuf + kmdb_prom_readbuf_tail, buf, n); 1757c478bd9Sstevel@tonic-gate kmdb_prom_readbuf_tail = (kmdb_prom_readbuf_tail + n) % 1767c478bd9Sstevel@tonic-gate KMDB_PROM_READBUF_SIZE; 1777c478bd9Sstevel@tonic-gate 1787c478bd9Sstevel@tonic-gate if (n == len) { 1797c478bd9Sstevel@tonic-gate /* 1807c478bd9Sstevel@tonic-gate * We filled the passed buffer from the first part, so there's 1817c478bd9Sstevel@tonic-gate * no need to read the second. 1827c478bd9Sstevel@tonic-gate */ 1837c478bd9Sstevel@tonic-gate return (n); 1847c478bd9Sstevel@tonic-gate } else { 1857c478bd9Sstevel@tonic-gate tailread = n; 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate n = MIN(kmdb_prom_readbuf_head, len - tailread); 1897c478bd9Sstevel@tonic-gate buf = (void *)((uintptr_t)buf + tailread); 1907c478bd9Sstevel@tonic-gate bcopy(kmdb_prom_readbuf, buf, n); 1917c478bd9Sstevel@tonic-gate 1927c478bd9Sstevel@tonic-gate kmdb_prom_readbuf_tail = (kmdb_prom_readbuf_tail + n) % 1937c478bd9Sstevel@tonic-gate KMDB_PROM_READBUF_SIZE; 1947c478bd9Sstevel@tonic-gate 1957c478bd9Sstevel@tonic-gate return (tailread + n); 1967c478bd9Sstevel@tonic-gate } 1977c478bd9Sstevel@tonic-gate 1987c478bd9Sstevel@tonic-gate static void 1997c478bd9Sstevel@tonic-gate check_int(char *buf, size_t len) 2007c478bd9Sstevel@tonic-gate { 2017c478bd9Sstevel@tonic-gate int i; 2027c478bd9Sstevel@tonic-gate 2037c478bd9Sstevel@tonic-gate for (i = 0; i < len; i++) { 204c7bf3205Sjohnlev if (buf[i] == CTRL('c')) { 2057c478bd9Sstevel@tonic-gate kmdb_prom_readbuf_tail = kmdb_prom_readbuf_head; 2067c478bd9Sstevel@tonic-gate if (mdb.m_intr == 0) 2077c478bd9Sstevel@tonic-gate longjmp(mdb.m_frame->f_pcb, MDB_ERR_SIGINT); 2087c478bd9Sstevel@tonic-gate else 2097c478bd9Sstevel@tonic-gate mdb.m_pend++; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate 214c7bf3205Sjohnlev /* 215c7bf3205Sjohnlev * Attempt to refill the ring buffer from the input stream. This called from 216c7bf3205Sjohnlev * two contexts: 217c7bf3205Sjohnlev * 218c7bf3205Sjohnlev * Direct read: read the input into our buffer until input is exhausted, or the 219c7bf3205Sjohnlev * buffer is full. 220c7bf3205Sjohnlev * 221c7bf3205Sjohnlev * Interrupt check: called 'asynchronously' from the normal read routines; read 222c7bf3205Sjohnlev * the input into our buffer until it is exhausted, discarding input if the 223c7bf3205Sjohnlev * buffer is full. In this case we look ahead for any interrupt characters, 224c7bf3205Sjohnlev * delivering an interrupt directly if we find one. 225c7bf3205Sjohnlev */ 226c7bf3205Sjohnlev static void 227ae115bc7Smrj kmdb_prom_fill_readbuf(int check_for_int, int wait) 2287c478bd9Sstevel@tonic-gate { 2297c478bd9Sstevel@tonic-gate int oldhead, left, n; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate /* 2327c478bd9Sstevel@tonic-gate * Calculate the number of slots left before we wrap around to the 2337c478bd9Sstevel@tonic-gate * beginning again. 2347c478bd9Sstevel@tonic-gate */ 2357c478bd9Sstevel@tonic-gate left = KMDB_PROM_READBUF_SIZE - kmdb_prom_readbuf_head; 2367c478bd9Sstevel@tonic-gate if (kmdb_prom_readbuf_tail == 0) 2377c478bd9Sstevel@tonic-gate left--; 2387c478bd9Sstevel@tonic-gate 2397c478bd9Sstevel@tonic-gate if (kmdb_prom_readbuf_head == kmdb_prom_readbuf_tail || 2407c478bd9Sstevel@tonic-gate (kmdb_prom_readbuf_head > kmdb_prom_readbuf_tail && left > 0)) { 2417c478bd9Sstevel@tonic-gate /* 2427c478bd9Sstevel@tonic-gate * head > tail, so we have to read in two parts - the slots 2437c478bd9Sstevel@tonic-gate * from head until we wrap back around to zero, and the ones 2447c478bd9Sstevel@tonic-gate * from zero to tail. We handle the first part here, and let 2457c478bd9Sstevel@tonic-gate * the common code handle the second. 2467c478bd9Sstevel@tonic-gate */ 2477c478bd9Sstevel@tonic-gate if ((n = kmdb_prom_reader(kmdb_prom_readbuf + 248ae115bc7Smrj kmdb_prom_readbuf_head, left, wait)) <= 0) 2497c478bd9Sstevel@tonic-gate return; 2507c478bd9Sstevel@tonic-gate 2517c478bd9Sstevel@tonic-gate oldhead = kmdb_prom_readbuf_head; 2527c478bd9Sstevel@tonic-gate kmdb_prom_readbuf_head = (kmdb_prom_readbuf_head + n) % 2537c478bd9Sstevel@tonic-gate KMDB_PROM_READBUF_SIZE; 2547c478bd9Sstevel@tonic-gate 255c7bf3205Sjohnlev if (check_for_int) 2567c478bd9Sstevel@tonic-gate check_int(kmdb_prom_readbuf + oldhead, n); 2577c478bd9Sstevel@tonic-gate 2587c478bd9Sstevel@tonic-gate if (n != left) 2597c478bd9Sstevel@tonic-gate return; 2607c478bd9Sstevel@tonic-gate } 2617c478bd9Sstevel@tonic-gate 2627c478bd9Sstevel@tonic-gate left = kmdb_prom_readbuf_tail - kmdb_prom_readbuf_head - 1; 2637c478bd9Sstevel@tonic-gate if (left > 0) { 2647c478bd9Sstevel@tonic-gate if ((n = kmdb_prom_reader(kmdb_prom_readbuf + 265ae115bc7Smrj kmdb_prom_readbuf_head, left, wait)) <= 0) 2667c478bd9Sstevel@tonic-gate return; 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate oldhead = kmdb_prom_readbuf_head; 2697c478bd9Sstevel@tonic-gate kmdb_prom_readbuf_head = (kmdb_prom_readbuf_head + n) % 2707c478bd9Sstevel@tonic-gate KMDB_PROM_READBUF_SIZE; 2717c478bd9Sstevel@tonic-gate 272c7bf3205Sjohnlev if (check_for_int) 2737c478bd9Sstevel@tonic-gate check_int(kmdb_prom_readbuf + oldhead, n); 2747c478bd9Sstevel@tonic-gate 2757c478bd9Sstevel@tonic-gate if (n != left) 2767c478bd9Sstevel@tonic-gate return; 2777c478bd9Sstevel@tonic-gate } 2787c478bd9Sstevel@tonic-gate 279c7bf3205Sjohnlev if (check_for_int) { 2807c478bd9Sstevel@tonic-gate char c; 2817c478bd9Sstevel@tonic-gate 282ae115bc7Smrj while (kmdb_prom_reader(&c, 1, 0) == 1) 2837c478bd9Sstevel@tonic-gate check_int(&c, 1); 2847c478bd9Sstevel@tonic-gate } 2857c478bd9Sstevel@tonic-gate } 2867c478bd9Sstevel@tonic-gate 2877c478bd9Sstevel@tonic-gate void 2887c478bd9Sstevel@tonic-gate kmdb_prom_check_interrupt(void) 2897c478bd9Sstevel@tonic-gate { 290ae115bc7Smrj kmdb_prom_fill_readbuf(1, 0); 2917c478bd9Sstevel@tonic-gate } 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate /* 2947c478bd9Sstevel@tonic-gate * OBP reads are always non-blocking. If there are characters available, 2957c478bd9Sstevel@tonic-gate * we'll return as many as we can. If nothing is available, we'll spin 2967c478bd9Sstevel@tonic-gate * until one shows up. 2977c478bd9Sstevel@tonic-gate */ 2987c478bd9Sstevel@tonic-gate ssize_t 2997c478bd9Sstevel@tonic-gate kmdb_prom_read(void *buf, size_t len, struct termios *tio) 3007c478bd9Sstevel@tonic-gate { 3017c478bd9Sstevel@tonic-gate size_t totread = 0; 3027c478bd9Sstevel@tonic-gate size_t thisread; 3037c478bd9Sstevel@tonic-gate char *c = (char *)buf; 304ae115bc7Smrj int wait = 1; 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate for (;;) { 307ae115bc7Smrj kmdb_prom_fill_readbuf(0, wait); 3087c478bd9Sstevel@tonic-gate thisread = kmdb_prom_drain_readbuf(c, len); 3097c478bd9Sstevel@tonic-gate len -= thisread; 3107c478bd9Sstevel@tonic-gate totread += thisread; 3117c478bd9Sstevel@tonic-gate c += thisread; 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate /* wait until something shows up */ 3147c478bd9Sstevel@tonic-gate if (totread == 0) 3157c478bd9Sstevel@tonic-gate continue; 3167c478bd9Sstevel@tonic-gate 317ae115bc7Smrj wait = 0; 318ae115bc7Smrj 3197c478bd9Sstevel@tonic-gate /* 3207c478bd9Sstevel@tonic-gate * We're done if we've exhausted available input or if we've 3217c478bd9Sstevel@tonic-gate * filled the provided buffer. 3227c478bd9Sstevel@tonic-gate */ 3237c478bd9Sstevel@tonic-gate if (len == 0 || thisread == 0) 3247c478bd9Sstevel@tonic-gate break; 3257c478bd9Sstevel@tonic-gate } 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate if (tio->c_iflag & ICRNL) { 3287c478bd9Sstevel@tonic-gate char *cbuf = buf; 3297c478bd9Sstevel@tonic-gate int i; 3307c478bd9Sstevel@tonic-gate 3317c478bd9Sstevel@tonic-gate for (i = 0; i < totread; i++) { 3327c478bd9Sstevel@tonic-gate if (cbuf[i] == '\r') 3337c478bd9Sstevel@tonic-gate cbuf[i] = '\n'; 3347c478bd9Sstevel@tonic-gate } 3357c478bd9Sstevel@tonic-gate } 3367c478bd9Sstevel@tonic-gate 3377c478bd9Sstevel@tonic-gate if (tio->c_lflag & ECHO) 3387c478bd9Sstevel@tonic-gate (void) kmdb_prom_write(buf, totread, tio); 3397c478bd9Sstevel@tonic-gate 3407c478bd9Sstevel@tonic-gate return (totread); 3417c478bd9Sstevel@tonic-gate } 3427c478bd9Sstevel@tonic-gate 3437c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3447c478bd9Sstevel@tonic-gate ssize_t 3457c478bd9Sstevel@tonic-gate kmdb_prom_write(const void *bufp, size_t len, struct termios *tio) 3467c478bd9Sstevel@tonic-gate { 3477c478bd9Sstevel@tonic-gate caddr_t buf = (caddr_t)bufp; 3487c478bd9Sstevel@tonic-gate size_t left = len; 3497c478bd9Sstevel@tonic-gate char *nl = "\r\n"; 3507c478bd9Sstevel@tonic-gate char *c; 3517c478bd9Sstevel@tonic-gate 3527c478bd9Sstevel@tonic-gate kmdb_prom_check_interrupt(); 3537c478bd9Sstevel@tonic-gate 3547c478bd9Sstevel@tonic-gate if (!(tio->c_oflag & ONLCR)) 3557c478bd9Sstevel@tonic-gate return (kmdb_prom_writer(buf, left)); 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate /* translate every \n into \r\n */ 3587c478bd9Sstevel@tonic-gate while ((c = strnchr(buf, '\n', left)) != NULL) { 3597c478bd9Sstevel@tonic-gate if (c != buf) { 3607c478bd9Sstevel@tonic-gate size_t sz = (size_t)(c - buf); 3617c478bd9Sstevel@tonic-gate (void) kmdb_prom_writer(buf, sz); 3627c478bd9Sstevel@tonic-gate left -= sz; 3637c478bd9Sstevel@tonic-gate } 3647c478bd9Sstevel@tonic-gate 3657c478bd9Sstevel@tonic-gate buf = c + 1; 3667c478bd9Sstevel@tonic-gate left--; 3677c478bd9Sstevel@tonic-gate 3687c478bd9Sstevel@tonic-gate (void) kmdb_prom_writer(nl, 2); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate if (*buf != '\0') 3727c478bd9Sstevel@tonic-gate (void) kmdb_prom_writer(buf, left); 3737c478bd9Sstevel@tonic-gate 3747c478bd9Sstevel@tonic-gate return (len); 3757c478bd9Sstevel@tonic-gate } 3767c478bd9Sstevel@tonic-gate 3777c478bd9Sstevel@tonic-gate static char * 3787c478bd9Sstevel@tonic-gate kmdb_get_ttyio_mode(kmdb_auxv_t *kav, char *devname) 3797c478bd9Sstevel@tonic-gate { 3807c478bd9Sstevel@tonic-gate char *modepname, *modepval; 3817c478bd9Sstevel@tonic-gate 3827c478bd9Sstevel@tonic-gate modepname = mdb_alloc(strlen(devname) + 5 + 1, UM_SLEEP); 38380148899SSurya Prakki (void) strcpy(modepname, devname); 38480148899SSurya Prakki (void) strcat(modepname, "-mode"); 3857c478bd9Sstevel@tonic-gate 386c7d88479Slq150181 modepval = kmdb_prom_get_ddi_prop(kav, modepname); 3877c478bd9Sstevel@tonic-gate 3887c478bd9Sstevel@tonic-gate strfree(modepname); 3897c478bd9Sstevel@tonic-gate 3907c478bd9Sstevel@tonic-gate return (modepval); 3917c478bd9Sstevel@tonic-gate } 3927c478bd9Sstevel@tonic-gate 3937c478bd9Sstevel@tonic-gate static int 3947c478bd9Sstevel@tonic-gate termios_setispeed(struct termios *tip, speed_t s) 3957c478bd9Sstevel@tonic-gate { 3967c478bd9Sstevel@tonic-gate if (s > (2 * CBAUD + 1)) 3977c478bd9Sstevel@tonic-gate return (-1); 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate if ((s << IBSHIFT) > CIBAUD) { 4007c478bd9Sstevel@tonic-gate tip->c_cflag |= CIBAUDEXT; 4017c478bd9Sstevel@tonic-gate s -= ((CIBAUD >> IBSHIFT) + 1); 4027c478bd9Sstevel@tonic-gate } else 4037c478bd9Sstevel@tonic-gate tip->c_cflag &= ~CIBAUDEXT; 4047c478bd9Sstevel@tonic-gate 4057c478bd9Sstevel@tonic-gate tip->c_cflag = (tip->c_cflag & ~CIBAUD) | ((s << IBSHIFT) & CIBAUD); 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate return (0); 4087c478bd9Sstevel@tonic-gate } 4097c478bd9Sstevel@tonic-gate 4107c478bd9Sstevel@tonic-gate static int 4117c478bd9Sstevel@tonic-gate termios_setospeed(struct termios *tip, speed_t s) 4127c478bd9Sstevel@tonic-gate { 4137c478bd9Sstevel@tonic-gate if (s > (2 * CBAUD + 1)) 4147c478bd9Sstevel@tonic-gate return (-1); 4157c478bd9Sstevel@tonic-gate 4167c478bd9Sstevel@tonic-gate if (s > CBAUD) { 4177c478bd9Sstevel@tonic-gate tip->c_cflag |= CBAUDEXT; 4187c478bd9Sstevel@tonic-gate s -= (CBAUD + 1); 4197c478bd9Sstevel@tonic-gate } else 4207c478bd9Sstevel@tonic-gate tip->c_cflag &= ~CBAUDEXT; 4217c478bd9Sstevel@tonic-gate 4227c478bd9Sstevel@tonic-gate tip->c_cflag = (tip->c_cflag & ~CBAUD) | (s & CBAUD); 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate return (0); 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate 4277c478bd9Sstevel@tonic-gate static int 4287c478bd9Sstevel@tonic-gate kmdb_parse_mode(const char *mode, struct termios *tip, int in) 4297c478bd9Sstevel@tonic-gate { 4307c478bd9Sstevel@tonic-gate static const uint_t baudmap[] = { 4317c478bd9Sstevel@tonic-gate 0, 50, 75, 110, 134, 150, 200, 300, 600, 1200, 4327c478bd9Sstevel@tonic-gate 1800, 2400, 4800, 9600, 19200, 38400, 57600, 433de81e71eSTim Marsland 76800, 115200, 153600, 230400, 307200, 460800, 921600 4347c478bd9Sstevel@tonic-gate }; 4357c478bd9Sstevel@tonic-gate static const uint_t bitsmap[] = { CS6, CS6, CS7, CS8 }; 4367c478bd9Sstevel@tonic-gate char *m = strdup(mode); 4377c478bd9Sstevel@tonic-gate char *w; 4387c478bd9Sstevel@tonic-gate int rc = -1; 4397c478bd9Sstevel@tonic-gate speed_t speed; 4407c478bd9Sstevel@tonic-gate int baud, i; 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate /* 4437c478bd9Sstevel@tonic-gate * termios supports different baud rates and flow control types for 4447c478bd9Sstevel@tonic-gate * input and output, but it requires character width, parity, and stop 4457c478bd9Sstevel@tonic-gate * bits to be equal in input and output. obp allows them to be 4467c478bd9Sstevel@tonic-gate * different, but we're going to (silently) assume that nobody will use 4477c478bd9Sstevel@tonic-gate * it that way. 4487c478bd9Sstevel@tonic-gate */ 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate /* baud rate - see baudmap above */ 4517c478bd9Sstevel@tonic-gate if ((w = strtok(m, ",")) == NULL) 4527c478bd9Sstevel@tonic-gate goto parse_mode_bail; 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate baud = strtol(w, NULL, 10); 4557c478bd9Sstevel@tonic-gate speed = 0; 4567c478bd9Sstevel@tonic-gate for (i = 0; i < sizeof (baudmap) / sizeof (baudmap[0]); i++) { 4577c478bd9Sstevel@tonic-gate if (baudmap[i] == baud) { 4587c478bd9Sstevel@tonic-gate speed = i; 4597c478bd9Sstevel@tonic-gate break; 4607c478bd9Sstevel@tonic-gate } 4617c478bd9Sstevel@tonic-gate } 4627c478bd9Sstevel@tonic-gate if (speed == 0) 4637c478bd9Sstevel@tonic-gate goto parse_mode_bail; 4647c478bd9Sstevel@tonic-gate 4657c478bd9Sstevel@tonic-gate if (in == 1) 4667c478bd9Sstevel@tonic-gate (void) termios_setispeed(tip, speed); 4677c478bd9Sstevel@tonic-gate else 4687c478bd9Sstevel@tonic-gate (void) termios_setospeed(tip, speed); 4697c478bd9Sstevel@tonic-gate 4707c478bd9Sstevel@tonic-gate /* character width (bits) - 5, 6, 7, or 8 */ 4717c478bd9Sstevel@tonic-gate if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 || *w < '5' || 4727c478bd9Sstevel@tonic-gate *w > '8') 4737c478bd9Sstevel@tonic-gate goto parse_mode_bail; 4747c478bd9Sstevel@tonic-gate tip->c_cflag = (tip->c_cflag & ~CSIZE) | bitsmap[*w - '5']; 4757c478bd9Sstevel@tonic-gate 4767c478bd9Sstevel@tonic-gate /* parity - `n' (none), `e' (even), or `o' (odd) */ 4777c478bd9Sstevel@tonic-gate if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 || 4787c478bd9Sstevel@tonic-gate strchr("neo", *w) == NULL) 4797c478bd9Sstevel@tonic-gate goto parse_mode_bail; 4807c478bd9Sstevel@tonic-gate 4817c478bd9Sstevel@tonic-gate tip->c_cflag = (tip->c_cflag & ~(PARENB|PARODD)); 4827c478bd9Sstevel@tonic-gate switch (*w) { 4837c478bd9Sstevel@tonic-gate case 'n': 4847c478bd9Sstevel@tonic-gate /* nothing */ 4857c478bd9Sstevel@tonic-gate break; 4867c478bd9Sstevel@tonic-gate case 'e': 4877c478bd9Sstevel@tonic-gate tip->c_cflag |= PARENB; 4887c478bd9Sstevel@tonic-gate break; 4897c478bd9Sstevel@tonic-gate case 'o': 4907c478bd9Sstevel@tonic-gate tip->c_cflag |= PARENB|PARODD; 4917c478bd9Sstevel@tonic-gate break; 4927c478bd9Sstevel@tonic-gate } 4937c478bd9Sstevel@tonic-gate 4947c478bd9Sstevel@tonic-gate /* 4957c478bd9Sstevel@tonic-gate * stop bits - 1, or 2. obp can, in theory, support 1.5 bits, 4967c478bd9Sstevel@tonic-gate * but we can't. how many angels can dance on half of a bit? 4977c478bd9Sstevel@tonic-gate */ 4987c478bd9Sstevel@tonic-gate if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 || *w < '1' || 4997c478bd9Sstevel@tonic-gate *w > '2') 5007c478bd9Sstevel@tonic-gate goto parse_mode_bail; 5017c478bd9Sstevel@tonic-gate 5027c478bd9Sstevel@tonic-gate if (*w == '1') 5037c478bd9Sstevel@tonic-gate tip->c_cflag &= ~CSTOPB; 5047c478bd9Sstevel@tonic-gate else 5057c478bd9Sstevel@tonic-gate tip->c_cflag |= CSTOPB; 5067c478bd9Sstevel@tonic-gate 5077c478bd9Sstevel@tonic-gate /* flow control - `-' (none), `h' (h/w), or `s' (s/w - XON/XOFF) */ 5087c478bd9Sstevel@tonic-gate if ((w = strtok(NULL, ",")) == NULL || strlen(w) != 1 || 5097c478bd9Sstevel@tonic-gate strchr("-hs", *w) == NULL) 5107c478bd9Sstevel@tonic-gate goto parse_mode_bail; 5117c478bd9Sstevel@tonic-gate 5127c478bd9Sstevel@tonic-gate tip->c_cflag &= ~(CRTSXOFF|CRTSCTS); 5137c478bd9Sstevel@tonic-gate tip->c_iflag &= ~(IXON|IXANY|IXOFF); 5147c478bd9Sstevel@tonic-gate 5157c478bd9Sstevel@tonic-gate switch (*w) { 5167c478bd9Sstevel@tonic-gate case 'h': 5177c478bd9Sstevel@tonic-gate tip->c_cflag |= (in == 1 ? CRTSXOFF : CRTSCTS); 5187c478bd9Sstevel@tonic-gate break; 5197c478bd9Sstevel@tonic-gate 5207c478bd9Sstevel@tonic-gate case 's': 5217c478bd9Sstevel@tonic-gate tip->c_iflag |= (in == 1 ? IXOFF : IXON); 5227c478bd9Sstevel@tonic-gate break; 5237c478bd9Sstevel@tonic-gate } 5247c478bd9Sstevel@tonic-gate 5257c478bd9Sstevel@tonic-gate rc = 0; 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate parse_mode_bail: 5287c478bd9Sstevel@tonic-gate strfree(m); 5297c478bd9Sstevel@tonic-gate 5307c478bd9Sstevel@tonic-gate return (rc); 5317c478bd9Sstevel@tonic-gate } 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate #ifdef __sparc 5347c478bd9Sstevel@tonic-gate #define ATTACHED_TERM_TYPE "sun" 5357c478bd9Sstevel@tonic-gate #else 5367c478bd9Sstevel@tonic-gate #define ATTACHED_TERM_TYPE "sun-color" 5377c478bd9Sstevel@tonic-gate #endif 5387c478bd9Sstevel@tonic-gate 5397c478bd9Sstevel@tonic-gate static void 5407c478bd9Sstevel@tonic-gate kmdb_prom_term_init(kmdb_auxv_t *kav, kmdb_promif_t *pif) 5417c478bd9Sstevel@tonic-gate { 5427c478bd9Sstevel@tonic-gate const char ccs[NCCS] = { 0x03, 0x1c, 0x08, 0x15, 0x04, 0x00, 0x00, 5437c478bd9Sstevel@tonic-gate 0x00, 0x11, 0x13, 0x1a, 0x19, 0x12, 0x0f, 0x17, 0x16 }; 5447c478bd9Sstevel@tonic-gate char *conin = NULL, *conout = NULL; 5457c478bd9Sstevel@tonic-gate 5467c478bd9Sstevel@tonic-gate if (kmdb_prom_stdout_is_framebuffer(kav)) 5477c478bd9Sstevel@tonic-gate pif->pif_oterm = ATTACHED_TERM_TYPE; 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate bzero(&pif->pif_tios, sizeof (struct termios)); 5507c478bd9Sstevel@tonic-gate 5517c478bd9Sstevel@tonic-gate /* output device characteristics */ 552c7d88479Slq150181 if ((conout = kmdb_prom_get_ddi_prop(kav, "output-device")) == 5537c478bd9Sstevel@tonic-gate NULL || strcmp(conout, "screen") == 0) { 5547c478bd9Sstevel@tonic-gate (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE, 5557c478bd9Sstevel@tonic-gate &pif->pif_tios, 0); 5567c478bd9Sstevel@tonic-gate } else if (*conout == '/') { 5577c478bd9Sstevel@tonic-gate /* 5587c478bd9Sstevel@tonic-gate * We're not going to be able to get characteristics for a 5597c478bd9Sstevel@tonic-gate * device that's specified as a path, so don't even try. 5607c478bd9Sstevel@tonic-gate * Conveniently, this allows us to avoid chattering on 5617c478bd9Sstevel@tonic-gate * Serengetis. 5627c478bd9Sstevel@tonic-gate */ 5637c478bd9Sstevel@tonic-gate (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE, 5647c478bd9Sstevel@tonic-gate &pif->pif_tios, 0); 5657c478bd9Sstevel@tonic-gate } else { 5667c478bd9Sstevel@tonic-gate char *mode = kmdb_get_ttyio_mode(kav, conout); 5677c478bd9Sstevel@tonic-gate 5687c478bd9Sstevel@tonic-gate #ifdef __sparc 5697c478bd9Sstevel@tonic-gate /* 5707c478bd9Sstevel@tonic-gate * Some platforms (Starfire) define a value of `ttya' for 5717c478bd9Sstevel@tonic-gate * output-device, but neglect to provide a specific property 5727c478bd9Sstevel@tonic-gate * with the characteristics. We'll provide a default value. 5737c478bd9Sstevel@tonic-gate */ 5747c478bd9Sstevel@tonic-gate if (mode == NULL && strcmp(conout, "ttya") == 0) { 5757c478bd9Sstevel@tonic-gate (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE, 5767c478bd9Sstevel@tonic-gate &pif->pif_tios, 0); 5777c478bd9Sstevel@tonic-gate } else 5787c478bd9Sstevel@tonic-gate #endif 5797c478bd9Sstevel@tonic-gate { 5807c478bd9Sstevel@tonic-gate if (mode == NULL || kmdb_parse_mode(mode, 5817c478bd9Sstevel@tonic-gate &pif->pif_tios, 0) < 0) { 5827c478bd9Sstevel@tonic-gate /* 5837c478bd9Sstevel@tonic-gate * Either we couldn't retrieve the 5847c478bd9Sstevel@tonic-gate * characteristics for this console, or they 5857c478bd9Sstevel@tonic-gate * weren't parseable. The console hasn't been 5867c478bd9Sstevel@tonic-gate * set up yet, so we can't warn. We'll have to 5877c478bd9Sstevel@tonic-gate * silently fall back to the default 5887c478bd9Sstevel@tonic-gate * characteristics. 5897c478bd9Sstevel@tonic-gate */ 5907c478bd9Sstevel@tonic-gate (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE, 5917c478bd9Sstevel@tonic-gate &pif->pif_tios, 0); 5927c478bd9Sstevel@tonic-gate } 5937c478bd9Sstevel@tonic-gate } 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate if (mode != NULL) 596c7d88479Slq150181 kmdb_prom_free_ddi_prop(mode); 5977c478bd9Sstevel@tonic-gate } 5987c478bd9Sstevel@tonic-gate 5997c478bd9Sstevel@tonic-gate /* input device characteristics */ 600c7d88479Slq150181 if ((conin = kmdb_prom_get_ddi_prop(kav, "input-device")) == NULL || 6017c478bd9Sstevel@tonic-gate strcmp(conin, "keyboard") == 0) { 6027c478bd9Sstevel@tonic-gate (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE, 6037c478bd9Sstevel@tonic-gate &pif->pif_tios, 1); 6047c478bd9Sstevel@tonic-gate } else if (*conin == '/') { 6057c478bd9Sstevel@tonic-gate /* See similar case in output-device above */ 6067c478bd9Sstevel@tonic-gate (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE, 6077c478bd9Sstevel@tonic-gate &pif->pif_tios, 1); 6087c478bd9Sstevel@tonic-gate } else { 6097c478bd9Sstevel@tonic-gate char *mode = kmdb_get_ttyio_mode(kav, conin); 6107c478bd9Sstevel@tonic-gate 6117c478bd9Sstevel@tonic-gate #ifdef __sparc 6127c478bd9Sstevel@tonic-gate /* 6137c478bd9Sstevel@tonic-gate * Some platforms (Starfire) define a value of `ttya' for 6147c478bd9Sstevel@tonic-gate * input-device, but neglect to provide a specific property 6157c478bd9Sstevel@tonic-gate * with the characteristics. We'll provide a default value. 6167c478bd9Sstevel@tonic-gate */ 6177c478bd9Sstevel@tonic-gate if (mode == NULL && strcmp(conin, "ttya") == 0) { 6187c478bd9Sstevel@tonic-gate (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE, 6197c478bd9Sstevel@tonic-gate &pif->pif_tios, 1); 6207c478bd9Sstevel@tonic-gate } else 6217c478bd9Sstevel@tonic-gate #endif 6227c478bd9Sstevel@tonic-gate { 6237c478bd9Sstevel@tonic-gate if (mode == NULL || kmdb_parse_mode(mode, 6247c478bd9Sstevel@tonic-gate &pif->pif_tios, 1) < 0) { 6257c478bd9Sstevel@tonic-gate /* 6267c478bd9Sstevel@tonic-gate * Either we couldn't retrieve the 6277c478bd9Sstevel@tonic-gate * characteristics for this console, or they 6287c478bd9Sstevel@tonic-gate * weren't parseable. The console hasn't been 6297c478bd9Sstevel@tonic-gate * set up yet, so we can't warn. We'll have to 6307c478bd9Sstevel@tonic-gate * silently fall back to the default 6317c478bd9Sstevel@tonic-gate * characteristics. 6327c478bd9Sstevel@tonic-gate */ 6337c478bd9Sstevel@tonic-gate (void) kmdb_parse_mode(KMDB_PROM_DEF_CONS_MODE, 6347c478bd9Sstevel@tonic-gate &pif->pif_tios, 1); 6357c478bd9Sstevel@tonic-gate } 6367c478bd9Sstevel@tonic-gate } 6377c478bd9Sstevel@tonic-gate 6387c478bd9Sstevel@tonic-gate if (mode != NULL) 639c7d88479Slq150181 kmdb_prom_free_ddi_prop(mode); 6407c478bd9Sstevel@tonic-gate } 6417c478bd9Sstevel@tonic-gate 6427c478bd9Sstevel@tonic-gate /* various characteristics of the prom read/write interface */ 6437c478bd9Sstevel@tonic-gate pif->pif_tios.c_iflag |= ICRNL; 6447c478bd9Sstevel@tonic-gate pif->pif_tios.c_lflag |= ECHO; 6457c478bd9Sstevel@tonic-gate bcopy(ccs, &pif->pif_tios.c_cc, sizeof (ccs)); 6467c478bd9Sstevel@tonic-gate 6477c478bd9Sstevel@tonic-gate if (conin != NULL) 648c7d88479Slq150181 kmdb_prom_free_ddi_prop(conin); 6497c478bd9Sstevel@tonic-gate if (conout != NULL) 650c7d88479Slq150181 kmdb_prom_free_ddi_prop(conout); 6517c478bd9Sstevel@tonic-gate } 6527c478bd9Sstevel@tonic-gate 6537c478bd9Sstevel@tonic-gate char * 6547c478bd9Sstevel@tonic-gate kmdb_prom_term_type(void) 6557c478bd9Sstevel@tonic-gate { 6567c478bd9Sstevel@tonic-gate return (mdb.m_promif->pif_oterm); 6577c478bd9Sstevel@tonic-gate } 6587c478bd9Sstevel@tonic-gate 6597c478bd9Sstevel@tonic-gate int 6607c478bd9Sstevel@tonic-gate kmdb_prom_term_ctl(int req, void *arg) 6617c478bd9Sstevel@tonic-gate { 6627c478bd9Sstevel@tonic-gate switch (req) { 6637c478bd9Sstevel@tonic-gate case TCGETS: { 6647c478bd9Sstevel@tonic-gate struct termios *ti = arg; 6657c478bd9Sstevel@tonic-gate bcopy(&mdb.m_promif->pif_tios, ti, sizeof (struct termios)); 6667c478bd9Sstevel@tonic-gate return (0); 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate case TIOCGWINSZ: 6697c478bd9Sstevel@tonic-gate /* 6707c478bd9Sstevel@tonic-gate * When kmdb is used over a serial console, we have no idea how 6717c478bd9Sstevel@tonic-gate * large the terminal window is. When we're invoked on a local 6727c478bd9Sstevel@tonic-gate * console, however, we do, and need to share that information 6737c478bd9Sstevel@tonic-gate * with the debugger in order to contradict potentially 6747c478bd9Sstevel@tonic-gate * incorrect sizing information retrieved from the terminfo 6757c478bd9Sstevel@tonic-gate * database. One specific case where this happens is with the 6767c478bd9Sstevel@tonic-gate * Intel console, which is 80x25. The terminfo entry for 6777c478bd9Sstevel@tonic-gate * sun-color -- the default terminal type for local Intel 6787c478bd9Sstevel@tonic-gate * consoles -- was cloned from sun, which has a height of 34 6797c478bd9Sstevel@tonic-gate * rows. 6807c478bd9Sstevel@tonic-gate */ 6817c478bd9Sstevel@tonic-gate if (mdb.m_promif->pif_oterm != NULL) { 6827c478bd9Sstevel@tonic-gate struct winsize *wsz = arg; 6837c478bd9Sstevel@tonic-gate wsz->ws_row = KMDB_PIF_WINSIZE_ROWS; 6847c478bd9Sstevel@tonic-gate wsz->ws_col = KMDB_PIF_WINSIZE_COLS; 6857c478bd9Sstevel@tonic-gate wsz->ws_xpixel = wsz->ws_ypixel = 0; 6867c478bd9Sstevel@tonic-gate return (0); 6877c478bd9Sstevel@tonic-gate } 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate return (set_errno(ENOTSUP)); 6907c478bd9Sstevel@tonic-gate default: 6917c478bd9Sstevel@tonic-gate return (set_errno(EINVAL)); 6927c478bd9Sstevel@tonic-gate } 6937c478bd9Sstevel@tonic-gate } 6947c478bd9Sstevel@tonic-gate 6957c478bd9Sstevel@tonic-gate int 6967c478bd9Sstevel@tonic-gate kmdb_prom_vtop(uintptr_t virt, physaddr_t *pap) 6977c478bd9Sstevel@tonic-gate { 6987c478bd9Sstevel@tonic-gate physaddr_t pa; 6997c478bd9Sstevel@tonic-gate int rc = kmdb_kdi_vtop(virt, &pa); 7007c478bd9Sstevel@tonic-gate 7017c478bd9Sstevel@tonic-gate #ifdef __sparc 7027c478bd9Sstevel@tonic-gate if (rc < 0 && errno == EAGAIN) 7037c478bd9Sstevel@tonic-gate rc = kmdb_prom_translate_virt(virt, &pa); 7047c478bd9Sstevel@tonic-gate #endif 7057c478bd9Sstevel@tonic-gate 7067c478bd9Sstevel@tonic-gate if (rc == 0 && pap != NULL) 7077c478bd9Sstevel@tonic-gate *pap = pa; 7087c478bd9Sstevel@tonic-gate 7097c478bd9Sstevel@tonic-gate return (rc); 7107c478bd9Sstevel@tonic-gate } 7117c478bd9Sstevel@tonic-gate 7127c478bd9Sstevel@tonic-gate void 7137c478bd9Sstevel@tonic-gate kmdb_prom_debugger_entry(void) 7147c478bd9Sstevel@tonic-gate { 7157c478bd9Sstevel@tonic-gate /* 7167c478bd9Sstevel@tonic-gate * While kmdb_prom_debugger_entry and kmdb_prom_debugger_exit are not 7177c478bd9Sstevel@tonic-gate * guaranteed to be called an identical number of times (an intentional 7187c478bd9Sstevel@tonic-gate * debugger fault will cause an additional entry call without a matching 7197c478bd9Sstevel@tonic-gate * exit call), we must ensure that the polled I/O entry and exit calls 7207c478bd9Sstevel@tonic-gate * match. 7217c478bd9Sstevel@tonic-gate */ 7227c478bd9Sstevel@tonic-gate if (mdb.m_pio == NULL) { 7237c478bd9Sstevel@tonic-gate mdb.m_pio = kmdb_kdi_get_polled_io(); 7247c478bd9Sstevel@tonic-gate 7257c478bd9Sstevel@tonic-gate if (mdb.m_pio != NULL && 7267c478bd9Sstevel@tonic-gate mdb.m_pio->cons_polledio_enter != NULL) { 7277c478bd9Sstevel@tonic-gate (void) kmdb_dpi_call( 7287c478bd9Sstevel@tonic-gate (uintptr_t)mdb.m_pio->cons_polledio_enter, 1, 7297c478bd9Sstevel@tonic-gate (uintptr_t *)&mdb.m_pio->cons_polledio_argument); 7307c478bd9Sstevel@tonic-gate } 7317c478bd9Sstevel@tonic-gate } 7327c478bd9Sstevel@tonic-gate } 7337c478bd9Sstevel@tonic-gate 7347c478bd9Sstevel@tonic-gate void 7357c478bd9Sstevel@tonic-gate kmdb_prom_debugger_exit(void) 7367c478bd9Sstevel@tonic-gate { 7377c478bd9Sstevel@tonic-gate if (mdb.m_pio != NULL && mdb.m_pio->cons_polledio_exit != NULL) { 7387c478bd9Sstevel@tonic-gate (void) kmdb_dpi_call((uintptr_t)mdb.m_pio->cons_polledio_exit, 7397c478bd9Sstevel@tonic-gate 1, (uintptr_t *)&mdb.m_pio->cons_polledio_argument); 7407c478bd9Sstevel@tonic-gate } 7417c478bd9Sstevel@tonic-gate 7427c478bd9Sstevel@tonic-gate mdb.m_pio = NULL; 7437c478bd9Sstevel@tonic-gate } 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate /* 746*7fd79137SRobert Mustacchi * The prom_* files use ASSERT, which is #defined as assfail(). We need to 747*7fd79137SRobert Mustacchi * redirect that to our assert function. This is also used by the various STAND 748*7fd79137SRobert Mustacchi * libraries. 7497c478bd9Sstevel@tonic-gate */ 7507c478bd9Sstevel@tonic-gate int 7517c478bd9Sstevel@tonic-gate kmdb_prom_assfail(const char *assertion, const char *file, int line) 7527c478bd9Sstevel@tonic-gate { 7537c478bd9Sstevel@tonic-gate (void) mdb_dassert(assertion, file, line); 7547c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 7557c478bd9Sstevel@tonic-gate return (0); 7567c478bd9Sstevel@tonic-gate } 7577c478bd9Sstevel@tonic-gate 7587c478bd9Sstevel@tonic-gate /* 7597c478bd9Sstevel@tonic-gate * Begin the initialization of the debugger/PROM interface. Initialization is 7607c478bd9Sstevel@tonic-gate * performed in two steps due to interlocking dependencies between promif and 7617c478bd9Sstevel@tonic-gate * both the memory allocator and mdb_create. The first phase is performed 7627c478bd9Sstevel@tonic-gate * before either of the others have been initialized, and thus must neither 7637c478bd9Sstevel@tonic-gate * attempt to allocate memory nor access/write to `mdb'. 7647c478bd9Sstevel@tonic-gate */ 7657c478bd9Sstevel@tonic-gate void 7667c478bd9Sstevel@tonic-gate kmdb_prom_init_begin(char *pgmname, kmdb_auxv_t *kav) 7677c478bd9Sstevel@tonic-gate { 7681ae08745Sheppo #ifdef sun4v 7691ae08745Sheppo if (kav->kav_domaining) 7701ae08745Sheppo kmdb_prom_init_promif(pgmname, kav); 7711ae08745Sheppo else 7727c478bd9Sstevel@tonic-gate prom_init(pgmname, kav->kav_romp); 7731ae08745Sheppo #else 7741ae08745Sheppo prom_init(pgmname, kav->kav_romp); 7751ae08745Sheppo #endif 7767c478bd9Sstevel@tonic-gate 7777c478bd9Sstevel@tonic-gate /* Initialize the interrupt ring buffer */ 7787c478bd9Sstevel@tonic-gate kmdb_prom_readbuf_head = kmdb_prom_readbuf_tail; 7797c478bd9Sstevel@tonic-gate 7807c478bd9Sstevel@tonic-gate #if defined(__i386) || defined(__amd64) 7817c478bd9Sstevel@tonic-gate kmdb_sysp = kav->kav_romp; 7827c478bd9Sstevel@tonic-gate #endif 7837c478bd9Sstevel@tonic-gate } 7847c478bd9Sstevel@tonic-gate 7851ae08745Sheppo #ifdef sun4v 7861ae08745Sheppo void 7871ae08745Sheppo kmdb_prom_init_promif(char *pgmname, kmdb_auxv_t *kav) 7881ae08745Sheppo { 7891ae08745Sheppo ASSERT(kav->kav_domaining); 7901ae08745Sheppo cif_init(pgmname, kav->kav_promif_root, 7911ae08745Sheppo kav->kav_promif_in, kav->kav_promif_out, 7921ae08745Sheppo kav->kav_promif_pin, kav->kav_promif_pout, 7931ae08745Sheppo kav->kav_promif_chosennode, kav->kav_promif_optionsnode); 7941ae08745Sheppo } 7951ae08745Sheppo #endif 7961ae08745Sheppo 7977c478bd9Sstevel@tonic-gate /* 7987c478bd9Sstevel@tonic-gate * Conclude the initialization of the debugger/PROM interface. Memory 7997c478bd9Sstevel@tonic-gate * allocation and the global `mdb' object are now available. 8007c478bd9Sstevel@tonic-gate */ 8017c478bd9Sstevel@tonic-gate void 8027c478bd9Sstevel@tonic-gate kmdb_prom_init_finish(kmdb_auxv_t *kav) 8037c478bd9Sstevel@tonic-gate { 8047c478bd9Sstevel@tonic-gate mdb.m_promif = mdb_zalloc(sizeof (kmdb_promif_t), UM_SLEEP); 8057c478bd9Sstevel@tonic-gate kmdb_prom_term_init(kav, mdb.m_promif); 8067c478bd9Sstevel@tonic-gate } 807