pcib.c revision 1.18.66.2 1 /* $NetBSD: pcib.c,v 1.18.66.2 2009/05/04 08:10:27 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.2 2009/05/04 08:10:27 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(struct device *self)
293 {
294 struct pcib_softc *sc = (struct pcib_softc *)self;
295 struct isabus_attach_args iba;
296
297 memset(&iba, 0, sizeof(iba));
298
299 #if defined(ALGOR_P5064)
300 {
301 struct p5064_config *acp = &p5064_configuration;
302
303 iba.iba_iot = &acp->ac_iot;
304 iba.iba_memt = &acp->ac_memt;
305 iba.iba_dmat = &acp->ac_isa_dmat;
306 }
307 #elif defined(ALGOR_P6032)
308 {
309 struct p6032_config *acp = &p6032_configuration;
310
311 iba.iba_iot = &acp->ac_iot;
312 iba.iba_memt = &acp->ac_memt;
313 iba.iba_dmat = &acp->ac_isa_dmat;
314 }
315 #endif
316
317 iba.iba_ic = &sc->sc_ic;
318 iba.iba_ic->ic_attach_hook = pcib_isa_attach_hook;
319
320 (void) config_found_ia(&sc->sc_dev, "isabus", &iba, isabusprint);
321 }
322
323 void
324 pcib_isa_attach_hook(struct device *parent, struct device *self,
325 struct isabus_attach_args *iba)
326 {
327
328 /* Nothing to do. */
329 }
330
331 void
332 pcib_set_icus(struct pcib_softc *sc)
333 {
334
335 /* Enable the cascade IRQ (2) if 8-15 is enabled. */
336 if ((sc->sc_imask & 0xff00) != 0xff00)
337 sc->sc_imask &= ~(1U << 2);
338 else
339 sc->sc_imask |= (1U << 2);
340
341 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW1,
342 sc->sc_imask & 0xff);
343 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2, PIC_OCW1,
344 (sc->sc_imask >> 8) & 0xff);
345
346 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 0,
347 sc->sc_elcr & 0xff);
348 bus_space_write_1(sc->sc_iot, sc->sc_ioh_elcr, 1,
349 (sc->sc_elcr >> 8) & 0xff);
350 }
351
352 int
353 pcib_intr(void *v)
354 {
355 struct pcib_softc *sc = v;
356 struct algor_intrhand *ih;
357 int irq;
358
359 for (;;) {
360 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3,
361 OCW3_SELECT | OCW3_POLL);
362 irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW3);
363 if ((irq & OCW3_POLL_PENDING) == 0)
364 return (1);
365
366 irq = OCW3_POLL_IRQ(irq);
367
368 if (irq == 2) {
369 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
370 PIC_OCW3, OCW3_SELECT | OCW3_POLL);
371 irq = bus_space_read_1(sc->sc_iot, sc->sc_ioh_icu2,
372 PIC_OCW3);
373 if (irq & OCW3_POLL_PENDING)
374 irq = OCW3_POLL_IRQ(irq) + 8;
375 else
376 irq = 2;
377 }
378
379 sc->sc_intrtab[irq].intr_count.ev_count++;
380 for (ih = LIST_FIRST(&sc->sc_intrtab[irq].intr_q);
381 ih != NULL; ih = LIST_NEXT(ih, ih_q)) {
382 (*ih->ih_func)(ih->ih_arg);
383 }
384
385 /* Send a specific EOI to the 8259. */
386 if (irq > 7) {
387 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu2,
388 PIC_OCW2, OCW2_SELECT | OCW2_EOI | OCW2_SL |
389 OCW2_ILS(irq & 7));
390 irq = 2;
391 }
392
393 bus_space_write_1(sc->sc_iot, sc->sc_ioh_icu1, PIC_OCW2,
394 OCW2_SELECT | OCW2_EOI | OCW2_SL | OCW2_ILS(irq));
395 }
396 }
397
398 const struct evcnt *
399 pcib_isa_intr_evcnt(void *v, int irq)
400 {
401 struct pcib_softc *sc = v;
402
403 #if defined(ALGOR_P5064)
404 if (p5064_isa_to_irqmap[irq] != -1)
405 return (isa_intr_evcnt(sc->sc_parent_ic, irq));
406 #endif
407
408 return (&sc->sc_intrtab[irq].intr_count);
409 }
410
411 void *
412 pcib_isa_intr_establish(void *v, int irq, int type, int level,
413 int (*func)(void *), void *arg)
414 {
415 struct pcib_softc *sc = v;
416 struct algor_intrhand *ih;
417 int s;
418
419 if (irq > 15 || irq == 2 || type == IST_NONE)
420 panic("pcib_isa_intr_establish: bad irq or type");
421
422 #if defined(ALGOR_P5064)
423 if (p5064_isa_to_irqmap[irq] != -1)
424 return (isa_intr_establish(sc->sc_parent_ic, irq, type,
425 level, func, arg));
426 #endif
427
428 switch (sc->sc_intrtab[irq].intr_type) {
429 case IST_NONE:
430 sc->sc_intrtab[irq].intr_type = type;
431 break;
432
433 case IST_EDGE:
434 case IST_LEVEL:
435 if (type == sc->sc_intrtab[irq].intr_type)
436 break;
437 /* FALLTHROUGH */
438 case IST_PULSE:
439 /*
440 * We can't share interrupts in this case.
441 */
442 return (NULL);
443 }
444
445 ih = malloc(sizeof(*ih), M_DEVBUF, M_NOWAIT);
446 if (ih == NULL)
447 return (NULL);
448
449 ih->ih_func = func;
450 ih->ih_arg = arg;
451 ih->ih_irq = irq;
452 ih->ih_irqmap = NULL;
453
454 s = splhigh();
455
456 /* Insert the handler into the table. */
457 LIST_INSERT_HEAD(&sc->sc_intrtab[irq].intr_q, ih, ih_q);
458 sc->sc_intrtab[irq].intr_type = type;
459
460 /* Enable it, set trigger mode. */
461 sc->sc_imask &= ~(1 << irq);
462 if (sc->sc_intrtab[irq].intr_type == IST_LEVEL)
463 sc->sc_elcr |= (1 << irq);
464 else
465 sc->sc_elcr &= ~(1 << irq);
466
467 pcib_set_icus(sc);
468
469 splx(s);
470
471 return (ih);
472 }
473
474 void
475 pcib_isa_intr_disestablish(void *v, void *arg)
476 {
477 struct pcib_softc *sc = v;
478 struct algor_intrhand *ih = arg;
479 int s;
480
481 #if defined(ALGOR_P5064)
482 if (p5064_isa_to_irqmap[ih->ih_irq] != -1) {
483 isa_intr_disestablish(sc->sc_parent_ic, ih);
484 return;
485 }
486 #endif
487
488 s = splhigh();
489
490 LIST_REMOVE(ih, ih_q);
491
492 /* If there are no more handlers on this IRQ, disable it. */
493 if (LIST_FIRST(&sc->sc_intrtab[ih->ih_irq].intr_q) == NULL) {
494 sc->sc_imask |= (1 << ih->ih_irq);
495 pcib_set_icus(sc);
496 }
497
498 splx(s);
499
500 free(ih, M_DEVBUF);
501 }
502
503 int
504 pcib_isa_intr_alloc(void *v, int mask, int type, int *irq)
505 {
506 struct pcib_softc *sc = v;
507 int i, tmp, bestirq, count;
508 struct algor_intrhand *ih;
509
510 if (type == IST_NONE)
511 panic("pcib_intr_alloc: bogus type");
512
513 bestirq = -1;
514 count = -1;
515
516 mask &= ~sc->sc_reserved;
517
518 #if 0
519 printf("pcib_intr_alloc: mask = 0x%04x\n", mask);
520 #endif
521
522 for (i = 0; i < 16; i++) {
523 if ((mask & (1 << i)) == 0)
524 continue;
525
526 switch (sc->sc_intrtab[i].intr_type) {
527 case IST_NONE:
528 /*
529 * If nothing's using the IRQ, just return it.
530 */
531 *irq = i;
532 return (0);
533
534 case IST_EDGE:
535 case IST_LEVEL:
536 if (type != sc->sc_intrtab[i].intr_type)
537 continue;
538 /*
539 * If the IRQ is sharable, count the number of
540 * other handlers, and if it's smaller than the
541 * last IRQ like this, remember it.
542 */
543 tmp = 0;
544 for (ih = LIST_FIRST(&sc->sc_intrtab[i].intr_q);
545 ih != NULL; ih = LIST_NEXT(ih, ih_q))
546 tmp++;
547 if (bestirq == -1 || count > tmp) {
548 bestirq = i;
549 count = tmp;
550 }
551 break;
552
553 case IST_PULSE:
554 /* This just isn't sharable. */
555 continue;
556 }
557 }
558
559 if (bestirq == -1)
560 return (1);
561
562 *irq = bestirq;
563 return (0);
564 }
565