kb_ap.c revision 1.4 1 /* $NetBSD: kb_ap.c,v 1.4 2002/10/02 04:27:51 thorpej Exp $ */
2
3 /*-
4 * Copyright (c) 2000 Tsubai Masanari. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
26 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29 #include <sys/param.h>
30 #include <sys/systm.h>
31 #include <sys/device.h>
32
33 #include <dev/wscons/wsconsio.h>
34 #include <dev/wscons/wskbdvar.h>
35 #include <dev/wscons/wsksymdef.h>
36
37 #include <machine/adrsmap.h>
38 #include <newsmips/apbus/apbusvar.h>
39
40 struct kbreg {
41 u_int kb_rx_data;
42 u_int kb_rx_stat;
43 u_int kb_rx_intr_en;
44 u_int kb_rx_reset;
45 u_int kb_rx_speed;
46
47 u_int ms_rx_data;
48 u_int ms_rx_stat;
49 u_int ms_rx_intr_en;
50 u_int ms_rx_reset;
51 u_int ms_rx_speed;
52
53 u_int kb_buzzf;
54 u_int kb_buzz;
55
56 u_int kb_tx_data;
57 u_int kb_tx_stat;
58 u_int kb_tx_intr_en;
59 u_int kb_tx_reset;
60 u_int kb_tx_speed;
61 };
62
63 struct kb_ap_softc {
64 struct device sc_dev;
65 volatile struct kbreg *sc_reg;
66 struct device *sc_wskbddev;
67 };
68
69 int kb_ap_match(struct device *, struct cfdata *, void *);
70 void kb_ap_attach(struct device *, struct device *, void *);
71 int kb_ap_intr(void *);
72
73 void kb_ap_cnattach(void);
74 void kb_ap_cngetc(void *, u_int *, int *);
75 void kb_ap_cnpollc(void *, int);
76
77 int kb_ap_enable(void *, int);
78 void kb_ap_setleds(void *, int);
79 int kb_ap_ioctl(void *, u_long, caddr_t, int, struct proc *);
80
81 extern struct wscons_keydesc newskb_keydesctab[];
82
83 CFATTACH_DECL(kb_ap, sizeof(struct kb_ap_softc),
84 kb_ap_match, kb_ap_attach, NULL, NULL);
85
86 struct wskbd_accessops kb_ap_accessops = {
87 kb_ap_enable,
88 kb_ap_setleds,
89 kb_ap_ioctl,
90 };
91
92 struct wskbd_consops kb_ap_consops = {
93 kb_ap_cngetc,
94 kb_ap_cnpollc,
95 };
96
97 struct wskbd_mapdata kb_ap_keymapdata = {
98 newskb_keydesctab,
99 KB_JP,
100 };
101
102 int
103 kb_ap_match(parent, cf, aux)
104 struct device *parent;
105 struct cfdata *cf;
106 void *aux;
107 {
108 struct apbus_attach_args *apa = aux;
109
110 if (strcmp(apa->apa_name, "kb") == 0)
111 return 1;
112
113 return 0;
114 }
115
116 void
117 kb_ap_attach(parent, self, aux)
118 struct device *parent, *self;
119 void *aux;
120 {
121 struct kb_ap_softc *sc = (void *)self;
122 struct apbus_attach_args *apa = aux;
123 volatile struct kbreg *reg = (void *)apa->apa_hwbase;
124 volatile int *dipsw = (void *)NEWS5000_DIP_SWITCH;
125 struct wskbddev_attach_args waa;
126 int cons = 0;
127
128 printf(" slot%d addr 0x%lx", apa->apa_slotno, apa->apa_hwbase);
129
130 sc->sc_reg = reg;
131
132 if (*dipsw & 7) {
133 printf(" (console)");
134 cons = 1;
135 }
136 printf("\n");
137
138 reg->kb_rx_reset = 0x03;
139 reg->kb_tx_reset = 0x03;
140
141 reg->kb_rx_speed = 0x04;
142 reg->kb_tx_speed = 0x04;
143
144 reg->kb_rx_intr_en = 1;
145 reg->kb_tx_intr_en = 0;
146
147 apbus_intr_establish(1, NEWS5000_INT1_KBD, 0, kb_ap_intr, sc,
148 "", apa->apa_ctlnum);
149
150 waa.console = cons;
151 waa.keymap = &kb_ap_keymapdata;
152 waa.accessops = &kb_ap_accessops;
153 waa.accesscookie = sc;
154
155 sc->sc_wskbddev = config_found(self, &waa, wskbddevprint);
156 }
157
158 int
159 kb_ap_intr(v)
160 void *v;
161 {
162 struct kb_ap_softc *sc = v;
163 volatile struct kbreg *reg = sc->sc_reg;
164 int key, val, type, release;
165 int rv = 0;
166
167 while (reg->kb_rx_stat & RX_KBRDY) {
168 key = reg->kb_rx_data;
169 val = key & 0x7f;
170 release = key & 0x80;
171 type = release ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
172
173 if (sc->sc_wskbddev)
174 wskbd_input(sc->sc_wskbddev, type, val);
175
176 rv = 1;
177 }
178
179 return rv;
180 }
181
182 void
183 kb_ap_cnattach()
184 {
185 wskbd_cnattach(&kb_ap_consops, (void *)0xbf900000, &kb_ap_keymapdata);
186 }
187
188 void
189 kb_ap_cngetc(v, type, data)
190 void *v;
191 u_int *type;
192 int *data;
193 {
194 volatile struct kbreg *reg = v;
195 int key, release, ointr;
196
197 /* Disable keyboard interrupt. */
198 ointr = reg->kb_rx_intr_en;
199 reg->kb_rx_intr_en = 0;
200
201 /* Wait for key data. */
202 while ((reg->kb_rx_stat & RX_KBRDY) == 0);
203
204 key = reg->kb_rx_data;
205 release = key & 0x80;
206 *data = key & 0x7f;
207 *type = release ? WSCONS_EVENT_KEY_UP : WSCONS_EVENT_KEY_DOWN;
208
209 reg->kb_rx_intr_en = ointr;
210 }
211
212 void
213 kb_ap_cnpollc(v, on)
214 void *v;
215 int on;
216 {
217 }
218
219 int
220 kb_ap_enable(v, on)
221 void *v;
222 int on;
223 {
224 return 0;
225 }
226
227 void
228 kb_ap_setleds(v, on)
229 void *v;
230 int on;
231 {
232 }
233
234 int
235 kb_ap_ioctl(v, cmd, data, flag, p)
236 void *v;
237 u_long cmd;
238 caddr_t data;
239 int flag;
240 struct proc *p;
241 {
242 switch (cmd) {
243 case WSKBDIO_GTYPE:
244 *(int *)data = 0; /* XXX */
245 return 0;
246 case WSKBDIO_SETLEDS:
247 return 0;
248 case WSKBDIO_GETLEDS:
249 *(int *)data = 0;
250 return 0;
251 }
252
253 return EPASSTHROUGH;
254 }
255