Home | History | Annotate | Line # | Download | only in dev
kd.c revision 1.2
      1 /*
      2  * Copyright (c) 1994 Gordon W. Ross
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions
      7  * are met:
      8  * 1. Redistributions of source code must retain the above copyright
      9  *    notice, this list of conditions and the following disclaimer.
     10  * 2. Redistributions in binary form must reproduce the above copyright
     11  *    notice, this list of conditions and the following disclaimer in the
     12  *    documentation and/or other materials provided with the distribution.
     13  * 3. The name of the author may not be used to endorse or promote products
     14  *    derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
     17  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     18  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
     19  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
     20  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
     21  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     22  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     23  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     24  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
     25  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     26  *
     27  *	$Id: kd.c,v 1.2 1994/05/05 04:46:51 gwr Exp $
     28  */
     29 
     30 /*
     31  * Keyboard/Display device.
     32  *
     33  * This driver exists simply to provide a tty device that
     34  * the indirect console driver can point to.
     35  * The kbd driver sends its input here.
     36  * Output goes to the screen via PROM printf.
     37  */
     38 
     39 #include <sys/param.h>
     40 #include <sys/proc.h>
     41 #include <sys/systm.h>
     42 #include <sys/ioctl.h>
     43 #include <sys/tty.h>
     44 #include <sys/file.h>
     45 #include <sys/conf.h>
     46 #include <sys/device.h>
     47 
     48 #include <machine/autoconf.h>
     49 #include <machine/mon.h>
     50 
     51 #include <dev/cons.h>
     52 
     53 #define BURST	64
     54 
     55 static int  kdmatch(struct device *, struct cfdata *, void *);
     56 static void kdattach(struct device *, struct device *, void *);
     57 
     58 struct cfdriver kdcd = {
     59 	NULL, "kd", kdmatch, kdattach, DV_TTY,
     60 	sizeof(struct device), 0};
     61 
     62 struct tty *kd_tty[1];
     63 
     64 int kdopen(dev_t, int, int, struct proc *);
     65 int kdclose(dev_t, int, int, struct proc *);
     66 int kdread(dev_t, struct uio *, int);
     67 int kdwrite(dev_t, struct uio *, int);
     68 int kdioctl(dev_t, int, caddr_t, int, struct proc *);
     69 
     70 static int kdparam(struct tty *, struct termios *);
     71 static void kdstart(struct tty *);
     72 
     73 static int
     74 kdmatch(struct device *parent, struct cfdata *cf, void *aux)
     75 {
     76 	/* XXX - Enforce unit zero? */
     77 	return 1;
     78 }
     79 
     80 static void
     81 kdattach(parent, self, args)
     82 	struct device *parent;
     83 	struct device *self;
     84 	void *args;
     85 {
     86 	int unit = self->dv_unit;
     87 
     88 	if (unit) {
     89 		printf(" not unit zero?\n");
     90 		return;
     91 	}
     92 	printf("\n");
     93 
     94 	kd_tty[0] = ttymalloc();
     95 
     96 	/* Tell keyboard module where to send read data. */
     97 	kbd_ascii(kd_tty[0]);
     98 }
     99 
    100 int
    101 kdopen(dev, flag, mode, p)
    102 	dev_t dev;
    103 	int flag, mode;
    104 	struct proc *p;
    105 {
    106 	int unit;
    107 	struct tty *tp;
    108 
    109 	unit = minor(dev);
    110 	if (unit) return ENXIO;
    111 
    112 	tp = kd_tty[unit];
    113 	if (tp == NULL)
    114 		return ENXIO;
    115 
    116 	tp->t_oproc = kdstart;
    117 	tp->t_param = kdparam;
    118 	tp->t_dev = dev;
    119 	if ((tp->t_state & TS_ISOPEN) == 0) {
    120 		tp->t_state |= TS_WOPEN;
    121 		ttychars(tp);
    122 		tp->t_iflag = TTYDEF_IFLAG;
    123 		tp->t_oflag = TTYDEF_OFLAG;
    124 		tp->t_cflag = TTYDEF_CFLAG;
    125 		tp->t_lflag = TTYDEF_LFLAG;
    126 		tp->t_ispeed = tp->t_ospeed = TTYDEF_SPEED;
    127 		kdparam(tp, &tp->t_termios);
    128 		ttsetwater(tp);
    129 	} else if (tp->t_state & TS_XCLUDE && p->p_ucred->cr_uid != 0)
    130 		return EBUSY;
    131 	tp->t_state |= TS_CARR_ON;
    132 
    133 	return ((*linesw[tp->t_line].l_open)(dev, tp));
    134 }
    135 
    136 int
    137 kdclose(dev, flag, mode, p)
    138 	dev_t dev;
    139 	int flag, mode;
    140 	struct proc *p;
    141 {
    142 	int unit = minor(dev);
    143 	struct tty *tp = kd_tty[unit];
    144 
    145 	(*linesw[tp->t_line].l_close)(tp, flag);
    146 	ttyclose(tp);
    147 	return (0);
    148 }
    149 
    150 int
    151 kdread(dev, uio, flag)
    152 	dev_t dev;
    153 	struct uio *uio;
    154 	int flag;
    155 {
    156 	int unit = minor(dev);
    157 	struct tty *tp = kd_tty[unit];
    158 
    159 	return ((*linesw[tp->t_line].l_read)(tp, uio, flag));
    160 }
    161 
    162 int
    163 kdwrite(dev, uio, flag)
    164 	dev_t dev;
    165 	struct uio *uio;
    166 	int flag;
    167 {
    168 	int unit = minor(dev);
    169 	struct tty *tp = kd_tty[unit];
    170 
    171 	return ((*linesw[tp->t_line].l_write)(tp, uio, flag));
    172 }
    173 
    174 int
    175 kdioctl(dev, cmd, data, flag, p)
    176 	dev_t dev;
    177 	int cmd;
    178 	caddr_t data;
    179 	int flag;
    180 	struct proc *p;
    181 {
    182 	int error;
    183 	int unit = minor(dev);
    184 	struct tty *tp = kd_tty[unit];
    185 
    186 	error = (*linesw[tp->t_line].l_ioctl)(tp, cmd, data, flag, p);
    187 	if (error >= 0)
    188 		return error;
    189 	error = ttioctl(tp, cmd, data, flag, p);
    190 	if (error >= 0)
    191 		return error;
    192 
    193 	/* Handle any ioctl commands specific to kbd/display. */
    194 	/* XXX - Send KB* ioctls to kbd module? */
    195 	/* XXX - Send FB* ioctls to fb module?  */
    196 
    197 	return ENOTTY;
    198 }
    199 
    200 void
    201 kdstart(tp)
    202 	struct tty *tp;
    203 {
    204 	struct clist *cl;
    205 	int s, len;
    206 	u_char buf[BURST];
    207 
    208 	s = spltty();
    209 	if (tp->t_state & (TS_BUSY|TS_TTSTOP|TS_TIMEOUT))
    210 		goto out;
    211 	tp->t_state |= TS_BUSY;
    212 	cl = &tp->t_outq;
    213 
    214 	/*
    215 	 * XXX - It might be nice to have our own fbputs() so
    216 	 * we would not have to use the (slow) PROM printf.
    217 	 */
    218 	while ((len = q_to_b(cl, buf, BURST-1)) > 0) {
    219 		buf[len] = '\0';
    220 		(void) splhigh();
    221 #if 0
    222 		/* XXX - Not yet.  Not sure what args should be. */
    223 		(romVectorPtr->fbWriteStr)(buf);
    224 #else
    225 		mon_printf("%s", buf);
    226 #endif
    227 		(void) spltty();
    228 	}
    229 
    230 	tp->t_state &= ~TS_BUSY;
    231 	if (tp->t_state & TS_ASLEEP) {
    232 		tp->t_state &= ~TS_ASLEEP;
    233 		wakeup((caddr_t)cl);
    234 	}
    235 	selwakeup(&tp->t_wsel);
    236 out:
    237 	splx(s);
    238 }
    239 
    240 static int
    241 kdparam(tp, t)
    242 	struct tty *tp;
    243 	struct termios *t;
    244 {
    245 	/* XXX - These are ignored... */
    246 	tp->t_ispeed = t->c_ispeed;
    247 	tp->t_ospeed = t->c_ospeed;
    248 	tp->t_cflag = t->c_cflag;
    249 	return 0;
    250 }
    251 
    252 
    253 /*
    254  * kd console support
    255  *
    256  * XXX - Using prom routines for now...
    257  */
    258 
    259 extern int zscnprobe_kbd();
    260 
    261 kdcnprobe(cp)
    262 	struct consdev *cp;
    263 {
    264 	int maj;
    265 
    266 	/* locate the major number */
    267 	for (maj = 0; maj < nchrdev; maj++)
    268 		if (cdevsw[maj].d_open == kdopen)
    269 			break;
    270 
    271 	/* initialize required fields */
    272 	cp->cn_dev = makedev(maj, 0);
    273 	cp->cn_pri = zscnprobe_kbd();
    274 }
    275 
    276 kdcninit(cp)
    277 	struct consdev *cp;
    278 {
    279 	mon_printf("console on kd0 (keyboard/display)\n");
    280 }
    281 
    282 kdcngetc(dev)
    283 	dev_t dev;
    284 {
    285 	int c, s;
    286 
    287 	/* XXX - Does mon_may_getchar() require the NMI clock? */
    288 	s = splhigh();
    289 	do c = mon_may_getchar();
    290 	while (c < 0);
    291 	splx(s);
    292 
    293 	if (c == '\r')
    294 		c = '\n';
    295 	return (c);
    296 }
    297 
    298 kdcnputc(dev, c)
    299 	dev_t dev;
    300 	int c;
    301 {
    302 	int s;
    303 
    304 	s = splhigh();
    305 #if 0
    306 	/* XXX - Is this worth doing? */
    307 	(romVectorPtr->fbWriteChar)(c);
    308 #else
    309 	mon_putchar(c);
    310 #endif
    311 	splx(s);
    312 }
    313