1 /* $OpenBSD: pckbc_ebus.c,v 1.10 2008/07/29 04:20:35 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 void pckbc_ebus_intr_establish(struct pckbc_softc *, pckbc_slot_t); 74 int pckbc_ebus_is_console(struct pckbc_ebus_softc *); 75 76 int 77 pckbc_ebus_match(parent, match, aux) 78 struct device *parent; 79 void *match; 80 void *aux; 81 { 82 struct ebus_attach_args *ea = aux; 83 84 if (strcmp(ea->ea_name, "8042") == 0) 85 return (1); 86 return (0); 87 } 88 89 void 90 pckbc_ebus_attach(parent, self, aux) 91 struct device *parent, *self; 92 void *aux; 93 { 94 struct pckbc_ebus_softc *sc = (void *)self; 95 struct pckbc_softc *psc = &sc->sc_pckbc; 96 struct ebus_attach_args *ea = aux; 97 struct pckbc_internal *t = NULL; 98 int console; 99 int flags = 0; 100 101 sc->sc_node = ea->ea_node; 102 console = pckbc_ebus_is_console(sc); 103 104 /* Use prom address if available, otherwise map it. */ 105 if (ea->ea_nvaddrs && bus_space_map(ea->ea_iotag, ea->ea_vaddrs[0], 0, 106 0, &sc->sc_ioh) == 0) { 107 sc->sc_iot = ea->ea_iotag; 108 } else if (ebus_bus_map(ea->ea_iotag, 0, 109 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 110 0, 0, &sc->sc_ioh) == 0) { 111 sc->sc_iot = ea->ea_iotag; 112 } else if (ebus_bus_map(ea->ea_memtag, 0, 113 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), ea->ea_regs[0].size, 114 0, 0, &sc->sc_ioh) == 0) { 115 sc->sc_iot = ea->ea_memtag; 116 } else { 117 printf(": can't map register space\n"); 118 return; 119 } 120 121 /* 122 * The 8042 controller found on the Tadpole SPARCLE doesn't 123 * implement XT scan code translation. 124 * XXX I have not checked the value of the model property on 125 * XXX UltraAXe boards... 126 */ 127 { 128 char model[128]; 129 OF_getprop(ea->ea_node, "model", &model, sizeof model); 130 if (strcmp(model, "INTC,80c42") == 0) 131 flags = PCKBC_CANT_TRANSLATE | PCKBC_NEED_AUXWRITE; 132 } 133 134 if (console) { 135 if (pckbc_cnattach(sc->sc_iot, 136 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), KBCMDP, 137 PCKBC_KBD_SLOT, flags) == 0) { 138 t = &pckbc_consdata; 139 pckbc_console_attached = 1; 140 sc->sc_ioh_c = t->t_ioh_c; 141 sc->sc_ioh_d = t->t_ioh_d; 142 } else 143 console = 0; 144 } 145 146 if (console == 0) { 147 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 148 KBCMDP, sizeof(u_int32_t), &sc->sc_ioh_c) != 0) { 149 printf(": couldn't get cmd subregion\n"); 150 return; 151 } 152 if (bus_space_subregion(sc->sc_iot, sc->sc_ioh, 153 KBDATAP, sizeof(u_int32_t), &sc->sc_ioh_d) != 0) { 154 printf(": couldn't get data subregion\n"); 155 return; 156 } 157 158 t = malloc(sizeof(*t), M_DEVBUF, M_NOWAIT | M_ZERO); 159 t->t_flags = flags; 160 } 161 162 psc->intr_establish = pckbc_ebus_intr_establish; 163 164 sc->sc_irq[0] = bus_intr_establish(sc->sc_iot, ea->ea_intrs[0], 165 IPL_TTY, 0, pckbcintr, psc, self->dv_xname); 166 if (sc->sc_irq[0] == NULL) { 167 printf(": couldn't get intr0\n"); 168 return; 169 } 170 171 sc->sc_irq[1] = bus_intr_establish(sc->sc_iot, ea->ea_intrs[1], 172 IPL_TTY, 0, pckbcintr, psc, self->dv_xname); 173 if (sc->sc_irq[1] == NULL) { 174 printf(": couldn't get intr1\n"); 175 return; 176 } 177 178 t->t_iot = sc->sc_iot; 179 t->t_ioh_c = sc->sc_ioh_c; 180 t->t_ioh_d = sc->sc_ioh_d; 181 t->t_cmdbyte = KC8_CPU; 182 t->t_sc = psc; 183 184 psc->id = t; 185 186 printf("\n"); 187 pckbc_attach(psc); 188 } 189 190 int 191 pckbc_ebus_is_console(sc) 192 struct pckbc_ebus_softc *sc; 193 { 194 char *name; 195 int node; 196 197 /* 198 * Loop through the children of 8042 and see if the keyboard 199 * exists, and further, whether it is the console input device. 200 * This is almost redundant because 8042 doesn't show up in 201 * device tree unless a keyboard is in fact attached. 202 */ 203 for (node = OF_child(sc->sc_node); node; node = OF_peer(node)) { 204 name = getpropstring(node, "name"); 205 if (name == NULL) 206 continue; 207 if (strcmp("kb_ps2", name) == 0 || 208 strcmp("keyboard", name) == 0) { 209 if (node == OF_instance_to_package(OF_stdin())) 210 return (1); 211 } 212 } 213 return (0); 214 } 215 216 void 217 pckbc_ebus_intr_establish(psc, slot) 218 struct pckbc_softc *psc; 219 pckbc_slot_t slot; 220 { 221 /* Nothing to do, interrupts were mapped in attach. */ 222 } 223