Home | History | Annotate | Line # | Download | only in dev
kbd.c revision 1.18
      1 /*	$NetBSD: kbd.c,v 1.18 1996/04/21 21:12:05 veego Exp $	*/
      2 
      3 /*
      4  * Copyright (c) 1982, 1986, 1990 The Regents of the University of California.
      5  * All rights reserved.
      6  *
      7  * Redistribution and use in source and binary forms, with or without
      8  * modification, are permitted provided that the following conditions
      9  * are met:
     10  * 1. Redistributions of source code must retain the above copyright
     11  *    notice, this list of conditions and the following disclaimer.
     12  * 2. Redistributions in binary form must reproduce the above copyright
     13  *    notice, this list of conditions and the following disclaimer in the
     14  *    documentation and/or other materials provided with the distribution.
     15  * 3. All advertising materials mentioning features or use of this software
     16  *    must display the following acknowledgement:
     17  *	This product includes software developed by the University of
     18  *	California, Berkeley and its contributors.
     19  * 4. Neither the name of the University nor the names of its contributors
     20  *    may be used to endorse or promote products derived from this software
     21  *    without specific prior written permission.
     22  *
     23  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
     24  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
     25  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
     26  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
     27  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     28  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     29  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     30  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     31  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     32  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     33  * SUCH DAMAGE.
     34  *
     35  *	kbd.c
     36  */
     37 #include <sys/param.h>
     38 #include <sys/systm.h>
     39 #include <sys/device.h>
     40 #include <sys/ioctl.h>
     41 #include <sys/tty.h>
     42 #include <sys/proc.h>
     43 #include <sys/file.h>
     44 #include <sys/kernel.h>
     45 #include <sys/syslog.h>
     46 #include <sys/signalvar.h>
     47 #include <dev/cons.h>
     48 #include <machine/cpu.h>
     49 #include <amiga/amiga/device.h>
     50 #include <amiga/amiga/custom.h>
     51 #include <amiga/amiga/cia.h>
     52 #include <amiga/dev/itevar.h>
     53 #include <amiga/dev/kbdreg.h>
     54 #include <amiga/dev/kbdmap.h>
     55 #include <amiga/dev/event_var.h>
     56 #include <amiga/dev/vuid_event.h>
     57 #include "kbd.h"
     58 
     59 #include <sys/conf.h>
     60 #include <machine/conf.h>
     61 
     62 struct kbd_softc {
     63 	int k_event_mode;	/* if true, collect events, else pass to ite */
     64 	struct evvar k_events;	/* event queue state */
     65 };
     66 struct kbd_softc kbd_softc;
     67 
     68 int kbdmatch __P((struct device *, void *, void *));
     69 void kbdattach __P((struct device *, struct device *, void *));
     70 void kbdintr __P((int));
     71 
     72 struct cfattach kbd_ca = {
     73 	sizeof(struct device), kbdmatch, kbdattach
     74 };
     75 
     76 struct cfdriver kbd_cd = {
     77 	NULL, "kbd", DV_DULL, NULL, 0
     78 };
     79 
     80 /*ARGSUSED*/
     81 int
     82 kbdmatch(pdp, match, auxp)
     83 	struct device *pdp;
     84 	void *match, *auxp;
     85 {
     86 
     87 	if (matchname((char *)auxp, "kbd"))
     88 		return(1);
     89 	return(0);
     90 }
     91 
     92 /*ARGSUSED*/
     93 void
     94 kbdattach(pdp, dp, auxp)
     95 	struct device *pdp, *dp;
     96 	void *auxp;
     97 {
     98 	printf("\n");
     99 }
    100 
    101 /* definitions for amiga keyboard encoding. */
    102 #define KEY_CODE(c)  ((c) & 0x7f)
    103 #define KEY_UP(c)    ((c) & 0x80)
    104 
    105 void
    106 kbdenable()
    107 {
    108 	int s;
    109 
    110 	/*
    111 	 * collides with external ints from SCSI, watch out for this when
    112 	 * enabling/disabling interrupts there !!
    113 	 */
    114 	s = spltty();
    115 	custom.intena = INTF_SETCLR | INTF_PORTS;
    116 	ciaa.icr = CIA_ICR_IR_SC | CIA_ICR_SP;  /* SP interrupt enable */
    117 	ciaa.cra &= ~(1<<6);		/* serial line == input */
    118 	kbd_softc.k_event_mode = 0;
    119 	kbd_softc.k_events.ev_io = 0;
    120 	splx(s);
    121 }
    122 
    123 
    124 int
    125 kbdopen(dev, flags, mode, p)
    126 	dev_t dev;
    127 	int flags, mode;
    128 	struct proc *p;
    129 {
    130 
    131 	if (kbd_softc.k_events.ev_io)
    132 		return EBUSY;
    133 
    134 	kbd_softc.k_events.ev_io = p;
    135 	ev_init(&kbd_softc.k_events);
    136 	return (0);
    137 }
    138 
    139 int
    140 kbdclose(dev, flags, mode, p)
    141 	dev_t dev;
    142 	int flags, mode;
    143 	struct proc *p;
    144 {
    145 
    146 	/* Turn off event mode, dump the queue */
    147 	kbd_softc.k_event_mode = 0;
    148 	ev_fini(&kbd_softc.k_events);
    149 	kbd_softc.k_events.ev_io = NULL;
    150 	return (0);
    151 }
    152 
    153 int
    154 kbdread(dev, uio, flags)
    155 	dev_t dev;
    156 	struct uio *uio;
    157 	int flags;
    158 {
    159 	return ev_read (&kbd_softc.k_events, uio, flags);
    160 }
    161 
    162 int
    163 kbdioctl(dev, cmd, data, flag, p)
    164 	dev_t dev;
    165 	u_long cmd;
    166 	register caddr_t data;
    167 	int flag;
    168 	struct proc *p;
    169 {
    170 	register struct kbd_softc *k = &kbd_softc;
    171 
    172 	switch (cmd) {
    173 		case KIOCTRANS:
    174 			if (*(int *)data == TR_UNTRANS_EVENT)
    175 				return 0;
    176 			break;
    177 
    178 		case KIOCGTRANS:
    179 			/* Get translation mode */
    180 			*(int *)data = TR_UNTRANS_EVENT;
    181 			return 0;
    182 
    183 		case KIOCSDIRECT:
    184 			k->k_event_mode = *(int *)data;
    185 			return 0;
    186 
    187 		case FIONBIO:	/* we will remove this someday (soon???) */
    188 			return 0;
    189 
    190 		case FIOASYNC:
    191 			k->k_events.ev_async = *(int *)data != 0;
    192 			return 0;
    193 
    194 		case TIOCSPGRP:
    195 			if (*(int *)data != k->k_events.ev_io->p_pgid)
    196 				return EPERM;
    197 			return 0;
    198 
    199 		default:
    200 			return ENOTTY;
    201 	}
    202 
    203 	/* We identified the ioctl, but we do not handle it. */
    204 	return EOPNOTSUPP;	/* misuse, but what the heck */
    205 }
    206 
    207 int
    208 kbdselect(dev, rw, p)
    209 	dev_t dev;
    210 	int rw;
    211 	struct proc *p;
    212 {
    213 	return ev_select (&kbd_softc.k_events, rw, p);
    214 }
    215 
    216 
    217 void
    218 kbdintr(mask)
    219 	int mask;
    220 {
    221 	u_char c;
    222 	struct kbd_softc *k = &kbd_softc;
    223 	struct firm_event *fe;
    224 	int put;
    225 #ifdef KBDRESET
    226 	static int reset_warn;
    227 #endif
    228 
    229 	/* now only invoked from generic CIA interrupt handler if there *is*
    230 	 * a keyboard interrupt pending
    231 	 */
    232 
    233 	c = ~ciaa.sdr;	/* keyboard data is inverted */
    234 	/* ack */
    235 	ciaa.cra |= (1 << 6);	/* serial line output */
    236 #ifdef KBDRESET
    237 	if (reset_warn && c == 0xf0) {
    238 #ifdef DEBUG
    239 		printf ("kbdintr: !!!! Reset Warning !!!!\n");
    240 #endif
    241 		bootsync();
    242 		reset_warn = 0;
    243 		DELAY(30000000);
    244 	}
    245 #endif
    246 	/* wait 200 microseconds (for bloody Cherry keyboards..) */
    247 	DELAY(2000);			/* fudge delay a bit for some keyboards */
    248 	ciaa.cra &= ~(1 << 6);
    249 
    250 	/* process the character */
    251 	c = (c >> 1) | (c << 7);	/* rotate right once */
    252 
    253 #ifdef KBDRESET
    254 	if (c == 0x78) {
    255 #ifdef DEBUG
    256 		printf ("kbdintr: Reset Warning started\n");
    257 #endif
    258 		++reset_warn;
    259 		return;
    260 	}
    261 #endif
    262 	/* if not in event mode, deliver straight to ite to process key stroke */
    263 	if (! k->k_event_mode) {
    264 		ite_filter (c, ITEFILT_TTY);
    265 		return;
    266 	}
    267 
    268 	/* Keyboard is generating events.  Turn this keystroke into an
    269 	 * event and put it in the queue.  If the queue is full, the
    270 	 * keystroke is lost (sorry!).
    271 	 */
    272 
    273 	put = k->k_events.ev_put;
    274 	fe = &k->k_events.ev_q[put];
    275 	put = (put + 1) % EV_QSIZE;
    276 	if (put == k->k_events.ev_get) {
    277 		log(LOG_WARNING, "keyboard event queue overflow\n"); /* ??? */
    278 		return;
    279 	}
    280 	fe->id = KEY_CODE(c);
    281 	fe->value = KEY_UP(c) ? VKEY_UP : VKEY_DOWN;
    282 	fe->time = time;
    283 	k->k_events.ev_put = put;
    284 	EV_WAKEUP(&k->k_events);
    285 }
    286 
    287 
    288 int
    289 kbdgetcn()
    290 {
    291 	int s = spltty ();
    292 	u_char ints, mask, c, in;
    293 
    294 	for (ints = 0; ! ((mask = ciaa.icr) & CIA_ICR_SP); ints |= mask) ;
    295 
    296 	in = ciaa.sdr;
    297 	c = ~in;
    298 
    299 	/* ack */
    300 	ciaa.cra |= (1 << 6);	/* serial line output */
    301 	ciaa.sdr = 0xff;		/* ack */
    302 	/* wait 200 microseconds */
    303 	DELAY(2000);    /* XXXX only works as long as DELAY doesn't use a timer and waits.. */
    304 	ciaa.cra &= ~(1 << 6);
    305 	ciaa.sdr = in;
    306 
    307 	splx (s);
    308 	c = (c >> 1) | (c << 7);
    309 
    310 	/* take care that no CIA-interrupts are lost */
    311 	if (ints)
    312 		dispatch_cia_ints (0, ints);
    313 
    314 	return c;
    315 }
    316