1 1.14 thorpej /* $NetBSD: kb_ap.c,v 1.14 2021/08/07 16:19:01 thorpej Exp $ */ 2 1.1 tsubai 3 1.1 tsubai /*- 4 1.1 tsubai * Copyright (c) 2000 Tsubai Masanari. All rights reserved. 5 1.1 tsubai * 6 1.1 tsubai * Redistribution and use in source and binary forms, with or without 7 1.1 tsubai * modification, are permitted provided that the following conditions 8 1.1 tsubai * are met: 9 1.1 tsubai * 1. Redistributions of source code must retain the above copyright 10 1.1 tsubai * notice, this list of conditions and the following disclaimer. 11 1.1 tsubai * 2. Redistributions in binary form must reproduce the above copyright 12 1.1 tsubai * notice, this list of conditions and the following disclaimer in the 13 1.1 tsubai * documentation and/or other materials provided with the distribution. 14 1.1 tsubai * 3. The name of the author may not be used to endorse or promote products 15 1.1 tsubai * derived from this software without specific prior written permission. 16 1.1 tsubai * 17 1.1 tsubai * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 18 1.1 tsubai * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 19 1.1 tsubai * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 20 1.1 tsubai * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 21 1.1 tsubai * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 22 1.1 tsubai * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 23 1.1 tsubai * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 24 1.1 tsubai * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 25 1.1 tsubai * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 26 1.1 tsubai * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 27 1.1 tsubai */ 28 1.5 lukem 29 1.5 lukem #include <sys/cdefs.h> 30 1.14 thorpej __KERNEL_RCSID(0, "$NetBSD: kb_ap.c,v 1.14 2021/08/07 16:19:01 thorpej Exp $"); 31 1.1 tsubai 32 1.1 tsubai #include <sys/param.h> 33 1.1 tsubai #include <sys/systm.h> 34 1.1 tsubai #include <sys/device.h> 35 1.1 tsubai 36 1.1 tsubai #include <dev/wscons/wsconsio.h> 37 1.1 tsubai #include <dev/wscons/wskbdvar.h> 38 1.1 tsubai #include <dev/wscons/wsksymdef.h> 39 1.1 tsubai 40 1.1 tsubai #include <machine/adrsmap.h> 41 1.12 tsutsui #include <machine/cpu.h> 42 1.1 tsubai #include <newsmips/apbus/apbusvar.h> 43 1.1 tsubai 44 1.1 tsubai struct kbreg { 45 1.9 tsutsui volatile uint32_t kb_rx_data; 46 1.9 tsutsui volatile uint32_t kb_rx_stat; 47 1.9 tsutsui volatile uint32_t kb_rx_intr_en; 48 1.9 tsutsui volatile uint32_t kb_rx_reset; 49 1.9 tsutsui volatile uint32_t kb_rx_speed; 50 1.9 tsutsui 51 1.9 tsutsui volatile uint32_t ms_rx_data; 52 1.9 tsutsui volatile uint32_t ms_rx_stat; 53 1.9 tsutsui volatile uint32_t ms_rx_intr_en; 54 1.9 tsutsui volatile uint32_t ms_rx_reset; 55 1.9 tsutsui volatile uint32_t ms_rx_speed; 56 1.9 tsutsui 57 1.9 tsutsui volatile uint32_t kb_buzzf; 58 1.9 tsutsui volatile uint32_t kb_buzz; 59 1.9 tsutsui 60 1.9 tsutsui volatile uint32_t kb_tx_data; 61 1.9 tsutsui volatile uint32_t kb_tx_stat; 62 1.9 tsutsui volatile uint32_t kb_tx_intr_en; 63 1.9 tsutsui volatile uint32_t kb_tx_reset; 64 1.9 tsutsui volatile uint32_t kb_tx_speed; 65 1.1 tsubai }; 66 1.1 tsubai 67 1.1 tsubai struct kb_ap_softc { 68 1.9 tsutsui device_t sc_dev; 69 1.9 tsutsui struct kbreg *sc_reg; 70 1.10 tsutsui device_t sc_wskbddev; 71 1.1 tsubai }; 72 1.1 tsubai 73 1.9 tsutsui int kb_ap_match(device_t, cfdata_t, void *); 74 1.9 tsutsui void kb_ap_attach(device_t, device_t, void *); 75 1.1 tsubai int kb_ap_intr(void *); 76 1.1 tsubai 77 1.1 tsubai void kb_ap_cnattach(void); 78 1.1 tsubai void kb_ap_cngetc(void *, u_int *, int *); 79 1.1 tsubai void kb_ap_cnpollc(void *, int); 80 1.1 tsubai 81 1.1 tsubai int kb_ap_enable(void *, int); 82 1.1 tsubai void kb_ap_setleds(void *, int); 83 1.8 christos int kb_ap_ioctl(void *, u_long, void *, int, struct lwp *); 84 1.1 tsubai 85 1.1 tsubai extern struct wscons_keydesc newskb_keydesctab[]; 86 1.1 tsubai 87 1.9 tsutsui CFATTACH_DECL_NEW(kb_ap, sizeof(struct kb_ap_softc), 88 1.4 thorpej kb_ap_match, kb_ap_attach, NULL, NULL); 89 1.1 tsubai 90 1.1 tsubai struct wskbd_accessops kb_ap_accessops = { 91 1.1 tsubai kb_ap_enable, 92 1.1 tsubai kb_ap_setleds, 93 1.1 tsubai kb_ap_ioctl, 94 1.1 tsubai }; 95 1.1 tsubai 96 1.1 tsubai struct wskbd_consops kb_ap_consops = { 97 1.1 tsubai kb_ap_cngetc, 98 1.1 tsubai kb_ap_cnpollc, 99 1.1 tsubai }; 100 1.1 tsubai 101 1.1 tsubai struct wskbd_mapdata kb_ap_keymapdata = { 102 1.1 tsubai newskb_keydesctab, 103 1.1 tsubai KB_JP, 104 1.1 tsubai }; 105 1.1 tsubai 106 1.1 tsubai int 107 1.9 tsutsui kb_ap_match(device_t parent, cfdata_t cf, void *aux) 108 1.1 tsubai { 109 1.1 tsubai struct apbus_attach_args *apa = aux; 110 1.1 tsubai 111 1.1 tsubai if (strcmp(apa->apa_name, "kb") == 0) 112 1.1 tsubai return 1; 113 1.1 tsubai 114 1.1 tsubai return 0; 115 1.1 tsubai } 116 1.1 tsubai 117 1.1 tsubai void 118 1.9 tsutsui kb_ap_attach(device_t parent, device_t self, void *aux) 119 1.1 tsubai { 120 1.9 tsutsui struct kb_ap_softc *sc = device_private(self); 121 1.1 tsubai struct apbus_attach_args *apa = aux; 122 1.9 tsutsui struct kbreg *reg = (void *)apa->apa_hwbase; 123 1.9 tsutsui volatile uint32_t *dipsw = (void *)NEWS5000_DIP_SWITCH; 124 1.1 tsubai struct wskbddev_attach_args waa; 125 1.1 tsubai int cons = 0; 126 1.1 tsubai 127 1.9 tsutsui sc->sc_dev = self; 128 1.9 tsutsui aprint_normal(" slot%d addr 0x%lx", apa->apa_slotno, apa->apa_hwbase); 129 1.1 tsubai 130 1.1 tsubai sc->sc_reg = reg; 131 1.1 tsubai 132 1.12 tsutsui if (systype == NEWS5000 && *dipsw & 7) { 133 1.9 tsutsui aprint_normal(" (console)"); 134 1.1 tsubai cons = 1; 135 1.1 tsubai } 136 1.9 tsutsui aprint_normal("\n"); 137 1.1 tsubai 138 1.1 tsubai reg->kb_rx_reset = 0x03; 139 1.1 tsubai reg->kb_tx_reset = 0x03; 140 1.1 tsubai 141 1.1 tsubai reg->kb_rx_speed = 0x04; 142 1.1 tsubai reg->kb_tx_speed = 0x04; 143 1.1 tsubai 144 1.1 tsubai reg->kb_rx_intr_en = 1; 145 1.1 tsubai reg->kb_tx_intr_en = 0; 146 1.1 tsubai 147 1.1 tsubai apbus_intr_establish(1, NEWS5000_INT1_KBD, 0, kb_ap_intr, sc, 148 1.11 tsutsui device_xname(self), apa->apa_ctlnum); 149 1.1 tsubai 150 1.1 tsubai waa.console = cons; 151 1.1 tsubai waa.keymap = &kb_ap_keymapdata; 152 1.1 tsubai waa.accessops = &kb_ap_accessops; 153 1.1 tsubai waa.accesscookie = sc; 154 1.1 tsubai 155 1.14 thorpej sc->sc_wskbddev = config_found(self, &waa, wskbddevprint, CFARGS_NONE); 156 1.1 tsubai } 157 1.1 tsubai 158 1.1 tsubai int 159 1.6 tsutsui kb_ap_intr(void *v) 160 1.1 tsubai { 161 1.1 tsubai struct kb_ap_softc *sc = v; 162 1.9 tsutsui struct kbreg *reg = sc->sc_reg; 163 1.1 tsubai int key, val, type, release; 164 1.1 tsubai int rv = 0; 165 1.1 tsubai 166 1.1 tsubai while (reg->kb_rx_stat & RX_KBRDY) { 167 1.1 tsubai key = reg->kb_rx_data; 168 1.1 tsubai val = key & 0x7f; 169 1.1 tsubai release = key & 0x80; 170 1.1 tsubai type = release ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 171 1.1 tsubai 172 1.1 tsubai if (sc->sc_wskbddev) 173 1.1 tsubai wskbd_input(sc->sc_wskbddev, type, val); 174 1.1 tsubai 175 1.1 tsubai rv = 1; 176 1.1 tsubai } 177 1.1 tsubai 178 1.1 tsubai return rv; 179 1.1 tsubai } 180 1.1 tsubai 181 1.1 tsubai void 182 1.6 tsutsui kb_ap_cnattach(void) 183 1.1 tsubai { 184 1.6 tsutsui 185 1.1 tsubai wskbd_cnattach(&kb_ap_consops, (void *)0xbf900000, &kb_ap_keymapdata); 186 1.1 tsubai } 187 1.1 tsubai 188 1.1 tsubai void 189 1.6 tsutsui kb_ap_cngetc(void *v, u_int *type, int *data) 190 1.1 tsubai { 191 1.9 tsutsui struct kbreg *reg = v; 192 1.1 tsubai int key, release, ointr; 193 1.1 tsubai 194 1.1 tsubai /* Disable keyboard interrupt. */ 195 1.1 tsubai ointr = reg->kb_rx_intr_en; 196 1.1 tsubai reg->kb_rx_intr_en = 0; 197 1.1 tsubai 198 1.1 tsubai /* Wait for key data. */ 199 1.9 tsutsui while ((reg->kb_rx_stat & RX_KBRDY) == 0) 200 1.9 tsutsui ; 201 1.1 tsubai 202 1.1 tsubai key = reg->kb_rx_data; 203 1.1 tsubai release = key & 0x80; 204 1.1 tsubai *data = key & 0x7f; 205 1.1 tsubai *type = release ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN; 206 1.1 tsubai 207 1.1 tsubai reg->kb_rx_intr_en = ointr; 208 1.1 tsubai } 209 1.1 tsubai 210 1.1 tsubai void 211 1.6 tsutsui kb_ap_cnpollc(void *v, int on) 212 1.1 tsubai { 213 1.1 tsubai } 214 1.1 tsubai 215 1.1 tsubai int 216 1.6 tsutsui kb_ap_enable(void *v, int on) 217 1.1 tsubai { 218 1.6 tsutsui 219 1.1 tsubai return 0; 220 1.1 tsubai } 221 1.1 tsubai 222 1.1 tsubai void 223 1.6 tsutsui kb_ap_setleds(void *v, int on) 224 1.1 tsubai { 225 1.1 tsubai } 226 1.1 tsubai 227 1.1 tsubai int 228 1.8 christos kb_ap_ioctl(void *v, u_long cmd, void *data, int flag, struct lwp *l) 229 1.1 tsubai { 230 1.6 tsutsui 231 1.1 tsubai switch (cmd) { 232 1.1 tsubai case WSKBDIO_GTYPE: 233 1.1 tsubai *(int *)data = 0; /* XXX */ 234 1.1 tsubai return 0; 235 1.1 tsubai case WSKBDIO_SETLEDS: 236 1.1 tsubai return 0; 237 1.1 tsubai case WSKBDIO_GETLEDS: 238 1.1 tsubai *(int *)data = 0; 239 1.1 tsubai return 0; 240 1.1 tsubai } 241 1.1 tsubai 242 1.2 atatat return EPASSTHROUGH; 243 1.1 tsubai } 244