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