shpcic.c revision 1.1 1 1.1 itojun /* $NetBSD: shpcic.c,v 1.1 1999/09/13 10:31:13 itojun Exp $ */
2 1.1 itojun
3 1.1 itojun #define SHPCICDEBUG
4 1.1 itojun
5 1.1 itojun /*
6 1.1 itojun * Copyright (c) 1997 Marc Horowitz. All rights reserved.
7 1.1 itojun *
8 1.1 itojun * Redistribution and use in source and binary forms, with or without
9 1.1 itojun * modification, are permitted provided that the following conditions
10 1.1 itojun * are met:
11 1.1 itojun * 1. Redistributions of source code must retain the above copyright
12 1.1 itojun * notice, this list of conditions and the following disclaimer.
13 1.1 itojun * 2. Redistributions in binary form must reproduce the above copyright
14 1.1 itojun * notice, this list of conditions and the following disclaimer in the
15 1.1 itojun * documentation and/or other materials provided with the distribution.
16 1.1 itojun * 3. All advertising materials mentioning features or use of this software
17 1.1 itojun * must display the following acknowledgement:
18 1.1 itojun * This product includes software developed by Marc Horowitz.
19 1.1 itojun * 4. The name of the author may not be used to endorse or promote products
20 1.1 itojun * derived from this software without specific prior written permission.
21 1.1 itojun *
22 1.1 itojun * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
23 1.1 itojun * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
24 1.1 itojun * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
25 1.1 itojun * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
26 1.1 itojun * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
27 1.1 itojun * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
28 1.1 itojun * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
29 1.1 itojun * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
30 1.1 itojun * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
31 1.1 itojun * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 1.1 itojun */
33 1.1 itojun
34 1.1 itojun #include <sys/types.h>
35 1.1 itojun #include <sys/param.h>
36 1.1 itojun #include <sys/systm.h>
37 1.1 itojun #include <sys/device.h>
38 1.1 itojun #include <sys/extent.h>
39 1.1 itojun #include <sys/kernel.h>
40 1.1 itojun #include <sys/malloc.h>
41 1.1 itojun #include <sys/kthread.h>
42 1.1 itojun
43 1.1 itojun #include <vm/vm.h>
44 1.1 itojun
45 1.1 itojun #include <machine/bus.h>
46 1.1 itojun #include <machine/intr.h>
47 1.1 itojun
48 1.1 itojun #include <dev/pcmcia/pcmciareg.h>
49 1.1 itojun #include <dev/pcmcia/pcmciavar.h>
50 1.1 itojun
51 1.1 itojun #include <sh3/sh3/shpcicreg.h>
52 1.1 itojun #include <sh3/sh3/shpcicvar.h>
53 1.1 itojun
54 1.1 itojun #include "locators.h"
55 1.1 itojun
56 1.1 itojun #ifdef SHPCICDEBUG
57 1.1 itojun int shpcic_debug = 0;
58 1.1 itojun #define DPRINTF(arg) if (shpcic_debug) printf arg;
59 1.1 itojun #else
60 1.1 itojun #define DPRINTF(arg)
61 1.1 itojun #endif
62 1.1 itojun
63 1.1 itojun #define PCIC_VENDOR_UNKNOWN 0
64 1.1 itojun #define PCIC_VENDOR_HITACHI 1
65 1.1 itojun
66 1.1 itojun /*
67 1.1 itojun * Individual drivers will allocate their own memory and io regions. Memory
68 1.1 itojun * regions must be a multiple of 4k, aligned on a 4k boundary.
69 1.1 itojun */
70 1.1 itojun
71 1.1 itojun #define SHPCIC_MEM_ALIGN SHPCIC_MEM_PAGESIZE
72 1.1 itojun
73 1.1 itojun void shpcic_attach_socket __P((struct shpcic_handle *));
74 1.1 itojun void shpcic_init_socket __P((struct shpcic_handle *));
75 1.1 itojun
76 1.1 itojun int shpcic_submatch __P((struct device *, struct cfdata *, void *));
77 1.1 itojun int shpcic_print __P((void *arg, const char *pnp));
78 1.1 itojun int shpcic_intr_socket __P((struct shpcic_handle *));
79 1.1 itojun
80 1.1 itojun void shpcic_attach_card __P((struct shpcic_handle *));
81 1.1 itojun void shpcic_detach_card __P((struct shpcic_handle *, int));
82 1.1 itojun void shpcic_deactivate_card __P((struct shpcic_handle *));
83 1.1 itojun
84 1.1 itojun void shpcic_chip_do_mem_map __P((struct shpcic_handle *, int));
85 1.1 itojun void shpcic_chip_do_io_map __P((struct shpcic_handle *, int));
86 1.1 itojun
87 1.1 itojun void shpcic_create_event_thread __P((void *));
88 1.1 itojun void shpcic_event_thread __P((void *));
89 1.1 itojun
90 1.1 itojun void shpcic_queue_event __P((struct shpcic_handle *, int));
91 1.1 itojun
92 1.1 itojun /* static void shpcic_wait_ready __P((struct shpcic_handle *)); */
93 1.1 itojun
94 1.1 itojun int
95 1.1 itojun shpcic_ident_ok(ident)
96 1.1 itojun int ident;
97 1.1 itojun {
98 1.1 itojun /* this is very empirical and heuristic */
99 1.1 itojun
100 1.1 itojun if ((ident == 0) || (ident == 0xff) || (ident & SHPCIC_IDENT_ZERO))
101 1.1 itojun return (0);
102 1.1 itojun
103 1.1 itojun if ((ident & SHPCIC_IDENT_IFTYPE_MASK) != SHPCIC_IDENT_IFTYPE_MEM_AND_IO) {
104 1.1 itojun #ifdef DIAGNOSTIC
105 1.1 itojun printf("shpcic: does not support memory and I/O cards, "
106 1.1 itojun "ignored (ident=%0x)\n", ident);
107 1.1 itojun #endif
108 1.1 itojun return (0);
109 1.1 itojun }
110 1.1 itojun return (1);
111 1.1 itojun }
112 1.1 itojun
113 1.1 itojun int
114 1.1 itojun shpcic_vendor(h)
115 1.1 itojun struct shpcic_handle *h;
116 1.1 itojun {
117 1.1 itojun return (PCIC_VENDOR_HITACHI);
118 1.1 itojun }
119 1.1 itojun
120 1.1 itojun char *
121 1.1 itojun shpcic_vendor_to_string(vendor)
122 1.1 itojun int vendor;
123 1.1 itojun {
124 1.1 itojun switch (vendor) {
125 1.1 itojun case PCIC_VENDOR_HITACHI:
126 1.1 itojun return ("Hitachi SH");
127 1.1 itojun }
128 1.1 itojun
129 1.1 itojun return ("Unknown controller");
130 1.1 itojun }
131 1.1 itojun
132 1.1 itojun void
133 1.1 itojun shpcic_attach(sc)
134 1.1 itojun struct shpcic_softc *sc;
135 1.1 itojun {
136 1.1 itojun int vendor, count, i;
137 1.1 itojun
138 1.1 itojun /* now check for each controller/socket */
139 1.1 itojun
140 1.1 itojun /*
141 1.1 itojun * this could be done with a loop, but it would violate the
142 1.1 itojun * abstraction
143 1.1 itojun */
144 1.1 itojun
145 1.1 itojun count = 0;
146 1.1 itojun
147 1.1 itojun #if 0
148 1.1 itojun DPRINTF(("shpcic ident regs:"));
149 1.1 itojun #endif
150 1.1 itojun
151 1.1 itojun sc->handle[0].sc = sc;
152 1.1 itojun sc->handle[0].sock = C0SA;
153 1.1 itojun sc->handle[0].flags = SHPCIC_FLAG_SOCKETP;
154 1.1 itojun sc->handle[0].laststate = SHPCIC_LASTSTATE_EMPTY;
155 1.1 itojun count++;
156 1.1 itojun
157 1.1 itojun sc->handle[1].sc = sc;
158 1.1 itojun sc->handle[1].sock = C0SB;
159 1.1 itojun sc->handle[1].flags = 0;
160 1.1 itojun sc->handle[1].laststate = SHPCIC_LASTSTATE_EMPTY;
161 1.1 itojun count++;
162 1.1 itojun
163 1.1 itojun sc->handle[2].sc = sc;
164 1.1 itojun sc->handle[2].sock = C1SA;
165 1.1 itojun sc->handle[2].flags = 0;
166 1.1 itojun sc->handle[2].laststate = SHPCIC_LASTSTATE_EMPTY;
167 1.1 itojun
168 1.1 itojun sc->handle[3].sc = sc;
169 1.1 itojun sc->handle[3].sock = C1SB;
170 1.1 itojun sc->handle[3].flags = 0;
171 1.1 itojun sc->handle[3].laststate = SHPCIC_LASTSTATE_EMPTY;
172 1.1 itojun
173 1.1 itojun if (count == 0)
174 1.1 itojun panic("shpcic_attach: attach found no sockets");
175 1.1 itojun
176 1.1 itojun /* establish the interrupt */
177 1.1 itojun
178 1.1 itojun /* XXX block interrupts? */
179 1.1 itojun
180 1.1 itojun for (i = 0; i < SHPCIC_NSLOTS; i++) {
181 1.1 itojun /*
182 1.1 itojun * this should work, but w/o it, setting tty flags hangs at
183 1.1 itojun * boot time.
184 1.1 itojun */
185 1.1 itojun if (sc->handle[i].flags & SHPCIC_FLAG_SOCKETP)
186 1.1 itojun {
187 1.1 itojun SIMPLEQ_INIT(&sc->handle[i].events);
188 1.1 itojun #if 0
189 1.1 itojun shpcic_write(&sc->handle[i], SHPCIC_CSC_INTR, 0);
190 1.1 itojun shpcic_read(&sc->handle[i], SHPCIC_CSC);
191 1.1 itojun #endif
192 1.1 itojun }
193 1.1 itojun }
194 1.1 itojun
195 1.1 itojun if ((sc->handle[0].flags & SHPCIC_FLAG_SOCKETP) ||
196 1.1 itojun (sc->handle[1].flags & SHPCIC_FLAG_SOCKETP)) {
197 1.1 itojun vendor = shpcic_vendor(&sc->handle[0]);
198 1.1 itojun
199 1.1 itojun printf("%s: controller 0 (%s) has ", sc->dev.dv_xname,
200 1.1 itojun shpcic_vendor_to_string(vendor));
201 1.1 itojun
202 1.1 itojun if ((sc->handle[0].flags & SHPCIC_FLAG_SOCKETP) &&
203 1.1 itojun (sc->handle[1].flags & SHPCIC_FLAG_SOCKETP))
204 1.1 itojun printf("sockets A and B\n");
205 1.1 itojun else if (sc->handle[0].flags & SHPCIC_FLAG_SOCKETP)
206 1.1 itojun printf("socket A only\n");
207 1.1 itojun else
208 1.1 itojun printf("socket B only\n");
209 1.1 itojun
210 1.1 itojun if (sc->handle[0].flags & SHPCIC_FLAG_SOCKETP)
211 1.1 itojun sc->handle[0].vendor = vendor;
212 1.1 itojun if (sc->handle[1].flags & SHPCIC_FLAG_SOCKETP)
213 1.1 itojun sc->handle[1].vendor = vendor;
214 1.1 itojun }
215 1.1 itojun }
216 1.1 itojun
217 1.1 itojun void
218 1.1 itojun shpcic_attach_sockets(sc)
219 1.1 itojun struct shpcic_softc *sc;
220 1.1 itojun {
221 1.1 itojun int i;
222 1.1 itojun
223 1.1 itojun for (i = 0; i < SHPCIC_NSLOTS; i++)
224 1.1 itojun if (sc->handle[i].flags & SHPCIC_FLAG_SOCKETP)
225 1.1 itojun shpcic_attach_socket(&sc->handle[i]);
226 1.1 itojun }
227 1.1 itojun
228 1.1 itojun void
229 1.1 itojun shpcic_attach_socket(h)
230 1.1 itojun struct shpcic_handle *h;
231 1.1 itojun {
232 1.1 itojun struct pcmciabus_attach_args paa;
233 1.1 itojun
234 1.1 itojun /* initialize the rest of the handle */
235 1.1 itojun
236 1.1 itojun h->shutdown = 0;
237 1.1 itojun h->memalloc = 0;
238 1.1 itojun h->ioalloc = 0;
239 1.1 itojun h->ih_irq = 0;
240 1.1 itojun
241 1.1 itojun /* now, config one pcmcia device per socket */
242 1.1 itojun
243 1.1 itojun paa.pct = (pcmcia_chipset_tag_t) h->sc->pct;
244 1.1 itojun paa.pch = (pcmcia_chipset_handle_t) h;
245 1.1 itojun paa.iobase = h->sc->iobase;
246 1.1 itojun paa.iosize = h->sc->iosize;
247 1.1 itojun
248 1.1 itojun h->pcmcia = config_found_sm(&h->sc->dev, &paa, shpcic_print,
249 1.1 itojun shpcic_submatch);
250 1.1 itojun
251 1.1 itojun /* if there's actually a pcmcia device attached, initialize the slot */
252 1.1 itojun
253 1.1 itojun if (h->pcmcia)
254 1.1 itojun shpcic_init_socket(h);
255 1.1 itojun }
256 1.1 itojun
257 1.1 itojun void
258 1.1 itojun shpcic_create_event_thread(arg)
259 1.1 itojun void *arg;
260 1.1 itojun {
261 1.1 itojun struct shpcic_handle *h = arg;
262 1.1 itojun const char *cs;
263 1.1 itojun
264 1.1 itojun switch (h->sock) {
265 1.1 itojun case C0SA:
266 1.1 itojun cs = "0,0";
267 1.1 itojun break;
268 1.1 itojun case C0SB:
269 1.1 itojun cs = "0,1";
270 1.1 itojun break;
271 1.1 itojun case C1SA:
272 1.1 itojun cs = "1,0";
273 1.1 itojun break;
274 1.1 itojun case C1SB:
275 1.1 itojun cs = "1,1";
276 1.1 itojun break;
277 1.1 itojun default:
278 1.1 itojun panic("shpcic_create_event_thread: unknown pcic socket");
279 1.1 itojun }
280 1.1 itojun
281 1.1 itojun if (kthread_create(shpcic_event_thread, h, &h->event_thread,
282 1.1 itojun "%s,%s", h->sc->dev.dv_xname, cs)) {
283 1.1 itojun printf("%s: unable to create event thread for sock 0x%02x\n",
284 1.1 itojun h->sc->dev.dv_xname, h->sock);
285 1.1 itojun panic("shpcic_create_event_thread");
286 1.1 itojun }
287 1.1 itojun }
288 1.1 itojun
289 1.1 itojun void
290 1.1 itojun shpcic_event_thread(arg)
291 1.1 itojun void *arg;
292 1.1 itojun {
293 1.1 itojun struct shpcic_handle *h = arg;
294 1.1 itojun struct shpcic_event *pe;
295 1.1 itojun int s;
296 1.1 itojun
297 1.1 itojun while (h->shutdown == 0) {
298 1.1 itojun s = splhigh();
299 1.1 itojun if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) {
300 1.1 itojun splx(s);
301 1.1 itojun (void) tsleep(&h->events, PWAIT, "shpcicev", 0);
302 1.1 itojun continue;
303 1.1 itojun } else {
304 1.1 itojun splx(s);
305 1.1 itojun /* sleep .25s to be enqueued chatterling interrupts */
306 1.1 itojun (void) tsleep((caddr_t)shpcic_event_thread, PWAIT, "shpcicss", hz/4);
307 1.1 itojun }
308 1.1 itojun s = splhigh();
309 1.1 itojun SIMPLEQ_REMOVE_HEAD(&h->events, pe, pe_q);
310 1.1 itojun splx(s);
311 1.1 itojun
312 1.1 itojun switch (pe->pe_type) {
313 1.1 itojun case SHPCIC_EVENT_INSERTION:
314 1.1 itojun s = splhigh();
315 1.1 itojun while (1) {
316 1.1 itojun struct shpcic_event *pe1, *pe2;
317 1.1 itojun
318 1.1 itojun if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
319 1.1 itojun break;
320 1.1 itojun if (pe1->pe_type != SHPCIC_EVENT_REMOVAL)
321 1.1 itojun break;
322 1.1 itojun if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
323 1.1 itojun break;
324 1.1 itojun if (pe2->pe_type == SHPCIC_EVENT_INSERTION) {
325 1.1 itojun SIMPLEQ_REMOVE_HEAD(&h->events, pe1, pe_q);
326 1.1 itojun free(pe1, M_TEMP);
327 1.1 itojun SIMPLEQ_REMOVE_HEAD(&h->events, pe2, pe_q);
328 1.1 itojun free(pe2, M_TEMP);
329 1.1 itojun }
330 1.1 itojun }
331 1.1 itojun splx(s);
332 1.1 itojun
333 1.1 itojun DPRINTF(("%s: insertion event\n", h->sc->dev.dv_xname));
334 1.1 itojun shpcic_attach_card(h);
335 1.1 itojun break;
336 1.1 itojun
337 1.1 itojun case SHPCIC_EVENT_REMOVAL:
338 1.1 itojun s = splhigh();
339 1.1 itojun while (1) {
340 1.1 itojun struct shpcic_event *pe1, *pe2;
341 1.1 itojun
342 1.1 itojun if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
343 1.1 itojun break;
344 1.1 itojun if (pe1->pe_type != SHPCIC_EVENT_INSERTION)
345 1.1 itojun break;
346 1.1 itojun if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
347 1.1 itojun break;
348 1.1 itojun if (pe2->pe_type == SHPCIC_EVENT_REMOVAL) {
349 1.1 itojun SIMPLEQ_REMOVE_HEAD(&h->events, pe1, pe_q);
350 1.1 itojun free(pe1, M_TEMP);
351 1.1 itojun SIMPLEQ_REMOVE_HEAD(&h->events, pe2, pe_q);
352 1.1 itojun free(pe2, M_TEMP);
353 1.1 itojun }
354 1.1 itojun }
355 1.1 itojun splx(s);
356 1.1 itojun
357 1.1 itojun DPRINTF(("%s: removal event\n", h->sc->dev.dv_xname));
358 1.1 itojun shpcic_detach_card(h, DETACH_FORCE);
359 1.1 itojun break;
360 1.1 itojun
361 1.1 itojun default:
362 1.1 itojun panic("shpcic_event_thread: unknown event %d",
363 1.1 itojun pe->pe_type);
364 1.1 itojun }
365 1.1 itojun free(pe, M_TEMP);
366 1.1 itojun }
367 1.1 itojun
368 1.1 itojun h->event_thread = NULL;
369 1.1 itojun
370 1.1 itojun /* In case parent is waiting for us to exit. */
371 1.1 itojun wakeup(h->sc);
372 1.1 itojun
373 1.1 itojun kthread_exit(0);
374 1.1 itojun }
375 1.1 itojun
376 1.1 itojun void
377 1.1 itojun shpcic_init_socket(h)
378 1.1 itojun struct shpcic_handle *h;
379 1.1 itojun {
380 1.1 itojun int reg;
381 1.1 itojun
382 1.1 itojun /*
383 1.1 itojun * queue creation of a kernel thread to handle insert/removal events.
384 1.1 itojun */
385 1.1 itojun #ifdef DIAGNOSTIC
386 1.1 itojun if (h->event_thread != NULL)
387 1.1 itojun panic("shpcic_attach_socket: event thread");
388 1.1 itojun #endif
389 1.1 itojun kthread_create_deferred(shpcic_create_event_thread, h);
390 1.1 itojun
391 1.1 itojun /* if there's a card there, then attach it. */
392 1.1 itojun
393 1.1 itojun reg = shpcic_read(h, SHPCIC_IF_STATUS);
394 1.1 itojun reg &= ~SHPCIC_IF_STATUS_BUSWIDTH; /* Set bus width to 16bit */
395 1.1 itojun
396 1.1 itojun if ((reg & SHPCIC_IF_STATUS_CARDDETECT_MASK) ==
397 1.1 itojun SHPCIC_IF_STATUS_CARDDETECT_PRESENT) {
398 1.1 itojun int i;
399 1.1 itojun
400 1.1 itojun /* reset the card */
401 1.1 itojun shpcic_write(h, SHPCIC_IF_STATUS, reg|SHPCIC_IF_STATUS_RESET);
402 1.1 itojun delay(1000); /* wait 1000 uSec */
403 1.1 itojun shpcic_write(h, SHPCIC_IF_STATUS,
404 1.1 itojun reg & ~SHPCIC_IF_STATUS_RESET);
405 1.1 itojun for (i = 0; i < 10000; i++)
406 1.1 itojun delay(1000); /* wait 1 mSec */
407 1.1 itojun
408 1.1 itojun shpcic_attach_card(h);
409 1.1 itojun h->laststate = SHPCIC_LASTSTATE_PRESENT;
410 1.1 itojun } else {
411 1.1 itojun h->laststate = SHPCIC_LASTSTATE_EMPTY;
412 1.1 itojun }
413 1.1 itojun }
414 1.1 itojun
415 1.1 itojun int
416 1.1 itojun shpcic_submatch(parent, cf, aux)
417 1.1 itojun struct device *parent;
418 1.1 itojun struct cfdata *cf;
419 1.1 itojun void *aux;
420 1.1 itojun {
421 1.1 itojun
422 1.1 itojun struct pcmciabus_attach_args *paa = aux;
423 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) paa->pch;
424 1.1 itojun
425 1.1 itojun switch (h->sock) {
426 1.1 itojun case C0SA:
427 1.1 itojun #ifdef TODO
428 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
429 1.1 itojun PCMCIABUSCF_CONTROLLER_DEFAULT &&
430 1.1 itojun cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 0)
431 1.1 itojun return 0;
432 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
433 1.1 itojun PCMCIABUSCF_SOCKET_DEFAULT &&
434 1.1 itojun cf->cf_loc[PCMCIABUSCF_SOCKET] != 0)
435 1.1 itojun return 0;
436 1.1 itojun #endif
437 1.1 itojun
438 1.1 itojun break;
439 1.1 itojun case C0SB:
440 1.1 itojun #ifdef TODO
441 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
442 1.1 itojun PCMCIABUSCF_CONTROLLER_DEFAULT &&
443 1.1 itojun cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 0)
444 1.1 itojun return 0;
445 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
446 1.1 itojun PCMCIABUSCF_SOCKET_DEFAULT &&
447 1.1 itojun cf->cf_loc[PCMCIABUSCF_SOCKET] != 1)
448 1.1 itojun return 0;
449 1.1 itojun #endif
450 1.1 itojun
451 1.1 itojun break;
452 1.1 itojun case C1SA:
453 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
454 1.1 itojun PCMCIABUSCF_CONTROLLER_DEFAULT &&
455 1.1 itojun cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 1)
456 1.1 itojun return 0;
457 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
458 1.1 itojun PCMCIABUSCF_SOCKET_DEFAULT &&
459 1.1 itojun cf->cf_loc[PCMCIABUSCF_SOCKET] != 0)
460 1.1 itojun return 0;
461 1.1 itojun
462 1.1 itojun break;
463 1.1 itojun case C1SB:
464 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
465 1.1 itojun PCMCIABUSCF_CONTROLLER_DEFAULT &&
466 1.1 itojun cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 1)
467 1.1 itojun return 0;
468 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
469 1.1 itojun PCMCIABUSCF_SOCKET_DEFAULT &&
470 1.1 itojun cf->cf_loc[PCMCIABUSCF_SOCKET] != 1)
471 1.1 itojun return 0;
472 1.1 itojun
473 1.1 itojun break;
474 1.1 itojun default:
475 1.1 itojun panic("unknown pcic socket");
476 1.1 itojun }
477 1.1 itojun
478 1.1 itojun return ((*cf->cf_attach->ca_match)(parent, cf, aux));
479 1.1 itojun }
480 1.1 itojun
481 1.1 itojun int
482 1.1 itojun shpcic_print(arg, pnp)
483 1.1 itojun void *arg;
484 1.1 itojun const char *pnp;
485 1.1 itojun {
486 1.1 itojun struct pcmciabus_attach_args *paa = arg;
487 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) paa->pch;
488 1.1 itojun
489 1.1 itojun /* Only "pcmcia"s can attach to "pcic"s... easy. */
490 1.1 itojun if (pnp)
491 1.1 itojun printf("pcmcia at %s", pnp);
492 1.1 itojun
493 1.1 itojun switch (h->sock) {
494 1.1 itojun case C0SA:
495 1.1 itojun printf(" controller 0 socket 0");
496 1.1 itojun break;
497 1.1 itojun case C0SB:
498 1.1 itojun printf(" controller 0 socket 1");
499 1.1 itojun break;
500 1.1 itojun case C1SA:
501 1.1 itojun printf(" controller 1 socket 0");
502 1.1 itojun break;
503 1.1 itojun case C1SB:
504 1.1 itojun printf(" controller 1 socket 1");
505 1.1 itojun break;
506 1.1 itojun default:
507 1.1 itojun panic("unknown pcic socket");
508 1.1 itojun }
509 1.1 itojun
510 1.1 itojun return (UNCONF);
511 1.1 itojun }
512 1.1 itojun
513 1.1 itojun int
514 1.1 itojun shpcic_intr(arg)
515 1.1 itojun void *arg;
516 1.1 itojun {
517 1.1 itojun struct shpcic_softc *sc = arg;
518 1.1 itojun int i, ret = 0;
519 1.1 itojun
520 1.1 itojun DPRINTF(("%s: intr\n", sc->dev.dv_xname));
521 1.1 itojun
522 1.1 itojun for (i = 0; i < SHPCIC_NSLOTS; i++)
523 1.1 itojun if (sc->handle[i].flags & SHPCIC_FLAG_SOCKETP)
524 1.1 itojun ret += shpcic_intr_socket(&sc->handle[i]);
525 1.1 itojun
526 1.1 itojun return (ret ? 1 : 0);
527 1.1 itojun }
528 1.1 itojun
529 1.1 itojun int
530 1.1 itojun shpcic_intr_socket(h)
531 1.1 itojun struct shpcic_handle *h;
532 1.1 itojun {
533 1.1 itojun int cscreg;
534 1.1 itojun
535 1.1 itojun cscreg = shpcic_read(h, SHPCIC_CSC);
536 1.1 itojun
537 1.1 itojun cscreg &= (SHPCIC_CSC_GPI |
538 1.1 itojun SHPCIC_CSC_CD |
539 1.1 itojun SHPCIC_CSC_READY |
540 1.1 itojun SHPCIC_CSC_BATTWARN |
541 1.1 itojun SHPCIC_CSC_BATTDEAD);
542 1.1 itojun
543 1.1 itojun if (cscreg & SHPCIC_CSC_GPI) {
544 1.1 itojun DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock));
545 1.1 itojun }
546 1.1 itojun if (cscreg & SHPCIC_CSC_CD) {
547 1.1 itojun int statreg;
548 1.1 itojun
549 1.1 itojun statreg = shpcic_read(h, SHPCIC_IF_STATUS);
550 1.1 itojun
551 1.1 itojun DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock,
552 1.1 itojun statreg));
553 1.1 itojun
554 1.1 itojun if ((statreg & SHPCIC_IF_STATUS_CARDDETECT_MASK) ==
555 1.1 itojun SHPCIC_IF_STATUS_CARDDETECT_PRESENT) {
556 1.1 itojun if (h->laststate != SHPCIC_LASTSTATE_PRESENT) {
557 1.1 itojun DPRINTF(("%s: enqueing INSERTION event\n",
558 1.1 itojun h->sc->dev.dv_xname));
559 1.1 itojun shpcic_queue_event(h, SHPCIC_EVENT_INSERTION);
560 1.1 itojun }
561 1.1 itojun h->laststate = SHPCIC_LASTSTATE_PRESENT;
562 1.1 itojun } else {
563 1.1 itojun if (h->laststate == SHPCIC_LASTSTATE_PRESENT) {
564 1.1 itojun /* Deactivate the card now. */
565 1.1 itojun DPRINTF(("%s: deactivating card\n",
566 1.1 itojun h->sc->dev.dv_xname));
567 1.1 itojun shpcic_deactivate_card(h);
568 1.1 itojun
569 1.1 itojun DPRINTF(("%s: enqueing REMOVAL event\n",
570 1.1 itojun h->sc->dev.dv_xname));
571 1.1 itojun shpcic_queue_event(h, SHPCIC_EVENT_REMOVAL);
572 1.1 itojun }
573 1.1 itojun h->laststate = ((statreg & SHPCIC_IF_STATUS_CARDDETECT_MASK) == 0)
574 1.1 itojun ? SHPCIC_LASTSTATE_EMPTY : SHPCIC_LASTSTATE_HALF;
575 1.1 itojun }
576 1.1 itojun }
577 1.1 itojun if (cscreg & SHPCIC_CSC_READY) {
578 1.1 itojun DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock));
579 1.1 itojun /* shouldn't happen */
580 1.1 itojun }
581 1.1 itojun if (cscreg & SHPCIC_CSC_BATTWARN) {
582 1.1 itojun DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock));
583 1.1 itojun }
584 1.1 itojun if (cscreg & SHPCIC_CSC_BATTDEAD) {
585 1.1 itojun DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock));
586 1.1 itojun }
587 1.1 itojun return (cscreg ? 1 : 0);
588 1.1 itojun }
589 1.1 itojun
590 1.1 itojun void
591 1.1 itojun shpcic_queue_event(h, event)
592 1.1 itojun struct shpcic_handle *h;
593 1.1 itojun int event;
594 1.1 itojun {
595 1.1 itojun struct shpcic_event *pe;
596 1.1 itojun int s;
597 1.1 itojun
598 1.1 itojun pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
599 1.1 itojun if (pe == NULL)
600 1.1 itojun panic("shpcic_queue_event: can't allocate event");
601 1.1 itojun
602 1.1 itojun pe->pe_type = event;
603 1.1 itojun s = splhigh();
604 1.1 itojun SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q);
605 1.1 itojun splx(s);
606 1.1 itojun wakeup(&h->events);
607 1.1 itojun }
608 1.1 itojun
609 1.1 itojun void
610 1.1 itojun shpcic_attach_card(h)
611 1.1 itojun struct shpcic_handle *h;
612 1.1 itojun {
613 1.1 itojun
614 1.1 itojun if (!(h->flags & SHPCIC_FLAG_CARDP)) {
615 1.1 itojun /* call the MI attach function */
616 1.1 itojun pcmcia_card_attach(h->pcmcia);
617 1.1 itojun
618 1.1 itojun h->flags |= SHPCIC_FLAG_CARDP;
619 1.1 itojun } else {
620 1.1 itojun DPRINTF(("shpcic_attach_card: already attached"));
621 1.1 itojun }
622 1.1 itojun }
623 1.1 itojun
624 1.1 itojun void
625 1.1 itojun shpcic_detach_card(h, flags)
626 1.1 itojun struct shpcic_handle *h;
627 1.1 itojun int flags; /* DETACH_* */
628 1.1 itojun {
629 1.1 itojun
630 1.1 itojun if (h->flags & SHPCIC_FLAG_CARDP) {
631 1.1 itojun h->flags &= ~SHPCIC_FLAG_CARDP;
632 1.1 itojun
633 1.1 itojun /* call the MI detach function */
634 1.1 itojun pcmcia_card_detach(h->pcmcia, flags);
635 1.1 itojun } else {
636 1.1 itojun DPRINTF(("shpcic_detach_card: already detached"));
637 1.1 itojun }
638 1.1 itojun }
639 1.1 itojun
640 1.1 itojun void
641 1.1 itojun shpcic_deactivate_card(h)
642 1.1 itojun struct shpcic_handle *h;
643 1.1 itojun {
644 1.1 itojun
645 1.1 itojun /* call the MI deactivate function */
646 1.1 itojun pcmcia_card_deactivate(h->pcmcia);
647 1.1 itojun
648 1.1 itojun #if 0
649 1.1 itojun /* power down the socket */
650 1.1 itojun shpcic_write(h, SHPCIC_PWRCTL, 0);
651 1.1 itojun
652 1.1 itojun /* reset the socket */
653 1.1 itojun shpcic_write(h, SHPCIC_INTR, 0);
654 1.1 itojun #endif
655 1.1 itojun }
656 1.1 itojun
657 1.1 itojun int
658 1.1 itojun shpcic_chip_mem_alloc(pch, size, pcmhp)
659 1.1 itojun pcmcia_chipset_handle_t pch;
660 1.1 itojun bus_size_t size;
661 1.1 itojun struct pcmcia_mem_handle *pcmhp;
662 1.1 itojun {
663 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
664 1.1 itojun bus_space_handle_t memh = 0;
665 1.1 itojun bus_addr_t addr;
666 1.1 itojun bus_size_t sizepg;
667 1.1 itojun int i, mask, mhandle;
668 1.1 itojun
669 1.1 itojun /* out of sc->memh, allocate as many pages as necessary */
670 1.1 itojun
671 1.1 itojun /* convert size to PCIC pages */
672 1.1 itojun sizepg = (size + (SHPCIC_MEM_ALIGN - 1)) / SHPCIC_MEM_ALIGN;
673 1.1 itojun if (sizepg > SHPCIC_MAX_MEM_PAGES)
674 1.1 itojun return (1);
675 1.1 itojun
676 1.1 itojun mask = (1 << sizepg) - 1;
677 1.1 itojun
678 1.1 itojun addr = 0; /* XXX gcc -Wuninitialized */
679 1.1 itojun mhandle = 0; /* XXX gcc -Wuninitialized */
680 1.1 itojun
681 1.1 itojun for (i = 0; i <= SHPCIC_MAX_MEM_PAGES - sizepg; i++) {
682 1.1 itojun if ((h->sc->subregionmask & (mask << i)) == (mask << i)) {
683 1.1 itojun #if 0
684 1.1 itojun if (bus_space_subregion(h->sc->memt, h->sc->memh,
685 1.1 itojun i * SHPCIC_MEM_PAGESIZE,
686 1.1 itojun sizepg * SHPCIC_MEM_PAGESIZE, &memh))
687 1.1 itojun return (1);
688 1.1 itojun #endif
689 1.1 itojun memh = h->sc->memh;
690 1.1 itojun mhandle = mask << i;
691 1.1 itojun addr = h->sc->membase + (i * SHPCIC_MEM_PAGESIZE);
692 1.1 itojun h->sc->subregionmask &= ~(mhandle);
693 1.1 itojun pcmhp->memt = h->sc->memt;
694 1.1 itojun pcmhp->memh = memh;
695 1.1 itojun pcmhp->addr = addr;
696 1.1 itojun pcmhp->size = size;
697 1.1 itojun pcmhp->mhandle = mhandle;
698 1.1 itojun pcmhp->realsize = sizepg * SHPCIC_MEM_PAGESIZE;
699 1.1 itojun return (0);
700 1.1 itojun }
701 1.1 itojun }
702 1.1 itojun
703 1.1 itojun return (1);
704 1.1 itojun }
705 1.1 itojun
706 1.1 itojun void
707 1.1 itojun shpcic_chip_mem_free(pch, pcmhp)
708 1.1 itojun pcmcia_chipset_handle_t pch;
709 1.1 itojun struct pcmcia_mem_handle *pcmhp;
710 1.1 itojun {
711 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
712 1.1 itojun
713 1.1 itojun h->sc->subregionmask |= pcmhp->mhandle;
714 1.1 itojun }
715 1.1 itojun
716 1.1 itojun int
717 1.1 itojun shpcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
718 1.1 itojun pcmcia_chipset_handle_t pch;
719 1.1 itojun int kind;
720 1.1 itojun bus_addr_t card_addr;
721 1.1 itojun bus_size_t size;
722 1.1 itojun struct pcmcia_mem_handle *pcmhp;
723 1.1 itojun bus_addr_t *offsetp;
724 1.1 itojun int *windowp;
725 1.1 itojun {
726 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
727 1.1 itojun bus_addr_t busaddr;
728 1.1 itojun long card_offset;
729 1.1 itojun int i, win;
730 1.1 itojun
731 1.1 itojun win = -1;
732 1.1 itojun for (i = 0; i < SHPCIC_WINS;
733 1.1 itojun i++) {
734 1.1 itojun if ((h->memalloc & (1 << i)) == 0) {
735 1.1 itojun win = i;
736 1.1 itojun h->memalloc |= (1 << i);
737 1.1 itojun break;
738 1.1 itojun }
739 1.1 itojun }
740 1.1 itojun
741 1.1 itojun if (win == -1)
742 1.1 itojun return (1);
743 1.1 itojun
744 1.1 itojun *windowp = win;
745 1.1 itojun
746 1.1 itojun /* XXX this is pretty gross */
747 1.1 itojun
748 1.1 itojun if (h->sc->memt != pcmhp->memt)
749 1.1 itojun panic("shpcic_chip_mem_map memt is bogus");
750 1.1 itojun
751 1.1 itojun busaddr = pcmhp->addr;
752 1.1 itojun
753 1.1 itojun /*
754 1.1 itojun * compute the address offset to the pcmcia address space for the
755 1.1 itojun * pcic. this is intentionally signed. The masks and shifts below
756 1.1 itojun * will cause TRT to happen in the pcic registers. Deal with making
757 1.1 itojun * sure the address is aligned, and return the alignment offset.
758 1.1 itojun */
759 1.1 itojun
760 1.1 itojun *offsetp = 0;
761 1.1 itojun card_addr -= *offsetp;
762 1.1 itojun
763 1.1 itojun DPRINTF(("shpcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr "
764 1.1 itojun "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
765 1.1 itojun (u_long) card_addr));
766 1.1 itojun
767 1.1 itojun /*
768 1.1 itojun * include the offset in the size, and decrement size by one, since
769 1.1 itojun * the hw wants start/stop
770 1.1 itojun */
771 1.1 itojun size += *offsetp - 1;
772 1.1 itojun
773 1.1 itojun card_offset = (((long) card_addr) - ((long) busaddr));
774 1.1 itojun
775 1.1 itojun h->mem[win].addr = busaddr;
776 1.1 itojun h->mem[win].size = size;
777 1.1 itojun h->mem[win].offset = card_offset;
778 1.1 itojun h->mem[win].kind = kind;
779 1.1 itojun
780 1.1 itojun if (kind == PCMCIA_MEM_ATTR) {
781 1.1 itojun pcmhp->memh = h->sc->memh + card_addr;
782 1.1 itojun } else {
783 1.1 itojun pcmhp->memh = h->sc->memh + card_addr + SHPCIC_ATTRMEM_SIZE;
784 1.1 itojun }
785 1.1 itojun #if 0
786 1.1 itojun shpcic_chip_do_mem_map(h, win);
787 1.1 itojun #endif
788 1.1 itojun
789 1.1 itojun return (0);
790 1.1 itojun }
791 1.1 itojun
792 1.1 itojun void
793 1.1 itojun shpcic_chip_mem_unmap(pch, window)
794 1.1 itojun pcmcia_chipset_handle_t pch;
795 1.1 itojun int window;
796 1.1 itojun {
797 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
798 1.1 itojun
799 1.1 itojun if (window >= SHPCIC_WINS)
800 1.1 itojun panic("shpcic_chip_mem_unmap: window out of range");
801 1.1 itojun
802 1.1 itojun h->memalloc &= ~(1 << window);
803 1.1 itojun }
804 1.1 itojun
805 1.1 itojun int
806 1.1 itojun shpcic_chip_io_alloc(pch, start, size, align, pcihp)
807 1.1 itojun pcmcia_chipset_handle_t pch;
808 1.1 itojun bus_addr_t start;
809 1.1 itojun bus_size_t size;
810 1.1 itojun bus_size_t align;
811 1.1 itojun struct pcmcia_io_handle *pcihp;
812 1.1 itojun {
813 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
814 1.1 itojun bus_space_tag_t iot;
815 1.1 itojun bus_space_handle_t ioh;
816 1.1 itojun bus_addr_t ioaddr;
817 1.1 itojun int flags = 0;
818 1.1 itojun
819 1.1 itojun /*
820 1.1 itojun * Allocate some arbitrary I/O space.
821 1.1 itojun */
822 1.1 itojun
823 1.1 itojun iot = h->sc->iot;
824 1.1 itojun
825 1.1 itojun if (start) {
826 1.1 itojun ioaddr = start;
827 1.1 itojun if (bus_space_map(iot, start, size, 0, &ioh))
828 1.1 itojun return (1);
829 1.1 itojun DPRINTF(("shpcic_chip_io_alloc map port %lx+%lx\n",
830 1.1 itojun (u_long) ioaddr, (u_long) size));
831 1.1 itojun } else {
832 1.1 itojun flags |= PCMCIA_IO_ALLOCATED;
833 1.1 itojun if (bus_space_alloc(iot, h->sc->iobase,
834 1.1 itojun h->sc->iobase + h->sc->iosize, size, align, 0, 0,
835 1.1 itojun &ioaddr, &ioh))
836 1.1 itojun return (1);
837 1.1 itojun DPRINTF(("shpcic_chip_io_alloc alloc port %lx+%lx\n",
838 1.1 itojun (u_long) ioaddr, (u_long) size));
839 1.1 itojun }
840 1.1 itojun
841 1.1 itojun pcihp->iot = iot;
842 1.1 itojun pcihp->ioh = ioh + h->sc->memh + SHPCIC_ATTRMEM_SIZE;;
843 1.1 itojun pcihp->addr = ioaddr;
844 1.1 itojun pcihp->size = size;
845 1.1 itojun pcihp->flags = flags;
846 1.1 itojun
847 1.1 itojun return (0);
848 1.1 itojun }
849 1.1 itojun
850 1.1 itojun void
851 1.1 itojun shpcic_chip_io_free(pch, pcihp)
852 1.1 itojun pcmcia_chipset_handle_t pch;
853 1.1 itojun struct pcmcia_io_handle *pcihp;
854 1.1 itojun {
855 1.1 itojun bus_space_tag_t iot = pcihp->iot;
856 1.1 itojun bus_space_handle_t ioh = pcihp->ioh;
857 1.1 itojun bus_size_t size = pcihp->size;
858 1.1 itojun
859 1.1 itojun if (pcihp->flags & PCMCIA_IO_ALLOCATED)
860 1.1 itojun bus_space_free(iot, ioh, size);
861 1.1 itojun else
862 1.1 itojun bus_space_unmap(iot, ioh, size);
863 1.1 itojun }
864 1.1 itojun
865 1.1 itojun int
866 1.1 itojun shpcic_chip_io_map(pch, width, offset, size, pcihp, windowp)
867 1.1 itojun pcmcia_chipset_handle_t pch;
868 1.1 itojun int width;
869 1.1 itojun bus_addr_t offset;
870 1.1 itojun bus_size_t size;
871 1.1 itojun struct pcmcia_io_handle *pcihp;
872 1.1 itojun int *windowp;
873 1.1 itojun {
874 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
875 1.1 itojun bus_addr_t ioaddr = pcihp->addr + offset;
876 1.1 itojun int i, win;
877 1.1 itojun #ifdef SHPCICDEBUG
878 1.1 itojun static char *width_names[] = { "auto", "io8", "io16" };
879 1.1 itojun #endif
880 1.1 itojun int reg;
881 1.1 itojun
882 1.1 itojun /* XXX Sanity check offset/size. */
883 1.1 itojun
884 1.1 itojun #ifdef MMEYE
885 1.1 itojun /* I/O width is hardwired to 16bit mode on mmeye. */
886 1.1 itojun width = PCMCIA_WIDTH_IO16;
887 1.1 itojun #endif
888 1.1 itojun
889 1.1 itojun win = -1;
890 1.1 itojun for (i = 0; i < SHPCIC_IOWINS; i++) {
891 1.1 itojun if ((h->ioalloc & (1 << i)) == 0) {
892 1.1 itojun win = i;
893 1.1 itojun h->ioalloc |= (1 << i);
894 1.1 itojun break;
895 1.1 itojun }
896 1.1 itojun }
897 1.1 itojun
898 1.1 itojun if (win == -1)
899 1.1 itojun return (1);
900 1.1 itojun
901 1.1 itojun *windowp = win;
902 1.1 itojun
903 1.1 itojun /* XXX this is pretty gross */
904 1.1 itojun
905 1.1 itojun if (h->sc->iot != pcihp->iot)
906 1.1 itojun panic("shpcic_chip_io_map iot is bogus");
907 1.1 itojun
908 1.1 itojun DPRINTF(("shpcic_chip_io_map window %d %s port %lx+%lx\n",
909 1.1 itojun win, width_names[width], (u_long) ioaddr, (u_long) size));
910 1.1 itojun
911 1.1 itojun /* XXX wtf is this doing here? */
912 1.1 itojun
913 1.1 itojun printf(" port 0x%lx", (u_long) ioaddr);
914 1.1 itojun if (size > 1)
915 1.1 itojun printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1);
916 1.1 itojun
917 1.1 itojun h->io[win].addr = ioaddr;
918 1.1 itojun h->io[win].size = size;
919 1.1 itojun h->io[win].width = width;
920 1.1 itojun
921 1.1 itojun pcihp->ioh = h->sc->memh + SHPCIC_ATTRMEM_SIZE;
922 1.1 itojun
923 1.1 itojun if (width == PCMCIA_WIDTH_IO8) { /* IO8 */
924 1.1 itojun reg = shpcic_read(h, SHPCIC_IF_STATUS);
925 1.1 itojun reg |= SHPCIC_IF_STATUS_BUSWIDTH; /* Set bus width to 8bit */
926 1.1 itojun shpcic_write(h, SHPCIC_IF_STATUS, reg);
927 1.1 itojun }
928 1.1 itojun
929 1.1 itojun #if 0
930 1.1 itojun shpcic_chip_do_io_map(h, win);
931 1.1 itojun #endif
932 1.1 itojun
933 1.1 itojun return (0);
934 1.1 itojun }
935 1.1 itojun
936 1.1 itojun void
937 1.1 itojun shpcic_chip_io_unmap(pch, window)
938 1.1 itojun pcmcia_chipset_handle_t pch;
939 1.1 itojun int window;
940 1.1 itojun {
941 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
942 1.1 itojun
943 1.1 itojun if (window >= SHPCIC_IOWINS)
944 1.1 itojun panic("shpcic_chip_io_unmap: window out of range");
945 1.1 itojun
946 1.1 itojun h->ioalloc &= ~(1 << window);
947 1.1 itojun }
948 1.1 itojun
949 1.1 itojun #if 0
950 1.1 itojun static void
951 1.1 itojun shpcic_wait_ready(h)
952 1.1 itojun struct shpcic_handle *h;
953 1.1 itojun {
954 1.1 itojun int i;
955 1.1 itojun
956 1.1 itojun for (i = 0; i < 10000; i++) {
957 1.1 itojun if (shpcic_read(h, SHPCIC_IF_STATUS) & SHPCIC_IF_STATUS_READY)
958 1.1 itojun return;
959 1.1 itojun delay(500);
960 1.1 itojun #ifdef SHPCICDEBUG
961 1.1 itojun if (shpcic_debug) {
962 1.1 itojun if ((i>5000) && (i%100 == 99))
963 1.1 itojun printf(".");
964 1.1 itojun }
965 1.1 itojun #endif
966 1.1 itojun }
967 1.1 itojun
968 1.1 itojun #ifdef DIAGNOSTIC
969 1.1 itojun printf("shpcic_wait_ready: ready never happened, status = %02x\n",
970 1.1 itojun shpcic_read(h, SHPCIC_IF_STATUS));
971 1.1 itojun #endif
972 1.1 itojun }
973 1.1 itojun #endif
974 1.1 itojun
975 1.1 itojun void
976 1.1 itojun shpcic_chip_socket_enable(pch)
977 1.1 itojun pcmcia_chipset_handle_t pch;
978 1.1 itojun {
979 1.1 itojun #if 0
980 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
981 1.1 itojun int cardtype, reg, win;
982 1.1 itojun
983 1.1 itojun /* this bit is mostly stolen from shpcic_attach_card */
984 1.1 itojun
985 1.1 itojun /* power down the socket to reset it, clear the card reset pin */
986 1.1 itojun
987 1.1 itojun shpcic_write(h, SHPCIC_PWRCTL, 0);
988 1.1 itojun
989 1.1 itojun /*
990 1.1 itojun * wait 300ms until power fails (Tpf). Then, wait 100ms since
991 1.1 itojun * we are changing Vcc (Toff).
992 1.1 itojun */
993 1.1 itojun delay((300 + 100) * 1000);
994 1.1 itojun
995 1.1 itojun #ifdef VADEM_POWER_HACK
996 1.1 itojun bus_space_write_1(h->sc->iot, h->sc->ioh, SHPCIC_REG_INDEX, 0x0e);
997 1.1 itojun bus_space_write_1(h->sc->iot, h->sc->ioh, SHPCIC_REG_INDEX, 0x37);
998 1.1 itojun printf("prcr = %02x\n", shpcic_read(h, 0x02));
999 1.1 itojun printf("cvsr = %02x\n", shpcic_read(h, 0x2f));
1000 1.1 itojun printf("DANGER WILL ROBINSON! Changing voltage select!\n");
1001 1.1 itojun shpcic_write(h, 0x2f, shpcic_read(h, 0x2f) & ~0x03);
1002 1.1 itojun printf("cvsr = %02x\n", shpcic_read(h, 0x2f));
1003 1.1 itojun #endif
1004 1.1 itojun
1005 1.1 itojun /* power up the socket */
1006 1.1 itojun
1007 1.1 itojun shpcic_write(h, SHPCIC_PWRCTL, SHPCIC_PWRCTL_DISABLE_RESETDRV
1008 1.1 itojun | SHPCIC_PWRCTL_PWR_ENABLE);
1009 1.1 itojun
1010 1.1 itojun /*
1011 1.1 itojun * wait 100ms until power raise (Tpr) and 20ms to become
1012 1.1 itojun * stable (Tsu(Vcc)).
1013 1.1 itojun *
1014 1.1 itojun * some machines require some more time to be settled
1015 1.1 itojun * (300ms is added here).
1016 1.1 itojun */
1017 1.1 itojun delay((100 + 20 + 300) * 1000);
1018 1.1 itojun
1019 1.1 itojun shpcic_write(h, SHPCIC_PWRCTL, SHPCIC_PWRCTL_DISABLE_RESETDRV | SHPCIC_PWRCTL_OE
1020 1.1 itojun | SHPCIC_PWRCTL_PWR_ENABLE);
1021 1.1 itojun shpcic_write(h, SHPCIC_INTR, 0);
1022 1.1 itojun
1023 1.1 itojun /*
1024 1.1 itojun * hold RESET at least 10us.
1025 1.1 itojun */
1026 1.1 itojun delay(10);
1027 1.1 itojun
1028 1.1 itojun /* clear the reset flag */
1029 1.1 itojun
1030 1.1 itojun shpcic_write(h, SHPCIC_INTR, SHPCIC_INTR_RESET);
1031 1.1 itojun
1032 1.1 itojun /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
1033 1.1 itojun
1034 1.1 itojun delay(20000);
1035 1.1 itojun
1036 1.1 itojun /* wait for the chip to finish initializing */
1037 1.1 itojun
1038 1.1 itojun #ifdef DIAGNOSTIC
1039 1.1 itojun reg = shpcic_read(h, SHPCIC_IF_STATUS);
1040 1.1 itojun if (!(reg & SHPCIC_IF_STATUS_POWERACTIVE)) {
1041 1.1 itojun printf("shpcic_chip_socket_enable: status %x", reg);
1042 1.1 itojun }
1043 1.1 itojun #endif
1044 1.1 itojun
1045 1.1 itojun shpcic_wait_ready(h);
1046 1.1 itojun
1047 1.1 itojun /* zero out the address windows */
1048 1.1 itojun
1049 1.1 itojun shpcic_write(h, SHPCIC_ADDRWIN_ENABLE, 0);
1050 1.1 itojun
1051 1.1 itojun /* set the card type */
1052 1.1 itojun
1053 1.1 itojun cardtype = pcmcia_card_gettype(h->pcmcia);
1054 1.1 itojun
1055 1.1 itojun reg = shpcic_read(h, SHPCIC_INTR);
1056 1.1 itojun reg &= ~(SHPCIC_INTR_CARDTYPE_MASK | SHPCIC_INTR_IRQ_MASK | SHPCIC_INTR_ENABLE);
1057 1.1 itojun reg |= ((cardtype == PCMCIA_IFTYPE_IO) ?
1058 1.1 itojun SHPCIC_INTR_CARDTYPE_IO :
1059 1.1 itojun SHPCIC_INTR_CARDTYPE_MEM);
1060 1.1 itojun reg |= h->ih_irq;
1061 1.1 itojun shpcic_write(h, SHPCIC_INTR, reg);
1062 1.1 itojun
1063 1.1 itojun DPRINTF(("%s: shpcic_chip_socket_enable %02x cardtype %s %02x\n",
1064 1.1 itojun h->sc->dev.dv_xname, h->sock,
1065 1.1 itojun ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg));
1066 1.1 itojun
1067 1.1 itojun /* reinstall all the memory and io mappings */
1068 1.1 itojun
1069 1.1 itojun for (win = 0; win < SHPCIC_MEM_WINS; win++)
1070 1.1 itojun if (h->memalloc & (1 << win))
1071 1.1 itojun shpcic_chip_do_mem_map(h, win);
1072 1.1 itojun
1073 1.1 itojun for (win = 0; win < SHPCIC_IO_WINS; win++)
1074 1.1 itojun if (h->ioalloc & (1 << win))
1075 1.1 itojun shpcic_chip_do_io_map(h, win);
1076 1.1 itojun #endif
1077 1.1 itojun }
1078 1.1 itojun
1079 1.1 itojun void
1080 1.1 itojun shpcic_chip_socket_disable(pch)
1081 1.1 itojun pcmcia_chipset_handle_t pch;
1082 1.1 itojun {
1083 1.1 itojun #if 0
1084 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
1085 1.1 itojun
1086 1.1 itojun DPRINTF(("shpcic_chip_socket_disable\n"));
1087 1.1 itojun
1088 1.1 itojun /* power down the socket */
1089 1.1 itojun
1090 1.1 itojun shpcic_write(h, SHPCIC_PWRCTL, 0);
1091 1.1 itojun
1092 1.1 itojun /*
1093 1.1 itojun * wait 300ms until power fails (Tpf).
1094 1.1 itojun */
1095 1.1 itojun delay(300 * 1000);
1096 1.1 itojun #endif
1097 1.1 itojun }
1098