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 * Copyright 2006 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * PROM I/O backend 30 */ 31 32 #include <sys/param.h> 33 #include <sys/types.h> 34 #include <sys/obpdefs.h> 35 #include <string.h> 36 #include <errno.h> 37 #include <ctype.h> 38 39 #include <mdb/mdb_modapi.h> 40 #include <mdb/mdb_io_impl.h> 41 #include <kmdb/kmdb_promif.h> 42 #include <kmdb/kmdb_io.h> 43 #include <mdb/mdb_debug.h> 44 #include <mdb/mdb_err.h> 45 #include <mdb/mdb.h> 46 47 #define PIO_FL_TIO_READ 0x001 48 49 typedef struct pio_data { 50 char pio_name[MAXPATHLEN]; 51 ihandle_t pio_fd; 52 uint_t pio_flags; 53 struct termios pio_ti; 54 } pio_data_t; 55 56 static pid_t pio_pgrp; 57 58 static ssize_t 59 pio_read(mdb_io_t *io, void *buf, size_t nbytes) 60 { 61 pio_data_t *pdp = io->io_data; 62 63 if (io->io_next == NULL) 64 return (kmdb_prom_read(buf, nbytes, &pdp->pio_ti)); 65 66 return (IOP_READ(io->io_next, buf, nbytes)); 67 } 68 69 static ssize_t 70 pio_write(mdb_io_t *io, const void *buf, size_t nbytes) 71 { 72 pio_data_t *pdp = io->io_data; 73 74 if (io->io_next == NULL) 75 return (kmdb_prom_write(buf, nbytes, &pdp->pio_ti)); 76 77 return (IOP_WRITE(io->io_next, buf, nbytes)); 78 } 79 80 static off64_t 81 pio_seek(mdb_io_t *io, off64_t offset, int whence) 82 { 83 if (io->io_next == NULL) 84 return (set_errno(ENOTSUP)); 85 86 return (IOP_SEEK(io->io_next, offset, whence)); 87 } 88 89 static int 90 pio_ctl(mdb_io_t *io, int req, void *arg) 91 { 92 pio_data_t *pdp = io->io_data; 93 94 if (io->io_next != NULL) 95 return (IOP_CTL(io->io_next, req, arg)); 96 97 switch (req) { 98 case TIOCGWINSZ: 99 return (kmdb_prom_term_ctl(TIOCGWINSZ, arg)); 100 101 case TCGETS: { 102 struct termios *ti = arg; 103 104 if (!(pdp->pio_flags & PIO_FL_TIO_READ)) { 105 (void) kmdb_prom_term_ctl(TCGETS, &pdp->pio_ti); 106 pdp->pio_flags |= PIO_FL_TIO_READ; 107 } 108 109 bcopy(&pdp->pio_ti, ti, sizeof (struct termios)); 110 111 mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: gets: i: 0%o o: 0%o c: " 112 "0%o l: 0%o\n", ti->c_iflag, ti->c_oflag, ti->c_cflag, 113 ti->c_lflag); 114 return (0); 115 } 116 117 case TCSETSW: { 118 struct termios *ti = arg; 119 120 mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: setsw: i: 0%o o: 0%o c: " 121 "0%o l: 0%o\n", ti->c_iflag, ti->c_oflag, ti->c_cflag, 122 ti->c_lflag); 123 124 bcopy(ti, &pdp->pio_ti, sizeof (struct termios)); 125 126 return (0); 127 } 128 129 case TIOCSPGRP: 130 pio_pgrp = *(pid_t *)arg; 131 mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: spgrp: %ld\n", 132 (long)pio_pgrp); 133 return (0); 134 135 case TIOCGPGRP: 136 mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: gpgrp: %ld\n", 137 (long)pio_pgrp); 138 *(pid_t *)arg = pio_pgrp; 139 return (0); 140 141 case MDB_IOC_CTTY: 142 mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: ignoring MDB_IOC_CTTY\n"); 143 return (0); 144 145 case MDB_IOC_GETFD: 146 return (set_errno(ENOTSUP)); 147 148 default: 149 warn("Unknown ioctl %d\n", req); 150 return (set_errno(EINVAL)); 151 } 152 } 153 154 void 155 pio_close(mdb_io_t *io) 156 { 157 pio_data_t *pdp = io->io_data; 158 159 mdb_free(pdp, sizeof (pio_data_t)); 160 } 161 162 static const char * 163 pio_name(mdb_io_t *io) 164 { 165 pio_data_t *pdp = io->io_data; 166 167 if (io->io_next == NULL) 168 return (pdp->pio_name); 169 170 return (IOP_NAME(io->io_next)); 171 } 172 173 static const mdb_io_ops_t promio_ops = { 174 pio_read, 175 pio_write, 176 pio_seek, 177 pio_ctl, 178 pio_close, 179 pio_name, 180 no_io_link, 181 no_io_unlink, 182 no_io_setattr, 183 no_io_suspend, 184 no_io_resume 185 }; 186 187 mdb_io_t * 188 kmdb_promio_create(char *name) 189 { 190 mdb_io_t *io; 191 pio_data_t *pdp; 192 ihandle_t hdl = kmdb_prom_get_handle(name); 193 194 if (hdl == -1) 195 return (NULL); 196 197 io = mdb_zalloc(sizeof (mdb_io_t), UM_SLEEP); 198 pdp = mdb_zalloc(sizeof (pio_data_t), UM_SLEEP); 199 200 strlcpy(pdp->pio_name, name, MAXPATHLEN); 201 pdp->pio_fd = hdl; 202 203 #ifdef __sparc 204 pdp->pio_ti.c_oflag |= ONLCR; 205 pdp->pio_ti.c_iflag |= ICRNL; 206 #endif 207 pdp->pio_ti.c_lflag |= ECHO; 208 209 io->io_data = pdp; 210 io->io_ops = &promio_ops; 211 212 return (io); 213 } 214 215 char 216 kmdb_getchar(void) 217 { 218 char c; 219 220 while (IOP_READ(mdb.m_term, &c, 1) != 1) 221 continue; 222 if (isprint(c) && c != '\n') 223 mdb_iob_printf(mdb.m_out, "%c", c); 224 mdb_iob_printf(mdb.m_out, "\n"); 225 226 return (c); 227 } 228