03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER START
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The contents of this file are subject to the terms of the
193974072f41a843678abf5f61979c748687e66bSherry Moore * Common Development and Distribution License (the "License").
193974072f41a843678abf5f61979c748687e66bSherry Moore * You may not use this file except in compliance with the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or http://www.opensolaris.org/os/licensing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * See the License for the specific language governing permissions
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and limitations under the License.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When distributing Covered Code, include this CDDL HEADER in each
03831d35f7499c87d51205817c93e9a8d42c4baestevel * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If applicable, add the following below this CDDL HEADER, with the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * fields enclosed by brackets "[]" replaced with your own identifying
03831d35f7499c87d51205817c93e9a8d42c4baestevel * information: Portions Copyright [yyyy] [name of copyright owner]
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * CDDL HEADER END
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use is subject to license terms.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * MT STREAMS Virtual Console Device Driver
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/types.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/open.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/param.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/systm.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/signal.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/cred.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/user.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/proc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/disp.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/vnode.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/uio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/buf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/file.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/kmem.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stat.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stream.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/stropts.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/strsubr.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/strsun.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/tty.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ptyvar.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/poll.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/debug.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/conf.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/ddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sunddi.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/errno.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/modctl.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sc_cvc.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/sc_cvcio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel#include <sys/iosramio.h>
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int cvc_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int cvc_attach(dev_info_t *, ddi_attach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int cvc_detach(dev_info_t *, ddi_detach_cmd_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int cvc_open(register queue_t *, dev_t *, int, int, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int cvc_close(queue_t *, int, cred_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int cvc_wput(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int cvc_wsrv(queue_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void cvc_ioctl(queue_t *, mblk_t *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void cvc_reioctl(void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void cvc_input_daemon(void);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void cvc_send_to_iosram(mblk_t **chainpp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void cvc_flush_queue(void *);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void cvc_iosram_ops(uint8_t);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void cvc_getstr(char *cp);
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void cvc_win_resize(int clear_flag);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define ESUCCESS 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifndef TRUE
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define TRUE 1
03831d35f7499c87d51205817c93e9a8d42c4baestevel#define FALSE 0
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Private copy of devinfo pointer; cvc_info uses it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic dev_info_t *cvcdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This structure reflects the layout of data in CONI and CONO. If you are
03831d35f7499c87d51205817c93e9a8d42c4baestevel * going to add fields that don't get written into those chunks, be sure to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * place them _after_ the buffer field.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct cvc_buf {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ushort_t count;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t buffer[MAX_XFER_COUTPUT];
03831d35f7499c87d51205817c93e9a8d42c4baestevel} cvc_buf_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baesteveltypedef struct cvc_s {
03831d35f7499c87d51205817c93e9a8d42c4baestevel bufcall_id_t cvc_wbufcid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tty_common_t cvc_tty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel} cvc_t;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_t cvc_common_tty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct module_info cvcm_info = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel 1313, /* mi_idnum Bad luck number ;-) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc", /* mi_idname */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, /* mi_minpsz */
03831d35f7499c87d51205817c93e9a8d42c4baestevel INFPSZ, /* mi_maxpsz */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 2048, /* mi_hiwat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel 2048 /* mi_lowat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct qinit cvcrinit = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_putp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_srvp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_open, /* qi_qopen */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_close, /* qi_qclose */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_qadmin */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &cvcm_info, /* qi_minfo */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL /* qi_mstat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct qinit cvcwinit = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_wput, /* qi_putp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_wsrv, /* qi_srvp */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_open, /* qi_qopen */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_close, /* qi_qclose */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* qi_qadmin */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &cvcm_info, /* qi_minfo */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL /* qi_mstat */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstruct streamtab cvcinfo = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &cvcrinit, /* st_rdinit */
03831d35f7499c87d51205817c93e9a8d42c4baestevel &cvcwinit, /* st_wrinit */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, /* st_muxrinit */
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL /* st_muxwrinit */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic krwlock_t cvclock; /* lock protecting everything here */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic queue_t *cvcinput_q; /* queue for console input */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic queue_t *cvcoutput_q; /* queue for console output */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int cvc_instance = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int cvc_stopped = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int cvc_suspended = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelkthread_id_t cvc_input_daemon_thread; /* just to aid debugging */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t cvcmutex; /* protects input */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic kmutex_t cvc_iosram_input_mutex; /* protects IOSRAM inp buff */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int input_ok = 0; /* true when stream is valid */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int via_iosram = 0; /* toggle switch */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic timeout_id_t cvc_timeout_id = (timeout_id_t)-1;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int input_daemon_started = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* debugging functions */
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baesteveluint32_t cvc_dbg_flags = 0x0;
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void cvc_dbg(uint32_t flag, char *fmt,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5);
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Module linkage information for the kernel.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelDDI_DEFINE_STREAM_OPS(cvcops, nulldev, nulldev, cvc_attach, cvc_detach,
193974072f41a843678abf5f61979c748687e66bSherry Moore nodev, cvc_info, (D_NEW|D_MTPERQ|D_MP), &cvcinfo,
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_quiesce_not_supported);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern int nodev(), nulldev();
03831d35f7499c87d51205817c93e9a8d42c4baestevelextern struct mod_ops mod_driverops;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modldrv modldrv = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel &mod_driverops, /* Type of module. This one is a pseudo driver */
193974072f41a843678abf5f61979c748687e66bSherry Moore "CVC driver 'cvc'",
03831d35f7499c87d51205817c93e9a8d42c4baestevel &cvcops, /* driver ops */
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic struct modlinkage modlinkage = {
03831d35f7499c87d51205817c93e9a8d42c4baestevel MODREV_1,
03831d35f7499c87d51205817c93e9a8d42c4baestevel &modldrv,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL
03831d35f7499c87d51205817c93e9a8d42c4baestevel};
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_init()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int status;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel status = mod_install(&modlinkage);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (status == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&cvcmutex, NULL, MUTEX_DEFAULT, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (status);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_fini()
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (EBUSY);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevel_info(struct modinfo *modinfop)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (mod_info(&modlinkage, modinfop));
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * DDI glue routines.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel static char been_here = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd == DDI_RESUME) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_suspended = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcinput_q != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(WR(cvcinput_q));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cvcmutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!been_here) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel been_here = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_init(&cvc_iosram_input_mutex, NULL, MUTEX_DEFAULT, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_init(&cvclock, NULL, RW_DRIVER, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_instance = ddi_get_instance(devi);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel#if defined(DEBUG)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE,
193974072f41a843678abf5f61979c748687e66bSherry Moore "cvc_attach: called multiple times!! (instance = %d)",
193974072f41a843678abf5f61979c748687e66bSherry Moore ddi_get_instance(devi));
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cvcmutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cvcmutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_create_minor_node(devi, "cvc", S_IFCHR,
03831d35f7499c87d51205817c93e9a8d42c4baestevel 0, NULL, NULL) == DDI_FAILURE) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_minor_node(devi, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (-1);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvcdip = devi;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvcinput_q = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvcoutput_q = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG0(CVC_DBG_ATTACH, "Attached");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd == DDI_SUSPEND) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_suspended = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cmd != DDI_DETACH) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_FAILURE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX this doesn't even begin to address the detach
03831d35f7499c87d51205817c93e9a8d42c4baestevel * issues - it doesn't terminate the outstanding thread,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it doesn't clean up mutexes, kill the timeout routine
03831d35f7499c87d51205817c93e9a8d42c4baestevel * etc.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvc_instance == ddi_get_instance(dip)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel ddi_remove_minor_node(dip, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG0(CVC_DBG_DETACH, "Detached");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (DDI_SUCCESS);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int error;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (infocmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_INFO_DEVT2DEVINFO:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcdip == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = DDI_FAILURE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = (void *)cvcdip;
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case DDI_INFO_DEVT2INSTANCE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *result = (void *)0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = DDI_FAILURE;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_open(register queue_t *q, dev_t *devp, int flag, int sflag, cred_t *crp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int unit = getminor(*devp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int err = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tty_common_t *tty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_t *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (unit != 0)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (ENXIO);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (q->q_ptr)
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = (cvc_t *)&cvc_common_tty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero((caddr_t)cp, sizeof (cvc_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->cvc_wbufcid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tty = &cp->cvc_tty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tty->t_readq = q;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tty->t_writeq = WR(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel WR(q)->q_ptr = q->q_ptr = (caddr_t)cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvcinput_q = RD(q); /* save for cvc_redir */
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocson(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cvcmutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel input_ok = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start the thread that handles input polling if it hasn't been started
03831d35f7499c87d51205817c93e9a8d42c4baestevel * previously.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!input_daemon_started) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel input_daemon_started = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cvcmutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_input_daemon_thread = thread_create(NULL, 0,
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_input_daemon, NULL, 0, &p0, TS_RUN, minclsyspri);
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG0(CVC_DBG_IOSRAM_RD, "Started input daemon");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cvcmutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Set the console window size.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cvc_iosram_input_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_win_resize(FALSE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cvc_iosram_input_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG0(CVC_DBG_OPEN, "Plumbed successfully");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_close(queue_t *q, int flag, cred_t *crp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register int err = DDI_SUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register cvc_t *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cvcmutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel input_ok = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cvcmutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = q->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cp->cvc_wbufcid != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unbufcall(cp->cvc_wbufcid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel ttycommon_close(&cp->cvc_tty);
03831d35f7499c87d51205817c93e9a8d42c4baestevel WR(q)->q_ptr = q->q_ptr = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvcinput_q = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel bzero((caddr_t)cp, sizeof (cvc_t));
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocsoff(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG0(CVC_DBG_CLOSE, "Un-plumbed successfully");
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (err);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_wput()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cn driver does a strwrite of console output data to rconsvp which has
03831d35f7499c87d51205817c93e9a8d42c4baestevel * been set by consconfig. The data enters the cvc stream at the streamhead
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and flows thru ttycompat and ldterm which have been pushed on the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * stream. Console output data gets sent out either to cvcredir, if the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * network path is available and selected, or to IOSRAM otherwise. Data is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sent to cvcredir via its read queue (cvcoutput_q, which gets set in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_register()). If the IOSRAM path is selected, or if previous mblks
03831d35f7499c87d51205817c93e9a8d42c4baestevel * are currently queued up for processing, the new mblk will be queued
03831d35f7499c87d51205817c93e9a8d42c4baestevel * and handled later on by cvc_wsrv.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_wput(queue_t *q, mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&cvclock, RW_READER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG2(CVC_DBG_WPUT, "mp 0x%x db_type 0x%x",
193974072f41a843678abf5f61979c748687e66bSherry Moore mp, mp->b_datap->db_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (mp->b_datap->db_type) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_IOCTL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_CTL: {
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (iocp->ioc_cmd) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * These ioctls are only supposed to be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processed after everything else that is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * already queued awaiting processing, so throw
03831d35f7499c87d51205817c93e9a8d42c4baestevel * them on the queue and let cvc_wsrv handle
03831d35f7499c87d51205817c93e9a8d42c4baestevel * them.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel case TCSETSW:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case TCSETSF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case TCSETAW:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case TCSETAF:
03831d35f7499c87d51205817c93e9a8d42c4baestevel case TCSBRK:
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) putq(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_ioctl(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_FLUSH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*mp->b_rptr & FLUSHW) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Flush our write queue.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(q, FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mp->b_rptr &= ~FLUSHW;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*mp->b_rptr & FLUSHR) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel flushq(RD(q), FLUSHDATA);
03831d35f7499c87d51205817c93e9a8d42c4baestevel qreply(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_STOP:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_stopped = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_START:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_stopped = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(q); /* Start up delayed messages */
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_READ:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ldterm handles this (VMIN/VTIME processing).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cvc_wput: unexpected mblk type - mp ="
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki " 0x%p, type = 0x%x", (void *)mp,
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki mp->b_datap->db_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case M_DATA:
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If there are other mblks queued up for transmission,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * or we're using IOSRAM either because cvcredir hasn't
03831d35f7499c87d51205817c93e9a8d42c4baestevel * registered yet or because we were configured that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * way, or cvc has been stopped or suspended, place this
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mblk on the input queue for future processing.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Otherwise, hand it off to cvcredir for transmission
03831d35f7499c87d51205817c93e9a8d42c4baestevel * via the network.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (q->q_first != NULL || cvcoutput_q == NULL ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel via_iosram || cvc_stopped == 1 ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_suspended == 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putq(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX - should canputnext be called here?
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Starfire's cvc doesn't do that, and it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * appears to work anyway.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnext(cvcoutput_q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&cvclock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_wsrv()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_wsrv handles mblks that have been queued by cvc_wput either because
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the IOSRAM path was selected or the queue contained preceding mblks. To
03831d35f7499c87d51205817c93e9a8d42c4baestevel * optimize processing (particularly if the IOSRAM path is selected), all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mblks are pulled off of the queue and chained together. Then, if there
03831d35f7499c87d51205817c93e9a8d42c4baestevel * are any mblks on the chain, they are either forwarded to cvcredir or
03831d35f7499c87d51205817c93e9a8d42c4baestevel * sent for IOSRAM processing as appropriate given current circumstances.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM processing may not be able to handle all of the data in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * chain, in which case the remaining data is placed back on the queue and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * a timeout routine is registered to reschedule cvc_wsrv in the future.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Automatic scheduling of the queue is disabled (noenable(q)) while
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_wsrv is running to avoid superfluous calls.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic int
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_wsrv(queue_t *q)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *total_mp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvc_stopped == 1 || cvc_suspended == 1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&cvclock, RW_READER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel noenable(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If there's already a timeout registered for scheduling this routine
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the future, it's a safe bet that we don't want to run right now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvc_timeout_id != (timeout_id_t)-1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel enableok(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&cvclock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start by linking all of the queued M_DATA mblks into a single chain
03831d35f7499c87d51205817c93e9a8d42c4baestevel * so we can flush as much as possible to IOSRAM (if we choose that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * route).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((mp = getq(q)) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Technically, certain IOCTLs are supposed to be processed only
03831d35f7499c87d51205817c93e9a8d42c4baestevel * after all preceding data has completely "drained". In an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * attempt to support that, we delay processing of those IOCTLs
03831d35f7499c87d51205817c93e9a8d42c4baestevel * until this point. It is still possible that an IOCTL will be
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processed before all preceding data is drained, for instance
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in the case where not all of the preceding data would fit
03831d35f7499c87d51205817c93e9a8d42c4baestevel * into IOSRAM and we have to place it back on the queue.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * However, since none of these IOCTLs really appear to have any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * relevance for cvc, and we weren't supporting delayed
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processing at _all_ previously, this partial implementation
03831d35f7499c87d51205817c93e9a8d42c4baestevel * should suffice. (Fully implementing the delayed IOCTL
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processing would be unjustifiably difficult given the nature
03831d35f7499c87d51205817c93e9a8d42c4baestevel * of the underlying IOSRAM console protocol.)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->b_datap->db_type == M_IOCTL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_ioctl(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We know that only M_IOCTL and M_DATA blocks are placed on our
03831d35f7499c87d51205817c93e9a8d42c4baestevel * queue. Since this block isn't an M_IOCTL, it must be M_DATA.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (total_mp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel linkb(total_mp, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel total_mp = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Do we actually have anything to do?
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (total_mp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel enableok(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&cvclock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Yes, we do, so send the data to either cvcredir or IOSRAM as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * appropriate. In the latter case, we might not be able to transmit
03831d35f7499c87d51205817c93e9a8d42c4baestevel * everything right now, so re-queue the remainder.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcoutput_q != NULL && !via_iosram) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG0(CVC_DBG_NETWORK_WR, "Sending to cvcredir.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX - should canputnext be called here? Starfire's cvc
03831d35f7499c87d51205817c93e9a8d42c4baestevel * doesn't do that, and it appears to work anyway.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnext(cvcoutput_q, total_mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG0(CVC_DBG_IOSRAM_WR, "Send to IOSRAM.");
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_send_to_iosram(&total_mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (total_mp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putbq(q, total_mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If there is still data queued at this point, make sure the queue
03831d35f7499c87d51205817c93e9a8d42c4baestevel * gets scheduled again after an appropriate delay (which has been
03831d35f7499c87d51205817c93e9a8d42c4baestevel * somewhat arbitrarily selected as half of the SC's input polling
03831d35f7499c87d51205817c93e9a8d42c4baestevel * frequency).
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel enableok(q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (q->q_first != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvc_timeout_id == (timeout_id_t)-1) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_timeout_id = timeout(cvc_flush_queue,
03831d35f7499c87d51205817c93e9a8d42c4baestevel NULL, drv_usectohz(CVC_IOSRAM_POLL_USECS / 2));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&cvclock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_ioctl()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * handle normal console ioctls.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_ioctl(register queue_t *q, register mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register cvc_t *cp = q->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int datasize;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Let ttycommon_ioctl take the first shot at processing the ioctl. If
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it fails because it can't allocate memory, schedule processing of the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ioctl later when a proper buffer is available. The mblk that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * couldn't be processed will have been stored in the tty structure by
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ttycommon_ioctl.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel datasize = ttycommon_ioctl(&cp->cvc_tty, q, mp, &error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (datasize != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cp->cvc_wbufcid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel unbufcall(cp->cvc_wbufcid);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->cvc_wbufcid = bufcall(datasize, BPRI_HI, cvc_reioctl, cp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ttycommon_ioctl didn't do anything, but there's nothing we really
03831d35f7499c87d51205817c93e9a8d42c4baestevel * support either with the exception of TCSBRK, which is supported
03831d35f7499c87d51205817c93e9a8d42c4baestevel * only to appear a bit more like a serial device for software that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * expects TCSBRK to work.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (error != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct iocblk *iocp = (struct iocblk *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_cmd == TCSBRK) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocack(q, mp, 0, 0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel miocnak(q, mp, 0, EINVAL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel qreply(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_redir()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from cvcredir:cvcr_wput() to handle console input
03831d35f7499c87d51205817c93e9a8d42c4baestevel * data. This routine puts the cvcredir write (downstream) data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * onto the cvc read (upstream) queues.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_redir(mblk_t *mp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register struct iocblk *iocp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rv = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This function shouldn't be called if cvcredir hasn't registered yet.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcinput_q == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Need to let caller know that it may be necessary for them to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * free the message buffer, so return 0.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG0(CVC_DBG_REDIR, "redirection not enabled");
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cvc_redir: cvcinput_q NULL!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (0);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG1(CVC_DBG_REDIR, "type 0x%x", mp->b_datap->db_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp->b_datap->db_type == M_DATA) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX - should canputnext be called here? Starfire's cvc
03831d35f7499c87d51205817c93e9a8d42c4baestevel * doesn't do that, and it appears to work anyway.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG1(CVC_DBG_NETWORK_RD, "Sending mp 0x%x", mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnext(cvcinput_q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (mp->b_datap->db_type == M_IOCTL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The cvcredir driver filters out ioctl mblks we wouldn't
03831d35f7499c87d51205817c93e9a8d42c4baestevel * understand, so we don't have to check for every conceivable
03831d35f7499c87d51205817c93e9a8d42c4baestevel * ioc_cmd. However, additional ioctls may be supported (again)
03831d35f7499c87d51205817c93e9a8d42c4baestevel * some day, so the code is structured to check the value even
03831d35f7499c87d51205817c93e9a8d42c4baestevel * though there's only one that is currently supported.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel iocp = (struct iocblk *)mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iocp->ioc_cmd == CVC_DISCONNECT) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnextctl(cvcinput_q, M_HANGUP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Since we don't know what this mblk is, we're not going to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * process it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG1(CVC_DBG_REDIR, "unrecognized mblk type: %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_datap->db_type);
03831d35f7499c87d51205817c93e9a8d42c4baestevel rv = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (rv);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_register()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from cvcredir to register it's queues. cvc
03831d35f7499c87d51205817c93e9a8d42c4baestevel * receives data from cn via the streamhead and sends it to cvcredir
03831d35f7499c87d51205817c93e9a8d42c4baestevel * via pointers to cvcredir's queues.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelint
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_register(queue_t *q)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int error = -1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcinput_q == NULL)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cvc_register: register w/ no console open!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&cvclock, RW_WRITER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcoutput_q == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvcoutput_q = RD(q); /* Make sure its the upstream q */
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocson(cvcoutput_q); /* must be done within cvclock */
03831d35f7499c87d51205817c93e9a8d42c4baestevel error = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cmn_err will call us, so release lock.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&cvclock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcoutput_q == q)
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cvc_register: duplicate q!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cvc_register: nondup q = 0x%p",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&cvclock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return (error);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_unregister()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * called from cvcredir to clear pointers to its queues.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvcredir no longer wants to send or receive data.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_unregister(queue_t *q)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&cvclock, RW_WRITER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (q == cvcoutput_q) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel qprocsoff(cvcoutput_q); /* must be done within cvclock */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvcoutput_q = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&cvclock);
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki cmn_err(CE_WARN, "cvc_unregister: q = 0x%p not registered",
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void *)q);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&cvclock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_reioctl()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Retry an "ioctl", now that "bufcall" claims we may be able
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to allocate the buffer we need.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_reioctl(void *unit)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel register queue_t *q;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel register cvc_t *cp = (cvc_t *)unit;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * The bufcall is no longer pending.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!cp->cvc_wbufcid) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->cvc_wbufcid = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((q = cp->cvc_tty.t_writeq) == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((mp = cp->cvc_tty.t_iocpending) != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* not pending any more */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp->cvc_tty.t_iocpending = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_ioctl(q, mp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_iosram_ops()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Process commands sent to cvc from netcon_server via IOSRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_iosram_ops(uint8_t op)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rval = ESUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static uint8_t stale_op = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(MUTEX_HELD(&cvc_iosram_input_mutex));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG1(CVC_DBG_IOSRAM_CNTL, "cntl msg 0x%x", op);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If this is a repeated notice of a command that was previously
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processed but couldn't be cleared due to EAGAIN (tunnel switch in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * progress), just clear the data_valid flag and return.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (op == stale_op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (iosram_set_flag(IOSRAM_KEY_CONC, IOSRAM_DATA_INVALID,
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_INT_NONE) == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel stale_op = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel stale_op = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (op) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_IOSRAM_BREAK: /* A console break (L1-A) */
03831d35f7499c87d51205817c93e9a8d42c4baestevel abort_sequence_enter((char *)NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_IOSRAM_DISCONNECT: /* Break connection, hang up */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcinput_q)
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnextctl(cvcinput_q, M_HANGUP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_IOSRAM_VIA_NET: /* console via network */
03831d35f7499c87d51205817c93e9a8d42c4baestevel via_iosram = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_IOSRAM_VIA_IOSRAM: /* console via iosram */
03831d35f7499c87d51205817c93e9a8d42c4baestevel via_iosram = 1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Tell cvcd to close any network connection it has.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&cvclock, RW_READER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcoutput_q != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnextctl(cvcoutput_q, M_HANGUP);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&cvclock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_IOSRAM_WIN_RESIZE: /* console window size data */
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * In the case of window resizing, we don't want to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * record a stale_op value because we should always use
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the most recent winsize info, which could change
03831d35f7499c87d51205817c93e9a8d42c4baestevel * between the time that we fail to clear the flag and
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the next time we try to process the command. So,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * we'll just let cvc_win_resize clear the data_valid
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flag itself (hence the TRUE parameter) and not worry
03831d35f7499c87d51205817c93e9a8d42c4baestevel * about whether or not it succeeds.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_win_resize(TRUE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* NOTREACHED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cvc: unknown IOSRAM opcode %d", op);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Clear CONC's data_valid flag to indicate that the chunk is available
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for further communications. If the flag can't be cleared due to an
03831d35f7499c87d51205817c93e9a8d42c4baestevel * error, record the op value so we'll know to ignore it when we see it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * on the next poll.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = iosram_set_flag(IOSRAM_KEY_CONC, IOSRAM_DATA_INVALID,
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_INT_NONE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel stale_op = op;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_iosram_ops: set flag for cntlbuf ret %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_send_to_iosram()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Flush as much data as possible to the CONO chunk. If successful, free
03831d35f7499c87d51205817c93e9a8d42c4baestevel * any mblks that were completely transmitted, update the b_rptr field in
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the first remaining mblk if it was partially transmitted, and update the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * caller's pointer to the new head of the mblk chain. Since the software
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that will be pulling this data out of IOSRAM (dxs on the SC) is just
03831d35f7499c87d51205817c93e9a8d42c4baestevel * polling at some frequency, we avoid attempts to flush data to IOSRAM any
03831d35f7499c87d51205817c93e9a8d42c4baestevel * faster than a large divisor of that polling frequency.
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Note that "cvc_buf_t out" is only declared "static" to keep it from
03831d35f7499c87d51205817c93e9a8d42c4baestevel * being allocated on the stack. Allocating 1K+ structures on the stack
03831d35f7499c87d51205817c93e9a8d42c4baestevel * seems rather antisocial.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_send_to_iosram(mblk_t **chainpp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rval;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t dvalid;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uchar_t *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *last_empty_mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static clock_t last_flush = (clock_t)-1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel static cvc_buf_t out; /* see note above about static */
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel ASSERT(chainpp != NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We _do_ have something to do, right?
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (*chainpp == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We can actually increase throughput by throttling back on attempts to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * flush data to IOSRAM, since trying to write every little bit of data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * as it shows up will actually generate more delays waiting for the SC
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to pick up each of those bits. Instead, we'll avoid attempting to
03831d35f7499c87d51205817c93e9a8d42c4baestevel * write data to IOSRAM any faster than half of the polling frequency we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * expect the SC to be using.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (ddi_get_lbolt() - last_flush <
03831d35f7499c87d51205817c93e9a8d42c4baestevel drv_usectohz(CVC_IOSRAM_POLL_USECS / 2)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If IOSRAM is inaccessible or the CONO chunk still holds data that
03831d35f7499c87d51205817c93e9a8d42c4baestevel * hasn't been picked up by the SC, there's nothing we can do right now.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = iosram_get_flag(IOSRAM_KEY_CONO, &dvalid, NULL);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rval != 0) || (dvalid == IOSRAM_DATA_VALID)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rval != 0) && (rval != EAGAIN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cvc_send_to_iosram: get_flag ret %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy up to MAX_XFER_COUTPUT chars from the mblk chain into a buffer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Don't change any of the mblks just yet, since we can't be certain
03831d35f7499c87d51205817c93e9a8d42c4baestevel * that we'll be successful in writing data to the CONO chunk.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel out.count = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = *chainpp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = mp->b_rptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_empty_mp = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((mp != NULL) && (out.count < MAX_XFER_COUTPUT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Process as many of the characters in the current mblk as
03831d35f7499c87d51205817c93e9a8d42c4baestevel * possible.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel while ((cp != mp->b_wptr) && (out.count < MAX_XFER_COUTPUT)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel out.buffer[out.count++] = *cp++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Did we process that entire mblk? If so, move on to the next
03831d35f7499c87d51205817c93e9a8d42c4baestevel * one. If not, we're done filling the buffer even if there's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * space left, because apparently there wasn't room to process
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the next character.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cp != mp->b_wptr) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * When this loop terminates, last_empty_mp will point to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * last mblk that was completely processed, mp will point to the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * following mblk (or NULL if no more mblks exist), and cp will
03831d35f7499c87d51205817c93e9a8d42c4baestevel * point to the first untransmitted character in the mblk
03831d35f7499c87d51205817c93e9a8d42c4baestevel * pointed to by mp. We'll need this data to update the mblk
03831d35f7499c87d51205817c93e9a8d42c4baestevel * chain if all of the data is successfully transmitted.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_empty_mp = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp = mp->b_cont;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = (mp != NULL) ? mp->b_rptr : NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we succeeded in preparing some data, try to transmit it through
03831d35f7499c87d51205817c93e9a8d42c4baestevel * IOSRAM. First write the count and the data, which can be done in a
03831d35f7499c87d51205817c93e9a8d42c4baestevel * single operation thanks to the buffer structure we use, then set the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * data_valid flag if the first step succeeded.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (out.count != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = iosram_wr(IOSRAM_KEY_CONO, COUNT_OFFSET,
03831d35f7499c87d51205817c93e9a8d42c4baestevel CONSBUF_COUNT_SIZE + out.count, (caddr_t)&out);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rval != 0) && (rval != EAGAIN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cvc_putc: write ret %d", rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* if the data write succeeded, set the data_valid flag */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = iosram_set_flag(IOSRAM_KEY_CONO,
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_DATA_VALID, IOSRAM_INT_NONE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rval != 0) && (rval != EAGAIN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_putc: set flags for outbuf ret %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If we successfully transmitted any data, modify the caller's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mblk chain to remove the data that was transmitted, freeing
03831d35f7499c87d51205817c93e9a8d42c4baestevel * all mblks that were completely processed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_flush = ddi_get_lbolt();
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If any data is left over, update the b_rptr field of
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the first remaining mblk in case some of its data was
03831d35f7499c87d51205817c93e9a8d42c4baestevel * processed.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mp->b_rptr = cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If any mblks have been emptied, unlink them from the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * residual chain, free them, and update the caller's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * mblk pointer.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (last_empty_mp != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel last_empty_mp->b_cont = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(*chainpp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel *chainpp = mp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_flush_queue()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Tell the STREAMS subsystem to schedule cvc_wsrv to process the queue we
03831d35f7499c87d51205817c93e9a8d42c4baestevel * use to gather console output.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_flush_queue(void *notused)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_enter(&cvclock, RW_WRITER);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcinput_q != NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel qenable(WR(cvcinput_q));
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_timeout_id = (timeout_id_t)-1;
03831d35f7499c87d51205817c93e9a8d42c4baestevel rw_exit(&cvclock);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_getstr()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Poll IOSRAM for console input while available.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_getstr(char *cp)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel short count;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t command = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rval = ESUCCESS;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t dvalid = IOSRAM_DATA_INVALID;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint8_t intrpending = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cvc_iosram_input_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel while (dvalid == IOSRAM_DATA_INVALID) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check the CONC data_valid flag to see if a control message is
03831d35f7499c87d51205817c93e9a8d42c4baestevel * available.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = iosram_get_flag(IOSRAM_KEY_CONC, &dvalid, &intrpending);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rval != 0) && (rval != EAGAIN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_getstr: get flag for cntl ret %d", rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If a control message is available, try to read and process
03831d35f7499c87d51205817c93e9a8d42c4baestevel * it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((dvalid == IOSRAM_DATA_VALID) && (rval == 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* read the control reg offset */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = iosram_rd(IOSRAM_KEY_CONC,
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_CTL_OFFSET(command), CVC_CTL_SIZE(command),
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)&command);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rval != 0) && (rval != EAGAIN)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_getstr: read for command ret %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* process the cntl msg and clear the data_valid flag */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval == 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_iosram_ops(command);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Check the CONI data_valid flag to see if console input data
03831d35f7499c87d51205817c93e9a8d42c4baestevel * is available.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = iosram_get_flag(IOSRAM_KEY_CONI, &dvalid, &intrpending);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rval != 0) && (rval != EAGAIN)) {
193974072f41a843678abf5f61979c748687e66bSherry Moore cmn_err(CE_WARN,
193974072f41a843678abf5f61979c748687e66bSherry Moore "cvc_getstr: get flag for inbuf ret %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((rval != 0) || (dvalid != IOSRAM_DATA_VALID)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Try to read the count.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = iosram_rd(IOSRAM_KEY_CONI, COUNT_OFFSET,
03831d35f7499c87d51205817c93e9a8d42c4baestevel CONSBUF_COUNT_SIZE, (caddr_t)&count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_getstr: read for count ret %d", rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * If there is data to be read, try to read it.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (count != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = iosram_rd(IOSRAM_KEY_CONI, DATA_OFFSET, count,
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)cp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_getstr: read for count ret %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel goto retry;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp[count] = '\0';
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Try to clear the data_valid flag to indicate that whatever
03831d35f7499c87d51205817c93e9a8d42c4baestevel * was in CONI was read successfully. If successful, and some
03831d35f7499c87d51205817c93e9a8d42c4baestevel * data was read, break out of the loop to return to the caller.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval = iosram_set_flag(IOSRAM_KEY_CONI, IOSRAM_DATA_INVALID,
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_INT_NONE);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_getstr: set flag for inbuf ret %d",
03831d35f7499c87d51205817c93e9a8d42c4baestevel rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else if (count != 0) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_DBG1(CVC_DBG_IOSRAM_RD, "Read 0x%x", count);
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Use a smaller delay between checks of IOSRAM for input
03831d35f7499c87d51205817c93e9a8d42c4baestevel * when cvcd/cvcredir are not running or "via_iosram" has
03831d35f7499c87d51205817c93e9a8d42c4baestevel * been set.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * We don't go away completely when i/o is going through the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * network via cvcd since a command may be sent via IOSRAM
03831d35f7499c87d51205817c93e9a8d42c4baestevel * to switch if the network is down or hung.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelretry:
03831d35f7499c87d51205817c93e9a8d42c4baestevel if ((cvcoutput_q == NULL) || (via_iosram))
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(drv_usectohz(CVC_IOSRAM_POLL_USECS));
03831d35f7499c87d51205817c93e9a8d42c4baestevel else
03831d35f7499c87d51205817c93e9a8d42c4baestevel delay(drv_usectohz(CVC_IOSRAM_POLL_USECS * 10));
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cvc_iosram_input_mutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_input_daemon()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * this function runs as a separate kernel thread and polls IOSRAM for
03831d35f7499c87d51205817c93e9a8d42c4baestevel * input, and possibly put it on read stream for the console.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * There are two poll rates (implemented in cvc_getstr):
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 100 000 uS (10 Hz) - no cvcd communications || via_iosram
03831d35f7499c87d51205817c93e9a8d42c4baestevel * 1000 000 uS ( 1 Hz) - cvcd communications
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This continues to run even if there are network console communications
03831d35f7499c87d51205817c93e9a8d42c4baestevel * in order to handle out-of-band signaling.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel/* ARGSUSED */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_input_daemon(void)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char linebuf[MAX_XFER_CINPUT + 1];
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mblk_t *mbp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int c;
03831d35f7499c87d51205817c93e9a8d42c4baestevel int dropped_read = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (;;) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_getstr(linebuf);
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel mbp = allocb(strlen(linebuf), BPRI_MED);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (mbp == NULL) { /* drop it & go on if no buffer */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (!dropped_read) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN, "cvc_input_daemon: "
03831d35f7499c87d51205817c93e9a8d42c4baestevel "dropping IOSRAM reads");
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel dropped_read++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel continue;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (dropped_read) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_input_daemon: dropped %d IOSRAM reads",
03831d35f7499c87d51205817c93e9a8d42c4baestevel dropped_read);
03831d35f7499c87d51205817c93e9a8d42c4baestevel dropped_read = 0;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel for (cp = linebuf; *cp != '\0'; cp++) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel c = (int)*cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (c == '\r')
03831d35f7499c87d51205817c93e9a8d42c4baestevel c = '\n';
03831d35f7499c87d51205817c93e9a8d42c4baestevel c &= 0177;
03831d35f7499c87d51205817c93e9a8d42c4baestevel *mbp->b_wptr = (char)c;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mbp->b_wptr++;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&cvcmutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (input_ok) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvcinput_q == NULL) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_input_daemon: cvcinput_q is NULL!");
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX - should canputnext be called here?
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Starfire's cvc doesn't do that, and it
03831d35f7499c87d51205817c93e9a8d42c4baestevel * appears to work anyway.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnext(cvcinput_q, mbp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel freemsg(mbp);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&cvcmutex);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /* NOTREACHED */
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel/*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_win_resize()
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cvc_win_resize will read winsize data from the CONC IOSRAM chunk and set
03831d35f7499c87d51205817c93e9a8d42c4baestevel * the console window size accordingly. If indicated by the caller, CONC's
03831d35f7499c87d51205817c93e9a8d42c4baestevel * data_valid flag will also be cleared. The flag isn't cleared in all
03831d35f7499c87d51205817c93e9a8d42c4baestevel * cases because we need to process winsize data at startup without waiting
03831d35f7499c87d51205817c93e9a8d42c4baestevel * for a command.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevelstatic void
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_win_resize(int clear_flag)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel int rval;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t rows;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t cols;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t xpixels;
03831d35f7499c87d51205817c93e9a8d42c4baestevel uint16_t ypixels;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tty_common_t *tty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel cvc_t *cp;
03831d35f7499c87d51205817c93e9a8d42c4baestevel struct winsize ws;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Start by reading the new window size out of the CONC chunk and, if
03831d35f7499c87d51205817c93e9a8d42c4baestevel * requested, clearing CONC's data_valid flag. If any of that fails,
03831d35f7499c87d51205817c93e9a8d42c4baestevel * return immediately. (Note that the rather bulky condition in the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * two "if" statements takes advantage of C's short-circuit logic
03831d35f7499c87d51205817c93e9a8d42c4baestevel * evaluation)
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (((rval = iosram_rd(IOSRAM_KEY_CONC, CVC_CTL_OFFSET(winsize_rows),
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_CTL_SIZE(winsize_rows), (caddr_t)&rows)) != 0) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((rval = iosram_rd(IOSRAM_KEY_CONC, CVC_CTL_OFFSET(winsize_cols),
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_CTL_SIZE(winsize_cols), (caddr_t)&cols)) != 0) ||
03831d35f7499c87d51205817c93e9a8d42c4baestevel ((rval = iosram_rd(IOSRAM_KEY_CONC,
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_CTL_OFFSET(winsize_xpixels), CVC_CTL_SIZE(winsize_xpixels),
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)&xpixels)) != 0) || ((rval = iosram_rd(IOSRAM_KEY_CONC,
03831d35f7499c87d51205817c93e9a8d42c4baestevel CVC_CTL_OFFSET(winsize_ypixels), CVC_CTL_SIZE(winsize_ypixels),
03831d35f7499c87d51205817c93e9a8d42c4baestevel (caddr_t)&ypixels)) != 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_win_resize: read for ctlbuf ret %d", rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (clear_flag && ((rval = iosram_set_flag(IOSRAM_KEY_CONC,
03831d35f7499c87d51205817c93e9a8d42c4baestevel IOSRAM_DATA_INVALID, IOSRAM_INT_NONE)) != 0)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (rval != EAGAIN) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_WARN,
03831d35f7499c87d51205817c93e9a8d42c4baestevel "cvc_win_resize: set_flag for ctlbuf ret %d", rval);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel return;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * Copy the parameters from IOSRAM to a winsize struct.
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel ws.ws_row = rows;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ws.ws_col = cols;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ws.ws_xpixel = xpixels;
03831d35f7499c87d51205817c93e9a8d42c4baestevel ws.ws_ypixel = ypixels;
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel /*
03831d35f7499c87d51205817c93e9a8d42c4baestevel * This code was taken from Starfire, and it appears to work correctly.
03831d35f7499c87d51205817c93e9a8d42c4baestevel * However, since the original developer felt it necessary to add the
03831d35f7499c87d51205817c93e9a8d42c4baestevel * following comment, it's probably worth preserving:
03831d35f7499c87d51205817c93e9a8d42c4baestevel *
03831d35f7499c87d51205817c93e9a8d42c4baestevel * XXX I hope this is safe...
03831d35f7499c87d51205817c93e9a8d42c4baestevel */
03831d35f7499c87d51205817c93e9a8d42c4baestevel cp = cvcinput_q->q_ptr;
03831d35f7499c87d51205817c93e9a8d42c4baestevel tty = &cp->cvc_tty;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_enter(&tty->t_excl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (bcmp((caddr_t)&tty->t_size, (caddr_t)&ws,
03831d35f7499c87d51205817c93e9a8d42c4baestevel sizeof (struct winsize))) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel tty->t_size = ws;
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&tty->t_excl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel (void) putnextctl1(cvcinput_q, M_PCSIG,
03831d35f7499c87d51205817c93e9a8d42c4baestevel SIGWINCH);
03831d35f7499c87d51205817c93e9a8d42c4baestevel } else {
03831d35f7499c87d51205817c93e9a8d42c4baestevel mutex_exit(&tty->t_excl);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#ifdef DEBUG
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevelvoid
03831d35f7499c87d51205817c93e9a8d42c4baestevelcvc_dbg(uint32_t flag, char *fmt,
03831d35f7499c87d51205817c93e9a8d42c4baestevel uintptr_t a1, uintptr_t a2, uintptr_t a3, uintptr_t a4, uintptr_t a5)
03831d35f7499c87d51205817c93e9a8d42c4baestevel{
03831d35f7499c87d51205817c93e9a8d42c4baestevel char *s = NULL;
03831d35f7499c87d51205817c93e9a8d42c4baestevel char buf[256];
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel if (cvc_dbg_flags && ((cvc_dbg_flags & flag) == flag)) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel switch (flag) {
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_ATTACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "attach";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_DETACH:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "detach";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_OPEN:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "open";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_CLOSE:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "close";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_IOCTL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "ioctl";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_REDIR:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "redir";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_WPUT:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "wput";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_WSRV:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "wsrv";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_IOSRAM_WR:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "iosram_wr";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_IOSRAM_RD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "iosram_rd";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_NETWORK_WR:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "network_wr";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_NETWORK_RD:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "network_rd";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel case CVC_DBG_IOSRAM_CNTL:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "iosram_cntlmsg";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel default:
03831d35f7499c87d51205817c93e9a8d42c4baestevel s = "Unknown debug flag";
03831d35f7499c87d51205817c93e9a8d42c4baestevel break;
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki (void) sprintf(buf, "!%s_%s(%d): %s", ddi_driver_name(cvcdip),
07d06da50d310a325b457d6330165aebab1e0064Surya Prakki s, cvc_instance, fmt);
03831d35f7499c87d51205817c93e9a8d42c4baestevel cmn_err(CE_NOTE, buf, a1, a2, a3, a4, a5);
03831d35f7499c87d51205817c93e9a8d42c4baestevel }
03831d35f7499c87d51205817c93e9a8d42c4baestevel}
03831d35f7499c87d51205817c93e9a8d42c4baestevel
03831d35f7499c87d51205817c93e9a8d42c4baestevel#endif /* DEBUG */