1*ae1f6b9eSfredette /* $NetBSD: kd.c,v 1.1 2002/03/22 00:22:44 fredette Exp $ */ 2*ae1f6b9eSfredette 3*ae1f6b9eSfredette /*- 4*ae1f6b9eSfredette * Copyright (c) 1996 The NetBSD Foundation, Inc. 5*ae1f6b9eSfredette * All rights reserved. 6*ae1f6b9eSfredette * 7*ae1f6b9eSfredette * This code is derived from software contributed to The NetBSD Foundation 8*ae1f6b9eSfredette * by Gordon W. Ross. 9*ae1f6b9eSfredette * 10*ae1f6b9eSfredette * Redistribution and use in source and binary forms, with or without 11*ae1f6b9eSfredette * modification, are permitted provided that the following conditions 12*ae1f6b9eSfredette * are met: 13*ae1f6b9eSfredette * 1. Redistributions of source code must retain the above copyright 14*ae1f6b9eSfredette * notice, this list of conditions and the following disclaimer. 15*ae1f6b9eSfredette * 2. Redistributions in binary form must reproduce the above copyright 16*ae1f6b9eSfredette * notice, this list of conditions and the following disclaimer in the 17*ae1f6b9eSfredette * documentation and/or other materials provided with the distribution. 18*ae1f6b9eSfredette * 3. All advertising materials mentioning features or use of this software 19*ae1f6b9eSfredette * must display the following acknowledgement: 20*ae1f6b9eSfredette * This product includes software developed by the NetBSD 21*ae1f6b9eSfredette * Foundation, Inc. and its contributors. 22*ae1f6b9eSfredette * 4. Neither the name of The NetBSD Foundation nor the names of its 23*ae1f6b9eSfredette * contributors may be used to endorse or promote products derived 24*ae1f6b9eSfredette * from this software without specific prior written permission. 25*ae1f6b9eSfredette * 26*ae1f6b9eSfredette * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 27*ae1f6b9eSfredette * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 28*ae1f6b9eSfredette * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 29*ae1f6b9eSfredette * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 30*ae1f6b9eSfredette * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 31*ae1f6b9eSfredette * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 32*ae1f6b9eSfredette * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 33*ae1f6b9eSfredette * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 34*ae1f6b9eSfredette * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 35*ae1f6b9eSfredette * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 36*ae1f6b9eSfredette * POSSIBILITY OF SUCH DAMAGE. 37*ae1f6b9eSfredette */ 38*ae1f6b9eSfredette 39*ae1f6b9eSfredette /* 40*ae1f6b9eSfredette * Keyboard/Display device. 41*ae1f6b9eSfredette * 42*ae1f6b9eSfredette * This driver exists simply to provide a tty device that 43*ae1f6b9eSfredette * the indirect console driver can point to. 44*ae1f6b9eSfredette * The kbd driver sends its input here. 45*ae1f6b9eSfredette * Output goes to the screen via PROM printf. 46*ae1f6b9eSfredette */ 47*ae1f6b9eSfredette 48*ae1f6b9eSfredette #include <sys/param.h> 49*ae1f6b9eSfredette #include <sys/proc.h> 50*ae1f6b9eSfredette #include <sys/systm.h> 51*ae1f6b9eSfredette #include <sys/ioctl.h> 52*ae1f6b9eSfredette #include <sys/tty.h> 53*ae1f6b9eSfredette #include <sys/file.h> 54*ae1f6b9eSfredette #include <sys/conf.h> 55*ae1f6b9eSfredette #include <sys/device.h> 56*ae1f6b9eSfredette 57*ae1f6b9eSfredette #include <machine/promlib.h> 58*ae1f6b9eSfredette #include <machine/eeprom.h> 59*ae1f6b9eSfredette #include <machine/psl.h> 60*ae1f6b9eSfredette #include <machine/cpu.h> 61*ae1f6b9eSfredette #include <machine/kbd.h> 62*ae1f6b9eSfredette #include <machine/autoconf.h> 63*ae1f6b9eSfredette #include <machine/conf.h> 64*ae1f6b9eSfredette 65*ae1f6b9eSfredette #ifdef RASTERCONSOLE 66*ae1f6b9eSfredette #include <dev/sun/fbio.h> 67*ae1f6b9eSfredette #include <machine/fbvar.h> 68*ae1f6b9eSfredette #endif 69*ae1f6b9eSfredette 70*ae1f6b9eSfredette 71*ae1f6b9eSfredette #include <dev/cons.h> 72*ae1f6b9eSfredette #include <dev/sun/event_var.h> 73*ae1f6b9eSfredette #include <dev/sun/kbd_xlate.h> 74*ae1f6b9eSfredette #include <dev/sun/kbdvar.h> 75*ae1f6b9eSfredette #include <sun2/dev/cons.h> 76*ae1f6b9eSfredette 77*ae1f6b9eSfredette struct tty *fbconstty = 0; /* tty structure for frame buffer console */ 78*ae1f6b9eSfredette 79*ae1f6b9eSfredette #define KDMAJOR 1 80*ae1f6b9eSfredette #define PUT_WSIZE 64 81*ae1f6b9eSfredette 82*ae1f6b9eSfredette struct kd_softc { 83*ae1f6b9eSfredette struct device kd_dev; /* required first: base device */ 84*ae1f6b9eSfredette struct tty *kd_tty; 85*ae1f6b9eSfredette int rows, cols; 86*ae1f6b9eSfredette 87*ae1f6b9eSfredette /* Console input hook */ 88*ae1f6b9eSfredette struct cons_channel *kd_in; 89*ae1f6b9eSfredette }; 90*ae1f6b9eSfredette 91*ae1f6b9eSfredette /* 92*ae1f6b9eSfredette * There is no point in pretending there might be 93*ae1f6b9eSfredette * more than one keyboard/display device. 94*ae1f6b9eSfredette */ 95*ae1f6b9eSfredette static struct kd_softc kd_softc; 96*ae1f6b9eSfredette static int kd_is_console; 97*ae1f6b9eSfredette 98*ae1f6b9eSfredette static int kdparam(struct tty *, struct termios *); 99*ae1f6b9eSfredette static void kdstart(struct tty *); 100*ae1f6b9eSfredette static void kd_init __P((struct kd_softc *)); 101*ae1f6b9eSfredette static void kd_cons_input __P((int)); 102*ae1f6b9eSfredette static int kdcngetc __P((dev_t)); 103*ae1f6b9eSfredette 104*ae1f6b9eSfredette int cons_ocount; /* output byte count */ 105*ae1f6b9eSfredette 106*ae1f6b9eSfredette /* 107*ae1f6b9eSfredette * This is called by kbd_attach() 108*ae1f6b9eSfredette * XXX - Make this a proper child of kbd? 109*ae1f6b9eSfredette */ 110*ae1f6b9eSfredette void 111*ae1f6b9eSfredette kd_init(kd) 112*ae1f6b9eSfredette struct kd_softc *kd; 113*ae1f6b9eSfredette { 114*ae1f6b9eSfredette struct tty *tp; 115*ae1f6b9eSfredette #ifdef PROM_OLDMON 116*ae1f6b9eSfredette struct eeprom *ep; 117*ae1f6b9eSfredette #endif 118*ae1f6b9eSfredette #ifdef notyet /* PROM_OBP_V2 */ 119*ae1f6b9eSfredette int i; 120*ae1f6b9eSfredette char *prop; 121*ae1f6b9eSfredette #endif 122*ae1f6b9eSfredette 123*ae1f6b9eSfredette kd = &kd_softc; /* XXX */ 124*ae1f6b9eSfredette 125*ae1f6b9eSfredette tp = ttymalloc(); 126*ae1f6b9eSfredette tp->t_oproc = kdstart; 127*ae1f6b9eSfredette tp->t_param = kdparam; 128*ae1f6b9eSfredette tp->t_dev = makedev(KDMAJOR, 0); 129*ae1f6b9eSfredette 130*ae1f6b9eSfredette tty_attach(tp); 131*ae1f6b9eSfredette kd->kd_tty = tp; 132*ae1f6b9eSfredette 133*ae1f6b9eSfredette /* 134*ae1f6b9eSfredette * get the console struct winsize. 135*ae1f6b9eSfredette */ 136*ae1f6b9eSfredette if (kd_is_console) { 137*ae1f6b9eSfredette fbconstty = tp; 138*ae1f6b9eSfredette #ifdef RASTERCONSOLE 139*ae1f6b9eSfredette kd->rows = fbrcons_rows(); 140*ae1f6b9eSfredette kd->cols = fbrcons_cols(); 141*ae1f6b9eSfredette rcons_ttyinit(tp); 142*ae1f6b9eSfredette #endif 143*ae1f6b9eSfredette } 144*ae1f6b9eSfredette 145*ae1f6b9eSfredette /* else, consult the PROM */ 146*ae1f6b9eSfredette switch (prom_version()) { 147*ae1f6b9eSfredette #ifdef PROM_OLDMON 148*ae1f6b9eSfredette case PROM_OLDMON: 149*ae1f6b9eSfredette if ((ep = (struct eeprom *)eeprom_va) == NULL) 150*ae1f6b9eSfredette break; 151*ae1f6b9eSfredette if (kd->rows == 0) 152*ae1f6b9eSfredette kd->rows = (u_short)ep->eeTtyRows; 153*ae1f6b9eSfredette if (kd->cols == 0) 154*ae1f6b9eSfredette kd->cols = (u_short)ep->eeTtyCols; 155*ae1f6b9eSfredette break; 156*ae1f6b9eSfredette #endif /* PROM_OLDMON */ 157*ae1f6b9eSfredette #ifdef notyet /* PROM_OBP_V2 */ 158*ae1f6b9eSfredette case PROM_OBP_V0: 159*ae1f6b9eSfredette case PROM_OBP_V2: 160*ae1f6b9eSfredette case PROM_OBP_V3: 161*ae1f6b9eSfredette case PROM_OPENFIRM: 162*ae1f6b9eSfredette 163*ae1f6b9eSfredette if (kd->rows == 0 && 164*ae1f6b9eSfredette (prop = PROM_getpropstring(optionsnode, "screen-#rows"))) { 165*ae1f6b9eSfredette i = 0; 166*ae1f6b9eSfredette while (*prop != '\0') 167*ae1f6b9eSfredette i = i * 10 + *prop++ - '0'; 168*ae1f6b9eSfredette kd->rows = (unsigned short)i; 169*ae1f6b9eSfredette } 170*ae1f6b9eSfredette if (kd->cols == 0 && 171*ae1f6b9eSfredette (prop = PROM_getpropstring(optionsnode, "screen-#columns"))) { 172*ae1f6b9eSfredette i = 0; 173*ae1f6b9eSfredette while (*prop != '\0') 174*ae1f6b9eSfredette i = i * 10 + *prop++ - '0'; 175*ae1f6b9eSfredette kd->cols = (unsigned short)i; 176*ae1f6b9eSfredette } 177*ae1f6b9eSfredette break; 178*ae1f6b9eSfredette #endif /* PROM_OBP_V2 */ 179*ae1f6b9eSfredette } 180*ae1f6b9eSfredette return; 181*ae1f6b9eSfredette } 182*ae1f6b9eSfredette 183*ae1f6b9eSfredette struct tty * 184*ae1f6b9eSfredette kdtty(dev) 185*ae1f6b9eSfredette dev_t dev; 186*ae1f6b9eSfredette { 187*ae1f6b9eSfredette struct kd_softc *kd; 188*ae1f6b9eSfredette 189*ae1f6b9eSfredette kd = &kd_softc; /* XXX */ 190*ae1f6b9eSfredette return (kd->kd_tty); 191*ae1f6b9eSfredette } 192*ae1f6b9eSfredette 193*ae1f6b9eSfredette int 194*ae1f6b9eSfredette kdopen(dev, flag, mode, p) 195*ae1f6b9eSfredette dev_t dev; 196*ae1f6b9eSfredette int flag, mode; 197*ae1f6b9eSfredette struct proc *p; 198*ae1f6b9eSfredette { 199*ae1f6b9eSfredette struct kd_softc *kd; 200*ae1f6b9eSfredette int error, s, unit; 201*ae1f6b9eSfredette struct tty *tp; 202*ae1f6b9eSfredette static int firstopen = 1; 203*ae1f6b9eSfredette 204*ae1f6b9eSfredette unit = minor(dev); 205*ae1f6b9eSfredette if (unit != 0) 206*ae1f6b9eSfredette return ENXIO; 207*ae1f6b9eSfredette kd = &kd_softc; /* XXX */ 208*ae1f6b9eSfredette 209*ae1f6b9eSfredette if (firstopen) { 210*ae1f6b9eSfredette kd_init(kd); 211*ae1f6b9eSfredette firstopen = 0; 212*ae1f6b9eSfredette } 213*ae1f6b9eSfredette tp = kd->kd_tty; 214*ae1f6b9eSfredette 215*ae1f6b9eSfredette /* It's simpler to do this up here. */ 216*ae1f6b9eSfredette if (((tp->t_state & (TS_ISOPEN | TS_XCLUDE)) 217*ae1f6b9eSfredette == (TS_ISOPEN | TS_XCLUDE)) 218*ae1f6b9eSfredette && (p->p_ucred->cr_uid != 0) ) 219*ae1f6b9eSfredette { 220*ae1f6b9eSfredette return (EBUSY); 221*ae1f6b9eSfredette } 222*ae1f6b9eSfredette 223*ae1f6b9eSfredette s = spltty(); 224*ae1f6b9eSfredette 225*ae1f6b9eSfredette if ((tp->t_state & TS_ISOPEN) == 0) { 226*ae1f6b9eSfredette /* First open. */ 227*ae1f6b9eSfredette 228*ae1f6b9eSfredette /* Notify the input device that serves us */ 229*ae1f6b9eSfredette struct cons_channel *cc = kd->kd_in; 230*ae1f6b9eSfredette if (cc != NULL && 231*ae1f6b9eSfredette (error = (*cc->cc_iopen)(cc)) != 0) { 232*ae1f6b9eSfredette splx(s); 233*ae1f6b9eSfredette return (error); 234*ae1f6b9eSfredette } 235*ae1f6b9eSfredette 236*ae1f6b9eSfredette ttychars(tp); 237*ae1f6b9eSfredette tp->t_iflag = TTYDEF_IFLAG; 238*ae1f6b9eSfredette tp->t_oflag = TTYDEF_OFLAG; 239*ae1f6b9eSfredette tp->t_cflag = TTYDEF_CFLAG; 240*ae1f6b9eSfredette tp->t_lflag = TTYDEF_LFLAG; 241*ae1f6b9eSfredette tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED; 242*ae1f6b9eSfredette (void) kdparam(tp, &tp->t_termios); 243*ae1f6b9eSfredette ttsetwater(tp); 244*ae1f6b9eSfredette tp->t_winsize.ws_row = kd->rows; 245*ae1f6b9eSfredette tp->t_winsize.ws_col = kd->cols; 246*ae1f6b9eSfredette /* Flush pending input? Clear translator? */ 247*ae1f6b9eSfredette /* This (pseudo)device always has SOFTCAR */ 248*ae1f6b9eSfredette tp->t_state |= TS_CARR_ON; 249*ae1f6b9eSfredette } 250*ae1f6b9eSfredette 251*ae1f6b9eSfredette splx(s); 252*ae1f6b9eSfredette 253*ae1f6b9eSfredette return ((*tp->t_linesw->l_open)(dev, tp)); 254*ae1f6b9eSfredette } 255*ae1f6b9eSfredette 256*ae1f6b9eSfredette int 257*ae1f6b9eSfredette kdclose(dev, flag, mode, p) 258*ae1f6b9eSfredette dev_t dev; 259*ae1f6b9eSfredette int flag, mode; 260*ae1f6b9eSfredette struct proc *p; 261*ae1f6b9eSfredette { 262*ae1f6b9eSfredette struct kd_softc *kd; 263*ae1f6b9eSfredette struct tty *tp; 264*ae1f6b9eSfredette struct cons_channel *cc; 265*ae1f6b9eSfredette 266*ae1f6b9eSfredette kd = &kd_softc; /* XXX */ 267*ae1f6b9eSfredette tp = kd->kd_tty; 268*ae1f6b9eSfredette 269*ae1f6b9eSfredette /* XXX This is for cons.c. */ 270*ae1f6b9eSfredette if ((tp->t_state & TS_ISOPEN) == 0) 271*ae1f6b9eSfredette return 0; 272*ae1f6b9eSfredette 273*ae1f6b9eSfredette (*tp->t_linesw->l_close)(tp, flag); 274*ae1f6b9eSfredette ttyclose(tp); 275*ae1f6b9eSfredette 276*ae1f6b9eSfredette if ((cc = kd->kd_in) != NULL) 277*ae1f6b9eSfredette (void)(*cc->cc_iclose)(cc->cc_dev); 278*ae1f6b9eSfredette 279*ae1f6b9eSfredette return (0); 280*ae1f6b9eSfredette } 281*ae1f6b9eSfredette 282*ae1f6b9eSfredette int 283*ae1f6b9eSfredette kdread(dev, uio, flag) 284*ae1f6b9eSfredette dev_t dev; 285*ae1f6b9eSfredette struct uio *uio; 286*ae1f6b9eSfredette int flag; 287*ae1f6b9eSfredette { 288*ae1f6b9eSfredette struct kd_softc *kd; 289*ae1f6b9eSfredette struct tty *tp; 290*ae1f6b9eSfredette 291*ae1f6b9eSfredette kd = &kd_softc; /* XXX */ 292*ae1f6b9eSfredette tp = kd->kd_tty; 293*ae1f6b9eSfredette 294*ae1f6b9eSfredette return ((*tp->t_linesw->l_read)(tp, uio, flag)); 295*ae1f6b9eSfredette } 296*ae1f6b9eSfredette 297*ae1f6b9eSfredette int 298*ae1f6b9eSfredette kdwrite(dev, uio, flag) 299*ae1f6b9eSfredette dev_t dev; 300*ae1f6b9eSfredette struct uio *uio; 301*ae1f6b9eSfredette int flag; 302*ae1f6b9eSfredette { 303*ae1f6b9eSfredette struct kd_softc *kd; 304*ae1f6b9eSfredette struct tty *tp; 305*ae1f6b9eSfredette 306*ae1f6b9eSfredette kd = &kd_softc; /* XXX */ 307*ae1f6b9eSfredette tp = kd->kd_tty; 308*ae1f6b9eSfredette 309*ae1f6b9eSfredette return ((*tp->t_linesw->l_write)(tp, uio, flag)); 310*ae1f6b9eSfredette } 311*ae1f6b9eSfredette 312*ae1f6b9eSfredette int 313*ae1f6b9eSfredette kdpoll(dev, events, p) 314*ae1f6b9eSfredette dev_t dev; 315*ae1f6b9eSfredette int events; 316*ae1f6b9eSfredette struct proc *p; 317*ae1f6b9eSfredette { 318*ae1f6b9eSfredette struct kd_softc *kd; 319*ae1f6b9eSfredette struct tty *tp; 320*ae1f6b9eSfredette 321*ae1f6b9eSfredette kd = &kd_softc; /* XXX */ 322*ae1f6b9eSfredette tp = kd->kd_tty; 323*ae1f6b9eSfredette 324*ae1f6b9eSfredette return ((*tp->t_linesw->l_poll)(tp, events, p)); 325*ae1f6b9eSfredette } 326*ae1f6b9eSfredette 327*ae1f6b9eSfredette int 328*ae1f6b9eSfredette kdioctl(dev, cmd, data, flag, p) 329*ae1f6b9eSfredette dev_t dev; 330*ae1f6b9eSfredette u_long cmd; 331*ae1f6b9eSfredette caddr_t data; 332*ae1f6b9eSfredette int flag; 333*ae1f6b9eSfredette struct proc *p; 334*ae1f6b9eSfredette { 335*ae1f6b9eSfredette struct kd_softc *kd; 336*ae1f6b9eSfredette struct tty *tp; 337*ae1f6b9eSfredette int error; 338*ae1f6b9eSfredette 339*ae1f6b9eSfredette kd = &kd_softc; /* XXX */ 340*ae1f6b9eSfredette tp = kd->kd_tty; 341*ae1f6b9eSfredette 342*ae1f6b9eSfredette error = (*tp->t_linesw->l_ioctl)(tp, cmd, data, flag, p); 343*ae1f6b9eSfredette if (error != EPASSTHROUGH) 344*ae1f6b9eSfredette return error; 345*ae1f6b9eSfredette 346*ae1f6b9eSfredette error = ttioctl(tp, cmd, data, flag, p); 347*ae1f6b9eSfredette if (error != EPASSTHROUGH) 348*ae1f6b9eSfredette return error; 349*ae1f6b9eSfredette 350*ae1f6b9eSfredette /* Handle any ioctl commands specific to kbd/display. */ 351*ae1f6b9eSfredette /* XXX - Send KB* ioctls to kbd module? */ 352*ae1f6b9eSfredette /* XXX - Send FB* ioctls to fb module? */ 353*ae1f6b9eSfredette 354*ae1f6b9eSfredette return EPASSTHROUGH; 355*ae1f6b9eSfredette } 356*ae1f6b9eSfredette 357*ae1f6b9eSfredette void 358*ae1f6b9eSfredette kdstop(tp, flag) 359*ae1f6b9eSfredette struct tty *tp; 360*ae1f6b9eSfredette int flag; 361*ae1f6b9eSfredette { 362*ae1f6b9eSfredette 363*ae1f6b9eSfredette } 364*ae1f6b9eSfredette 365*ae1f6b9eSfredette 366*ae1f6b9eSfredette static int 367*ae1f6b9eSfredette kdparam(tp, t) 368*ae1f6b9eSfredette struct tty *tp; 369*ae1f6b9eSfredette struct termios *t; 370*ae1f6b9eSfredette { 371*ae1f6b9eSfredette /* XXX - These are ignored... */ 372*ae1f6b9eSfredette tp->t_ispeed = t->c_ispeed; 373*ae1f6b9eSfredette tp->t_ospeed = t->c_ospeed; 374*ae1f6b9eSfredette tp->t_cflag = t->c_cflag; 375*ae1f6b9eSfredette return 0; 376*ae1f6b9eSfredette } 377*ae1f6b9eSfredette 378*ae1f6b9eSfredette 379*ae1f6b9eSfredette static void kd_later(void*); 380*ae1f6b9eSfredette static void kd_putfb(struct tty *); 381*ae1f6b9eSfredette 382*ae1f6b9eSfredette static void 383*ae1f6b9eSfredette kdstart(tp) 384*ae1f6b9eSfredette struct tty *tp; 385*ae1f6b9eSfredette { 386*ae1f6b9eSfredette struct clist *cl; 387*ae1f6b9eSfredette register int s; 388*ae1f6b9eSfredette 389*ae1f6b9eSfredette s = spltty(); 390*ae1f6b9eSfredette if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT)) 391*ae1f6b9eSfredette goto out; 392*ae1f6b9eSfredette 393*ae1f6b9eSfredette cl = &tp->t_outq; 394*ae1f6b9eSfredette if (cl->c_cc) { 395*ae1f6b9eSfredette if (kd_is_console) { 396*ae1f6b9eSfredette tp->t_state |= TS_BUSY; 397*ae1f6b9eSfredette if (is_spl0(s)) { 398*ae1f6b9eSfredette /* called at level zero - update screen now. */ 399*ae1f6b9eSfredette (void) spllowersoftclock(); 400*ae1f6b9eSfredette kd_putfb(tp); 401*ae1f6b9eSfredette (void) spltty(); 402*ae1f6b9eSfredette tp->t_state &= ~TS_BUSY; 403*ae1f6b9eSfredette } else { 404*ae1f6b9eSfredette /* called at interrupt level - do it later */ 405*ae1f6b9eSfredette callout_reset(&tp->t_rstrt_ch, 0, 406*ae1f6b9eSfredette kd_later, tp); 407*ae1f6b9eSfredette } 408*ae1f6b9eSfredette } else { 409*ae1f6b9eSfredette /* 410*ae1f6b9eSfredette * This driver uses the PROM for writing the screen, 411*ae1f6b9eSfredette * and that only works if this is the console device. 412*ae1f6b9eSfredette * If this is not the console, just flush the output. 413*ae1f6b9eSfredette * Sorry. (In that case, use xdm instead of getty.) 414*ae1f6b9eSfredette */ 415*ae1f6b9eSfredette ndflush(cl, cl->c_cc); 416*ae1f6b9eSfredette } 417*ae1f6b9eSfredette } 418*ae1f6b9eSfredette if (cl->c_cc <= tp->t_lowat) { 419*ae1f6b9eSfredette if (tp->t_state & TS_ASLEEP) { 420*ae1f6b9eSfredette tp->t_state &= ~TS_ASLEEP; 421*ae1f6b9eSfredette wakeup((caddr_t)cl); 422*ae1f6b9eSfredette } 423*ae1f6b9eSfredette selwakeup(&tp->t_wsel); 424*ae1f6b9eSfredette } 425*ae1f6b9eSfredette out: 426*ae1f6b9eSfredette splx(s); 427*ae1f6b9eSfredette } 428*ae1f6b9eSfredette 429*ae1f6b9eSfredette /* 430*ae1f6b9eSfredette * Timeout function to do delayed writes to the screen. 431*ae1f6b9eSfredette * Called at splsoftclock when requested by kdstart. 432*ae1f6b9eSfredette */ 433*ae1f6b9eSfredette static void 434*ae1f6b9eSfredette kd_later(tpaddr) 435*ae1f6b9eSfredette void *tpaddr; 436*ae1f6b9eSfredette { 437*ae1f6b9eSfredette struct tty *tp = tpaddr; 438*ae1f6b9eSfredette register int s; 439*ae1f6b9eSfredette 440*ae1f6b9eSfredette kd_putfb(tp); 441*ae1f6b9eSfredette 442*ae1f6b9eSfredette s = spltty(); 443*ae1f6b9eSfredette tp->t_state &= ~TS_BUSY; 444*ae1f6b9eSfredette (*tp->t_linesw->l_start)(tp); 445*ae1f6b9eSfredette splx(s); 446*ae1f6b9eSfredette } 447*ae1f6b9eSfredette 448*ae1f6b9eSfredette /* 449*ae1f6b9eSfredette * Put text on the screen using the PROM monitor. 450*ae1f6b9eSfredette * This can take a while, so to avoid missing 451*ae1f6b9eSfredette * interrupts, this is called at splsoftclock. 452*ae1f6b9eSfredette */ 453*ae1f6b9eSfredette static void 454*ae1f6b9eSfredette kd_putfb(tp) 455*ae1f6b9eSfredette struct tty *tp; 456*ae1f6b9eSfredette { 457*ae1f6b9eSfredette char buf[PUT_WSIZE]; 458*ae1f6b9eSfredette struct clist *cl = &tp->t_outq; 459*ae1f6b9eSfredette char *p, *end; 460*ae1f6b9eSfredette int len; 461*ae1f6b9eSfredette 462*ae1f6b9eSfredette while ((len = q_to_b(cl, buf, PUT_WSIZE-1)) > 0) { 463*ae1f6b9eSfredette /* PROM will barf if high bits are set. */ 464*ae1f6b9eSfredette p = buf; 465*ae1f6b9eSfredette end = buf + len; 466*ae1f6b9eSfredette while (p < end) 467*ae1f6b9eSfredette *p++ &= 0x7f; 468*ae1f6b9eSfredette /* Now let the PROM print it. */ 469*ae1f6b9eSfredette prom_putstr(buf, len); 470*ae1f6b9eSfredette } 471*ae1f6b9eSfredette } 472*ae1f6b9eSfredette 473*ae1f6b9eSfredette /* 474*ae1f6b9eSfredette * Default PROM-based console input stream 475*ae1f6b9eSfredette */ 476*ae1f6b9eSfredette static int kd_rom_iopen __P((struct cons_channel *)); 477*ae1f6b9eSfredette static int kd_rom_iclose __P((struct cons_channel *)); 478*ae1f6b9eSfredette 479*ae1f6b9eSfredette static struct cons_channel prom_cons_channel; 480*ae1f6b9eSfredette 481*ae1f6b9eSfredette int 482*ae1f6b9eSfredette kd_rom_iopen(cc) 483*ae1f6b9eSfredette struct cons_channel *cc; 484*ae1f6b9eSfredette { 485*ae1f6b9eSfredette return (0); 486*ae1f6b9eSfredette } 487*ae1f6b9eSfredette 488*ae1f6b9eSfredette int 489*ae1f6b9eSfredette kd_rom_iclose(cc) 490*ae1f6b9eSfredette struct cons_channel *cc; 491*ae1f6b9eSfredette { 492*ae1f6b9eSfredette return (0); 493*ae1f6b9eSfredette } 494*ae1f6b9eSfredette 495*ae1f6b9eSfredette /* 496*ae1f6b9eSfredette * Our "interrupt" routine for input. This is called by 497*ae1f6b9eSfredette * the keyboard driver (dev/sun/kbd.c) at spltty. 498*ae1f6b9eSfredette */ 499*ae1f6b9eSfredette void 500*ae1f6b9eSfredette kd_cons_input(c) 501*ae1f6b9eSfredette int c; 502*ae1f6b9eSfredette { 503*ae1f6b9eSfredette struct kd_softc *kd = &kd_softc; 504*ae1f6b9eSfredette struct tty *tp; 505*ae1f6b9eSfredette 506*ae1f6b9eSfredette /* XXX: Make sure the device is open. */ 507*ae1f6b9eSfredette tp = kd->kd_tty; 508*ae1f6b9eSfredette if (tp == NULL) 509*ae1f6b9eSfredette return; 510*ae1f6b9eSfredette if ((tp->t_state & TS_ISOPEN) == 0) 511*ae1f6b9eSfredette return; 512*ae1f6b9eSfredette 513*ae1f6b9eSfredette (*tp->t_linesw->l_rint)(c, tp); 514*ae1f6b9eSfredette } 515*ae1f6b9eSfredette 516*ae1f6b9eSfredette 517*ae1f6b9eSfredette /**************************************************************** 518*ae1f6b9eSfredette * kd console support 519*ae1f6b9eSfredette ****************************************************************/ 520*ae1f6b9eSfredette 521*ae1f6b9eSfredette /* The debugger gets its own key translation state. */ 522*ae1f6b9eSfredette static struct kbd_state *kdcn_state; 523*ae1f6b9eSfredette 524*ae1f6b9eSfredette static void kdcnprobe __P((struct consdev *)); 525*ae1f6b9eSfredette static void kdcninit __P((struct consdev *)); 526*ae1f6b9eSfredette static void kdcnputc __P((dev_t, int)); 527*ae1f6b9eSfredette static void kdcnpollc __P((dev_t, int)); 528*ae1f6b9eSfredette 529*ae1f6b9eSfredette /* The keyboard driver uses cn_hw to access the real console driver */ 530*ae1f6b9eSfredette extern struct consdev consdev_prom; 531*ae1f6b9eSfredette struct consdev consdev_kd = { 532*ae1f6b9eSfredette kdcnprobe, 533*ae1f6b9eSfredette kdcninit, 534*ae1f6b9eSfredette kdcngetc, 535*ae1f6b9eSfredette kdcnputc, 536*ae1f6b9eSfredette kdcnpollc, 537*ae1f6b9eSfredette NULL, 538*ae1f6b9eSfredette }; 539*ae1f6b9eSfredette struct consdev *cn_hw = &consdev_kd; 540*ae1f6b9eSfredette 541*ae1f6b9eSfredette void 542*ae1f6b9eSfredette cons_attach_input(cc, cn) 543*ae1f6b9eSfredette struct cons_channel *cc; 544*ae1f6b9eSfredette struct consdev *cn; 545*ae1f6b9eSfredette { 546*ae1f6b9eSfredette struct kd_softc *kd = &kd_softc; 547*ae1f6b9eSfredette struct kbd_softc *kds = cc->cc_dev; 548*ae1f6b9eSfredette struct kbd_state *ks; 549*ae1f6b9eSfredette 550*ae1f6b9eSfredette /* Share the keyboard state */ 551*ae1f6b9eSfredette kdcn_state = ks = &kds->k_state; 552*ae1f6b9eSfredette 553*ae1f6b9eSfredette kd->kd_in = cc; 554*ae1f6b9eSfredette cc->cc_upstream = kd_cons_input; 555*ae1f6b9eSfredette 556*ae1f6b9eSfredette /* Attach lower level. */ 557*ae1f6b9eSfredette cn_hw->cn_dev = cn->cn_dev; 558*ae1f6b9eSfredette cn_hw->cn_pollc = cn->cn_pollc; 559*ae1f6b9eSfredette cn_hw->cn_getc = cn->cn_getc; 560*ae1f6b9eSfredette 561*ae1f6b9eSfredette /* Attach us as console. */ 562*ae1f6b9eSfredette cn_tab->cn_dev = makedev(KDMAJOR, 0); 563*ae1f6b9eSfredette cn_tab->cn_probe = kdcnprobe; 564*ae1f6b9eSfredette cn_tab->cn_init = kdcninit; 565*ae1f6b9eSfredette cn_tab->cn_getc = kdcngetc; 566*ae1f6b9eSfredette cn_tab->cn_pollc = kdcnpollc; 567*ae1f6b9eSfredette cn_tab->cn_pri = CN_INTERNAL; 568*ae1f6b9eSfredette 569*ae1f6b9eSfredette /* Set up initial PROM input channel for /dev/console */ 570*ae1f6b9eSfredette prom_cons_channel.cc_dev = NULL; 571*ae1f6b9eSfredette prom_cons_channel.cc_iopen = kd_rom_iopen; 572*ae1f6b9eSfredette prom_cons_channel.cc_iclose = kd_rom_iclose; 573*ae1f6b9eSfredette 574*ae1f6b9eSfredette /* Indicate that it is OK to use the PROM fbwrite */ 575*ae1f6b9eSfredette kd_is_console = 1; 576*ae1f6b9eSfredette } 577*ae1f6b9eSfredette 578*ae1f6b9eSfredette 579*ae1f6b9eSfredette void kd_attach_input(struct cons_channel *); 580*ae1f6b9eSfredette void 581*ae1f6b9eSfredette kd_attach_input(cc) 582*ae1f6b9eSfredette struct cons_channel *cc; 583*ae1f6b9eSfredette { 584*ae1f6b9eSfredette struct kd_softc *kd = &kd_softc; 585*ae1f6b9eSfredette 586*ae1f6b9eSfredette kd->kd_in = cc; 587*ae1f6b9eSfredette cc->cc_upstream = kd_cons_input; 588*ae1f6b9eSfredette } 589*ae1f6b9eSfredette 590*ae1f6b9eSfredette 591*ae1f6b9eSfredette /* We never call this. */ 592*ae1f6b9eSfredette static void 593*ae1f6b9eSfredette kdcnprobe(cn) 594*ae1f6b9eSfredette struct consdev *cn; 595*ae1f6b9eSfredette { 596*ae1f6b9eSfredette } 597*ae1f6b9eSfredette 598*ae1f6b9eSfredette static void 599*ae1f6b9eSfredette kdcninit(cn) 600*ae1f6b9eSfredette struct consdev *cn; 601*ae1f6b9eSfredette { 602*ae1f6b9eSfredette #if 0 603*ae1f6b9eSfredette struct kbd_state *ks = kdcn_state; 604*ae1f6b9eSfredette 605*ae1f6b9eSfredette cn->cn_dev = makedev(KDMAJOR, 0); 606*ae1f6b9eSfredette cn->cn_pri = CN_INTERNAL; 607*ae1f6b9eSfredette 608*ae1f6b9eSfredette /* This prepares kbd_translate() */ 609*ae1f6b9eSfredette ks->kbd_id = KBD_MIN_TYPE; 610*ae1f6b9eSfredette kbd_xlate_init(ks); 611*ae1f6b9eSfredette 612*ae1f6b9eSfredette /* Set up initial PROM input channel for /dev/console */ 613*ae1f6b9eSfredette prom_cons_channel.cc_dev = NULL; 614*ae1f6b9eSfredette prom_cons_channel.cc_iopen = kd_rom_iopen; 615*ae1f6b9eSfredette prom_cons_channel.cc_iclose = kd_rom_iclose; 616*ae1f6b9eSfredette cons_attach_input(&prom_cons_channel); 617*ae1f6b9eSfredette 618*ae1f6b9eSfredette /* Indicate that it is OK to use the PROM fbwrite */ 619*ae1f6b9eSfredette kd_is_console = 1; 620*ae1f6b9eSfredette #endif 621*ae1f6b9eSfredette } 622*ae1f6b9eSfredette 623*ae1f6b9eSfredette static int 624*ae1f6b9eSfredette kdcngetc(dev) 625*ae1f6b9eSfredette dev_t dev; 626*ae1f6b9eSfredette { 627*ae1f6b9eSfredette struct kbd_state *ks = kdcn_state; 628*ae1f6b9eSfredette int code, class, data, keysym; 629*ae1f6b9eSfredette extern int prom_cngetc __P((dev_t)); 630*ae1f6b9eSfredette 631*ae1f6b9eSfredette 632*ae1f6b9eSfredette if (cn_hw->cn_getc == prom_cngetc) return (*cn_hw->cn_getc)(dev); 633*ae1f6b9eSfredette for (;;) { 634*ae1f6b9eSfredette code = (*cn_hw->cn_getc)(dev); 635*ae1f6b9eSfredette keysym = kbd_code_to_keysym(ks, code); 636*ae1f6b9eSfredette class = KEYSYM_CLASS(keysym); 637*ae1f6b9eSfredette 638*ae1f6b9eSfredette switch (class) { 639*ae1f6b9eSfredette case KEYSYM_ASCII: 640*ae1f6b9eSfredette goto out; 641*ae1f6b9eSfredette 642*ae1f6b9eSfredette case KEYSYM_CLRMOD: 643*ae1f6b9eSfredette case KEYSYM_SETMOD: 644*ae1f6b9eSfredette data = (keysym & 0x1F); 645*ae1f6b9eSfredette /* Only allow ctrl or shift. */ 646*ae1f6b9eSfredette if (data > KBMOD_SHIFT_R) 647*ae1f6b9eSfredette break; 648*ae1f6b9eSfredette data = 1 << data; 649*ae1f6b9eSfredette if (class == KEYSYM_SETMOD) 650*ae1f6b9eSfredette ks->kbd_modbits |= data; 651*ae1f6b9eSfredette else 652*ae1f6b9eSfredette ks->kbd_modbits &= ~data; 653*ae1f6b9eSfredette break; 654*ae1f6b9eSfredette 655*ae1f6b9eSfredette case KEYSYM_ALL_UP: 656*ae1f6b9eSfredette /* No toggle keys here. */ 657*ae1f6b9eSfredette ks->kbd_modbits = 0; 658*ae1f6b9eSfredette break; 659*ae1f6b9eSfredette 660*ae1f6b9eSfredette default: /* ignore all other keysyms */ 661*ae1f6b9eSfredette break; 662*ae1f6b9eSfredette } 663*ae1f6b9eSfredette } 664*ae1f6b9eSfredette out: 665*ae1f6b9eSfredette return (keysym); 666*ae1f6b9eSfredette } 667*ae1f6b9eSfredette 668*ae1f6b9eSfredette static void 669*ae1f6b9eSfredette kdcnputc(dev, c) 670*ae1f6b9eSfredette dev_t dev; 671*ae1f6b9eSfredette int c; 672*ae1f6b9eSfredette { 673*ae1f6b9eSfredette int s; 674*ae1f6b9eSfredette 675*ae1f6b9eSfredette s = splhigh(); 676*ae1f6b9eSfredette prom_putchar(c); 677*ae1f6b9eSfredette splx(s); 678*ae1f6b9eSfredette } 679*ae1f6b9eSfredette 680*ae1f6b9eSfredette static void 681*ae1f6b9eSfredette kdcnpollc(dev, on) 682*ae1f6b9eSfredette dev_t dev; 683*ae1f6b9eSfredette int on; 684*ae1f6b9eSfredette { 685*ae1f6b9eSfredette struct kbd_state *ks = kdcn_state; 686*ae1f6b9eSfredette 687*ae1f6b9eSfredette if (on) { 688*ae1f6b9eSfredette /* Entering debugger. */ 689*ae1f6b9eSfredette #if NFB > 0 690*ae1f6b9eSfredette fb_unblank(); 691*ae1f6b9eSfredette #endif 692*ae1f6b9eSfredette /* Clear shift keys too. */ 693*ae1f6b9eSfredette ks->kbd_modbits = 0; 694*ae1f6b9eSfredette } else { 695*ae1f6b9eSfredette /* Resuming kernel. */ 696*ae1f6b9eSfredette } 697*ae1f6b9eSfredette (*cn_hw->cn_pollc)(dev, on); 698*ae1f6b9eSfredette } 699