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