1 /* $NetBSD: m38813c.c,v 1.11 2006/03/04 17:33:29 peter Exp $ */
4 * Copyright (c) 1999, 2001 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
33 * Device driver for MITUBISHI M38813 controller
36 #include <sys/cdefs.h>
37 __KERNEL_RCSID(0, "$NetBSD: m38813c.c,v 1.11 2006/03/04 17:33:29 peter Exp $");
39 #include "opt_use_poll.h"
41 #include <sys/param.h>
42 #include <sys/systm.h>
43 #include <sys/device.h>
45 #include <machine/bus.h>
46 #include <machine/intr.h>
48 #include <dev/hpc/hpckbdvar.h>
50 #include <hpcmips/tx/tx39var.h>
51 #include <hpcmips/tx/txcsbusvar.h>
52 #include <hpcmips/dev/m38813cvar.h>
55 bus_space_tag_t scc_cst
;
56 bus_space_handle_t scc_csh
;
62 struct hpckbd_ic_if scc_if
;
63 struct hpckbd_if
*scc_hpckbd
;
66 struct m38813c_softc
{
68 struct m38813c_chip
*sc_chip
;
69 tx_chipset_tag_t sc_tc
;
73 int m38813c_match(struct device
*, struct cfdata
*, void *);
74 void m38813c_attach(struct device
*, struct device
*, void *);
75 int m38813c_intr(void *);
76 int m38813c_poll(void *);
77 void m38813c_ifsetup(struct m38813c_chip
*);
78 int m38813c_input_establish(void *, struct hpckbd_if
*);
80 struct m38813c_chip m38813c_chip
;
82 CFATTACH_DECL(m38813c
, sizeof(struct m38813c_softc
),
83 m38813c_match
, m38813c_attach
, NULL
, NULL
);
86 m38813c_match(struct device
*parent
, struct cfdata
*cf
, void *aux
)
93 m38813c_attach(struct device
*parent
, struct device
*self
, void *aux
)
95 struct cs_attach_args
*ca
= aux
;
96 struct m38813c_softc
*sc
= (void*)self
;
97 struct hpckbd_attach_args haa
;
99 sc
->sc_tc
= ca
->ca_tc
;
100 sc
->sc_chip
= &m38813c_chip
;
101 sc
->sc_chip
->scc_cst
= ca
->ca_csio
.cstag
;
103 if (bus_space_map(sc
->sc_chip
->scc_cst
, ca
->ca_csio
.csbase
,
104 ca
->ca_csio
.cssize
, 0, &sc
->sc_chip
->scc_csh
)) {
105 printf(": can't map i/o space\n");
109 #error options USE_POLL required.
111 if (!(sc
->sc_ih
= tx39_poll_establish(sc
->sc_tc
, 1,
112 IPL_TTY
, m38813c_intr
,
114 printf(": can't establish interrupt\n");
119 /* setup upper interface */
120 m38813c_ifsetup(sc
->sc_chip
);
122 haa
.haa_ic
= &sc
->sc_chip
->scc_if
;
124 config_found(self
, &haa
, hpckbd_print
);
128 m38813c_ifsetup(struct m38813c_chip
*scc
)
131 scc
->scc_if
.hii_ctx
= scc
;
133 scc
->scc_if
.hii_establish
= m38813c_input_establish
;
134 scc
->scc_if
.hii_poll
= m38813c_intr
;
138 m38813c_cnattach(paddr_t addr
)
140 struct m38813c_chip
*scc
= &m38813c_chip
;
142 scc
->scc_csh
= MIPS_PHYS_TO_KSEG1(addr
);
144 m38813c_ifsetup(scc
);
146 hpckbd_cnattach(&scc
->scc_if
);
152 m38813c_input_establish(void *ic
, struct hpckbd_if
*kbdif
)
154 struct m38813c_chip
*scc
= ic
;
156 /* save lower interface */
157 scc
->scc_hpckbd
= kbdif
;
159 scc
->scc_enabled
= 1;
164 #define KBR_EXTENDED0 0xE0 /* extended key sequence */
165 #define KBR_EXTENDED1 0xE1 /* extended key sequence */
168 m38813c_intr(void *arg
)
170 struct m38813c_softc
*sc
= arg
;
172 return (m38813c_poll(sc
->sc_chip
));
176 m38813c_poll(void *arg
)
178 struct m38813c_chip
*scc
= arg
;
179 bus_space_tag_t t
= scc
->scc_cst
;
180 bus_space_handle_t h
= scc
->scc_csh
;
181 int datain
, type
, key
;
183 if (!scc
->scc_enabled
) {
187 datain
= bus_space_read_1(t
, h
, 0);
189 hpckbd_input_hook(scc
->scc_hpckbd
);
191 if (datain
== KBR_EXTENDED0
) {
194 } else if (datain
== KBR_EXTENDED1
) {
195 scc
->t_extended1
= 2;
199 /* map extended keys to (unused) codes 128-254 */
200 key
= (datain
& 0x7f) | (scc
->t_extended
? 0x80 : 0);
204 * process BREAK key (EXT1 1D 45 EXT1 9D C5):
205 * map to (unused) code 7F
207 if (scc
->t_extended1
== 2 && (datain
== 0x1d || datain
== 0x9d)) {
208 scc
->t_extended1
= 1;
210 } else if (scc
->t_extended1
== 1 &&
211 (datain
== 0x45 || datain
== 0xc5)) {
212 scc
->t_extended1
= 0;
214 } else if (scc
->t_extended1
> 0) {
215 scc
->t_extended1
= 0;
222 /* Always ignore typematic keys */
223 if (key
== scc
->t_lastchar
)
225 scc
->t_lastchar
= key
;
229 hpckbd_input(scc
->scc_hpckbd
, type
, key
);