/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2009 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ /* * PROM I/O backend */ #include #include #include #include #include #include #include #include #include #include #include #include #include #define PIO_FL_TIO_READ 0x001 typedef struct pio_data { char pio_name[MAXPATHLEN]; ihandle_t pio_fd; uint_t pio_flags; struct termios pio_ti; } pio_data_t; static pid_t pio_pgrp; static ssize_t pio_read(mdb_io_t *io, void *buf, size_t nbytes) { pio_data_t *pdp = io->io_data; if (io->io_next == NULL) return (kmdb_prom_read(buf, nbytes, &pdp->pio_ti)); return (IOP_READ(io->io_next, buf, nbytes)); } static ssize_t pio_write(mdb_io_t *io, const void *buf, size_t nbytes) { pio_data_t *pdp = io->io_data; if (io->io_next == NULL) return (kmdb_prom_write(buf, nbytes, &pdp->pio_ti)); return (IOP_WRITE(io->io_next, buf, nbytes)); } static off64_t pio_seek(mdb_io_t *io, off64_t offset, int whence) { if (io->io_next == NULL) return (set_errno(ENOTSUP)); return (IOP_SEEK(io->io_next, offset, whence)); } static int pio_ctl(mdb_io_t *io, int req, void *arg) { pio_data_t *pdp = io->io_data; if (io->io_next != NULL) return (IOP_CTL(io->io_next, req, arg)); switch (req) { case TIOCGWINSZ: return (kmdb_prom_term_ctl(TIOCGWINSZ, arg)); case TCGETS: { struct termios *ti = arg; if (!(pdp->pio_flags & PIO_FL_TIO_READ)) { (void) kmdb_prom_term_ctl(TCGETS, &pdp->pio_ti); pdp->pio_flags |= PIO_FL_TIO_READ; } bcopy(&pdp->pio_ti, ti, sizeof (struct termios)); mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: gets: i: 0%o o: 0%o c: " "0%o l: 0%o\n", ti->c_iflag, ti->c_oflag, ti->c_cflag, ti->c_lflag); return (0); } case TCSETSW: { struct termios *ti = arg; mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: setsw: i: 0%o o: 0%o c: " "0%o l: 0%o\n", ti->c_iflag, ti->c_oflag, ti->c_cflag, ti->c_lflag); bcopy(ti, &pdp->pio_ti, sizeof (struct termios)); return (0); } case TIOCSPGRP: pio_pgrp = *(pid_t *)arg; mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: spgrp: %ld\n", (long)pio_pgrp); return (0); case TIOCGPGRP: mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: gpgrp: %ld\n", (long)pio_pgrp); *(pid_t *)arg = pio_pgrp; return (0); case MDB_IOC_CTTY: mdb_dprintf(MDB_DBG_CMDBUF, "pio_ctl: ignoring MDB_IOC_CTTY\n"); return (0); case MDB_IOC_GETFD: return (set_errno(ENOTSUP)); default: warn("Unknown ioctl %d\n", req); return (set_errno(EINVAL)); } } void pio_close(mdb_io_t *io) { pio_data_t *pdp = io->io_data; mdb_free(pdp, sizeof (pio_data_t)); } static const char * pio_name(mdb_io_t *io) { pio_data_t *pdp = io->io_data; if (io->io_next == NULL) return (pdp->pio_name); return (IOP_NAME(io->io_next)); } static const mdb_io_ops_t promio_ops = { .io_read = pio_read, .io_write = pio_write, .io_seek = pio_seek, .io_ctl = pio_ctl, .io_close = pio_close, .io_name = pio_name, .io_link = no_io_link, .io_unlink = no_io_unlink, .io_setattr = no_io_setattr, .io_suspend = no_io_suspend, .io_resume = no_io_resume, }; mdb_io_t * kmdb_promio_create(char *name) { mdb_io_t *io; pio_data_t *pdp; ihandle_t hdl = kmdb_prom_get_handle(name); if (hdl == -1) return (NULL); io = mdb_zalloc(sizeof (mdb_io_t), UM_SLEEP); pdp = mdb_zalloc(sizeof (pio_data_t), UM_SLEEP); (void) strlcpy(pdp->pio_name, name, MAXPATHLEN); pdp->pio_fd = hdl; #ifdef __sparc pdp->pio_ti.c_oflag |= ONLCR; pdp->pio_ti.c_iflag |= ICRNL; #endif pdp->pio_ti.c_lflag |= ECHO; io->io_data = pdp; io->io_ops = &promio_ops; return (io); } char kmdb_getchar(void) { char c; while (IOP_READ(mdb.m_term, &c, 1) != 1) continue; if (isprint(c) && c != '\n') mdb_iob_printf(mdb.m_out, "%c", c); mdb_iob_printf(mdb.m_out, "\n"); return (c); }