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