Annotation of sys/dev/ic/i82365.c, Revision 1.1.1.1
1.1 nbrk 1: /* $OpenBSD: i82365.c,v 1.25 2005/11/23 11:39:37 mickey Exp $ */
2: /* $NetBSD: i82365.c,v 1.10 1998/06/09 07:36:55 thorpej Exp $ */
3:
4: /*
5: * Copyright (c) 1997 Marc Horowitz. All rights reserved.
6: *
7: * Redistribution and use in source and binary forms, with or without
8: * modification, are permitted provided that the following conditions
9: * are met:
10: * 1. Redistributions of source code must retain the above copyright
11: * notice, this list of conditions and the following disclaimer.
12: * 2. Redistributions in binary form must reproduce the above copyright
13: * notice, this list of conditions and the following disclaimer in the
14: * documentation and/or other materials provided with the distribution.
15: * 3. All advertising materials mentioning features or use of this software
16: * must display the following acknowledgement:
17: * This product includes software developed by Marc Horowitz.
18: * 4. The name of the author may not be used to endorse or promote products
19: * derived from this software without specific prior written permission.
20: *
21: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
22: * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
23: * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
24: * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
25: * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
26: * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27: * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28: * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29: * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
30: * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31: */
32:
33: #include <sys/types.h>
34: #include <sys/param.h>
35: #include <sys/systm.h>
36: #include <sys/device.h>
37: #include <sys/extent.h>
38: #include <sys/kernel.h>
39: #include <sys/malloc.h>
40: #include <sys/kthread.h>
41:
42: #include <uvm/uvm_extern.h>
43:
44: #include <machine/bus.h>
45: #include <machine/intr.h>
46:
47: #include <dev/pcmcia/pcmciareg.h>
48: #include <dev/pcmcia/pcmciavar.h>
49:
50: #include <dev/ic/i82365reg.h>
51: #include <dev/ic/i82365var.h>
52:
53: #ifdef PCICDEBUG
54: #define DPRINTF(arg) printf arg;
55: #else
56: #define DPRINTF(arg)
57: #endif
58:
59: #define PCIC_VENDOR_UNKNOWN 0
60: #define PCIC_VENDOR_I82365SLR0 1
61: #define PCIC_VENDOR_I82365SLR1 2
62: #define PCIC_VENDOR_I82365SLR2 3
63: #define PCIC_VENDOR_CIRRUS_PD6710 4
64: #define PCIC_VENDOR_CIRRUS_PD672X 5
65: #define PCIC_VENDOR_VADEM_VG468 6
66: #define PCIC_VENDOR_VADEM_VG469 7
67:
68: static char *pcic_vendor_to_string[] = {
69: "Unknown",
70: "Intel 82365SL rev 0",
71: "Intel 82365SL rev 1",
72: "Intel 82365SL rev 2",
73: "Cirrus PD6710",
74: "Cirrus PD672X",
75: "Vadem VG468",
76: "Vadem VG469",
77: };
78:
79: /*
80: * Individual drivers will allocate their own memory and io regions. Memory
81: * regions must be a multiple of 4k, aligned on a 4k boundary.
82: */
83:
84: #define PCIC_MEM_ALIGN PCIC_MEM_PAGESIZE
85:
86: void pcic_attach_socket(struct pcic_handle *);
87: void pcic_init_socket(struct pcic_handle *);
88:
89: int pcic_submatch(struct device *, void *, void *);
90: int pcic_print(void *arg, const char *pnp);
91: int pcic_intr_socket(struct pcic_handle *);
92:
93: void pcic_attach_card(struct pcic_handle *);
94: void pcic_detach_card(struct pcic_handle *, int);
95: void pcic_deactivate_card(struct pcic_handle *);
96:
97: void pcic_chip_do_mem_map(struct pcic_handle *, int);
98: void pcic_chip_do_io_map(struct pcic_handle *, int);
99:
100: void pcic_create_event_thread(void *);
101: void pcic_event_thread(void *);
102: void pcic_event_process(struct pcic_handle *, struct pcic_event *);
103: void pcic_queue_event(struct pcic_handle *, int);
104:
105: void pcic_wait_ready(struct pcic_handle *);
106:
107: u_int8_t st_pcic_read(struct pcic_handle *, int);
108: void st_pcic_write(struct pcic_handle *, int, int);
109:
110: struct cfdriver pcic_cd = {
111: NULL, "pcic", DV_DULL
112: };
113:
114: int
115: pcic_ident_ok(ident)
116: int ident;
117: {
118: /* this is very empirical and heuristic */
119:
120: if (ident == 0 || ident == 0xff || (ident & PCIC_IDENT_ZERO))
121: return (0);
122:
123: if ((ident & PCIC_IDENT_IFTYPE_MASK) != PCIC_IDENT_IFTYPE_MEM_AND_IO) {
124: #ifdef DIAGNOSTIC
125: printf("pcic: does not support memory and I/O cards, "
126: "ignored (ident=%0x)\n", ident);
127: #endif
128: return (0);
129: }
130: return (1);
131: }
132:
133: int
134: pcic_vendor(h)
135: struct pcic_handle *h;
136: {
137: int vendor, reg;
138:
139: /*
140: * the chip_id of the cirrus toggles between 11 and 00 after a write.
141: * weird.
142: */
143:
144: pcic_write(h, PCIC_CIRRUS_CHIP_INFO, 0);
145: reg = pcic_read(h, -1);
146:
147: if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) ==
148: PCIC_CIRRUS_CHIP_INFO_CHIP_ID) {
149: reg = pcic_read(h, -1);
150: if ((reg & PCIC_CIRRUS_CHIP_INFO_CHIP_ID) == 0) {
151: if (reg & PCIC_CIRRUS_CHIP_INFO_SLOTS)
152: return (PCIC_VENDOR_CIRRUS_PD672X);
153: else
154: return (PCIC_VENDOR_CIRRUS_PD6710);
155: }
156: }
157:
158: reg = pcic_read(h, PCIC_IDENT);
159:
160: switch (reg) {
161: case PCIC_IDENT_REV_I82365SLR0:
162: vendor = PCIC_VENDOR_I82365SLR0;
163: break;
164: case PCIC_IDENT_REV_I82365SLR1:
165: vendor = PCIC_VENDOR_I82365SLR1;
166: break;
167: case PCIC_IDENT_REV_I82365SLR2:
168: vendor = PCIC_VENDOR_I82365SLR2;
169: break;
170: default:
171: vendor = PCIC_VENDOR_UNKNOWN;
172: break;
173: }
174:
175: pcic_write(h, 0x0e, -1);
176: pcic_write(h, 0x37, -1);
177:
178: reg = pcic_read(h, PCIC_VG468_MISC);
179: reg |= PCIC_VG468_MISC_VADEMREV;
180: pcic_write(h, PCIC_VG468_MISC, reg);
181:
182: reg = pcic_read(h, PCIC_IDENT);
183:
184: if (reg & PCIC_IDENT_VADEM_MASK) {
185: if ((reg & 7) >= 4)
186: vendor = PCIC_VENDOR_VADEM_VG469;
187: else
188: vendor = PCIC_VENDOR_VADEM_VG468;
189:
190: reg = pcic_read(h, PCIC_VG468_MISC);
191: reg &= ~PCIC_VG468_MISC_VADEMREV;
192: pcic_write(h, PCIC_VG468_MISC, reg);
193: }
194:
195: return (vendor);
196: }
197:
198: void
199: pcic_attach(sc)
200: struct pcic_softc *sc;
201: {
202: int vendor, count, i, reg;
203:
204: /* now check for each controller/socket */
205:
206: /*
207: * this could be done with a loop, but it would violate the
208: * abstraction
209: */
210:
211: count = 0;
212:
213: DPRINTF(("pcic ident regs:"));
214:
215: sc->handle[0].ph_parent = (struct device *)sc;
216: sc->handle[0].sock = C0SA;
217: /* initialise pcic_read and pcic_write functions */
218: sc->handle[0].ph_read = st_pcic_read;
219: sc->handle[0].ph_write = st_pcic_write;
220: sc->handle[0].ph_bus_t = sc->iot;
221: sc->handle[0].ph_bus_h = sc->ioh;
222: if (pcic_ident_ok(reg = pcic_read(&sc->handle[0], PCIC_IDENT))) {
223: sc->handle[0].flags = PCIC_FLAG_SOCKETP;
224: count++;
225: } else {
226: sc->handle[0].flags = 0;
227: }
228: sc->handle[0].laststate = PCIC_LASTSTATE_EMPTY;
229:
230: DPRINTF((" 0x%02x", reg));
231:
232: sc->handle[1].ph_parent = (struct device *)sc;
233: sc->handle[1].sock = C0SB;
234: /* initialise pcic_read and pcic_write functions */
235: sc->handle[1].ph_read = st_pcic_read;
236: sc->handle[1].ph_write = st_pcic_write;
237: sc->handle[1].ph_bus_t = sc->iot;
238: sc->handle[1].ph_bus_h = sc->ioh;
239: if (pcic_ident_ok(reg = pcic_read(&sc->handle[1], PCIC_IDENT))) {
240: sc->handle[1].flags = PCIC_FLAG_SOCKETP;
241: count++;
242: } else {
243: sc->handle[1].flags = 0;
244: }
245: sc->handle[1].laststate = PCIC_LASTSTATE_EMPTY;
246:
247: DPRINTF((" 0x%02x", reg));
248:
249: /*
250: * The CL-PD6729 has only one controller and always returns 0
251: * if you try to read from the second one. Maybe pcic_ident_ok
252: * shouldn't accept 0?
253: */
254: sc->handle[2].ph_parent = (struct device *)sc;
255: sc->handle[2].sock = C1SA;
256: /* initialise pcic_read and pcic_write functions */
257: sc->handle[2].ph_read = st_pcic_read;
258: sc->handle[2].ph_write = st_pcic_write;
259: sc->handle[2].ph_bus_t = sc->iot;
260: sc->handle[2].ph_bus_h = sc->ioh;
261: if (pcic_vendor(&sc->handle[0]) != PCIC_VENDOR_CIRRUS_PD672X ||
262: pcic_read(&sc->handle[2], PCIC_IDENT) != 0) {
263: if (pcic_ident_ok(reg = pcic_read(&sc->handle[2],
264: PCIC_IDENT))) {
265: sc->handle[2].flags = PCIC_FLAG_SOCKETP;
266: count++;
267: } else {
268: sc->handle[2].flags = 0;
269: }
270: sc->handle[2].laststate = PCIC_LASTSTATE_EMPTY;
271:
272: DPRINTF((" 0x%02x", reg));
273:
274: sc->handle[3].ph_parent = (struct device *)sc;
275: sc->handle[3].sock = C1SB;
276: /* initialise pcic_read and pcic_write functions */
277: sc->handle[3].ph_read = st_pcic_read;
278: sc->handle[3].ph_write = st_pcic_write;
279: sc->handle[3].ph_bus_t = sc->iot;
280: sc->handle[3].ph_bus_h = sc->ioh;
281: if (pcic_ident_ok(reg = pcic_read(&sc->handle[3],
282: PCIC_IDENT))) {
283: sc->handle[3].flags = PCIC_FLAG_SOCKETP;
284: count++;
285: } else {
286: sc->handle[3].flags = 0;
287: }
288: sc->handle[3].laststate = PCIC_LASTSTATE_EMPTY;
289:
290: DPRINTF((" 0x%02x\n", reg));
291: } else {
292: sc->handle[2].flags = 0;
293: sc->handle[3].flags = 0;
294: }
295:
296: if (count == 0)
297: return;
298:
299: /* establish the interrupt */
300:
301: /* XXX block interrupts? */
302:
303: for (i = 0; i < PCIC_NSLOTS; i++) {
304: /*
305: * this should work, but w/o it, setting tty flags hangs at
306: * boot time.
307: */
308: if (sc->handle[i].flags & PCIC_FLAG_SOCKETP) {
309: SIMPLEQ_INIT(&sc->handle[i].events);
310: pcic_write(&sc->handle[i], PCIC_CSC_INTR, 0);
311: pcic_read(&sc->handle[i], PCIC_CSC);
312: }
313: }
314:
315: for (i = 0; i < PCIC_NSLOTS; i += 2) {
316: if ((sc->handle[i+0].flags & PCIC_FLAG_SOCKETP) ||
317: (sc->handle[i+1].flags & PCIC_FLAG_SOCKETP)) {
318: vendor = pcic_vendor(&sc->handle[i]);
319:
320: printf("%s controller %d: <%s> has socket",
321: sc->dev.dv_xname, i/2,
322: pcic_vendor_to_string[vendor]);
323:
324: if ((sc->handle[i+0].flags & PCIC_FLAG_SOCKETP) &&
325: (sc->handle[i+1].flags & PCIC_FLAG_SOCKETP))
326: printf("s A and B\n");
327: else if (sc->handle[i+0].flags & PCIC_FLAG_SOCKETP)
328: printf(" A only\n");
329: else
330: printf(" B only\n");
331:
332: if (sc->handle[i+0].flags & PCIC_FLAG_SOCKETP)
333: sc->handle[i+0].vendor = vendor;
334: if (sc->handle[i+1].flags & PCIC_FLAG_SOCKETP)
335: sc->handle[i+1].vendor = vendor;
336: }
337: }
338: }
339:
340: void
341: pcic_attach_sockets(sc)
342: struct pcic_softc *sc;
343: {
344: int i;
345:
346: for (i = 0; i < PCIC_NSLOTS; i++)
347: if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
348: pcic_attach_socket(&sc->handle[i]);
349: }
350:
351: void
352: pcic_attach_socket(h)
353: struct pcic_handle *h;
354: {
355: struct pcmciabus_attach_args paa;
356: struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
357:
358: /* initialize the rest of the handle */
359:
360: h->shutdown = 0;
361: h->memalloc = 0;
362: h->ioalloc = 0;
363: h->ih_irq = 0;
364:
365: /* now, config one pcmcia device per socket */
366:
367: paa.paa_busname = "pcmcia";
368: paa.pct = (pcmcia_chipset_tag_t) sc->pct;
369: paa.pch = (pcmcia_chipset_handle_t) h;
370: paa.iobase = sc->iobase;
371: paa.iosize = sc->iosize;
372:
373: h->pcmcia = config_found_sm(&sc->dev, &paa, pcic_print,
374: pcic_submatch);
375:
376: /* if there's actually a pcmcia device attached, initialize the slot */
377:
378: if (h->pcmcia)
379: pcic_init_socket(h);
380: else
381: h->flags &= ~PCIC_FLAG_SOCKETP;
382: }
383:
384: void
385: pcic_create_event_thread(arg)
386: void *arg;
387: {
388: struct pcic_handle *h = arg;
389: const char *cs;
390:
391: switch (h->sock) {
392: case C0SA:
393: cs = "0,0";
394: break;
395: case C0SB:
396: cs = "0,1";
397: break;
398: case C1SA:
399: cs = "1,0";
400: break;
401: case C1SB:
402: cs = "1,1";
403: break;
404: default:
405: panic("pcic_create_event_thread: unknown pcic socket");
406: }
407:
408: if (kthread_create(pcic_event_thread, h, &h->event_thread,
409: "%s,%s", h->ph_parent->dv_xname, cs)) {
410: printf("%s: unable to create event thread for sock 0x%02x\n",
411: h->ph_parent->dv_xname, h->sock);
412: panic("pcic_create_event_thread");
413: }
414: }
415:
416: void
417: pcic_event_thread(arg)
418: void *arg;
419: {
420: struct pcic_handle *h = arg;
421: struct pcic_event *pe;
422: int s;
423: struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
424:
425: while (h->shutdown == 0) {
426: s = splhigh();
427: if ((pe = SIMPLEQ_FIRST(&h->events)) == NULL) {
428: splx(s);
429: (void) tsleep(&h->events, PWAIT, "pcicev", 0);
430: continue;
431: } else {
432: splx(s);
433: /* sleep .25s to be enqueued chatterling interrupts */
434: (void) tsleep((caddr_t)pcic_event_thread, PWAIT,
435: "pcicss", hz/4);
436: }
437: pcic_event_process(h, pe);
438: }
439:
440: h->event_thread = NULL;
441:
442: /* In case parent is waiting for us to exit. */
443: wakeup(sc);
444:
445: kthread_exit(0);
446: }
447:
448: void
449: pcic_event_process(h, pe)
450: struct pcic_handle *h;
451: struct pcic_event *pe;
452: {
453: int s;
454:
455: s = splhigh();
456: SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
457: splx(s);
458:
459: switch (pe->pe_type) {
460: case PCIC_EVENT_INSERTION:
461: s = splhigh();
462: while (1) {
463: struct pcic_event *pe1, *pe2;
464:
465: if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
466: break;
467: if (pe1->pe_type != PCIC_EVENT_REMOVAL)
468: break;
469: if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
470: break;
471: if (pe2->pe_type == PCIC_EVENT_INSERTION) {
472: SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
473: free(pe1, M_TEMP);
474: SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
475: free(pe2, M_TEMP);
476: }
477: }
478: splx(s);
479:
480: DPRINTF(("%s: insertion event\n", h->ph_parent->dv_xname));
481: pcic_attach_card(h);
482: break;
483:
484: case PCIC_EVENT_REMOVAL:
485: s = splhigh();
486: while (1) {
487: struct pcic_event *pe1, *pe2;
488:
489: if ((pe1 = SIMPLEQ_FIRST(&h->events)) == NULL)
490: break;
491: if (pe1->pe_type != PCIC_EVENT_INSERTION)
492: break;
493: if ((pe2 = SIMPLEQ_NEXT(pe1, pe_q)) == NULL)
494: break;
495: if (pe2->pe_type == PCIC_EVENT_REMOVAL) {
496: SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
497: free(pe1, M_TEMP);
498: SIMPLEQ_REMOVE_HEAD(&h->events, pe_q);
499: free(pe2, M_TEMP);
500: }
501: }
502: splx(s);
503:
504: DPRINTF(("%s: removal event\n", h->ph_parent->dv_xname));
505: pcic_detach_card(h, DETACH_FORCE);
506: break;
507:
508: default:
509: panic("pcic_event_thread: unknown event %d", pe->pe_type);
510: }
511: free(pe, M_TEMP);
512: }
513:
514: void
515: pcic_init_socket(h)
516: struct pcic_handle *h;
517: {
518: int reg;
519: struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
520:
521: /*
522: * queue creation of a kernel thread to handle insert/removal events.
523: */
524: #ifdef DIAGNOSTIC
525: if (h->event_thread != NULL)
526: panic("pcic_attach_socket: event thread");
527: #endif
528: kthread_create_deferred(pcic_create_event_thread, h);
529:
530: /* set up the card to interrupt on card detect */
531:
532: pcic_write(h, PCIC_CSC_INTR, (sc->irq << PCIC_CSC_INTR_IRQ_SHIFT) |
533: PCIC_CSC_INTR_CD_ENABLE);
534: pcic_write(h, PCIC_INTR, 0);
535: pcic_read(h, PCIC_CSC);
536:
537: /* unsleep the cirrus controller */
538:
539: if ((h->vendor == PCIC_VENDOR_CIRRUS_PD6710) ||
540: (h->vendor == PCIC_VENDOR_CIRRUS_PD672X)) {
541: reg = pcic_read(h, PCIC_CIRRUS_MISC_CTL_2);
542: if (reg & PCIC_CIRRUS_MISC_CTL_2_SUSPEND) {
543: DPRINTF(("%s: socket %02x was suspended\n",
544: h->ph_parent->dv_xname, h->sock));
545: reg &= ~PCIC_CIRRUS_MISC_CTL_2_SUSPEND;
546: pcic_write(h, PCIC_CIRRUS_MISC_CTL_2, reg);
547: }
548: }
549: /* if there's a card there, then attach it. */
550:
551: reg = pcic_read(h, PCIC_IF_STATUS);
552:
553: if ((reg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
554: PCIC_IF_STATUS_CARDDETECT_PRESENT) {
555: pcic_attach_card(h);
556: h->laststate = PCIC_LASTSTATE_PRESENT;
557: } else
558: h->laststate = PCIC_LASTSTATE_EMPTY;
559: }
560:
561: int
562: pcic_submatch(parent, match, aux)
563: struct device *parent;
564: void *match, *aux;
565: {
566: struct cfdata *cf = match;
567: struct pcmciabus_attach_args *paa = aux;
568: struct pcic_handle *h = (struct pcic_handle *) paa->pch;
569:
570: switch (h->sock) {
571: case C0SA:
572: if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
573: -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
574: cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 0)
575: return 0;
576: if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
577: -1 /* PCICCF_SOCKET_DEFAULT */ &&
578: cf->cf_loc[1 /* PCICCF_SOCKET */] != 0)
579: return 0;
580:
581: break;
582: case C0SB:
583: if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
584: -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
585: cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 0)
586: return 0;
587: if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
588: -1 /* PCICCF_SOCKET_DEFAULT */ &&
589: cf->cf_loc[1 /* PCICCF_SOCKET */] != 1)
590: return 0;
591:
592: break;
593: case C1SA:
594: if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
595: -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
596: cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 1)
597: return 0;
598: if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
599: -1 /* PCICCF_SOCKET_DEFAULT */ &&
600: cf->cf_loc[1 /* PCICCF_SOCKET */] != 0)
601: return 0;
602:
603: break;
604: case C1SB:
605: if (cf->cf_loc[0 /* PCICCF_CONTROLLER */] !=
606: -1 /* PCICCF_CONTROLLER_DEFAULT */ &&
607: cf->cf_loc[0 /* PCICCF_CONTROLLER */] != 1)
608: return 0;
609: if (cf->cf_loc[1 /* PCICCF_SOCKET */] !=
610: -1 /* PCICCF_SOCKET_DEFAULT */ &&
611: cf->cf_loc[1 /* PCICCF_SOCKET */] != 1)
612: return 0;
613:
614: break;
615: default:
616: panic("unknown pcic socket");
617: }
618:
619: return ((*cf->cf_attach->ca_match)(parent, cf, aux));
620: }
621:
622: int
623: pcic_print(arg, pnp)
624: void *arg;
625: const char *pnp;
626: {
627: struct pcmciabus_attach_args *paa = arg;
628: struct pcic_handle *h = (struct pcic_handle *) paa->pch;
629:
630: /* Only "pcmcia"s can attach to "pcic"s... easy. */
631: if (pnp)
632: printf("pcmcia at %s", pnp);
633:
634: switch (h->sock) {
635: case C0SA:
636: printf(" controller 0 socket 0");
637: break;
638: case C0SB:
639: printf(" controller 0 socket 1");
640: break;
641: case C1SA:
642: printf(" controller 1 socket 0");
643: break;
644: case C1SB:
645: printf(" controller 1 socket 1");
646: break;
647: default:
648: panic("unknown pcic socket");
649: }
650:
651: return (UNCONF);
652: }
653:
654: int
655: pcic_intr(arg)
656: void *arg;
657: {
658: struct pcic_softc *sc = arg;
659: int i, ret = 0;
660:
661: DPRINTF(("%s: intr\n", sc->dev.dv_xname));
662:
663: for (i = 0; i < PCIC_NSLOTS; i++)
664: if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
665: ret += pcic_intr_socket(&sc->handle[i]);
666:
667: return (ret ? 1 : 0);
668: }
669:
670: void
671: pcic_poll_intr(arg)
672: void *arg;
673: {
674: struct pcic_softc *sc = arg;
675: int i, s;
676:
677: /*
678: * Since we're polling, we aren't in interrupt context, so block any
679: * actual interrupts coming from the pcic.
680: */
681: s = spltty();
682:
683: for (i = 0; i < PCIC_NSLOTS; i++)
684: if (sc->handle[i].flags & PCIC_FLAG_SOCKETP)
685: pcic_intr_socket(&sc->handle[i]);
686:
687: timeout_add(&sc->poll_timeout, hz / 2);
688:
689: splx(s);
690: }
691:
692: int
693: pcic_intr_socket(h)
694: struct pcic_handle *h;
695: {
696: int cscreg;
697:
698: cscreg = pcic_read(h, PCIC_CSC);
699:
700: cscreg &= (PCIC_CSC_GPI |
701: PCIC_CSC_CD |
702: PCIC_CSC_READY |
703: PCIC_CSC_BATTWARN |
704: PCIC_CSC_BATTDEAD);
705:
706: if (cscreg & PCIC_CSC_GPI) {
707: DPRINTF(("%s: %02x GPI\n", h->ph_parent->dv_xname, h->sock));
708: }
709: if (cscreg & PCIC_CSC_CD) {
710: int statreg;
711:
712: statreg = pcic_read(h, PCIC_IF_STATUS);
713:
714: DPRINTF(("%s: %02x CD %x\n", h->ph_parent->dv_xname, h->sock,
715: statreg));
716:
717: if ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) ==
718: PCIC_IF_STATUS_CARDDETECT_PRESENT) {
719: if (h->laststate != PCIC_LASTSTATE_PRESENT) {
720: DPRINTF(("%s: enqueing INSERTION event\n",
721: h->ph_parent->dv_xname));
722: pcic_queue_event(h, PCIC_EVENT_INSERTION);
723: }
724: h->laststate = PCIC_LASTSTATE_PRESENT;
725: } else {
726: if (h->laststate == PCIC_LASTSTATE_PRESENT) {
727: /* Deactivate the card now. */
728: DPRINTF(("%s: deactivating card\n",
729: h->ph_parent->dv_xname));
730: pcic_deactivate_card(h);
731:
732: DPRINTF(("%s: enqueing REMOVAL event\n",
733: h->ph_parent->dv_xname));
734: pcic_queue_event(h, PCIC_EVENT_REMOVAL);
735: }
736: h->laststate =
737: ((statreg & PCIC_IF_STATUS_CARDDETECT_MASK) == 0)
738: ? PCIC_LASTSTATE_EMPTY : PCIC_LASTSTATE_HALF;
739: }
740: }
741: if (cscreg & PCIC_CSC_READY) {
742: DPRINTF(("%s: %02x READY\n", h->ph_parent->dv_xname, h->sock));
743: /* shouldn't happen */
744: }
745: if (cscreg & PCIC_CSC_BATTWARN) {
746: DPRINTF(("%s: %02x BATTWARN\n", h->ph_parent->dv_xname,
747: h->sock));
748: }
749: if (cscreg & PCIC_CSC_BATTDEAD) {
750: DPRINTF(("%s: %02x BATTDEAD\n", h->ph_parent->dv_xname,
751: h->sock));
752: }
753: return (cscreg ? 1 : 0);
754: }
755:
756: void
757: pcic_queue_event(h, event)
758: struct pcic_handle *h;
759: int event;
760: {
761: struct pcic_event *pe;
762: int s;
763:
764: pe = malloc(sizeof(*pe), M_TEMP, M_NOWAIT);
765: if (pe == NULL)
766: panic("pcic_queue_event: can't allocate event");
767:
768: pe->pe_type = event;
769: s = splhigh();
770: SIMPLEQ_INSERT_TAIL(&h->events, pe, pe_q);
771: splx(s);
772: wakeup(&h->events);
773: }
774:
775: void
776: pcic_attach_card(h)
777: struct pcic_handle *h;
778: {
779: if (h->flags & PCIC_FLAG_CARDP)
780: panic("pcic_attach_card: already attached");
781:
782: /* call the MI attach function */
783: pcmcia_card_attach(h->pcmcia);
784:
785: h->flags |= PCIC_FLAG_CARDP;
786: }
787:
788: void
789: pcic_detach_card(h, flags)
790: struct pcic_handle *h;
791: int flags; /* DETACH_* */
792: {
793:
794: if (h->flags & PCIC_FLAG_CARDP) {
795: h->flags &= ~PCIC_FLAG_CARDP;
796:
797: /* call the MI detach function */
798: pcmcia_card_detach(h->pcmcia, flags);
799: } else {
800: DPRINTF(("pcic_detach_card: already detached"));
801: }
802: }
803:
804: void
805: pcic_deactivate_card(h)
806: struct pcic_handle *h;
807: {
808: struct device *dev = (struct device *)h->pcmcia;
809:
810: /*
811: * At suspend, apm deactivates any connected cards. If we've woken up
812: * to find a previously-connected device missing, and we're detaching
813: * it, we don't want to deactivate it again.
814: */
815: if (dev->dv_flags & DVF_ACTIVE)
816: pcmcia_card_deactivate(h->pcmcia);
817:
818: /* power down the socket */
819: pcic_write(h, PCIC_PWRCTL, 0);
820:
821: /* reset the socket */
822: pcic_write(h, PCIC_INTR, 0);
823: }
824:
825: /*
826: * The pcic_power() function must execute BEFORE the pcmcia_power() hooks.
827: * During suspend, a card may have been ejected. If so, we must detach it
828: * completely before pcmcia_power() tries to activate it. Attempting to
829: * activate a card that isn't there is bad news.
830: */
831: void
832: pcic_power(why, arg)
833: int why;
834: void *arg;
835: {
836: struct pcic_handle *h = (struct pcic_handle *)arg;
837: struct pcic_softc *sc = (struct pcic_softc *)h->ph_parent;
838: struct pcic_event *pe;
839:
840: if (why != PWR_RESUME) {
841: if (timeout_pending(&sc->poll_timeout))
842: timeout_del(&sc->poll_timeout);
843: }
844: else {
845: pcic_intr_socket(h);
846:
847: while ((pe = SIMPLEQ_FIRST(&h->events)))
848: pcic_event_process(h, pe);
849:
850: timeout_add(&sc->poll_timeout, hz / 2);
851: }
852: }
853:
854: int
855: pcic_chip_mem_alloc(pch, size, pcmhp)
856: pcmcia_chipset_handle_t pch;
857: bus_size_t size;
858: struct pcmcia_mem_handle *pcmhp;
859: {
860: struct pcic_handle *h = (struct pcic_handle *) pch;
861: bus_space_handle_t memh;
862: bus_addr_t addr;
863: bus_size_t sizepg;
864: int i, mask, mhandle;
865: struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
866:
867: /* out of sc->memh, allocate as many pages as necessary */
868:
869: /* convert size to PCIC pages */
870: sizepg = (size + (PCIC_MEM_ALIGN - 1)) / PCIC_MEM_ALIGN;
871: if (sizepg > PCIC_MAX_MEM_PAGES)
872: return (1);
873:
874: mask = (1 << sizepg) - 1;
875:
876: addr = 0; /* XXX gcc -Wuninitialized */
877: mhandle = 0; /* XXX gcc -Wuninitialized */
878:
879: for (i = 0; i <= PCIC_MAX_MEM_PAGES - sizepg; i++) {
880: if ((sc->subregionmask & (mask << i)) == (mask << i)) {
881: if (bus_space_subregion(sc->memt, sc->memh,
882: i * PCIC_MEM_PAGESIZE,
883: sizepg * PCIC_MEM_PAGESIZE, &memh))
884: return (1);
885: mhandle = mask << i;
886: addr = sc->membase + (i * PCIC_MEM_PAGESIZE);
887: sc->subregionmask &= ~(mhandle);
888: pcmhp->memt = sc->memt;
889: pcmhp->memh = memh;
890: pcmhp->addr = addr;
891: pcmhp->size = size;
892: pcmhp->mhandle = mhandle;
893: pcmhp->realsize = sizepg * PCIC_MEM_PAGESIZE;
894:
895: DPRINTF(("pcic_chip_mem_alloc bus addr 0x%lx+0x%lx\n",
896: (u_long) addr, (u_long) size));
897:
898: return (0);
899: }
900: }
901:
902: return (1);
903: }
904:
905: void
906: pcic_chip_mem_free(pch, pcmhp)
907: pcmcia_chipset_handle_t pch;
908: struct pcmcia_mem_handle *pcmhp;
909: {
910: struct pcic_handle *h = (struct pcic_handle *) pch;
911: struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
912:
913: sc->subregionmask |= pcmhp->mhandle;
914: }
915:
916: static struct mem_map_index_st {
917: int sysmem_start_lsb;
918: int sysmem_start_msb;
919: int sysmem_stop_lsb;
920: int sysmem_stop_msb;
921: int cardmem_lsb;
922: int cardmem_msb;
923: int memenable;
924: } mem_map_index[] = {
925: {
926: PCIC_SYSMEM_ADDR0_START_LSB,
927: PCIC_SYSMEM_ADDR0_START_MSB,
928: PCIC_SYSMEM_ADDR0_STOP_LSB,
929: PCIC_SYSMEM_ADDR0_STOP_MSB,
930: PCIC_CARDMEM_ADDR0_LSB,
931: PCIC_CARDMEM_ADDR0_MSB,
932: PCIC_ADDRWIN_ENABLE_MEM0,
933: },
934: {
935: PCIC_SYSMEM_ADDR1_START_LSB,
936: PCIC_SYSMEM_ADDR1_START_MSB,
937: PCIC_SYSMEM_ADDR1_STOP_LSB,
938: PCIC_SYSMEM_ADDR1_STOP_MSB,
939: PCIC_CARDMEM_ADDR1_LSB,
940: PCIC_CARDMEM_ADDR1_MSB,
941: PCIC_ADDRWIN_ENABLE_MEM1,
942: },
943: {
944: PCIC_SYSMEM_ADDR2_START_LSB,
945: PCIC_SYSMEM_ADDR2_START_MSB,
946: PCIC_SYSMEM_ADDR2_STOP_LSB,
947: PCIC_SYSMEM_ADDR2_STOP_MSB,
948: PCIC_CARDMEM_ADDR2_LSB,
949: PCIC_CARDMEM_ADDR2_MSB,
950: PCIC_ADDRWIN_ENABLE_MEM2,
951: },
952: {
953: PCIC_SYSMEM_ADDR3_START_LSB,
954: PCIC_SYSMEM_ADDR3_START_MSB,
955: PCIC_SYSMEM_ADDR3_STOP_LSB,
956: PCIC_SYSMEM_ADDR3_STOP_MSB,
957: PCIC_CARDMEM_ADDR3_LSB,
958: PCIC_CARDMEM_ADDR3_MSB,
959: PCIC_ADDRWIN_ENABLE_MEM3,
960: },
961: {
962: PCIC_SYSMEM_ADDR4_START_LSB,
963: PCIC_SYSMEM_ADDR4_START_MSB,
964: PCIC_SYSMEM_ADDR4_STOP_LSB,
965: PCIC_SYSMEM_ADDR4_STOP_MSB,
966: PCIC_CARDMEM_ADDR4_LSB,
967: PCIC_CARDMEM_ADDR4_MSB,
968: PCIC_ADDRWIN_ENABLE_MEM4,
969: },
970: };
971:
972: void
973: pcic_chip_do_mem_map(h, win)
974: struct pcic_handle *h;
975: int win;
976: {
977: int reg;
978: int kind = h->mem[win].kind & ~PCMCIA_WIDTH_MEM_MASK;
979: int mem8 =
980: (h->mem[win].kind & PCMCIA_WIDTH_MEM_MASK) == PCMCIA_WIDTH_MEM8
981: || (kind == PCMCIA_MEM_ATTR);
982:
983: pcic_write(h, mem_map_index[win].sysmem_start_lsb,
984: (h->mem[win].addr >> PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
985: pcic_write(h, mem_map_index[win].sysmem_start_msb,
986: ((h->mem[win].addr >> (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
987: PCIC_SYSMEM_ADDRX_START_MSB_ADDR_MASK) |
988: (mem8 ? 0 : PCIC_SYSMEM_ADDRX_START_MSB_DATASIZE_16BIT));
989:
990: pcic_write(h, mem_map_index[win].sysmem_stop_lsb,
991: ((h->mem[win].addr + h->mem[win].size) >>
992: PCIC_SYSMEM_ADDRX_SHIFT) & 0xff);
993: pcic_write(h, mem_map_index[win].sysmem_stop_msb,
994: (((h->mem[win].addr + h->mem[win].size) >>
995: (PCIC_SYSMEM_ADDRX_SHIFT + 8)) &
996: PCIC_SYSMEM_ADDRX_STOP_MSB_ADDR_MASK) |
997: PCIC_SYSMEM_ADDRX_STOP_MSB_WAIT2);
998:
999: pcic_write(h, mem_map_index[win].cardmem_lsb,
1000: (h->mem[win].offset >> PCIC_CARDMEM_ADDRX_SHIFT) & 0xff);
1001: pcic_write(h, mem_map_index[win].cardmem_msb,
1002: ((h->mem[win].offset >> (PCIC_CARDMEM_ADDRX_SHIFT + 8)) &
1003: PCIC_CARDMEM_ADDRX_MSB_ADDR_MASK) |
1004: ((kind == PCMCIA_MEM_ATTR) ?
1005: PCIC_CARDMEM_ADDRX_MSB_REGACTIVE_ATTR : 0));
1006:
1007: reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
1008: reg |= (mem_map_index[win].memenable | PCIC_ADDRWIN_ENABLE_MEMCS16);
1009: pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
1010:
1011: #ifdef PCICDEBUG
1012: {
1013: int r1, r2, r3, r4, r5, r6;
1014:
1015: r1 = pcic_read(h, mem_map_index[win].sysmem_start_msb);
1016: r2 = pcic_read(h, mem_map_index[win].sysmem_start_lsb);
1017: r3 = pcic_read(h, mem_map_index[win].sysmem_stop_msb);
1018: r4 = pcic_read(h, mem_map_index[win].sysmem_stop_lsb);
1019: r5 = pcic_read(h, mem_map_index[win].cardmem_msb);
1020: r6 = pcic_read(h, mem_map_index[win].cardmem_lsb);
1021:
1022: DPRINTF(("pcic_chip_do_mem_map window %d: %02x%02x %02x%02x "
1023: "%02x%02x\n", win, r1, r2, r3, r4, r5, r6));
1024: }
1025: #endif
1026: }
1027:
1028: int
1029: pcic_chip_mem_map(pch, kind, card_addr, size, pcmhp, offsetp, windowp)
1030: pcmcia_chipset_handle_t pch;
1031: int kind;
1032: bus_addr_t card_addr;
1033: bus_size_t size;
1034: struct pcmcia_mem_handle *pcmhp;
1035: bus_size_t *offsetp;
1036: int *windowp;
1037: {
1038: struct pcic_handle *h = (struct pcic_handle *) pch;
1039: bus_addr_t busaddr;
1040: long card_offset;
1041: int i, win;
1042: struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
1043:
1044: win = -1;
1045: for (i = 0; i < (sizeof(mem_map_index) / sizeof(mem_map_index[0]));
1046: i++) {
1047: if ((h->memalloc & (1 << i)) == 0) {
1048: win = i;
1049: h->memalloc |= (1 << i);
1050: break;
1051: }
1052: }
1053:
1054: if (win == -1)
1055: return (1);
1056:
1057: *windowp = win;
1058:
1059: /* XXX this is pretty gross */
1060:
1061: if (sc->memt != pcmhp->memt)
1062: panic("pcic_chip_mem_map memt is bogus");
1063:
1064: busaddr = pcmhp->addr;
1065:
1066: /*
1067: * Compute the address offset to the pcmcia address space for the
1068: * pcic. This is intentionally signed. The masks and shifts below
1069: * will cause TRT to happen in the pcic registers. Deal with making
1070: * sure the address is aligned, and return the alignment offset.
1071: */
1072:
1073: *offsetp = card_addr % PCIC_MEM_ALIGN;
1074: card_addr -= *offsetp;
1075:
1076: DPRINTF(("pcic_chip_mem_map window %d bus %lx+%lx+%lx at card addr "
1077: "%lx\n", win, (u_long) busaddr, (u_long) * offsetp, (u_long) size,
1078: (u_long) card_addr));
1079:
1080: /*
1081: * include the offset in the size, and decrement size by one, since
1082: * the hw wants start/stop
1083: */
1084: size += *offsetp - 1;
1085:
1086: card_offset = (((long) card_addr) - ((long) busaddr));
1087:
1088: h->mem[win].addr = busaddr;
1089: h->mem[win].size = size;
1090: h->mem[win].offset = card_offset;
1091: h->mem[win].kind = kind;
1092:
1093: pcic_chip_do_mem_map(h, win);
1094:
1095: return (0);
1096: }
1097:
1098: void
1099: pcic_chip_mem_unmap(pch, window)
1100: pcmcia_chipset_handle_t pch;
1101: int window;
1102: {
1103: struct pcic_handle *h = (struct pcic_handle *) pch;
1104: int reg;
1105:
1106: if (window >= (sizeof(mem_map_index) / sizeof(mem_map_index[0])))
1107: panic("pcic_chip_mem_unmap: window out of range");
1108:
1109: reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
1110: reg &= ~mem_map_index[window].memenable;
1111: pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
1112:
1113: h->memalloc &= ~(1 << window);
1114: }
1115:
1116: int
1117: pcic_chip_io_alloc(pch, start, size, align, pcihp)
1118: pcmcia_chipset_handle_t pch;
1119: bus_addr_t start;
1120: bus_size_t size;
1121: bus_size_t align;
1122: struct pcmcia_io_handle *pcihp;
1123: {
1124: struct pcic_handle *h = (struct pcic_handle *) pch;
1125: bus_space_tag_t iot;
1126: bus_space_handle_t ioh;
1127: bus_addr_t ioaddr, beg, fin;
1128: int flags = 0;
1129: struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
1130: struct pcic_ranges *range;
1131:
1132: /*
1133: * Allocate some arbitrary I/O space.
1134: */
1135:
1136: iot = sc->iot;
1137:
1138: if (start) {
1139: ioaddr = start;
1140: if (bus_space_map(iot, start, size, 0, &ioh))
1141: return (1);
1142: DPRINTF(("pcic_chip_io_alloc map port %lx+%lx\n",
1143: (u_long)ioaddr, (u_long)size));
1144: } else if (sc->ranges) {
1145: flags |= PCMCIA_IO_ALLOCATED;
1146:
1147: /*
1148: * In this case, we know the "size" and "align" that
1149: * we want. So we need to start walking down
1150: * sc->ranges, searching for a similar space that
1151: * is (1) large enough for the size and alignment
1152: * (2) then we need to try to allocate
1153: * (3) if it fails to allocate, we try next range.
1154: *
1155: * We must also check that the start/size of each
1156: * allocation we are about to do is within the bounds
1157: * of "sc->iobase" and "sc->iosize".
1158: * (Some pcmcia controllers handle a 12 bits of addressing,
1159: * but we want to use the same range structure)
1160: */
1161: for (range = sc->ranges; range->start; range++) {
1162: /* Potentially trim the range because of bounds. */
1163: beg = max(range->start, sc->iobase);
1164: fin = min(range->start + range->len,
1165: sc->iobase + sc->iosize);
1166:
1167: /* Short-circuit easy cases. */
1168: if (fin < beg || fin - beg < size)
1169: continue;
1170:
1171: /*
1172: * This call magically fulfills our alignment
1173: * requirements.
1174: */
1175: DPRINTF(("pcic_chip_io_alloc beg-fin %lx-%lx\n",
1176: (u_long)beg, (u_long)fin));
1177: if (bus_space_alloc(iot, beg, fin, size, align, 0, 0,
1178: &ioaddr, &ioh) == 0)
1179: break;
1180: }
1181: if (range->start == 0)
1182: return (1);
1183: DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n",
1184: (u_long)ioaddr, (u_long)size));
1185:
1186: } else {
1187: flags |= PCMCIA_IO_ALLOCATED;
1188: if (bus_space_alloc(iot, sc->iobase,
1189: sc->iobase + sc->iosize, size, align, 0, 0,
1190: &ioaddr, &ioh))
1191: return (1);
1192: DPRINTF(("pcic_chip_io_alloc alloc port %lx+%lx\n",
1193: (u_long)ioaddr, (u_long)size));
1194: }
1195:
1196: pcihp->iot = iot;
1197: pcihp->ioh = ioh;
1198: pcihp->addr = ioaddr;
1199: pcihp->size = size;
1200: pcihp->flags = flags;
1201:
1202: return (0);
1203: }
1204:
1205: void
1206: pcic_chip_io_free(pch, pcihp)
1207: pcmcia_chipset_handle_t pch;
1208: struct pcmcia_io_handle *pcihp;
1209: {
1210: bus_space_tag_t iot = pcihp->iot;
1211: bus_space_handle_t ioh = pcihp->ioh;
1212: bus_size_t size = pcihp->size;
1213:
1214: if (pcihp->flags & PCMCIA_IO_ALLOCATED)
1215: bus_space_free(iot, ioh, size);
1216: else
1217: bus_space_unmap(iot, ioh, size);
1218: }
1219:
1220:
1221: static struct io_map_index_st {
1222: int start_lsb;
1223: int start_msb;
1224: int stop_lsb;
1225: int stop_msb;
1226: int ioenable;
1227: int ioctlmask;
1228: int ioctlbits[3]; /* indexed by PCMCIA_WIDTH_* */
1229: } io_map_index[] = {
1230: {
1231: PCIC_IOADDR0_START_LSB,
1232: PCIC_IOADDR0_START_MSB,
1233: PCIC_IOADDR0_STOP_LSB,
1234: PCIC_IOADDR0_STOP_MSB,
1235: PCIC_ADDRWIN_ENABLE_IO0,
1236: PCIC_IOCTL_IO0_WAITSTATE | PCIC_IOCTL_IO0_ZEROWAIT |
1237: PCIC_IOCTL_IO0_IOCS16SRC_MASK | PCIC_IOCTL_IO0_DATASIZE_MASK,
1238: {
1239: PCIC_IOCTL_IO0_IOCS16SRC_CARD,
1240: PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
1241: PCIC_IOCTL_IO0_DATASIZE_8BIT,
1242: PCIC_IOCTL_IO0_IOCS16SRC_DATASIZE |
1243: PCIC_IOCTL_IO0_DATASIZE_16BIT,
1244: },
1245: },
1246: {
1247: PCIC_IOADDR1_START_LSB,
1248: PCIC_IOADDR1_START_MSB,
1249: PCIC_IOADDR1_STOP_LSB,
1250: PCIC_IOADDR1_STOP_MSB,
1251: PCIC_ADDRWIN_ENABLE_IO1,
1252: PCIC_IOCTL_IO1_WAITSTATE | PCIC_IOCTL_IO1_ZEROWAIT |
1253: PCIC_IOCTL_IO1_IOCS16SRC_MASK | PCIC_IOCTL_IO1_DATASIZE_MASK,
1254: {
1255: PCIC_IOCTL_IO1_IOCS16SRC_CARD,
1256: PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE |
1257: PCIC_IOCTL_IO1_DATASIZE_8BIT,
1258: PCIC_IOCTL_IO1_IOCS16SRC_DATASIZE |
1259: PCIC_IOCTL_IO1_DATASIZE_16BIT,
1260: },
1261: },
1262: };
1263:
1264: void
1265: pcic_chip_do_io_map(h, win)
1266: struct pcic_handle *h;
1267: int win;
1268: {
1269: int reg;
1270:
1271: DPRINTF(("pcic_chip_do_io_map win %d addr %lx size %lx width %d\n",
1272: win, (long) h->io[win].addr, (long) h->io[win].size,
1273: h->io[win].width * 8));
1274:
1275: pcic_write(h, io_map_index[win].start_lsb, h->io[win].addr & 0xff);
1276: pcic_write(h, io_map_index[win].start_msb,
1277: (h->io[win].addr >> 8) & 0xff);
1278:
1279: pcic_write(h, io_map_index[win].stop_lsb,
1280: (h->io[win].addr + h->io[win].size - 1) & 0xff);
1281: pcic_write(h, io_map_index[win].stop_msb,
1282: ((h->io[win].addr + h->io[win].size - 1) >> 8) & 0xff);
1283:
1284: reg = pcic_read(h, PCIC_IOCTL);
1285: reg &= ~io_map_index[win].ioctlmask;
1286: reg |= io_map_index[win].ioctlbits[h->io[win].width];
1287: pcic_write(h, PCIC_IOCTL, reg);
1288:
1289: reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
1290: reg |= io_map_index[win].ioenable;
1291: pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
1292: }
1293:
1294: int
1295: pcic_chip_io_map(pch, width, offset, size, pcihp, windowp)
1296: pcmcia_chipset_handle_t pch;
1297: int width;
1298: bus_addr_t offset;
1299: bus_size_t size;
1300: struct pcmcia_io_handle *pcihp;
1301: int *windowp;
1302: {
1303: struct pcic_handle *h = (struct pcic_handle *) pch;
1304: bus_addr_t ioaddr = pcihp->addr + offset;
1305: int i, win;
1306: #ifdef PCICDEBUG
1307: static char *width_names[] = { "auto", "io8", "io16" };
1308: #endif
1309: struct pcic_softc *sc = (struct pcic_softc *)(h->ph_parent);
1310:
1311: /* XXX Sanity check offset/size. */
1312:
1313: win = -1;
1314: for (i = 0; i < (sizeof(io_map_index) / sizeof(io_map_index[0])); i++) {
1315: if ((h->ioalloc & (1 << i)) == 0) {
1316: win = i;
1317: h->ioalloc |= (1 << i);
1318: break;
1319: }
1320: }
1321:
1322: if (win == -1)
1323: return (1);
1324:
1325: *windowp = win;
1326:
1327: /* XXX this is pretty gross */
1328:
1329: if (sc->iot != pcihp->iot)
1330: panic("pcic_chip_io_map iot is bogus");
1331:
1332: DPRINTF(("pcic_chip_io_map window %d %s port %lx+%lx\n",
1333: win, width_names[width], (u_long) ioaddr, (u_long) size));
1334:
1335: h->io[win].addr = ioaddr;
1336: h->io[win].size = size;
1337: h->io[win].width = width;
1338:
1339: pcic_chip_do_io_map(h, win);
1340:
1341: return (0);
1342: }
1343:
1344: void
1345: pcic_chip_io_unmap(pch, window)
1346: pcmcia_chipset_handle_t pch;
1347: int window;
1348: {
1349: struct pcic_handle *h = (struct pcic_handle *) pch;
1350: int reg;
1351:
1352: if (window >= (sizeof(io_map_index) / sizeof(io_map_index[0])))
1353: panic("pcic_chip_io_unmap: window out of range");
1354:
1355: reg = pcic_read(h, PCIC_ADDRWIN_ENABLE);
1356: reg &= ~io_map_index[window].ioenable;
1357: pcic_write(h, PCIC_ADDRWIN_ENABLE, reg);
1358:
1359: h->ioalloc &= ~(1 << window);
1360: }
1361:
1362: void
1363: pcic_wait_ready(h)
1364: struct pcic_handle *h;
1365: {
1366: int i;
1367:
1368: for (i = 0; i < 10000; i++) {
1369: if (pcic_read(h, PCIC_IF_STATUS) & PCIC_IF_STATUS_READY)
1370: return;
1371: delay(500);
1372: #ifdef PCICDEBUG
1373: if ((i>5000) && (i%100 == 99))
1374: printf(".");
1375: #endif
1376: }
1377:
1378: #ifdef DIAGNOSTIC
1379: printf("pcic_wait_ready: ready never happened, status = %02x\n",
1380: pcic_read(h, PCIC_IF_STATUS));
1381: #endif
1382: }
1383:
1384: void
1385: pcic_chip_socket_enable(pch)
1386: pcmcia_chipset_handle_t pch;
1387: {
1388: struct pcic_handle *h = (struct pcic_handle *) pch;
1389: int cardtype, reg, win;
1390:
1391: /* this bit is mostly stolen from pcic_attach_card */
1392:
1393: /* power down the socket to reset it, clear the card reset pin */
1394:
1395: pcic_write(h, PCIC_PWRCTL, 0);
1396:
1397: /*
1398: * wait 300ms until power fails (Tpf). Then, wait 100ms since
1399: * we are changing Vcc (Toff).
1400: */
1401: delay((300 + 100) * 1000);
1402:
1403: if (h->vendor == PCIC_VENDOR_VADEM_VG469) {
1404: reg = pcic_read(h, PCIC_VG469_VSELECT);
1405: reg &= ~PCIC_VG469_VSELECT_VCC;
1406: pcic_write(h, PCIC_VG469_VSELECT, reg);
1407: }
1408:
1409: /* power up the socket */
1410:
1411: pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV
1412: | PCIC_PWRCTL_PWR_ENABLE);
1413:
1414: /*
1415: * wait 100ms until power raise (Tpr) and 20ms to become
1416: * stable (Tsu(Vcc)).
1417: *
1418: * some machines require some more time to be settled
1419: * (another 200ms is added here).
1420: */
1421: delay((100 + 20 + 200) * 1000);
1422:
1423: pcic_write(h, PCIC_PWRCTL, PCIC_PWRCTL_DISABLE_RESETDRV |
1424: PCIC_PWRCTL_OE | PCIC_PWRCTL_PWR_ENABLE);
1425: pcic_write(h, PCIC_INTR, 0);
1426:
1427: /*
1428: * hold RESET at least 10us.
1429: */
1430: delay(10);
1431:
1432: /* clear the reset flag */
1433:
1434: pcic_write(h, PCIC_INTR, PCIC_INTR_RESET);
1435:
1436: /* wait 20ms as per pc card standard (r2.01) section 4.3.6 */
1437:
1438: delay(20000);
1439:
1440: /* wait for the chip to finish initializing */
1441:
1442: #ifdef DIAGNOSTIC
1443: reg = pcic_read(h, PCIC_IF_STATUS);
1444: if (!(reg & PCIC_IF_STATUS_POWERACTIVE)) {
1445: printf("pcic_chip_socket_enable: status %x\n", reg);
1446: }
1447: #endif
1448:
1449: pcic_wait_ready(h);
1450:
1451: /* zero out the address windows */
1452:
1453: pcic_write(h, PCIC_ADDRWIN_ENABLE, 0);
1454:
1455: /* set the card type */
1456:
1457: cardtype = pcmcia_card_gettype(h->pcmcia);
1458:
1459: reg = pcic_read(h, PCIC_INTR);
1460: reg &= ~PCIC_INTR_CARDTYPE_MASK;
1461: reg |= ((cardtype == PCMCIA_IFTYPE_IO) ?
1462: PCIC_INTR_CARDTYPE_IO :
1463: PCIC_INTR_CARDTYPE_MEM);
1464: reg |= h->ih_irq;
1465: pcic_write(h, PCIC_INTR, reg);
1466:
1467: DPRINTF(("%s: pcic_chip_socket_enable %02x cardtype %s %02x\n",
1468: h->ph_parent->dv_xname, h->sock,
1469: ((cardtype == PCMCIA_IFTYPE_IO) ? "io" : "mem"), reg));
1470:
1471: /* reinstall all the memory and io mappings */
1472:
1473: for (win = 0; win < PCIC_MEM_WINS; win++)
1474: if (h->memalloc & (1 << win))
1475: pcic_chip_do_mem_map(h, win);
1476:
1477: for (win = 0; win < PCIC_IO_WINS; win++)
1478: if (h->ioalloc & (1 << win))
1479: pcic_chip_do_io_map(h, win);
1480: }
1481:
1482: void
1483: pcic_chip_socket_disable(pch)
1484: pcmcia_chipset_handle_t pch;
1485: {
1486: struct pcic_handle *h = (struct pcic_handle *) pch;
1487:
1488: DPRINTF(("pcic_chip_socket_disable\n"));
1489:
1490: /* power down the socket */
1491:
1492: pcic_write(h, PCIC_PWRCTL, 0);
1493:
1494: /*
1495: * wait 300ms until power fails (Tpf).
1496: */
1497: delay(300 * 1000);
1498: }
1499:
1500: u_int8_t
1501: st_pcic_read(h, idx)
1502: struct pcic_handle *h;
1503: int idx;
1504: {
1505: if (idx != -1)
1506: bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_INDEX,
1507: h->sock + idx);
1508: return bus_space_read_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_DATA);
1509: }
1510:
1511: void
1512: st_pcic_write(h, idx, data)
1513: struct pcic_handle *h;
1514: int idx;
1515: int data;
1516: {
1517: if (idx != -1)
1518: bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_INDEX,
1519: h->sock + idx);
1520: if (data != -1)
1521: bus_space_write_1(h->ph_bus_t, h->ph_bus_h, PCIC_REG_DATA,
1522: data);
1523: }
CVSweb