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
pckbc_ebus_match(struct device * parent,void * match,void * aux)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
pckbc_ebus_attach(struct device * parent,struct device * self,void * aux)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
pckbc_ebus_is_console(struct pckbc_ebus_softc * sc)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