1 /* $OpenBSD: pckbc_ebus.c,v 1.13 2015/05/24 10:57:47 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/types.h> 40 #include <sys/param.h> 41 #include <sys/systm.h> 42 #include <sys/device.h> 43 #include <sys/conf.h> 44 #include <sys/malloc.h> 45 46 #include <machine/bus.h> 47 #include <machine/autoconf.h> 48 #include <machine/openfirm.h> 49 50 #include <sparc64/dev/ebusreg.h> 51 #include <sparc64/dev/ebusvar.h> 52 53 #include <dev/ic/i8042reg.h> 54 #include <dev/ic/pckbcvar.h> 55 56 struct pckbc_ebus_softc { 57 struct pckbc_softc sc_pckbc; 58 bus_space_tag_t sc_iot; 59 bus_space_handle_t sc_ioh; 60 bus_space_handle_t sc_ioh_c; 61 bus_space_handle_t sc_ioh_d; 62 void *sc_irq[2]; 63 int sc_node; 64 }; 65 66 int pckbc_ebus_match(struct device *, void *, void *); 67 void pckbc_ebus_attach(struct device *, struct device *, void *); 68 69 struct cfattach pckbc_ebus_ca = { 70 sizeof(struct pckbc_ebus_softc), pckbc_ebus_match, pckbc_ebus_attach 71 }; 72 73 int pckbc_ebus_is_console(struct pckbc_ebus_softc *); 74 75 int 76 pckbc_ebus_match(parent, match, aux) 77 struct device *parent; 78 void *match; 79 void *aux; 80 { 81 struct ebus_attach_args *ea = aux; 82 83 if (strcmp(ea->ea_name, "8042") == 0) 84 return (1); 85 return (0); 86 } 87 88 void 89 pckbc_ebus_attach(parent, self, aux) 90 struct device *parent, *self; 91 void *aux; 92 { 93 struct pckbc_ebus_softc *sc = (void *)self; 94 struct pckbc_softc *psc = &sc->sc_pckbc; 95 struct ebus_attach_args *ea = aux; 96 struct pckbc_internal *t = NULL; 97 int console; 98 int flags = 0; 99 100 sc->sc_node = ea->ea_node; 101 console = pckbc_ebus_is_console(sc); 102 103 /* Use prom address if available, otherwise map it. */ 104 if (ea->ea_nvaddrs && bus_space_map(ea->ea_iotag, ea->ea_vaddrs[0], 0, 105 0, &sc->sc_ioh) == 0) { 106 sc->sc_iot = ea->ea_iotag; 107 } else if (ebus_bus_map(ea->ea_iotag, 0, 108 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 109 0, 0, &sc->sc_ioh) == 0) { 110 sc->sc_iot = ea->ea_iotag; 111 } else if (ebus_bus_map(ea->ea_memtag, 0, 112 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 113 0, 0, &sc->sc_ioh) == 0) { 114 sc->sc_iot = ea->ea_memtag; 115 } else { 116 printf(": can't map register space\n"); 117 return; 118 } 119 120 /* 121 * The 8042 controller found on the Tadpole SPARCLE doesn't 122 * implement XT scan code translation. 123 * XXX I have not checked the value of the model property on 124 * XXX UltraAXe boards... 125 */ 126 { 127 char model[128]; 128 OF_getprop(ea->ea_node, "model", &model, sizeof model); 129 if (strcmp(model, "INTC,80c42") == 0) 130 flags = PCKBC_CANT_TRANSLATE | PCKBC_NEED_AUXWRITE; 131 } 132 133 if (console) { 134 if (pckbc_cnattach(sc->sc_iot, 135 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), KBCMDP, flags) == 0) { 136 t = &pckbc_consdata; 137 pckbc_console_attached = 1; 138 sc->sc_ioh_c = t->t_ioh_c; 139 sc->sc_ioh_d = t->t_ioh_d; 140 } else 141 console = 0; 142 } 143 144 if (console == 0) { 145 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 146 KBCMDP, sizeof(u_int32_t), &sc->sc_ioh_c) != 0) { 147 printf(": couldn't get cmd subregion\n"); 148 return; 149 } 150 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 151 KBDATAP, sizeof(u_int32_t), &sc->sc_ioh_d) != 0) { 152 printf(": couldn't get data subregion\n"); 153 return; 154 } 155 156 t = malloc(sizeof(*t), M_DEVBUF, M_NOWAIT | M_ZERO); 157 t->t_flags = flags; 158 } 159 160 sc->sc_irq[0] = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0], 161 IPL_TTY, 0, pckbcintr, psc, self->dv_xname); 162 if (sc->sc_irq[0] == NULL) { 163 printf(": couldn't get intr0\n"); 164 return; 165 } 166 167 sc->sc_irq[1] = bus_intr_establish(sc->sc_iot, ea->ea_intrs[1], 168 IPL_TTY, 0, pckbcintr, psc, self->dv_xname); 169 if (sc->sc_irq[1] == NULL) { 170 printf(": couldn't get intr1\n"); 171 return; 172 } 173 174 t->t_iot = sc->sc_iot; 175 t->t_ioh_c = sc->sc_ioh_c; 176 t->t_ioh_d = sc->sc_ioh_d; 177 t->t_cmdbyte = KC8_CPU; 178 t->t_sc = psc; 179 180 psc->id = t; 181 182 printf("\n"); 183 pckbc_attach(psc, 0); 184 } 185 186 int 187 pckbc_ebus_is_console(sc) 188 struct pckbc_ebus_softc *sc; 189 { 190 char *name; 191 int node; 192 193 /* 194 * Loop through the children of 8042 and see if the keyboard 195 * exists, and further, whether it is the console input device. 196 * This is almost redundant because 8042 doesn't show up in 197 * device tree unless a keyboard is in fact attached. 198 */ 199 for (node = OF_child(sc->sc_node); node; node = OF_peer(node)) { 200 name = getpropstring(node, "name"); 201 if (name == NULL) 202 continue; 203 if (strcmp("kb_ps2", name) == 0 || 204 strcmp("keyboard", name) == 0) { 205 if (node == OF_instance_to_package(OF_stdin())) 206 return (1); 207 } 208 } 209 return (0); 210 } 211