pcib.c revision 1.18.66.1 1 /* $NetBSD: pcib.c,v 1.18.66.1 2008/05/16 02:21:44 yamt Exp $ */
2
3 /*-
4 * Copyright (c) 2000, 2001 The NetBSD Foundation, Inc.
5 * All rights reserved.
6 *
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Jason R. Thorpe.
9 *
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
12 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
18 *
19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29 * POSSIBILITY OF SUCH DAMAGE.
30 */
31
32 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */
33
34 __KERNEL_RCSID(0, "$NetBSD: pcib.c,v 1.18.66.1 2008/05/16 02:21:44 yamt Exp $");
35
36 #include "opt_algor_p5064.h"
37 #include "opt_algor_p6032.h"
38
39 #include <sys/param.h>
40 #include <sys/systm.h>
41 #include <sys/kernel.h>
42 #include <sys/device.h>
43 #include <sys/malloc.h>
44
45 #include <machine/intr.h>
46 #include <machine/bus.h>
47
48 #include <dev/isa/isareg.h>
49 #include <dev/isa/isavar.h>
50
51 #include <dev/pci/pcireg.h>
52 #include <dev/pci/pcivar.h>
53 #include <dev/pci/pcidevs.h>
54
55 #include <dev/ic/i8259reg.h>
56
57 #ifdef ALGOR_P5064
58 #include <algor/algor/algor_p5064var.h>
59 #endif
60
61 #ifdef ALGOR_P6032
62 #include <algor/algor/algor_p6032var.h>
63 #endif
64
65 const char *pcib_intrnames[16] = {
66 "irq 0",
67 "irq 1",
68 "irq 2",
69 "irq 3",
70 "irq 4",
71 "irq 5",
72 "irq 6",
73 "irq 7",
74 "irq 8",
75 "irq 9",
76 "irq 10",
77 "irq 11",
78 "irq 12",
79 "irq 13",
80 "irq 14",
81 "irq 15",
82 };
83
84 struct pcib_intrhead {
85 LIST_HEAD(, algor_intrhand) intr_q;
86 struct evcnt intr_count;
87 int intr_type;
88 };
89
90 struct pcib_softc {
91 struct device sc_dev;
92
93 bus_space_tag_t sc_iot;
94 bus_space_handle_t sc_ioh_icu1;
95 bus_space_handle_t sc_ioh_icu2;
96 bus_space_handle_t sc_ioh_elcr;
97
98 struct algor_isa_chipset sc_ic;
99
100 struct pcib_intrhead sc_intrtab[16];
101
102 u_int16_t sc_imask;
103 u_int16_t sc_elcr;
104
105 #if defined(ALGOR_P5064)
106 isa_chipset_tag_t sc_parent_ic;
107 #endif
108
109 u_int16_t sc_reserved;
110
111 void *sc_ih;
112 };
113
114 int pcib_match(struct device *, struct cfdata *, void *);
115 void pcib_attach(struct device *, struct device *, void *);
116
117 CFATTACH_DECL(pcib, sizeof(struct pcib_softc),
118 pcib_match, pcib_attach, NULL, NULL);
119
120 void pcib_isa_attach_hook(struct device *, struct device *,
121 struct isabus_attach_args *);
122
123 int pcib_intr(void *);
124
125 void pcib_bridge_callback(struct device *);
126
127 const struct evcnt *pcib_isa_intr_evcnt(void *, int);
128 void *pcib_isa_intr_establish(void *, int, int, int,
129 int (*)(void *), void *);
130 void pcib_isa_intr_disestablish(void *, void *);
131 int pcib_isa_intr_alloc(void *, int, int, int *);
132
133 void pcib_set_icus(struct pcib_softc *);
134
135 int
136 pcib_match(struct device *parent, struct cfdata *match, void *aux)
137 {
138 struct pci_attach_args *pa = aux;
139
140 if (PCI_CLASS(pa->pa_class) == PCI_CLASS_BRIDGE &&
141 PCI_SUBCLASS(pa->pa_class) == PCI_SUBCLASS_BRIDGE_ISA)
142 return (1);
143
144 return (0);
145 }
146
147 void
148 pcib_attach(struct device *parent, struct device *self, void *aux)
149 {
150 struct pcib_softc *sc = (void *) self;
151 struct pci_attach_args *pa = aux;
152 char devinfo[256];
153 int i;
154
155 pci_devinfo(pa->pa_id, pa->pa_class, 0, devinfo, sizeof(devinfo));
156 printf(": %s (rev. 0x%02x)\n", devinfo,
157 PCI_REVISION(pa->pa_class));
158
159 sc->sc_iot = pa->pa_iot;
160
161 /*
162 * Map the PIC/ELCR registers.
163 */
164 if (bus_space_map(sc->sc_iot, 0x4d0, 2, 0, &sc->sc_ioh_elcr) != 0)
165 printf("%s: unable to map ELCR registers\n",
166 sc->sc_dev.dv_xname);
167 if (bus_space_map(sc->sc_iot, IO_ICU1, 2, 0, &sc->sc_ioh_icu1) != 0)
168 printf("%s: unable to map ICU1 registers\n",
169 sc->sc_dev.dv_xname);
170 if (bus_space_map(sc->sc_iot, IO_ICU2, 2, 0, &sc->sc_ioh_icu2) != 0)
171 printf("%s: unable to map ICU2 registers\n",
172 sc->sc_dev.dv_xname);
173
174 /* All interrupts default to "masked off". */
175 sc->sc_imask = 0xffff;
176
177 /* All interrupts default to edge-triggered. */
178 sc->sc_elcr = 0;
179
180 /*
181 * Initialize the 8259s.
182 */
183
184 /* reset, program device, 4 bytes */
185 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW1,
186 ICW1_SELECT | ICW1_IC4);
187 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW2,
188 ICW2_VECTOR(0)/*XXX*/);
189 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW3,
190 ICW3_CASCADE(2));
191 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_ICW4,
192 ICW4_8086);
193
194 /* mask all interrupts */
195 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1,
196 sc->sc_imask & 0xff);
197
198 /* enable special mask mode */
199 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
200 OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
201
202 /* read IRR by default */
203 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
204 OCW3_SELECT | OCW3_RR);
205
206 /* reset; program device, 4 bytes */
207 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW1,
208 ICW1_SELECT | ICW1_IC4);
209 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW2,
210 ICW2_VECTOR(0)/*XXX*/);
211 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW3,
212 ICW3_SIC(2));
213 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_ICW4,
214 ICW4_8086);
215
216 /* mask all interrupts */
217 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1,
218 (sc->sc_imask >> 8) & 0xff);
219
220 /* enable special mask mode */
221 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3,
222 OCW3_SELECT | OCW3_SSMM | OCW3_SMM);
223
224 /* read IRR by default */
225 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW3,
226 OCW3_SELECT | OCW3_RR);
227
228 /*
229 * Default all interrupts to edge-triggered.
230 */
231 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
232 sc->sc_elcr & 0xff);
233 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
234 (sc->sc_elcr >> 8) & 0xff);
235
236 /*
237 * Some ISA interrupts are reserved for devices that
238 * we know are hard-wired to certain IRQs.
239 */
240 sc->sc_reserved =
241 (1U << 0) | /* timer */
242 (1U << 1) | /* keyboard controller */
243 (1U << 2) | /* PIC cascade */
244 (1U << 3) | /* COM 2 */
245 (1U << 4) | /* COM 1 */
246 (1U << 6) | /* floppy */
247 (1U << 7) | /* centronics */
248 (1U << 8) | /* RTC */
249 (1U << 12) | /* keyboard controller */
250 (1U << 14) | /* IDE 0 */
251 (1U << 15); /* IDE 1 */
252
253 #if defined(ALGOR_P5064)
254 /*
255 * Some "ISA" interrupts are a little wacky, wired up directly
256 * to the P-5064 interrupt controller.
257 */
258 sc->sc_parent_ic = &p5064_configuration.ac_ic;
259 #endif /* ALGOR_P5064 */
260
261 /* Set up our ISA chipset. */
262 sc->sc_ic.ic_v = sc;
263 sc->sc_ic.ic_intr_evcnt = pcib_isa_intr_evcnt;
264 sc->sc_ic.ic_intr_establish = pcib_isa_intr_establish;
265 sc->sc_ic.ic_intr_disestablish = pcib_isa_intr_disestablish;
266 sc->sc_ic.ic_intr_alloc = pcib_isa_intr_alloc;
267
268 /* Initialize our interrupt table. */
269 for (i = 0; i < 16; i++) {
270 LIST_INIT(&sc->sc_intrtab[i].intr_q);
271 evcnt_attach_dynamic(&sc->sc_intrtab[i].intr_count,
272 EVCNT_TYPE_INTR, NULL, "pcib", pcib_intrnames[i]);
273 sc->sc_intrtab[i].intr_type = IST_NONE;
274 }
275
276 /* Hook up our interrupt handler. */
277 #if defined(ALGOR_P5064)
278 sc->sc_ih = (*algor_intr_establish)(P5064_IRQ_ISABRIDGE,
279 pcib_intr, sc);
280 #elif defined(ALGOR_P6032)
281 sc->sc_ih = (*algor_intr_establish)(P6032_IRQ_ISABRIDGE,
282 pcib_intr, sc);
283 #endif
284 if (sc->sc_ih == NULL)
285 printf("%s: WARNING: unable to register interrupt handler\n",
286 sc->sc_dev.dv_xname);
287
288 config_defer(self, pcib_bridge_callback);
289 }
290
291 void
292 pcib_bridge_callback(self)
293 struct device *self;
294 {
295 struct pcib_softc *sc = (struct pcib_softc *)self;
296 struct isabus_attach_args iba;
297
298 memset(&iba, 0, sizeof(iba));
299
300 #if defined(ALGOR_P5064)
301 {
302 struct p5064_config *acp = &p5064_configuration;
303
304 iba.iba_iot = &acp->ac_iot;
305 iba.iba_memt = &acp->ac_memt;
306 iba.iba_dmat = &acp->ac_isa_dmat;
307 }
308 #elif defined(ALGOR_P6032)
309 {
310 struct p6032_config *acp = &p6032_configuration;
311
312 iba.iba_iot = &acp->ac_iot;
313 iba.iba_memt = &acp->ac_memt;
314 iba.iba_dmat = &acp->ac_isa_dmat;
315 }
316 #endif
317
318 iba.iba_ic = &sc->sc_ic;
319 iba.iba_ic->ic_attach_hook = pcib_isa_attach_hook;
320
321 (void) config_found_ia(&sc->sc_dev, "isabus", &iba, isabusprint);
322 }
323
324 void
325 pcib_isa_attach_hook(struct device *parent, struct device *self,
326 struct isabus_attach_args *iba)
327 {
328
329 /* Nothing to do. */
330 }
331
332 void
333 pcib_set_icus(struct pcib_softc *sc)
334 {
335
336 /* Enable the cascade IRQ (2) if 8-15 is enabled. */
337 if ((sc->sc_imask & 0xff00) != 0xff00)
338 sc->sc_imask &= ~(1U << 2);
339 else
340 sc->sc_imask |= (1U << 2);
341
342 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1,
343 sc->sc_imask & 0xff);
344 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1,
345 (sc->sc_imask >> 8) & 0xff);
346
347 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
348 sc->sc_elcr & 0xff);
349 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
350 (sc->sc_elcr >> 8) & 0xff);
351 }
352
353 int
354 pcib_intr(void *v)
355 {
356 struct pcib_softc *sc = v;
357 struct algor_intrhand *ih;
358 int irq;
359
360 for (;;) {
361 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
362 OCW3_SELECT | OCW3_POLL);
363 irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3);
364 if ((irq & OCW3_POLL_PENDING) == 0)
365 return (1);
366
367 irq = OCW3_POLL_IRQ(irq);
368
369 if (irq == 2) {
370 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
371 PIC_OCW3, OCW3_SELECT | OCW3_POLL);
372 irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu2,
373 PIC_OCW3);
374 if (irq & OCW3_POLL_PENDING)
375 irq = OCW3_POLL_IRQ(irq) + 8;
376 else
377 irq = 2;
378 }
379
380 sc->sc_intrtab[irq].intr_count.ev_count++;
381 for (ih = LIST_FIRST(&sc->sc_intrtab[irq].intr_q);
382 ih != NULL; ih = LIST_NEXT(ih, ih_q)) {
383 (*ih->ih_func)(ih->ih_arg);
384 }
385
386 /* Send a specific EOI to the 8259. */
387 if (irq > 7) {
388 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
389 PIC_OCW2, OCW2_SELECT | OCW2_EOI | OCW2_SL |
390 OCW2_ILS(irq & 7));
391 irq = 2;
392 }
393
394 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW2,
395 OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(irq));
396 }
397 }
398
399 const struct evcnt *
400 pcib_isa_intr_evcnt(void *v, int irq)
401 {
402 struct pcib_softc *sc = v;
403
404 #if defined(ALGOR_P5064)
405 if (p5064_isa_to_irqmap[irq] != -1)
406 return (isa_intr_evcnt(sc->sc_parent_ic, irq));
407 #endif
408
409 return (&sc->sc_intrtab[irq].intr_count);
410 }
411
412 void *
413 pcib_isa_intr_establish(void *v, int irq, int type, int level,
414 int (*func)(void *), void *arg)
415 {
416 struct pcib_softc *sc = v;
417 struct algor_intrhand *ih;
418 int s;
419
420 if (irq > 15 || irq == 2 || type == IST_NONE)
421 panic("pcib_isa_intr_establish: bad irq or type");
422
423 #if defined(ALGOR_P5064)
424 if (p5064_isa_to_irqmap[irq] != -1)
425 return (isa_intr_establish(sc->sc_parent_ic, irq, type,
426 level, func, arg));
427 #endif
428
429 switch (sc->sc_intrtab[irq].intr_type) {
430 case IST_NONE:
431 sc->sc_intrtab[irq].intr_type = type;
432 break;
433
434 case IST_EDGE:
435 case IST_LEVEL:
436 if (type == sc->sc_intrtab[irq].intr_type)
437 break;
438 /* FALLTHROUGH */
439 case IST_PULSE:
440 /*
441 * We can't share interrupts in this case.
442 */
443 return (NULL);
444 }
445
446 ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
447 if (ih == NULL)
448 return (NULL);
449
450 ih->ih_func = func;
451 ih->ih_arg = arg;
452 ih->ih_irq = irq;
453 ih->ih_irqmap = NULL;
454
455 s = splhigh();
456
457 /* Insert the handler into the table. */
458 LIST_INSERT_HEAD(&sc->sc_intrtab[irq].intr_q, ih, ih_q);
459 sc->sc_intrtab[irq].intr_type = type;
460
461 /* Enable it, set trigger mode. */
462 sc->sc_imask &= ~(1 << irq);
463 if (sc->sc_intrtab[irq].intr_type == IST_LEVEL)
464 sc->sc_elcr |= (1 << irq);
465 else
466 sc->sc_elcr &= ~(1 << irq);
467
468 pcib_set_icus(sc);
469
470 splx(s);
471
472 return (ih);
473 }
474
475 void
476 pcib_isa_intr_disestablish(void *v, void *arg)
477 {
478 struct pcib_softc *sc = v;
479 struct algor_intrhand *ih = arg;
480 int s;
481
482 #if defined(ALGOR_P5064)
483 if (p5064_isa_to_irqmap[ih->ih_irq] != -1) {
484 isa_intr_disestablish(sc->sc_parent_ic, ih);
485 return;
486 }
487 #endif
488
489 s = splhigh();
490
491 LIST_REMOVE(ih, ih_q);
492
493 /* If there are no more handlers on this IRQ, disable it. */
494 if (LIST_FIRST(&sc->sc_intrtab[ih->ih_irq].intr_q) == NULL) {
495 sc->sc_imask |= (1 << ih->ih_irq);
496 pcib_set_icus(sc);
497 }
498
499 splx(s);
500
501 free(ih, M_DEVBUF);
502 }
503
504 int
505 pcib_isa_intr_alloc(void *v, int mask, int type, int *irq)
506 {
507 struct pcib_softc *sc = v;
508 int i, tmp, bestirq, count;
509 struct algor_intrhand *ih;
510
511 if (type == IST_NONE)
512 panic("pcib_intr_alloc: bogus type");
513
514 bestirq = -1;
515 count = -1;
516
517 mask &= ~sc->sc_reserved;
518
519 #if 0
520 printf("pcib_intr_alloc: mask = 0x%04x\n", mask);
521 #endif
522
523 for (i = 0; i < 16; i++) {
524 if ((mask & (1 << i)) == 0)
525 continue;
526
527 switch (sc->sc_intrtab[i].intr_type) {
528 case IST_NONE:
529 /*
530 * If nothing's using the IRQ, just return it.
531 */
532 *irq = i;
533 return (0);
534
535 case IST_EDGE:
536 case IST_LEVEL:
537 if (type != sc->sc_intrtab[i].intr_type)
538 continue;
539 /*
540 * If the IRQ is sharable, count the number of
541 * other handlers, and if it's smaller than the
542 * last IRQ like this, remember it.
543 */
544 tmp = 0;
545 for (ih = LIST_FIRST(&sc->sc_intrtab[i].intr_q);
546 ih != NULL; ih = LIST_NEXT(ih, ih_q))
547 tmp++;
548 if (bestirq == -1 || count > tmp) {
549 bestirq = i;
550 count = tmp;
551 }
552 break;
553
554 case IST_PULSE:
555 /* This just isn't sharable. */
556 continue;
557 }
558 }
559
560 if (bestirq == -1)
561 return (1);
562
563 *irq = bestirq;
564 return (0);
565 }
566