1 /* $OpenBSD: pckbc_ebus.c,v 1.17 2023/07/25 10:00:44 miod Exp $ */ 2 3 /* 4 * Copyright (c) 2002 Jason L. Wright (jason@thought.net) 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 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, 20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN 25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 26 * POSSIBILITY OF SUCH DAMAGE. 27 */ 28 29 /* 30 * Driver for i8042 keyboard controller found on some PCI based 31 * UltraSPARCs 32 * 33 * Effort sponsored in part by the Defense Advanced Research Projects 34 * Agency (DARPA) and Air Force Research Laboratory, Air Force 35 * Materiel Command, USAF, under agreement number F30602-01-2-0537. 36 * 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/device.h> 42 #include <sys/conf.h> 43 #include <sys/malloc.h> 44 45 #include <machine/bus.h> 46 #include <machine/autoconf.h> 47 #include <machine/openfirm.h> 48 49 #include <sparc64/dev/ebusreg.h> 50 #include <sparc64/dev/ebusvar.h> 51 52 #include <dev/ic/i8042reg.h> 53 #include <dev/ic/pckbcvar.h> 54 55 struct pckbc_ebus_softc { 56 struct pckbc_softc sc_pckbc; 57 bus_space_tag_t sc_iot; 58 bus_space_handle_t sc_ioh; 59 bus_space_handle_t sc_ioh_c; 60 bus_space_handle_t sc_ioh_d; 61 void *sc_irq[2]; 62 int sc_node; 63 }; 64 65 int pckbc_ebus_match(struct device *, void *, void *); 66 void pckbc_ebus_attach(struct device *, struct device *, void *); 67 68 const struct cfattach pckbc_ebus_ca = { 69 sizeof(struct pckbc_ebus_softc), pckbc_ebus_match, pckbc_ebus_attach 70 }; 71 72 int pckbc_ebus_is_console(struct pckbc_ebus_softc *); 73 74 int 75 pckbc_ebus_match(struct device *parent, void *match, void *aux) 76 { 77 struct ebus_attach_args *ea = aux; 78 79 if (strcmp(ea->ea_name, "8042") == 0) 80 return (1); 81 return (0); 82 } 83 84 void 85 pckbc_ebus_attach(struct device *parent, struct device *self, void *aux) 86 { 87 struct pckbc_ebus_softc *sc = (void *)self; 88 struct pckbc_softc *psc = &sc->sc_pckbc; 89 struct ebus_attach_args *ea = aux; 90 struct pckbc_internal *t = NULL; 91 int console; 92 int flags = 0; 93 94 sc->sc_node = ea->ea_node; 95 console = pckbc_ebus_is_console(sc); 96 97 /* Use prom address if available, otherwise map it. */ 98 if (ea->ea_nvaddrs && bus_space_map(ea->ea_iotag, ea->ea_vaddrs[0], 0, 99 0, &sc->sc_ioh) == 0) { 100 sc->sc_iot = ea->ea_iotag; 101 } else if (ebus_bus_map(ea->ea_iotag, 0, 102 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 103 0, 0, &sc->sc_ioh) == 0) { 104 sc->sc_iot = ea->ea_iotag; 105 } else if (ebus_bus_map(ea->ea_memtag, 0, 106 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 107 0, 0, &sc->sc_ioh) == 0) { 108 sc->sc_iot = ea->ea_memtag; 109 } else { 110 printf(": can't map register space\n"); 111 return; 112 } 113 114 /* 115 * Tadpole/RDI systems use a 8042 controller which does not 116 * implement XT scan code translation. 117 * - on the SPARCLE and the Viper, which sport a PC-style 118 * keyboard with no L function keys, the keyboard defaults 119 * to scan code set #2. 120 * - on the UltraBook IIe, which sports a complete Sun-style 121 * keyboard with L function keys and diamond keys, 122 * the keyboard defaults to scan code set #3. 123 */ 124 { 125 char buf[128]; 126 OF_getprop(ea->ea_node, "model", buf, sizeof buf); 127 if (strcmp(buf, "INTC,80c42") == 0) { 128 /* 129 * This is a Tadpole/RDI system. Tell the RDI design 130 * (UltraBook IIe) from the Tadpole design (SPARCLE) 131 * by looking for a tadpmu child node in the latter. 132 */ 133 int sparcle = 0; 134 int node; 135 for (node = OF_child(sc->sc_node); node; 136 node = OF_peer(node)) { 137 if (OF_getprop(node, "name", buf, 138 sizeof buf) <= 0) 139 continue; 140 if (strcmp(buf, "tadpmu") == 0) { 141 sparcle = 1; 142 break; 143 } 144 } 145 flags = PCKBC_NEED_AUXWRITE; 146 if (sparcle) 147 flags |= PCKBC_FIXED_SET2; 148 else 149 flags |= PCKBC_FIXED_SET3; 150 } 151 } 152 153 if (console) { 154 if (pckbc_cnattach(sc->sc_iot, 155 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), KBCMDP, flags) == 0) { 156 t = &pckbc_consdata; 157 pckbc_console_attached = 1; 158 sc->sc_ioh_c = t->t_ioh_c; 159 sc->sc_ioh_d = t->t_ioh_d; 160 } else 161 console = 0; 162 } 163 164 if (console == 0) { 165 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 166 KBCMDP, sizeof(u_int32_t), &sc->sc_ioh_c) != 0) { 167 printf(": couldn't get cmd subregion\n"); 168 return; 169 } 170 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 171 KBDATAP, sizeof(u_int32_t), &sc->sc_ioh_d) != 0) { 172 printf(": couldn't get data subregion\n"); 173 return; 174 } 175 176 t = malloc(sizeof(*t), M_DEVBUF, M_NOWAIT | M_ZERO); 177 t->t_flags = flags; 178 } 179 180 sc->sc_irq[0] = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0], 181 IPL_TTY, 0, pckbcintr, psc, self->dv_xname); 182 if (sc->sc_irq[0] == NULL) { 183 printf(": couldn't get intr0\n"); 184 return; 185 } 186 187 sc->sc_irq[1] = bus_intr_establish(sc->sc_iot, ea->ea_intrs[1], 188 IPL_TTY, 0, pckbcintr, psc, self->dv_xname); 189 if (sc->sc_irq[1] == NULL) { 190 printf(": couldn't get intr1\n"); 191 return; 192 } 193 194 t->t_iot = sc->sc_iot; 195 t->t_ioh_c = sc->sc_ioh_c; 196 t->t_ioh_d = sc->sc_ioh_d; 197 t->t_cmdbyte = KC8_CPU; 198 t->t_sc = psc; 199 200 psc->id = t; 201 202 printf("\n"); 203 pckbc_attach(psc, 0); 204 } 205 206 int 207 pckbc_ebus_is_console(struct pckbc_ebus_softc *sc) 208 { 209 char *name; 210 int node; 211 212 /* 213 * Loop through the children of 8042 and see if the keyboard 214 * exists, and further, whether it is the console input device. 215 * This is almost redundant because 8042 doesn't show up in 216 * device tree unless a keyboard is in fact attached. 217 */ 218 for (node = OF_child(sc->sc_node); node; node = OF_peer(node)) { 219 name = getpropstring(node, "name"); 220 if (name == NULL) 221 continue; 222 if (strcmp("kb_ps2", name) == 0 || 223 strcmp("keyboard", name) == 0) { 224 if (node == OF_instance_to_package(OF_stdin())) 225 return (1); 226 } 227 } 228 return (0); 229 } 230