10Sstevel@tonic-gate /* 20Sstevel@tonic-gate * CDDL HEADER START 30Sstevel@tonic-gate * 40Sstevel@tonic-gate * The contents of this file are subject to the terms of the 51253Slq150181 * Common Development and Distribution License (the "License"). 61253Slq150181 * You may not use this file except in compliance with the License. 70Sstevel@tonic-gate * 80Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 90Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 100Sstevel@tonic-gate * See the License for the specific language governing permissions 110Sstevel@tonic-gate * and limitations under the License. 120Sstevel@tonic-gate * 130Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 140Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 150Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 160Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 170Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 180Sstevel@tonic-gate * 190Sstevel@tonic-gate * CDDL HEADER END 200Sstevel@tonic-gate */ 211253Slq150181 220Sstevel@tonic-gate /* 23*10064SJames.Anderson@Sun.COM * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 240Sstevel@tonic-gate * Use is subject to license terms. 250Sstevel@tonic-gate */ 260Sstevel@tonic-gate 270Sstevel@tonic-gate /* 280Sstevel@tonic-gate * Indirect console driver for Sun. 290Sstevel@tonic-gate * 300Sstevel@tonic-gate * Redirects all I/O to the device designated as the underlying "hardware" 310Sstevel@tonic-gate * console, as given by the value of rconsvp. The implementation assumes that 320Sstevel@tonic-gate * rconsvp denotes a STREAMS device; the assumption is justified since 330Sstevel@tonic-gate * consoles must be capable of effecting tty semantics. 340Sstevel@tonic-gate * 350Sstevel@tonic-gate * rconsvp is set in autoconf.c:consconfig(), based on information obtained 360Sstevel@tonic-gate * from the EEPROM. 370Sstevel@tonic-gate * 380Sstevel@tonic-gate * XXX: The driver still needs to be converted to use ANSI C consistently 390Sstevel@tonic-gate * throughout. 400Sstevel@tonic-gate */ 410Sstevel@tonic-gate 420Sstevel@tonic-gate #include <sys/types.h> 430Sstevel@tonic-gate #include <sys/open.h> 440Sstevel@tonic-gate #include <sys/param.h> 450Sstevel@tonic-gate #include <sys/systm.h> 460Sstevel@tonic-gate #include <sys/signal.h> 470Sstevel@tonic-gate #include <sys/cred.h> 480Sstevel@tonic-gate #include <sys/user.h> 490Sstevel@tonic-gate #include <sys/proc.h> 500Sstevel@tonic-gate #include <sys/disp.h> 510Sstevel@tonic-gate #include <sys/file.h> 520Sstevel@tonic-gate #include <sys/taskq.h> 530Sstevel@tonic-gate #include <sys/log.h> 540Sstevel@tonic-gate #include <sys/vnode.h> 550Sstevel@tonic-gate #include <sys/uio.h> 560Sstevel@tonic-gate #include <sys/stat.h> 570Sstevel@tonic-gate 580Sstevel@tonic-gate #include <sys/console.h> 590Sstevel@tonic-gate #include <sys/consdev.h> 600Sstevel@tonic-gate 610Sstevel@tonic-gate #include <sys/stream.h> 620Sstevel@tonic-gate #include <sys/strsubr.h> 630Sstevel@tonic-gate #include <sys/poll.h> 640Sstevel@tonic-gate 650Sstevel@tonic-gate #include <sys/debug.h> 660Sstevel@tonic-gate 670Sstevel@tonic-gate #include <sys/conf.h> 680Sstevel@tonic-gate #include <sys/ddi.h> 690Sstevel@tonic-gate #include <sys/sunddi.h> 700Sstevel@tonic-gate 710Sstevel@tonic-gate static int cnopen(dev_t *, int, int, struct cred *); 720Sstevel@tonic-gate static int cnclose(dev_t, int, int, struct cred *); 730Sstevel@tonic-gate static int cnread(dev_t, struct uio *, struct cred *); 740Sstevel@tonic-gate static int cnwrite(dev_t, struct uio *, struct cred *); 750Sstevel@tonic-gate static int cnioctl(dev_t, int, intptr_t, int, struct cred *, int *); 760Sstevel@tonic-gate static int cnpoll(dev_t, short, int, short *, struct pollhead **); 770Sstevel@tonic-gate static int cn_info(dev_info_t *, ddi_info_cmd_t, void *, void **); 780Sstevel@tonic-gate static int cn_attach(dev_info_t *, ddi_attach_cmd_t); 790Sstevel@tonic-gate static int cn_detach(dev_info_t *, ddi_detach_cmd_t); 800Sstevel@tonic-gate 810Sstevel@tonic-gate static dev_info_t *cn_dip; /* private copy of devinfo pointer */ 820Sstevel@tonic-gate 830Sstevel@tonic-gate static struct cb_ops cn_cb_ops = { 840Sstevel@tonic-gate 850Sstevel@tonic-gate cnopen, /* open */ 860Sstevel@tonic-gate cnclose, /* close */ 870Sstevel@tonic-gate nodev, /* strategy */ 880Sstevel@tonic-gate nodev, /* print */ 890Sstevel@tonic-gate nodev, /* dump */ 900Sstevel@tonic-gate cnread, /* read */ 910Sstevel@tonic-gate cnwrite, /* write */ 920Sstevel@tonic-gate cnioctl, /* ioctl */ 930Sstevel@tonic-gate nodev, /* devmap */ 940Sstevel@tonic-gate nodev, /* mmap */ 950Sstevel@tonic-gate nodev, /* segmap */ 960Sstevel@tonic-gate cnpoll, /* poll */ 970Sstevel@tonic-gate ddi_prop_op, /* cb_prop_op */ 980Sstevel@tonic-gate 0, /* streamtab */ 990Sstevel@tonic-gate D_NEW | D_MP /* Driver compatibility flag */ 1000Sstevel@tonic-gate 1010Sstevel@tonic-gate }; 1020Sstevel@tonic-gate 1030Sstevel@tonic-gate static struct dev_ops cn_ops = { 1040Sstevel@tonic-gate 1050Sstevel@tonic-gate DEVO_REV, /* devo_rev, */ 1060Sstevel@tonic-gate 0, /* refcnt */ 1070Sstevel@tonic-gate cn_info, /* info */ 1080Sstevel@tonic-gate nulldev, /* identify */ 1090Sstevel@tonic-gate nulldev, /* probe */ 1100Sstevel@tonic-gate cn_attach, /* attach */ 1110Sstevel@tonic-gate cn_detach, /* detach */ 1120Sstevel@tonic-gate nodev, /* reset */ 1130Sstevel@tonic-gate &cn_cb_ops, /* driver operations */ 1147656SSherry.Moore@Sun.COM (struct bus_ops *)0, /* bus operations */ 1157656SSherry.Moore@Sun.COM NULL, /* power */ 1167656SSherry.Moore@Sun.COM ddi_quiesce_not_needed, /* quiesce */ 1170Sstevel@tonic-gate 1180Sstevel@tonic-gate }; 1190Sstevel@tonic-gate 1200Sstevel@tonic-gate /* 1210Sstevel@tonic-gate * Global variables associated with the console device: 1220Sstevel@tonic-gate * 1230Sstevel@tonic-gate * XXX: There are too many of these! 1245331Samw * moved to space.c to become resident in the kernel so that cons 1250Sstevel@tonic-gate * can be loadable. 1260Sstevel@tonic-gate */ 1270Sstevel@tonic-gate 1280Sstevel@tonic-gate extern dev_t rconsdev; /* "hardware" console */ 1290Sstevel@tonic-gate extern vnode_t *rconsvp; /* pointer to vnode for that device */ 1300Sstevel@tonic-gate 1310Sstevel@tonic-gate /* 1320Sstevel@tonic-gate * XXX: consulted in prsubr.c, for /proc entry point for obtaining ps info. 1330Sstevel@tonic-gate */ 1340Sstevel@tonic-gate extern dev_t uconsdev; /* What the user thinks is the console device */ 1350Sstevel@tonic-gate 1360Sstevel@tonic-gate /* 1370Sstevel@tonic-gate * Private driver state: 1380Sstevel@tonic-gate */ 1390Sstevel@tonic-gate 1400Sstevel@tonic-gate /* 1410Sstevel@tonic-gate * The underlying console device potentially can be opened through (at least) 1420Sstevel@tonic-gate * two paths: through this driver and through the underlying device's driver. 1430Sstevel@tonic-gate * To ensure that reference counts are meaningful and therefore that close 1440Sstevel@tonic-gate * routines are called at the right time, it's important to make sure that 1450Sstevel@tonic-gate * rconsvp's s_count field (i.e., the count on the underlying device) never 1460Sstevel@tonic-gate * has a contribution of more than one through this driver, regardless of how 1470Sstevel@tonic-gate * many times this driver's been opened. rconsopen keeps track of the 1480Sstevel@tonic-gate * necessary information to ensure this property. 1490Sstevel@tonic-gate */ 1500Sstevel@tonic-gate static uint_t rconsopen; 1510Sstevel@tonic-gate 1520Sstevel@tonic-gate 1530Sstevel@tonic-gate #include <sys/types.h> 1540Sstevel@tonic-gate #include <sys/conf.h> 1550Sstevel@tonic-gate #include <sys/param.h> 1560Sstevel@tonic-gate #include <sys/systm.h> 1570Sstevel@tonic-gate #include <sys/errno.h> 1580Sstevel@tonic-gate #include <sys/modctl.h> 1590Sstevel@tonic-gate 1600Sstevel@tonic-gate 1610Sstevel@tonic-gate extern int nodev(), nulldev(); 1620Sstevel@tonic-gate extern int dseekneg_flag; 1630Sstevel@tonic-gate extern struct mod_ops mod_driverops; 1640Sstevel@tonic-gate extern struct dev_ops cn_ops; 1650Sstevel@tonic-gate 1660Sstevel@tonic-gate /* 1670Sstevel@tonic-gate * Module linkage information for the kernel. 1680Sstevel@tonic-gate */ 1690Sstevel@tonic-gate 1700Sstevel@tonic-gate static struct modldrv modldrv = { 1710Sstevel@tonic-gate &mod_driverops, /* Type of module. This one is a pseudo driver */ 1727656SSherry.Moore@Sun.COM "Console redirection driver", 1730Sstevel@tonic-gate &cn_ops, /* driver ops */ 1740Sstevel@tonic-gate }; 1750Sstevel@tonic-gate 1760Sstevel@tonic-gate static struct modlinkage modlinkage = { 1770Sstevel@tonic-gate MODREV_1, 1780Sstevel@tonic-gate &modldrv, 1790Sstevel@tonic-gate NULL 1800Sstevel@tonic-gate }; 1810Sstevel@tonic-gate 1820Sstevel@tonic-gate int 1830Sstevel@tonic-gate _init(void) 1840Sstevel@tonic-gate { 1850Sstevel@tonic-gate return (mod_install(&modlinkage)); 1860Sstevel@tonic-gate } 1870Sstevel@tonic-gate 1880Sstevel@tonic-gate int 1890Sstevel@tonic-gate _fini(void) 1900Sstevel@tonic-gate { 1910Sstevel@tonic-gate return (EBUSY); 1920Sstevel@tonic-gate } 1930Sstevel@tonic-gate 1940Sstevel@tonic-gate int 1950Sstevel@tonic-gate _info(struct modinfo *modinfop) 1960Sstevel@tonic-gate { 1970Sstevel@tonic-gate return (mod_info(&modlinkage, modinfop)); 1980Sstevel@tonic-gate } 1990Sstevel@tonic-gate 2000Sstevel@tonic-gate /* 2010Sstevel@tonic-gate * DDI glue routines 2020Sstevel@tonic-gate */ 2030Sstevel@tonic-gate static int 2040Sstevel@tonic-gate cn_attach(dev_info_t *devi, ddi_attach_cmd_t cmd) 2050Sstevel@tonic-gate { 2060Sstevel@tonic-gate if (cmd != DDI_ATTACH) 2070Sstevel@tonic-gate return (DDI_FAILURE); 2080Sstevel@tonic-gate 2090Sstevel@tonic-gate if (ddi_create_minor_node(devi, "syscon", S_IFCHR, 2100Sstevel@tonic-gate 0, DDI_PSEUDO, NULL) == DDI_FAILURE) { 2110Sstevel@tonic-gate return (DDI_FAILURE); 2120Sstevel@tonic-gate } 2130Sstevel@tonic-gate if (ddi_create_minor_node(devi, "systty", S_IFCHR, 2140Sstevel@tonic-gate 0, DDI_PSEUDO, NULL) == DDI_FAILURE) { 2150Sstevel@tonic-gate ddi_remove_minor_node(devi, NULL); 2160Sstevel@tonic-gate return (DDI_FAILURE); 2170Sstevel@tonic-gate } 2180Sstevel@tonic-gate if (ddi_create_minor_node(devi, "console", S_IFCHR, 2190Sstevel@tonic-gate 0, DDI_PSEUDO, NULL) == DDI_FAILURE) { 2200Sstevel@tonic-gate ddi_remove_minor_node(devi, NULL); 2210Sstevel@tonic-gate return (DDI_FAILURE); 2220Sstevel@tonic-gate } 2237688SAaron.Zang@Sun.COM 2240Sstevel@tonic-gate cn_dip = devi; 2250Sstevel@tonic-gate return (DDI_SUCCESS); 2260Sstevel@tonic-gate } 2270Sstevel@tonic-gate 2280Sstevel@tonic-gate static int 2290Sstevel@tonic-gate cn_detach(dev_info_t *devi, ddi_detach_cmd_t cmd) 2300Sstevel@tonic-gate { 2310Sstevel@tonic-gate if (cmd != DDI_DETACH) 2320Sstevel@tonic-gate return (DDI_FAILURE); 2330Sstevel@tonic-gate ddi_remove_minor_node(devi, NULL); 2340Sstevel@tonic-gate uconsdev = NODEV; 2350Sstevel@tonic-gate return (DDI_SUCCESS); 2360Sstevel@tonic-gate } 2370Sstevel@tonic-gate 2380Sstevel@tonic-gate /* ARGSUSED */ 2390Sstevel@tonic-gate static int 2400Sstevel@tonic-gate cn_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result) 2410Sstevel@tonic-gate { 2420Sstevel@tonic-gate int error = DDI_FAILURE; 2430Sstevel@tonic-gate 2440Sstevel@tonic-gate switch (infocmd) { 2450Sstevel@tonic-gate case DDI_INFO_DEVT2DEVINFO: 2460Sstevel@tonic-gate if (getminor((dev_t)arg) == 0 && cn_dip != NULL) { 2470Sstevel@tonic-gate *result = (void *) cn_dip; 2480Sstevel@tonic-gate error = DDI_SUCCESS; 2490Sstevel@tonic-gate } 2500Sstevel@tonic-gate break; 2510Sstevel@tonic-gate 2520Sstevel@tonic-gate case DDI_INFO_DEVT2INSTANCE: 2530Sstevel@tonic-gate if (getminor((dev_t)arg) == 0) { 2540Sstevel@tonic-gate *result = (void *)0; 2550Sstevel@tonic-gate error = DDI_SUCCESS; 2560Sstevel@tonic-gate } 2570Sstevel@tonic-gate break; 2580Sstevel@tonic-gate 2590Sstevel@tonic-gate default: 2600Sstevel@tonic-gate break; 2610Sstevel@tonic-gate } 2620Sstevel@tonic-gate 2630Sstevel@tonic-gate return (error); 2640Sstevel@tonic-gate } 2650Sstevel@tonic-gate 2660Sstevel@tonic-gate /* 2670Sstevel@tonic-gate * XXX Caution: before allowing more than 256 minor devices on the 2680Sstevel@tonic-gate * console, make sure you understand the 'compatibility' hack 2690Sstevel@tonic-gate * in ufs_iget() that translates old dev_t's to new dev_t's. 2700Sstevel@tonic-gate * See bugid 1098104 for the sordid details. 2710Sstevel@tonic-gate */ 2720Sstevel@tonic-gate 2730Sstevel@tonic-gate /* ARGSUSED */ 2740Sstevel@tonic-gate static int 2750Sstevel@tonic-gate cnopen(dev_t *dev, int flag, int state, struct cred *cred) 2760Sstevel@tonic-gate { 2770Sstevel@tonic-gate int err; 2780Sstevel@tonic-gate static int been_here; 2790Sstevel@tonic-gate vnode_t *vp = rconsvp; 2800Sstevel@tonic-gate 2810Sstevel@tonic-gate ASSERT(cred != NULL); 2820Sstevel@tonic-gate 2830Sstevel@tonic-gate if (rconsvp == NULL) 2840Sstevel@tonic-gate return (0); 2850Sstevel@tonic-gate 286*10064SJames.Anderson@Sun.COM /* 287*10064SJames.Anderson@Sun.COM * Enable virtual console I/O for console logging if needed. 288*10064SJames.Anderson@Sun.COM */ 289*10064SJames.Anderson@Sun.COM if (vsconsvp != NULL && vsconsvp->v_stream == NULL) { 290*10064SJames.Anderson@Sun.COM if (VOP_OPEN(&vsconsvp, FREAD | FWRITE, cred, NULL) != 0) { 291*10064SJames.Anderson@Sun.COM cmn_err(CE_WARN, "cnopen: failed to open vsconsvp " 292*10064SJames.Anderson@Sun.COM "for virtual console logging"); 293*10064SJames.Anderson@Sun.COM } 294*10064SJames.Anderson@Sun.COM } 2950Sstevel@tonic-gate 2960Sstevel@tonic-gate /* 2970Sstevel@tonic-gate * XXX: Clean up inactive PIDs from previous opens if any. 2980Sstevel@tonic-gate * These would have been created as a result of an I_SETSIG 2990Sstevel@tonic-gate * issued against console. This is a workaround, and 3000Sstevel@tonic-gate * console driver must be correctly redesigned not to need 3010Sstevel@tonic-gate * this hook. 3020Sstevel@tonic-gate */ 3030Sstevel@tonic-gate if (vp->v_stream) { 3040Sstevel@tonic-gate str_cn_clean(vp); 3050Sstevel@tonic-gate } 3060Sstevel@tonic-gate 3070Sstevel@tonic-gate /* 3080Sstevel@tonic-gate * XXX: Set hook to tell /proc about underlying console. (There's 3090Sstevel@tonic-gate * gotta be a better way...) 3100Sstevel@tonic-gate */ 3110Sstevel@tonic-gate if (state != OTYP_CHR || getminor(*dev) != 0) 3120Sstevel@tonic-gate return (ENXIO); 3130Sstevel@tonic-gate if (been_here == 0) { 3140Sstevel@tonic-gate uconsdev = *dev; 3150Sstevel@tonic-gate been_here = 1; 3160Sstevel@tonic-gate if (vn_open("/dev/console", UIO_SYSSPACE, FWRITE | FNOCTTY, 3170Sstevel@tonic-gate 0, &console_vnode, 0, 0) == 0) 3180Sstevel@tonic-gate console_taskq = taskq_create("console_taskq", 3190Sstevel@tonic-gate 1, maxclsyspri - 1, LOG_LOWAT / LOG_MSGSIZE, 3200Sstevel@tonic-gate LOG_HIWAT / LOG_MSGSIZE, TASKQ_PREPOPULATE); 3210Sstevel@tonic-gate } 3220Sstevel@tonic-gate 3235331Samw if ((err = VOP_OPEN(&vp, flag, cred, NULL)) != 0) 3240Sstevel@tonic-gate return (err); 3250Sstevel@tonic-gate 3260Sstevel@tonic-gate /* 3270Sstevel@tonic-gate * The underlying driver is not allowed to have cloned itself 3280Sstevel@tonic-gate * for this open. 3290Sstevel@tonic-gate */ 3300Sstevel@tonic-gate if (vp != rconsvp) { 3310Sstevel@tonic-gate /* 3320Sstevel@tonic-gate * It might happen that someone set rconsvp to NULL 3330Sstevel@tonic-gate * whilst we were in the middle of the open. 3340Sstevel@tonic-gate */ 3350Sstevel@tonic-gate if (rconsvp == NULL) { 3365331Samw (void) VOP_CLOSE(vp, flag, 1, (offset_t)0, cred, NULL); 3370Sstevel@tonic-gate return (0); 3380Sstevel@tonic-gate } 3390Sstevel@tonic-gate cmn_err(CE_PANIC, "cnopen: cloned open"); 3400Sstevel@tonic-gate } 3410Sstevel@tonic-gate 3420Sstevel@tonic-gate rconsopen++; 3430Sstevel@tonic-gate 3440Sstevel@tonic-gate return (0); 3450Sstevel@tonic-gate } 3460Sstevel@tonic-gate 3470Sstevel@tonic-gate /* ARGSUSED */ 3480Sstevel@tonic-gate static int 3490Sstevel@tonic-gate cnclose(dev_t dev, int flag, int state, struct cred *cred) 3500Sstevel@tonic-gate { 3510Sstevel@tonic-gate int err = 0; 3520Sstevel@tonic-gate vnode_t *vp; 3530Sstevel@tonic-gate 3540Sstevel@tonic-gate /* 3550Sstevel@tonic-gate * Since this is the _last_ close, it's our last chance to close the 3560Sstevel@tonic-gate * underlying device. (Note that if someone else has the underlying 3570Sstevel@tonic-gate * hardware console device open, we won't get here, since spec_close 3580Sstevel@tonic-gate * will see s_count > 1.) 3590Sstevel@tonic-gate */ 3600Sstevel@tonic-gate if (state != OTYP_CHR) 3610Sstevel@tonic-gate return (ENXIO); 3620Sstevel@tonic-gate 3630Sstevel@tonic-gate if (rconsvp == NULL) 3640Sstevel@tonic-gate return (0); 3650Sstevel@tonic-gate 3660Sstevel@tonic-gate while ((rconsopen != 0) && ((vp = rconsvp) != NULL)) { 3675331Samw err = VOP_CLOSE(vp, flag, 1, (offset_t)0, cred, NULL); 3680Sstevel@tonic-gate if (!err) { 3690Sstevel@tonic-gate rconsopen--; 3700Sstevel@tonic-gate } 3710Sstevel@tonic-gate } 3720Sstevel@tonic-gate return (err); 3730Sstevel@tonic-gate } 3740Sstevel@tonic-gate 3750Sstevel@tonic-gate /* ARGSUSED */ 3760Sstevel@tonic-gate static int 3770Sstevel@tonic-gate cnread(dev_t dev, struct uio *uio, struct cred *cred) 3780Sstevel@tonic-gate { 3790Sstevel@tonic-gate kcondvar_t sleep_forever; 3800Sstevel@tonic-gate kmutex_t sleep_forever_mutex; 3810Sstevel@tonic-gate 3820Sstevel@tonic-gate if (rconsvp == NULL) { 3830Sstevel@tonic-gate /* 3840Sstevel@tonic-gate * Go to sleep forever. This seems like the least 3850Sstevel@tonic-gate * harmful thing to do if there's no console. 3860Sstevel@tonic-gate * EOF might be better if we're ending up single-user 3870Sstevel@tonic-gate * mode. 3880Sstevel@tonic-gate */ 3890Sstevel@tonic-gate cv_init(&sleep_forever, NULL, CV_DRIVER, NULL); 3900Sstevel@tonic-gate mutex_init(&sleep_forever_mutex, NULL, MUTEX_DRIVER, NULL); 3910Sstevel@tonic-gate mutex_enter(&sleep_forever_mutex); 3920Sstevel@tonic-gate (void) cv_wait_sig(&sleep_forever, &sleep_forever_mutex); 3930Sstevel@tonic-gate mutex_exit(&sleep_forever_mutex); 3940Sstevel@tonic-gate return (EIO); 3950Sstevel@tonic-gate } 3960Sstevel@tonic-gate 3970Sstevel@tonic-gate if (rconsvp->v_stream != NULL) 3980Sstevel@tonic-gate return (strread(rconsvp, uio, cred)); 3990Sstevel@tonic-gate else 4000Sstevel@tonic-gate return (cdev_read(rconsdev, uio, cred)); 4010Sstevel@tonic-gate } 4020Sstevel@tonic-gate 4030Sstevel@tonic-gate /* ARGSUSED */ 4040Sstevel@tonic-gate static int 4050Sstevel@tonic-gate cnwrite(dev_t dev, struct uio *uio, struct cred *cred) 4060Sstevel@tonic-gate { 4070Sstevel@tonic-gate if (rconsvp == NULL) { 4080Sstevel@tonic-gate uio->uio_resid = 0; 4090Sstevel@tonic-gate return (0); 4100Sstevel@tonic-gate } 4110Sstevel@tonic-gate 412*10064SJames.Anderson@Sun.COM /* 413*10064SJames.Anderson@Sun.COM * Output to virtual console for logging if enabled. 414*10064SJames.Anderson@Sun.COM */ 415*10064SJames.Anderson@Sun.COM if (vsconsvp != NULL && vsconsvp->v_stream != NULL) { 416*10064SJames.Anderson@Sun.COM struiod_t uiod; 417*10064SJames.Anderson@Sun.COM 418*10064SJames.Anderson@Sun.COM /* 419*10064SJames.Anderson@Sun.COM * strwrite modifies uio so need to make copy. 420*10064SJames.Anderson@Sun.COM */ 421*10064SJames.Anderson@Sun.COM (void) uiodup(uio, &uiod.d_uio, uiod.d_iov, 422*10064SJames.Anderson@Sun.COM sizeof (uiod.d_iov) / sizeof (*uiod.d_iov)); 423*10064SJames.Anderson@Sun.COM 424*10064SJames.Anderson@Sun.COM (void) strwrite(vsconsvp, &uiod.d_uio, cred); 425*10064SJames.Anderson@Sun.COM } 426*10064SJames.Anderson@Sun.COM 4270Sstevel@tonic-gate if (rconsvp->v_stream != NULL) 4280Sstevel@tonic-gate return (strwrite(rconsvp, uio, cred)); 4290Sstevel@tonic-gate else 4300Sstevel@tonic-gate return (cdev_write(rconsdev, uio, cred)); 4310Sstevel@tonic-gate } 4320Sstevel@tonic-gate 4330Sstevel@tonic-gate /* ARGSUSED */ 4340Sstevel@tonic-gate static int 4351253Slq150181 cnprivateioc(dev_t dev, int cmd, intptr_t arg, int flag, struct cred *cred, 4361253Slq150181 int *rvalp) 4371253Slq150181 { 4381253Slq150181 4391253Slq150181 /* currently we only support one ioctl */ 4401253Slq150181 if (cmd != CONS_GETTERM) 4411253Slq150181 return (EINVAL); 4421253Slq150181 4431253Slq150181 /* Confirm iwscn is immediate target of cn redirection */ 4441253Slq150181 if (rconsvp != wsconsvp) 4451253Slq150181 return (ENODEV); 4461253Slq150181 4471253Slq150181 /* 4481253Slq150181 * If the redirection client is not wc, it should return 4491253Slq150181 * error upon receiving the CONS_GETTERM ioctl. 4501253Slq150181 * 4511253Slq150181 * if it is wc, we know that the target supports the CONS_GETTERM 4521253Slq150181 * ioctl, which very conviently has the exact same data 4531253Slq150181 * format as this ioctl... so let's just pass it on. 4541253Slq150181 */ 4551253Slq150181 return (cdev_ioctl(rconsdev, CONS_GETTERM, arg, flag, cred, rvalp)); 4561253Slq150181 } 4571253Slq150181 4581253Slq150181 /* ARGSUSED */ 4591253Slq150181 static int 4600Sstevel@tonic-gate cnioctl(dev_t dev, int cmd, intptr_t arg, int flag, struct cred *cred, 4610Sstevel@tonic-gate int *rvalp) 4620Sstevel@tonic-gate { 4630Sstevel@tonic-gate if (rconsvp == NULL) 4640Sstevel@tonic-gate return (0); 4650Sstevel@tonic-gate 4661253Slq150181 if ((cmd & _CNIOC_MASK) == _CNIOC) 4671253Slq150181 return (cnprivateioc(dev, cmd, arg, flag, cred, rvalp)); 4681253Slq150181 else if (rconsvp->v_stream != NULL) 4690Sstevel@tonic-gate return (strioctl(rconsvp, cmd, arg, flag, U_TO_K, cred, 4700Sstevel@tonic-gate rvalp)); 4710Sstevel@tonic-gate else 4720Sstevel@tonic-gate return (cdev_ioctl(rconsdev, cmd, arg, flag, cred, rvalp)); 4730Sstevel@tonic-gate } 4740Sstevel@tonic-gate 4750Sstevel@tonic-gate /* ARGSUSED */ 4760Sstevel@tonic-gate static int 4770Sstevel@tonic-gate cnpoll(dev_t dev, short events, int anyyet, short *reventsp, 4780Sstevel@tonic-gate struct pollhead **phpp) 4790Sstevel@tonic-gate { 4800Sstevel@tonic-gate if (rconsvp == NULL) 4810Sstevel@tonic-gate return (nochpoll(dev, events, anyyet, reventsp, phpp)); 4820Sstevel@tonic-gate 4830Sstevel@tonic-gate if (rconsvp->v_stream != NULL) 4840Sstevel@tonic-gate return (strpoll(rconsvp->v_stream, events, anyyet, reventsp, 4850Sstevel@tonic-gate phpp)); 4860Sstevel@tonic-gate else 4870Sstevel@tonic-gate return (cdev_poll(rconsdev, events, anyyet, reventsp, phpp)); 4880Sstevel@tonic-gate } 489