shpcic.c revision 1.4 1 1.4 mrg /* $NetBSD: shpcic.c,v 1.4 2000/06/29 07:44:02 mrg 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.4 mrg #include <uvm/uvm_extern.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.2 tsubai #include <sh3/dev/shpcicreg.h>
52 1.2 tsubai #include <sh3/dev/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.3 tsubai paa.paa_busname = "pcmcia";
244 1.1 itojun paa.pct = (pcmcia_chipset_tag_t) h->sc->pct;
245 1.1 itojun paa.pch = (pcmcia_chipset_handle_t) h;
246 1.1 itojun paa.iobase = h->sc->iobase;
247 1.1 itojun paa.iosize = h->sc->iosize;
248 1.1 itojun
249 1.1 itojun h->pcmcia = config_found_sm(&h->sc->dev, &paa, shpcic_print,
250 1.1 itojun shpcic_submatch);
251 1.1 itojun
252 1.1 itojun /* if there's actually a pcmcia device attached, initialize the slot */
253 1.1 itojun
254 1.1 itojun if (h->pcmcia)
255 1.1 itojun shpcic_init_socket(h);
256 1.1 itojun }
257 1.1 itojun
258 1.1 itojun void
259 1.1 itojun shpcic_create_event_thread(arg)
260 1.1 itojun void *arg;
261 1.1 itojun {
262 1.1 itojun struct shpcic_handle *h = arg;
263 1.1 itojun const char *cs;
264 1.1 itojun
265 1.1 itojun switch (h->sock) {
266 1.1 itojun case C0SA:
267 1.1 itojun cs = "0,0";
268 1.1 itojun break;
269 1.1 itojun case C0SB:
270 1.1 itojun cs = "0,1";
271 1.1 itojun break;
272 1.1 itojun case C1SA:
273 1.1 itojun cs = "1,0";
274 1.1 itojun break;
275 1.1 itojun case C1SB:
276 1.1 itojun cs = "1,1";
277 1.1 itojun break;
278 1.1 itojun default:
279 1.1 itojun panic("shpcic_create_event_thread: unknown pcic socket");
280 1.1 itojun }
281 1.1 itojun
282 1.2 tsubai if (kthread_create1(shpcic_event_thread, h, &h->event_thread,
283 1.1 itojun "%s,%s", h->sc->dev.dv_xname, cs)) {
284 1.1 itojun printf("%s: unable to create event thread for sock 0x%02x\n",
285 1.1 itojun h->sc->dev.dv_xname, h->sock);
286 1.1 itojun panic("shpcic_create_event_thread");
287 1.1 itojun }
288 1.1 itojun }
289 1.1 itojun
290 1.1 itojun void
291 1.1 itojun shpcic_event_thread(arg)
292 1.1 itojun void *arg;
293 1.1 itojun {
294 1.1 itojun struct shpcic_handle *h = arg;
295 1.1 itojun struct shpcic_event *pe;
296 1.1 itojun int s;
297 1.1 itojun
298 1.1 itojun while (h->shutdown == 0) {
299 1.1 itojun s = splhigh();
300 1.1 itojun if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) {
301 1.1 itojun splx(s);
302 1.1 itojun (void) tsleep(&h->events, PWAIT, "shpcicev", 0);
303 1.1 itojun continue;
304 1.1 itojun } else {
305 1.1 itojun splx(s);
306 1.1 itojun /* sleep .25s to be enqueued chatterling interrupts */
307 1.1 itojun (void) tsleep((caddr_t)shpcic_event_thread, PWAIT, "shpcicss", hz/4);
308 1.1 itojun }
309 1.1 itojun s = splhigh();
310 1.1 itojun SIMPLEQ_REMOVE_HEAD(&h->events, pe, pe_q);
311 1.1 itojun splx(s);
312 1.1 itojun
313 1.1 itojun switch (pe->pe_type) {
314 1.1 itojun case SHPCIC_EVENT_INSERTION:
315 1.1 itojun s = splhigh();
316 1.1 itojun while (1) {
317 1.1 itojun struct shpcic_event *pe1, *pe2;
318 1.1 itojun
319 1.1 itojun if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
320 1.1 itojun break;
321 1.1 itojun if (pe1->pe_type != SHPCIC_EVENT_REMOVAL)
322 1.1 itojun break;
323 1.1 itojun if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
324 1.1 itojun break;
325 1.1 itojun if (pe2->pe_type == SHPCIC_EVENT_INSERTION) {
326 1.1 itojun SIMPLEQ_REMOVE_HEAD(&h->events, pe1, pe_q);
327 1.1 itojun free(pe1, M_TEMP);
328 1.1 itojun SIMPLEQ_REMOVE_HEAD(&h->events, pe2, pe_q);
329 1.1 itojun free(pe2, M_TEMP);
330 1.1 itojun }
331 1.1 itojun }
332 1.1 itojun splx(s);
333 1.1 itojun
334 1.1 itojun DPRINTF(("%s: insertion event\n", h->sc->dev.dv_xname));
335 1.1 itojun shpcic_attach_card(h);
336 1.1 itojun break;
337 1.1 itojun
338 1.1 itojun case SHPCIC_EVENT_REMOVAL:
339 1.1 itojun s = splhigh();
340 1.1 itojun while (1) {
341 1.1 itojun struct shpcic_event *pe1, *pe2;
342 1.1 itojun
343 1.1 itojun if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
344 1.1 itojun break;
345 1.1 itojun if (pe1->pe_type != SHPCIC_EVENT_INSERTION)
346 1.1 itojun break;
347 1.1 itojun if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
348 1.1 itojun break;
349 1.1 itojun if (pe2->pe_type == SHPCIC_EVENT_REMOVAL) {
350 1.1 itojun SIMPLEQ_REMOVE_HEAD(&h->events, pe1, pe_q);
351 1.1 itojun free(pe1, M_TEMP);
352 1.1 itojun SIMPLEQ_REMOVE_HEAD(&h->events, pe2, pe_q);
353 1.1 itojun free(pe2, M_TEMP);
354 1.1 itojun }
355 1.1 itojun }
356 1.1 itojun splx(s);
357 1.1 itojun
358 1.1 itojun DPRINTF(("%s: removal event\n", h->sc->dev.dv_xname));
359 1.1 itojun shpcic_detach_card(h, DETACH_FORCE);
360 1.1 itojun break;
361 1.1 itojun
362 1.1 itojun default:
363 1.1 itojun panic("shpcic_event_thread: unknown event %d",
364 1.1 itojun pe->pe_type);
365 1.1 itojun }
366 1.1 itojun free(pe, M_TEMP);
367 1.1 itojun }
368 1.1 itojun
369 1.1 itojun h->event_thread = NULL;
370 1.1 itojun
371 1.1 itojun /* In case parent is waiting for us to exit. */
372 1.1 itojun wakeup(h->sc);
373 1.1 itojun
374 1.1 itojun kthread_exit(0);
375 1.1 itojun }
376 1.1 itojun
377 1.1 itojun void
378 1.1 itojun shpcic_init_socket(h)
379 1.1 itojun struct shpcic_handle *h;
380 1.1 itojun {
381 1.1 itojun int reg;
382 1.1 itojun
383 1.1 itojun /*
384 1.1 itojun * queue creation of a kernel thread to handle insert/removal events.
385 1.1 itojun */
386 1.1 itojun #ifdef DIAGNOSTIC
387 1.1 itojun if (h->event_thread != NULL)
388 1.1 itojun panic("shpcic_attach_socket: event thread");
389 1.1 itojun #endif
390 1.2 tsubai kthread_create(shpcic_create_event_thread, h);
391 1.1 itojun
392 1.1 itojun /* if there's a card there, then attach it. */
393 1.1 itojun
394 1.1 itojun reg = shpcic_read(h, SHPCIC_IF_STATUS);
395 1.1 itojun reg &= ~SHPCIC_IF_STATUS_BUSWIDTH; /* Set bus width to 16bit */
396 1.1 itojun
397 1.1 itojun if ((reg & SHPCIC_IF_STATUS_CARDDETECT_MASK) ==
398 1.1 itojun SHPCIC_IF_STATUS_CARDDETECT_PRESENT) {
399 1.1 itojun int i;
400 1.1 itojun
401 1.1 itojun /* reset the card */
402 1.1 itojun shpcic_write(h, SHPCIC_IF_STATUS, reg|SHPCIC_IF_STATUS_RESET);
403 1.1 itojun delay(1000); /* wait 1000 uSec */
404 1.1 itojun shpcic_write(h, SHPCIC_IF_STATUS,
405 1.1 itojun reg & ~SHPCIC_IF_STATUS_RESET);
406 1.1 itojun for (i = 0; i < 10000; i++)
407 1.1 itojun delay(1000); /* wait 1 mSec */
408 1.1 itojun
409 1.1 itojun shpcic_attach_card(h);
410 1.1 itojun h->laststate = SHPCIC_LASTSTATE_PRESENT;
411 1.1 itojun } else {
412 1.1 itojun h->laststate = SHPCIC_LASTSTATE_EMPTY;
413 1.1 itojun }
414 1.1 itojun }
415 1.1 itojun
416 1.1 itojun int
417 1.1 itojun shpcic_submatch(parent, cf, aux)
418 1.1 itojun struct device *parent;
419 1.1 itojun struct cfdata *cf;
420 1.1 itojun void *aux;
421 1.1 itojun {
422 1.1 itojun
423 1.1 itojun struct pcmciabus_attach_args *paa = aux;
424 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) paa->pch;
425 1.1 itojun
426 1.1 itojun switch (h->sock) {
427 1.1 itojun case C0SA:
428 1.1 itojun #ifdef TODO
429 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
430 1.1 itojun PCMCIABUSCF_CONTROLLER_DEFAULT &&
431 1.1 itojun cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 0)
432 1.1 itojun return 0;
433 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
434 1.1 itojun PCMCIABUSCF_SOCKET_DEFAULT &&
435 1.1 itojun cf->cf_loc[PCMCIABUSCF_SOCKET] != 0)
436 1.1 itojun return 0;
437 1.1 itojun #endif
438 1.1 itojun
439 1.1 itojun break;
440 1.1 itojun case C0SB:
441 1.1 itojun #ifdef TODO
442 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
443 1.1 itojun PCMCIABUSCF_CONTROLLER_DEFAULT &&
444 1.1 itojun cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 0)
445 1.1 itojun return 0;
446 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
447 1.1 itojun PCMCIABUSCF_SOCKET_DEFAULT &&
448 1.1 itojun cf->cf_loc[PCMCIABUSCF_SOCKET] != 1)
449 1.1 itojun return 0;
450 1.1 itojun #endif
451 1.1 itojun
452 1.1 itojun break;
453 1.1 itojun case C1SA:
454 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
455 1.1 itojun PCMCIABUSCF_CONTROLLER_DEFAULT &&
456 1.1 itojun cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 1)
457 1.1 itojun return 0;
458 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
459 1.1 itojun PCMCIABUSCF_SOCKET_DEFAULT &&
460 1.1 itojun cf->cf_loc[PCMCIABUSCF_SOCKET] != 0)
461 1.1 itojun return 0;
462 1.1 itojun
463 1.1 itojun break;
464 1.1 itojun case C1SB:
465 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_CONTROLLER] !=
466 1.1 itojun PCMCIABUSCF_CONTROLLER_DEFAULT &&
467 1.1 itojun cf->cf_loc[PCMCIABUSCF_CONTROLLER] != 1)
468 1.1 itojun return 0;
469 1.1 itojun if (cf->cf_loc[PCMCIABUSCF_SOCKET] !=
470 1.1 itojun PCMCIABUSCF_SOCKET_DEFAULT &&
471 1.1 itojun cf->cf_loc[PCMCIABUSCF_SOCKET] != 1)
472 1.1 itojun return 0;
473 1.1 itojun
474 1.1 itojun break;
475 1.1 itojun default:
476 1.1 itojun panic("unknown pcic socket");
477 1.1 itojun }
478 1.1 itojun
479 1.1 itojun return ((*cf->cf_attach->ca_match)(parent, cf, aux));
480 1.1 itojun }
481 1.1 itojun
482 1.1 itojun int
483 1.1 itojun shpcic_print(arg, pnp)
484 1.1 itojun void *arg;
485 1.1 itojun const char *pnp;
486 1.1 itojun {
487 1.1 itojun struct pcmciabus_attach_args *paa = arg;
488 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) paa->pch;
489 1.1 itojun
490 1.1 itojun /* Only "pcmcia"s can attach to "pcic"s... easy. */
491 1.1 itojun if (pnp)
492 1.1 itojun printf("pcmcia at %s", pnp);
493 1.1 itojun
494 1.1 itojun switch (h->sock) {
495 1.1 itojun case C0SA:
496 1.1 itojun printf(" controller 0 socket 0");
497 1.1 itojun break;
498 1.1 itojun case C0SB:
499 1.1 itojun printf(" controller 0 socket 1");
500 1.1 itojun break;
501 1.1 itojun case C1SA:
502 1.1 itojun printf(" controller 1 socket 0");
503 1.1 itojun break;
504 1.1 itojun case C1SB:
505 1.1 itojun printf(" controller 1 socket 1");
506 1.1 itojun break;
507 1.1 itojun default:
508 1.1 itojun panic("unknown pcic socket");
509 1.1 itojun }
510 1.1 itojun
511 1.1 itojun return (UNCONF);
512 1.1 itojun }
513 1.1 itojun
514 1.1 itojun int
515 1.1 itojun shpcic_intr(arg)
516 1.1 itojun void *arg;
517 1.1 itojun {
518 1.1 itojun struct shpcic_softc *sc = arg;
519 1.1 itojun int i, ret = 0;
520 1.1 itojun
521 1.1 itojun DPRINTF(("%s: intr\n", sc->dev.dv_xname));
522 1.1 itojun
523 1.1 itojun for (i = 0; i < SHPCIC_NSLOTS; i++)
524 1.1 itojun if (sc->handle[i].flags & SHPCIC_FLAG_SOCKETP)
525 1.1 itojun ret += shpcic_intr_socket(&sc->handle[i]);
526 1.1 itojun
527 1.1 itojun return (ret ? 1 : 0);
528 1.1 itojun }
529 1.1 itojun
530 1.1 itojun int
531 1.1 itojun shpcic_intr_socket(h)
532 1.1 itojun struct shpcic_handle *h;
533 1.1 itojun {
534 1.1 itojun int cscreg;
535 1.1 itojun
536 1.1 itojun cscreg = shpcic_read(h, SHPCIC_CSC);
537 1.1 itojun
538 1.1 itojun cscreg &= (SHPCIC_CSC_GPI |
539 1.1 itojun SHPCIC_CSC_CD |
540 1.1 itojun SHPCIC_CSC_READY |
541 1.1 itojun SHPCIC_CSC_BATTWARN |
542 1.1 itojun SHPCIC_CSC_BATTDEAD);
543 1.1 itojun
544 1.1 itojun if (cscreg & SHPCIC_CSC_GPI) {
545 1.1 itojun DPRINTF(("%s: %02x GPI\n", h->sc->dev.dv_xname, h->sock));
546 1.1 itojun }
547 1.1 itojun if (cscreg & SHPCIC_CSC_CD) {
548 1.1 itojun int statreg;
549 1.1 itojun
550 1.1 itojun statreg = shpcic_read(h, SHPCIC_IF_STATUS);
551 1.1 itojun
552 1.1 itojun DPRINTF(("%s: %02x CD %x\n", h->sc->dev.dv_xname, h->sock,
553 1.1 itojun statreg));
554 1.1 itojun
555 1.1 itojun if ((statreg & SHPCIC_IF_STATUS_CARDDETECT_MASK) ==
556 1.1 itojun SHPCIC_IF_STATUS_CARDDETECT_PRESENT) {
557 1.1 itojun if (h->laststate != SHPCIC_LASTSTATE_PRESENT) {
558 1.1 itojun DPRINTF(("%s: enqueing INSERTION event\n",
559 1.1 itojun h->sc->dev.dv_xname));
560 1.1 itojun shpcic_queue_event(h, SHPCIC_EVENT_INSERTION);
561 1.1 itojun }
562 1.1 itojun h->laststate = SHPCIC_LASTSTATE_PRESENT;
563 1.1 itojun } else {
564 1.1 itojun if (h->laststate == SHPCIC_LASTSTATE_PRESENT) {
565 1.1 itojun /* Deactivate the card now. */
566 1.1 itojun DPRINTF(("%s: deactivating card\n",
567 1.1 itojun h->sc->dev.dv_xname));
568 1.1 itojun shpcic_deactivate_card(h);
569 1.1 itojun
570 1.1 itojun DPRINTF(("%s: enqueing REMOVAL event\n",
571 1.1 itojun h->sc->dev.dv_xname));
572 1.1 itojun shpcic_queue_event(h, SHPCIC_EVENT_REMOVAL);
573 1.1 itojun }
574 1.1 itojun h->laststate = ((statreg & SHPCIC_IF_STATUS_CARDDETECT_MASK) == 0)
575 1.1 itojun ? SHPCIC_LASTSTATE_EMPTY : SHPCIC_LASTSTATE_HALF;
576 1.1 itojun }
577 1.1 itojun }
578 1.1 itojun if (cscreg & SHPCIC_CSC_READY) {
579 1.1 itojun DPRINTF(("%s: %02x READY\n", h->sc->dev.dv_xname, h->sock));
580 1.1 itojun /* shouldn't happen */
581 1.1 itojun }
582 1.1 itojun if (cscreg & SHPCIC_CSC_BATTWARN) {
583 1.1 itojun DPRINTF(("%s: %02x BATTWARN\n", h->sc->dev.dv_xname, h->sock));
584 1.1 itojun }
585 1.1 itojun if (cscreg & SHPCIC_CSC_BATTDEAD) {
586 1.1 itojun DPRINTF(("%s: %02x BATTDEAD\n", h->sc->dev.dv_xname, h->sock));
587 1.1 itojun }
588 1.1 itojun return (cscreg ? 1 : 0);
589 1.1 itojun }
590 1.1 itojun
591 1.1 itojun void
592 1.1 itojun shpcic_queue_event(h, event)
593 1.1 itojun struct shpcic_handle *h;
594 1.1 itojun int event;
595 1.1 itojun {
596 1.1 itojun struct shpcic_event *pe;
597 1.1 itojun int s;
598 1.1 itojun
599 1.1 itojun pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
600 1.1 itojun if (pe == NULL)
601 1.1 itojun panic("shpcic_queue_event: can't allocate event");
602 1.1 itojun
603 1.1 itojun pe->pe_type = event;
604 1.1 itojun s = splhigh();
605 1.1 itojun SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q);
606 1.1 itojun splx(s);
607 1.1 itojun wakeup(&h->events);
608 1.1 itojun }
609 1.1 itojun
610 1.1 itojun void
611 1.1 itojun shpcic_attach_card(h)
612 1.1 itojun struct shpcic_handle *h;
613 1.1 itojun {
614 1.1 itojun
615 1.1 itojun if (!(h->flags & SHPCIC_FLAG_CARDP)) {
616 1.1 itojun /* call the MI attach function */
617 1.1 itojun pcmcia_card_attach(h->pcmcia);
618 1.1 itojun
619 1.1 itojun h->flags |= SHPCIC_FLAG_CARDP;
620 1.1 itojun } else {
621 1.1 itojun DPRINTF(("shpcic_attach_card: already attached"));
622 1.1 itojun }
623 1.1 itojun }
624 1.1 itojun
625 1.1 itojun void
626 1.1 itojun shpcic_detach_card(h, flags)
627 1.1 itojun struct shpcic_handle *h;
628 1.1 itojun int flags; /* DETACH_* */
629 1.1 itojun {
630 1.1 itojun
631 1.1 itojun if (h->flags & SHPCIC_FLAG_CARDP) {
632 1.1 itojun h->flags &= ~SHPCIC_FLAG_CARDP;
633 1.1 itojun
634 1.1 itojun /* call the MI detach function */
635 1.1 itojun pcmcia_card_detach(h->pcmcia, flags);
636 1.1 itojun } else {
637 1.1 itojun DPRINTF(("shpcic_detach_card: already detached"));
638 1.1 itojun }
639 1.1 itojun }
640 1.1 itojun
641 1.1 itojun void
642 1.1 itojun shpcic_deactivate_card(h)
643 1.1 itojun struct shpcic_handle *h;
644 1.1 itojun {
645 1.1 itojun
646 1.1 itojun /* call the MI deactivate function */
647 1.1 itojun pcmcia_card_deactivate(h->pcmcia);
648 1.1 itojun
649 1.1 itojun #if 0
650 1.1 itojun /* power down the socket */
651 1.1 itojun shpcic_write(h, SHPCIC_PWRCTL, 0);
652 1.1 itojun
653 1.1 itojun /* reset the socket */
654 1.1 itojun shpcic_write(h, SHPCIC_INTR, 0);
655 1.1 itojun #endif
656 1.1 itojun }
657 1.1 itojun
658 1.1 itojun int
659 1.1 itojun shpcic_chip_mem_alloc(pch, size, pcmhp)
660 1.1 itojun pcmcia_chipset_handle_t pch;
661 1.1 itojun bus_size_t size;
662 1.1 itojun struct pcmcia_mem_handle *pcmhp;
663 1.1 itojun {
664 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
665 1.1 itojun bus_space_handle_t memh = 0;
666 1.1 itojun bus_addr_t addr;
667 1.1 itojun bus_size_t sizepg;
668 1.1 itojun int i, mask, mhandle;
669 1.1 itojun
670 1.1 itojun /* out of sc->memh, allocate as many pages as necessary */
671 1.1 itojun
672 1.1 itojun /* convert size to PCIC pages */
673 1.1 itojun sizepg = (size + (SHPCIC_MEM_ALIGN - 1)) / SHPCIC_MEM_ALIGN;
674 1.1 itojun if (sizepg > SHPCIC_MAX_MEM_PAGES)
675 1.1 itojun return (1);
676 1.1 itojun
677 1.1 itojun mask = (1 << sizepg) - 1;
678 1.1 itojun
679 1.1 itojun addr = 0; /* XXX gcc -Wuninitialized */
680 1.1 itojun mhandle = 0; /* XXX gcc -Wuninitialized */
681 1.1 itojun
682 1.1 itojun for (i = 0; i <= SHPCIC_MAX_MEM_PAGES - sizepg; i++) {
683 1.1 itojun if ((h->sc->subregionmask & (mask << i)) == (mask << i)) {
684 1.1 itojun #if 0
685 1.1 itojun if (bus_space_subregion(h->sc->memt, h->sc->memh,
686 1.1 itojun i * SHPCIC_MEM_PAGESIZE,
687 1.1 itojun sizepg * SHPCIC_MEM_PAGESIZE, &memh))
688 1.1 itojun return (1);
689 1.1 itojun #endif
690 1.1 itojun memh = h->sc->memh;
691 1.1 itojun mhandle = mask << i;
692 1.1 itojun addr = h->sc->membase + (i * SHPCIC_MEM_PAGESIZE);
693 1.1 itojun h->sc->subregionmask &= ~(mhandle);
694 1.1 itojun pcmhp->memt = h->sc->memt;
695 1.1 itojun pcmhp->memh = memh;
696 1.1 itojun pcmhp->addr = addr;
697 1.1 itojun pcmhp->size = size;
698 1.1 itojun pcmhp->mhandle = mhandle;
699 1.1 itojun pcmhp->realsize = sizepg * SHPCIC_MEM_PAGESIZE;
700 1.1 itojun return (0);
701 1.1 itojun }
702 1.1 itojun }
703 1.1 itojun
704 1.1 itojun return (1);
705 1.1 itojun }
706 1.1 itojun
707 1.1 itojun void
708 1.1 itojun shpcic_chip_mem_free(pch, pcmhp)
709 1.1 itojun pcmcia_chipset_handle_t pch;
710 1.1 itojun struct pcmcia_mem_handle *pcmhp;
711 1.1 itojun {
712 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
713 1.1 itojun
714 1.1 itojun h->sc->subregionmask |= pcmhp->mhandle;
715 1.1 itojun }
716 1.1 itojun
717 1.1 itojun int
718 1.1 itojun shpcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
719 1.1 itojun pcmcia_chipset_handle_t pch;
720 1.1 itojun int kind;
721 1.1 itojun bus_addr_t card_addr;
722 1.1 itojun bus_size_t size;
723 1.1 itojun struct pcmcia_mem_handle *pcmhp;
724 1.1 itojun bus_addr_t *offsetp;
725 1.1 itojun int *windowp;
726 1.1 itojun {
727 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
728 1.1 itojun bus_addr_t busaddr;
729 1.1 itojun long card_offset;
730 1.1 itojun int i, win;
731 1.1 itojun
732 1.1 itojun win = -1;
733 1.1 itojun for (i = 0; i < SHPCIC_WINS;
734 1.1 itojun i++) {
735 1.1 itojun if ((h->memalloc & (1 << i)) == 0) {
736 1.1 itojun win = i;
737 1.1 itojun h->memalloc |= (1 << i);
738 1.1 itojun break;
739 1.1 itojun }
740 1.1 itojun }
741 1.1 itojun
742 1.1 itojun if (win == -1)
743 1.1 itojun return (1);
744 1.1 itojun
745 1.1 itojun *windowp = win;
746 1.1 itojun
747 1.1 itojun /* XXX this is pretty gross */
748 1.1 itojun
749 1.1 itojun if (h->sc->memt != pcmhp->memt)
750 1.1 itojun panic("shpcic_chip_mem_map memt is bogus");
751 1.1 itojun
752 1.1 itojun busaddr = pcmhp->addr;
753 1.1 itojun
754 1.1 itojun /*
755 1.1 itojun * compute the address offset to the pcmcia address space for the
756 1.1 itojun * pcic. this is intentionally signed. The masks and shifts below
757 1.1 itojun * will cause TRT to happen in the pcic registers. Deal with making
758 1.1 itojun * sure the address is aligned, and return the alignment offset.
759 1.1 itojun */
760 1.1 itojun
761 1.1 itojun *offsetp = 0;
762 1.1 itojun card_addr -= *offsetp;
763 1.1 itojun
764 1.1 itojun DPRINTF(("shpcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr "
765 1.1 itojun "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
766 1.1 itojun (u_long) card_addr));
767 1.1 itojun
768 1.1 itojun /*
769 1.1 itojun * include the offset in the size, and decrement size by one, since
770 1.1 itojun * the hw wants start/stop
771 1.1 itojun */
772 1.1 itojun size += *offsetp - 1;
773 1.1 itojun
774 1.1 itojun card_offset = (((long) card_addr) - ((long) busaddr));
775 1.1 itojun
776 1.1 itojun h->mem[win].addr = busaddr;
777 1.1 itojun h->mem[win].size = size;
778 1.1 itojun h->mem[win].offset = card_offset;
779 1.1 itojun h->mem[win].kind = kind;
780 1.1 itojun
781 1.1 itojun if (kind == PCMCIA_MEM_ATTR) {
782 1.1 itojun pcmhp->memh = h->sc->memh + card_addr;
783 1.1 itojun } else {
784 1.1 itojun pcmhp->memh = h->sc->memh + card_addr + SHPCIC_ATTRMEM_SIZE;
785 1.1 itojun }
786 1.1 itojun #if 0
787 1.1 itojun shpcic_chip_do_mem_map(h, win);
788 1.1 itojun #endif
789 1.1 itojun
790 1.1 itojun return (0);
791 1.1 itojun }
792 1.1 itojun
793 1.1 itojun void
794 1.1 itojun shpcic_chip_mem_unmap(pch, window)
795 1.1 itojun pcmcia_chipset_handle_t pch;
796 1.1 itojun int window;
797 1.1 itojun {
798 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
799 1.1 itojun
800 1.1 itojun if (window >= SHPCIC_WINS)
801 1.1 itojun panic("shpcic_chip_mem_unmap: window out of range");
802 1.1 itojun
803 1.1 itojun h->memalloc &= ~(1 << window);
804 1.1 itojun }
805 1.1 itojun
806 1.1 itojun int
807 1.1 itojun shpcic_chip_io_alloc(pch, start, size, align, pcihp)
808 1.1 itojun pcmcia_chipset_handle_t pch;
809 1.1 itojun bus_addr_t start;
810 1.1 itojun bus_size_t size;
811 1.1 itojun bus_size_t align;
812 1.1 itojun struct pcmcia_io_handle *pcihp;
813 1.1 itojun {
814 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
815 1.1 itojun bus_space_tag_t iot;
816 1.1 itojun bus_space_handle_t ioh;
817 1.1 itojun bus_addr_t ioaddr;
818 1.1 itojun int flags = 0;
819 1.1 itojun
820 1.1 itojun /*
821 1.1 itojun * Allocate some arbitrary I/O space.
822 1.1 itojun */
823 1.1 itojun
824 1.1 itojun iot = h->sc->iot;
825 1.1 itojun
826 1.1 itojun if (start) {
827 1.1 itojun ioaddr = start;
828 1.1 itojun if (bus_space_map(iot, start, size, 0, &ioh))
829 1.1 itojun return (1);
830 1.1 itojun DPRINTF(("shpcic_chip_io_alloc map port %lx+%lx\n",
831 1.1 itojun (u_long) ioaddr, (u_long) size));
832 1.1 itojun } else {
833 1.1 itojun flags |= PCMCIA_IO_ALLOCATED;
834 1.1 itojun if (bus_space_alloc(iot, h->sc->iobase,
835 1.1 itojun h->sc->iobase + h->sc->iosize, size, align, 0, 0,
836 1.1 itojun &ioaddr, &ioh))
837 1.1 itojun return (1);
838 1.1 itojun DPRINTF(("shpcic_chip_io_alloc alloc port %lx+%lx\n",
839 1.1 itojun (u_long) ioaddr, (u_long) size));
840 1.1 itojun }
841 1.1 itojun
842 1.1 itojun pcihp->iot = iot;
843 1.1 itojun pcihp->ioh = ioh + h->sc->memh + SHPCIC_ATTRMEM_SIZE;;
844 1.1 itojun pcihp->addr = ioaddr;
845 1.1 itojun pcihp->size = size;
846 1.1 itojun pcihp->flags = flags;
847 1.1 itojun
848 1.1 itojun return (0);
849 1.1 itojun }
850 1.1 itojun
851 1.1 itojun void
852 1.1 itojun shpcic_chip_io_free(pch, pcihp)
853 1.1 itojun pcmcia_chipset_handle_t pch;
854 1.1 itojun struct pcmcia_io_handle *pcihp;
855 1.1 itojun {
856 1.1 itojun bus_space_tag_t iot = pcihp->iot;
857 1.1 itojun bus_space_handle_t ioh = pcihp->ioh;
858 1.1 itojun bus_size_t size = pcihp->size;
859 1.1 itojun
860 1.1 itojun if (pcihp->flags & PCMCIA_IO_ALLOCATED)
861 1.1 itojun bus_space_free(iot, ioh, size);
862 1.1 itojun else
863 1.1 itojun bus_space_unmap(iot, ioh, size);
864 1.1 itojun }
865 1.1 itojun
866 1.1 itojun int
867 1.1 itojun shpcic_chip_io_map(pch, width, offset, size, pcihp, windowp)
868 1.1 itojun pcmcia_chipset_handle_t pch;
869 1.1 itojun int width;
870 1.1 itojun bus_addr_t offset;
871 1.1 itojun bus_size_t size;
872 1.1 itojun struct pcmcia_io_handle *pcihp;
873 1.1 itojun int *windowp;
874 1.1 itojun {
875 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
876 1.1 itojun bus_addr_t ioaddr = pcihp->addr + offset;
877 1.1 itojun int i, win;
878 1.1 itojun #ifdef SHPCICDEBUG
879 1.1 itojun static char *width_names[] = { "auto", "io8", "io16" };
880 1.1 itojun #endif
881 1.1 itojun int reg;
882 1.1 itojun
883 1.1 itojun /* XXX Sanity check offset/size. */
884 1.1 itojun
885 1.1 itojun #ifdef MMEYE
886 1.1 itojun /* I/O width is hardwired to 16bit mode on mmeye. */
887 1.1 itojun width = PCMCIA_WIDTH_IO16;
888 1.1 itojun #endif
889 1.1 itojun
890 1.1 itojun win = -1;
891 1.1 itojun for (i = 0; i < SHPCIC_IOWINS; i++) {
892 1.1 itojun if ((h->ioalloc & (1 << i)) == 0) {
893 1.1 itojun win = i;
894 1.1 itojun h->ioalloc |= (1 << i);
895 1.1 itojun break;
896 1.1 itojun }
897 1.1 itojun }
898 1.1 itojun
899 1.1 itojun if (win == -1)
900 1.1 itojun return (1);
901 1.1 itojun
902 1.1 itojun *windowp = win;
903 1.1 itojun
904 1.1 itojun /* XXX this is pretty gross */
905 1.1 itojun
906 1.1 itojun if (h->sc->iot != pcihp->iot)
907 1.1 itojun panic("shpcic_chip_io_map iot is bogus");
908 1.1 itojun
909 1.1 itojun DPRINTF(("shpcic_chip_io_map window %d %s port %lx+%lx\n",
910 1.1 itojun win, width_names[width], (u_long) ioaddr, (u_long) size));
911 1.1 itojun
912 1.1 itojun /* XXX wtf is this doing here? */
913 1.1 itojun
914 1.1 itojun printf(" port 0x%lx", (u_long) ioaddr);
915 1.1 itojun if (size > 1)
916 1.1 itojun printf("-0x%lx", (u_long) ioaddr + (u_long) size - 1);
917 1.1 itojun
918 1.1 itojun h->io[win].addr = ioaddr;
919 1.1 itojun h->io[win].size = size;
920 1.1 itojun h->io[win].width = width;
921 1.1 itojun
922 1.1 itojun pcihp->ioh = h->sc->memh + SHPCIC_ATTRMEM_SIZE;
923 1.1 itojun
924 1.1 itojun if (width == PCMCIA_WIDTH_IO8) { /* IO8 */
925 1.1 itojun reg = shpcic_read(h, SHPCIC_IF_STATUS);
926 1.1 itojun reg |= SHPCIC_IF_STATUS_BUSWIDTH; /* Set bus width to 8bit */
927 1.1 itojun shpcic_write(h, SHPCIC_IF_STATUS, reg);
928 1.1 itojun }
929 1.1 itojun
930 1.1 itojun #if 0
931 1.1 itojun shpcic_chip_do_io_map(h, win);
932 1.1 itojun #endif
933 1.1 itojun
934 1.1 itojun return (0);
935 1.1 itojun }
936 1.1 itojun
937 1.1 itojun void
938 1.1 itojun shpcic_chip_io_unmap(pch, window)
939 1.1 itojun pcmcia_chipset_handle_t pch;
940 1.1 itojun int window;
941 1.1 itojun {
942 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
943 1.1 itojun
944 1.1 itojun if (window >= SHPCIC_IOWINS)
945 1.1 itojun panic("shpcic_chip_io_unmap: window out of range");
946 1.1 itojun
947 1.1 itojun h->ioalloc &= ~(1 << window);
948 1.1 itojun }
949 1.1 itojun
950 1.1 itojun #if 0
951 1.1 itojun static void
952 1.1 itojun shpcic_wait_ready(h)
953 1.1 itojun struct shpcic_handle *h;
954 1.1 itojun {
955 1.1 itojun int i;
956 1.1 itojun
957 1.1 itojun for (i = 0; i < 10000; i++) {
958 1.1 itojun if (shpcic_read(h, SHPCIC_IF_STATUS) & SHPCIC_IF_STATUS_READY)
959 1.1 itojun return;
960 1.1 itojun delay(500);
961 1.1 itojun #ifdef SHPCICDEBUG
962 1.1 itojun if (shpcic_debug) {
963 1.1 itojun if ((i>5000) && (i%100 == 99))
964 1.1 itojun printf(".");
965 1.1 itojun }
966 1.1 itojun #endif
967 1.1 itojun }
968 1.1 itojun
969 1.1 itojun #ifdef DIAGNOSTIC
970 1.1 itojun printf("shpcic_wait_ready: ready never happened, status = %02x\n",
971 1.1 itojun shpcic_read(h, SHPCIC_IF_STATUS));
972 1.1 itojun #endif
973 1.1 itojun }
974 1.1 itojun #endif
975 1.1 itojun
976 1.1 itojun void
977 1.1 itojun shpcic_chip_socket_enable(pch)
978 1.1 itojun pcmcia_chipset_handle_t pch;
979 1.1 itojun {
980 1.1 itojun #if 0
981 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
982 1.1 itojun int cardtype, reg, win;
983 1.1 itojun
984 1.1 itojun /* this bit is mostly stolen from shpcic_attach_card */
985 1.1 itojun
986 1.1 itojun /* power down the socket to reset it, clear the card reset pin */
987 1.1 itojun
988 1.1 itojun shpcic_write(h, SHPCIC_PWRCTL, 0);
989 1.1 itojun
990 1.1 itojun /*
991 1.1 itojun * wait 300ms until power fails (Tpf). Then, wait 100ms since
992 1.1 itojun * we are changing Vcc (Toff).
993 1.1 itojun */
994 1.1 itojun delay((300 + 100) * 1000);
995 1.1 itojun
996 1.1 itojun #ifdef VADEM_POWER_HACK
997 1.1 itojun bus_space_write_1(h->sc->iot, h->sc->ioh, SHPCIC_REG_INDEX, 0x0e);
998 1.1 itojun bus_space_write_1(h->sc->iot, h->sc->ioh, SHPCIC_REG_INDEX, 0x37);
999 1.1 itojun printf("prcr = %02x\n", shpcic_read(h, 0x02));
1000 1.1 itojun printf("cvsr = %02x\n", shpcic_read(h, 0x2f));
1001 1.1 itojun printf("DANGER WILL ROBINSON! Changing voltage select!\n");
1002 1.1 itojun shpcic_write(h, 0x2f, shpcic_read(h, 0x2f) & ~0x03);
1003 1.1 itojun printf("cvsr = %02x\n", shpcic_read(h, 0x2f));
1004 1.1 itojun #endif
1005 1.1 itojun
1006 1.1 itojun /* power up the socket */
1007 1.1 itojun
1008 1.1 itojun shpcic_write(h, SHPCIC_PWRCTL, SHPCIC_PWRCTL_DISABLE_RESETDRV
1009 1.1 itojun | SHPCIC_PWRCTL_PWR_ENABLE);
1010 1.1 itojun
1011 1.1 itojun /*
1012 1.1 itojun * wait 100ms until power raise (Tpr) and 20ms to become
1013 1.1 itojun * stable (Tsu(Vcc)).
1014 1.1 itojun *
1015 1.1 itojun * some machines require some more time to be settled
1016 1.1 itojun * (300ms is added here).
1017 1.1 itojun */
1018 1.1 itojun delay((100 + 20 + 300) * 1000);
1019 1.1 itojun
1020 1.1 itojun shpcic_write(h, SHPCIC_PWRCTL, SHPCIC_PWRCTL_DISABLE_RESETDRV | SHPCIC_PWRCTL_OE
1021 1.1 itojun | SHPCIC_PWRCTL_PWR_ENABLE);
1022 1.1 itojun shpcic_write(h, SHPCIC_INTR, 0);
1023 1.1 itojun
1024 1.1 itojun /*
1025 1.1 itojun * hold RESET at least 10us.
1026 1.1 itojun */
1027 1.1 itojun delay(10);
1028 1.1 itojun
1029 1.1 itojun /* clear the reset flag */
1030 1.1 itojun
1031 1.1 itojun shpcic_write(h, SHPCIC_INTR, SHPCIC_INTR_RESET);
1032 1.1 itojun
1033 1.1 itojun /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
1034 1.1 itojun
1035 1.1 itojun delay(20000);
1036 1.1 itojun
1037 1.1 itojun /* wait for the chip to finish initializing */
1038 1.1 itojun
1039 1.1 itojun #ifdef DIAGNOSTIC
1040 1.1 itojun reg = shpcic_read(h, SHPCIC_IF_STATUS);
1041 1.1 itojun if (!(reg & SHPCIC_IF_STATUS_POWERACTIVE)) {
1042 1.1 itojun printf("shpcic_chip_socket_enable: status %x", reg);
1043 1.1 itojun }
1044 1.1 itojun #endif
1045 1.1 itojun
1046 1.1 itojun shpcic_wait_ready(h);
1047 1.1 itojun
1048 1.1 itojun /* zero out the address windows */
1049 1.1 itojun
1050 1.1 itojun shpcic_write(h, SHPCIC_ADDRWIN_ENABLE, 0);
1051 1.1 itojun
1052 1.1 itojun /* set the card type */
1053 1.1 itojun
1054 1.1 itojun cardtype = pcmcia_card_gettype(h->pcmcia);
1055 1.1 itojun
1056 1.1 itojun reg = shpcic_read(h, SHPCIC_INTR);
1057 1.1 itojun reg &= ~(SHPCIC_INTR_CARDTYPE_MASK | SHPCIC_INTR_IRQ_MASK | SHPCIC_INTR_ENABLE);
1058 1.1 itojun reg |= ((cardtype == PCMCIA_IFTYPE_IO) ?
1059 1.1 itojun SHPCIC_INTR_CARDTYPE_IO :
1060 1.1 itojun SHPCIC_INTR_CARDTYPE_MEM);
1061 1.1 itojun reg |= h->ih_irq;
1062 1.1 itojun shpcic_write(h, SHPCIC_INTR, reg);
1063 1.1 itojun
1064 1.1 itojun DPRINTF(("%s: shpcic_chip_socket_enable %02x cardtype %s %02x\n",
1065 1.1 itojun h->sc->dev.dv_xname, h->sock,
1066 1.1 itojun ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg));
1067 1.1 itojun
1068 1.1 itojun /* reinstall all the memory and io mappings */
1069 1.1 itojun
1070 1.1 itojun for (win = 0; win < SHPCIC_MEM_WINS; win++)
1071 1.1 itojun if (h->memalloc & (1 << win))
1072 1.1 itojun shpcic_chip_do_mem_map(h, win);
1073 1.1 itojun
1074 1.1 itojun for (win = 0; win < SHPCIC_IO_WINS; win++)
1075 1.1 itojun if (h->ioalloc & (1 << win))
1076 1.1 itojun shpcic_chip_do_io_map(h, win);
1077 1.1 itojun #endif
1078 1.1 itojun }
1079 1.1 itojun
1080 1.1 itojun void
1081 1.1 itojun shpcic_chip_socket_disable(pch)
1082 1.1 itojun pcmcia_chipset_handle_t pch;
1083 1.1 itojun {
1084 1.1 itojun #if 0
1085 1.1 itojun struct shpcic_handle *h = (struct shpcic_handle *) pch;
1086 1.1 itojun
1087 1.1 itojun DPRINTF(("shpcic_chip_socket_disable\n"));
1088 1.1 itojun
1089 1.1 itojun /* power down the socket */
1090 1.1 itojun
1091 1.1 itojun shpcic_write(h, SHPCIC_PWRCTL, 0);
1092 1.1 itojun
1093 1.1 itojun /*
1094 1.1 itojun * wait 300ms until power fails (Tpf).
1095 1.1 itojun */
1096 1.1 itojun delay(300 * 1000);
1097 1.1 itojun #endif
1098 1.1 itojun }
1099