m38813c.c revision 1.3 1 /* $NetBSD: m38813c.c,v 1.3 2000/09/21 14:17:29 takemura Exp $ */
2
3 /*
4 * Copyright (c) 1999, 2000, by UCHIYAMA Yasushi
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. The name of the developer may NOT be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 */
28
29 /*
30 * Device driver for MITUBISHI M38813 controller
31 */
32
33 #include "opt_tx39_debug.h"
34 #include "opt_use_poll.h"
35
36 #include <sys/param.h>
37 #include <sys/systm.h>
38 #include <sys/device.h>
39
40 #include <machine/bus.h>
41 #include <machine/intr.h>
42
43 #include <hpcmips/tx/tx39var.h>
44 #include <hpcmips/tx/txcsbusvar.h>
45
46 #include <hpcmips/dev/m38813cvar.h>
47 #include <hpcmips/dev/hpckbdvar.h>
48
49 struct m38813c_chip {
50 bus_space_tag_t scc_cst;
51 bus_space_handle_t scc_csh;
52 int scc_enabled;
53 int t_lastchar;
54 int t_extended;
55 int t_extended1;
56
57 struct hpckbd_ic_if scc_if;
58 struct hpckbd_if *scc_hpckbd;
59 };
60
61 struct m38813c_softc {
62 struct device sc_dev;
63 struct m38813c_chip *sc_chip;
64 tx_chipset_tag_t sc_tc;
65 void *sc_ih;
66 };
67
68 int m38813c_match __P((struct device*, struct cfdata*, void*));
69 void m38813c_attach __P((struct device*, struct device*, void*));
70 int m38813c_intr __P((void*));
71 int m38813c_poll __P((void*));
72 void m38813c_ifsetup __P((struct m38813c_chip*));
73 int m38813c_input_establish __P((void*, struct hpckbd_if*));
74
75 struct m38813c_chip m38813c_chip;
76
77 struct cfattach m38813c_ca = {
78 sizeof(struct m38813c_softc), m38813c_match, m38813c_attach
79 };
80
81 int
82 m38813c_match(parent, cf, aux)
83 struct device *parent;
84 struct cfdata *cf;
85 void *aux;
86 {
87 return 1;
88 }
89
90 void
91 m38813c_attach(parent, self, aux)
92 struct device *parent;
93 struct device *self;
94 void *aux;
95 {
96 struct cs_attach_args *ca = aux;
97 struct m38813c_softc *sc = (void*)self;
98 struct hpckbd_attach_args haa;
99
100 sc->sc_tc = ca->ca_tc;
101 sc->sc_chip = &m38813c_chip;
102 sc->sc_chip->scc_cst = ca->ca_csio.cstag;
103
104 if (bus_space_map(sc->sc_chip->scc_cst, ca->ca_csio.csbase,
105 ca->ca_csio.cssize, 0, &sc->sc_chip->scc_csh)) {
106 printf(": can't map i/o space\n");
107 }
108
109 #ifndef USE_POLL
110 #error options USE_POLL requied.
111 #endif
112 if (!(sc->sc_ih = tx39_poll_establish(sc->sc_tc, 1,
113 IPL_TTY, m38813c_intr,
114 sc))) {
115 printf(": can't establish interrupt\n");
116 }
117
118 printf("\n");
119
120 /* setup upper interface */
121 m38813c_ifsetup(sc->sc_chip);
122
123 haa.haa_ic = &sc->sc_chip->scc_if;
124
125 config_found(self, &haa, hpckbd_print);
126 }
127
128 void
129 m38813c_ifsetup(scc)
130 struct m38813c_chip *scc;
131 {
132 scc->scc_if.hii_ctx = scc;
133
134 scc->scc_if.hii_establish = m38813c_input_establish;
135 scc->scc_if.hii_poll = m38813c_intr;
136 }
137
138 int
139 m38813c_cnattach(addr)
140 paddr_t addr;
141 {
142 struct m38813c_chip *scc = &m38813c_chip;
143
144 scc->scc_csh = MIPS_PHYS_TO_KSEG1(addr);
145
146 m38813c_ifsetup(scc);
147
148 hpckbd_cnattach(&scc->scc_if);
149
150 return 0;
151 }
152
153 int
154 m38813c_input_establish(ic, kbdif)
155 void *ic;
156 struct hpckbd_if *kbdif;
157 {
158 struct m38813c_chip *scc = ic;
159
160 /* save lower interface */
161 scc->scc_hpckbd = kbdif;
162
163 scc->scc_enabled = 1;
164
165 return 0;
166 }
167
168 #define KBR_EXTENDED0 0xE0 /* extended key sequence */
169 #define KBR_EXTENDED1 0xE1 /* extended key sequence */
170
171 int
172 m38813c_intr(arg)
173 void *arg;
174 {
175 struct m38813c_softc *sc = arg;
176
177 return m38813c_poll(sc->sc_chip);
178 }
179
180 int
181 m38813c_poll(arg)
182 void *arg;
183 {
184 struct m38813c_chip *scc = arg;
185 bus_space_tag_t t = scc->scc_cst;
186 bus_space_handle_t h = scc->scc_csh;
187 int datain, type, key;
188
189 if (!scc->scc_enabled) {
190 return 0;
191 }
192
193 datain= bus_space_read_1(t, h, 0);
194
195 hpckbd_input_hook(scc->scc_hpckbd);
196
197 if (datain == KBR_EXTENDED0) {
198 scc->t_extended = 1;
199 return 0;
200 } else if (datain == KBR_EXTENDED1) {
201 scc->t_extended1 = 2;
202 return 0;
203 }
204
205 /* map extended keys to (unused) codes 128-254 */
206 key = (datain & 0x7f) | (scc->t_extended ? 0x80 : 0);
207 scc->t_extended = 0;
208
209 /*
210 * process BREAK key (EXT1 1D 45 EXT1 9D C5):
211 * map to (unused) code 7F
212 */
213 if (scc->t_extended1 == 2 && (datain == 0x1d || datain == 0x9d)) {
214 scc->t_extended1 = 1;
215 return 0;
216 } else if (scc->t_extended1 == 1 &&
217 (datain == 0x45 || datain == 0xc5)) {
218 scc->t_extended1 = 0;
219 key = 0x7f;
220 } else if (scc->t_extended1 > 0) {
221 scc->t_extended1 = 0;
222 }
223
224 if (datain & 0x80) {
225 scc->t_lastchar = 0;
226 type = 0;
227 } else {
228 /* Always ignore typematic keys */
229 if (key == scc->t_lastchar)
230 return 0;
231 scc->t_lastchar = key;
232 type = 1;
233 }
234
235 hpckbd_input(scc->scc_hpckbd, type, key);
236
237 return 0;
238 }
239