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