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