]> CyberLeo.Net >> Repos - FreeBSD/releng/7.2.git/blob - sys/amd64/isa/atpic.c
Create releng/7.2 from stable/7 in preparation for 7.2-RELEASE.
[FreeBSD/releng/7.2.git] / sys / amd64 / isa / atpic.c
1 /*-
2  * Copyright (c) 2003 John Baldwin <jhb@FreeBSD.org>
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Redistributions in binary form must reproduce the above copyright
11  *    notice, this list of conditions and the following disclaimer in the
12  *    documentation and/or other materials provided with the distribution.
13  * 3. Neither the name of the author nor the names of any co-contributors
14  *    may be used to endorse or promote products derived from this software
15  *    without specific prior written permission.
16  *
17  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27  * SUCH DAMAGE.
28  */
29
30 /*
31  * PIC driver for the 8259A Master and Slave PICs in PC/AT machines.
32  */
33
34 #include <sys/cdefs.h>
35 __FBSDID("$FreeBSD$");
36
37 #include "opt_auto_eoi.h"
38 #include "opt_isa.h"
39
40 #include <sys/param.h>
41 #include <sys/systm.h>
42 #include <sys/bus.h>
43 #include <sys/interrupt.h>
44 #include <sys/kernel.h>
45 #include <sys/lock.h>
46 #include <sys/module.h>
47 #include <sys/mutex.h>
48
49 #include <machine/cpufunc.h>
50 #include <machine/frame.h>
51 #include <machine/intr_machdep.h>
52 #include <machine/md_var.h>
53 #include <machine/resource.h>
54 #include <machine/segments.h>
55
56 #include <dev/ic/i8259.h>
57 #include <amd64/isa/icu.h>
58 #include <amd64/isa/isa.h>
59
60 #include <isa/isavar.h>
61
62 #define MASTER  0
63 #define SLAVE   1
64
65 /*
66  * PC-AT machines wire the slave PIC to pin 2 on the master PIC.
67  */
68 #define ICU_SLAVEID     2
69
70 /*
71  * Determine the base master and slave modes not including auto EOI support.
72  * All machines that FreeBSD supports use 8086 mode.
73  */
74 #define BASE_MASTER_MODE        ICW4_8086
75 #define BASE_SLAVE_MODE         ICW4_8086
76
77 /* Enable automatic EOI if requested. */
78 #ifdef AUTO_EOI_1
79 #define MASTER_MODE             (BASE_MASTER_MODE | ICW4_AEOI)
80 #else
81 #define MASTER_MODE             BASE_MASTER_MODE
82 #endif
83 #ifdef AUTO_EOI_2
84 #define SLAVE_MODE              (BASE_SLAVE_MODE | ICW4_AEOI)
85 #else
86 #define SLAVE_MODE              BASE_SLAVE_MODE
87 #endif
88
89 #define IRQ_MASK(irq)           (1 << (irq))
90 #define IMEN_MASK(ai)           (IRQ_MASK((ai)->at_irq))
91
92 #define NUM_ISA_IRQS            16
93
94 static void     atpic_init(void *dummy);
95
96 unsigned int imen;      /* XXX */
97
98 inthand_t
99         IDTVEC(atpic_intr0), IDTVEC(atpic_intr1), IDTVEC(atpic_intr2),
100         IDTVEC(atpic_intr3), IDTVEC(atpic_intr4), IDTVEC(atpic_intr5),
101         IDTVEC(atpic_intr6), IDTVEC(atpic_intr7), IDTVEC(atpic_intr8),
102         IDTVEC(atpic_intr9), IDTVEC(atpic_intr10), IDTVEC(atpic_intr11),
103         IDTVEC(atpic_intr12), IDTVEC(atpic_intr13), IDTVEC(atpic_intr14),
104         IDTVEC(atpic_intr15);
105
106 #define IRQ(ap, ai)     ((ap)->at_irqbase + (ai)->at_irq)
107
108 #define ATPIC(io, base, eoi, imenptr)                                   \
109         { { atpic_enable_source, atpic_disable_source, (eoi),           \
110             atpic_enable_intr, atpic_disable_intr, atpic_vector,        \
111             atpic_source_pending, NULL, atpic_resume, atpic_config_intr,\
112             atpic_assign_cpu }, (io), (base), IDT_IO_INTS + (base),     \
113             (imenptr) }
114
115 #define INTSRC(irq)                                                     \
116         { { &atpics[(irq) / 8].at_pic }, IDTVEC(atpic_intr ## irq ),    \
117             (irq) % 8 }
118
119 struct atpic {
120         struct pic at_pic;
121         int     at_ioaddr;
122         int     at_irqbase;
123         uint8_t at_intbase;
124         uint8_t *at_imen;
125 };
126
127 struct atpic_intsrc {
128         struct intsrc at_intsrc;
129         inthand_t *at_intr;
130         int     at_irq;                 /* Relative to PIC base. */
131         enum intr_trigger at_trigger;
132         u_long  at_count;
133         u_long  at_straycount;
134 };
135
136 static void atpic_enable_source(struct intsrc *isrc);
137 static void atpic_disable_source(struct intsrc *isrc, int eoi);
138 static void atpic_eoi_master(struct intsrc *isrc);
139 static void atpic_eoi_slave(struct intsrc *isrc);
140 static void atpic_enable_intr(struct intsrc *isrc);
141 static void atpic_disable_intr(struct intsrc *isrc);
142 static int atpic_vector(struct intsrc *isrc);
143 static void atpic_resume(struct pic *pic);
144 static int atpic_source_pending(struct intsrc *isrc);
145 static int atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
146     enum intr_polarity pol);
147 static void atpic_assign_cpu(struct intsrc *isrc, u_int apic_id);
148 static void i8259_init(struct atpic *pic, int slave);
149
150 static struct atpic atpics[] = {
151         ATPIC(IO_ICU1, 0, atpic_eoi_master, (uint8_t *)&imen),
152         ATPIC(IO_ICU2, 8, atpic_eoi_slave, ((uint8_t *)&imen) + 1)
153 };
154
155 static struct atpic_intsrc atintrs[] = {
156         INTSRC(0),
157         INTSRC(1),
158         INTSRC(2),
159         INTSRC(3),
160         INTSRC(4),
161         INTSRC(5),
162         INTSRC(6),
163         INTSRC(7),
164         INTSRC(8),
165         INTSRC(9),
166         INTSRC(10),
167         INTSRC(11),
168         INTSRC(12),
169         INTSRC(13),
170         INTSRC(14),
171         INTSRC(15),
172 };
173
174 CTASSERT(sizeof(atintrs) / sizeof(atintrs[0]) == NUM_ISA_IRQS);
175
176 static __inline void
177 _atpic_eoi_master(struct intsrc *isrc)
178 {
179
180         KASSERT(isrc->is_pic == &atpics[MASTER].at_pic,
181             ("%s: mismatched pic", __func__));
182 #ifndef AUTO_EOI_1
183         outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
184 #endif
185 }
186
187 /*
188  * The data sheet says no auto-EOI on slave, but it sometimes works.
189  * So, if AUTO_EOI_2 is enabled, we use it.
190  */
191 static __inline void
192 _atpic_eoi_slave(struct intsrc *isrc)
193 {
194
195         KASSERT(isrc->is_pic == &atpics[SLAVE].at_pic,
196             ("%s: mismatched pic", __func__));
197 #ifndef AUTO_EOI_2
198         outb(atpics[SLAVE].at_ioaddr, OCW2_EOI);
199 #ifndef AUTO_EOI_1
200         outb(atpics[MASTER].at_ioaddr, OCW2_EOI);
201 #endif
202 #endif
203 }
204
205 static void
206 atpic_enable_source(struct intsrc *isrc)
207 {
208         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
209         struct atpic *ap = (struct atpic *)isrc->is_pic;
210
211         mtx_lock_spin(&icu_lock);
212         if (*ap->at_imen & IMEN_MASK(ai)) {
213                 *ap->at_imen &= ~IMEN_MASK(ai);
214                 outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
215         }
216         mtx_unlock_spin(&icu_lock);
217 }
218
219 static void
220 atpic_disable_source(struct intsrc *isrc, int eoi)
221 {
222         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
223         struct atpic *ap = (struct atpic *)isrc->is_pic;
224
225         mtx_lock_spin(&icu_lock);
226         if (ai->at_trigger != INTR_TRIGGER_EDGE) {
227                 *ap->at_imen |= IMEN_MASK(ai);
228                 outb(ap->at_ioaddr + ICU_IMR_OFFSET, *ap->at_imen);
229         }
230
231         /*
232          * Take care to call these functions directly instead of through
233          * a function pointer.  All of the referenced variables should
234          * still be hot in the cache.
235          */
236         if (eoi == PIC_EOI) {
237                 if (isrc->is_pic == &atpics[MASTER].at_pic)
238                         _atpic_eoi_master(isrc);
239                 else
240                         _atpic_eoi_slave(isrc);
241         }
242
243         mtx_unlock_spin(&icu_lock);
244 }
245
246 static void
247 atpic_eoi_master(struct intsrc *isrc)
248 {
249 #ifndef AUTO_EOI_1
250         mtx_lock_spin(&icu_lock);
251         _atpic_eoi_master(isrc);
252         mtx_unlock_spin(&icu_lock);
253 #endif
254 }
255
256 static void
257 atpic_eoi_slave(struct intsrc *isrc)
258 {
259 #ifndef AUTO_EOI_2
260         mtx_lock_spin(&icu_lock);
261         _atpic_eoi_slave(isrc);
262         mtx_unlock_spin(&icu_lock);
263 #endif
264 }
265
266 static void
267 atpic_enable_intr(struct intsrc *isrc)
268 {
269 }
270
271 static void
272 atpic_disable_intr(struct intsrc *isrc)
273 {
274 }
275
276
277 static int
278 atpic_vector(struct intsrc *isrc)
279 {
280         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
281         struct atpic *ap = (struct atpic *)isrc->is_pic;
282
283         return (IRQ(ap, ai));
284 }
285
286 static int
287 atpic_source_pending(struct intsrc *isrc)
288 {
289         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
290         struct atpic *ap = (struct atpic *)isrc->is_pic;
291
292         return (inb(ap->at_ioaddr) & IMEN_MASK(ai));
293 }
294
295 static void
296 atpic_resume(struct pic *pic)
297 {
298         struct atpic *ap = (struct atpic *)pic;
299
300         i8259_init(ap, ap == &atpics[SLAVE]);
301         if (ap == &atpics[SLAVE] && elcr_found)
302                 elcr_resume();
303 }
304
305 static int
306 atpic_config_intr(struct intsrc *isrc, enum intr_trigger trig,
307     enum intr_polarity pol)
308 {
309         struct atpic_intsrc *ai = (struct atpic_intsrc *)isrc;
310         u_int vector;
311
312         /* Map conforming values to edge/hi and sanity check the values. */
313         if (trig == INTR_TRIGGER_CONFORM)
314                 trig = INTR_TRIGGER_EDGE;
315         if (pol == INTR_POLARITY_CONFORM)
316                 pol = INTR_POLARITY_HIGH;
317         vector = atpic_vector(isrc);
318         if ((trig == INTR_TRIGGER_EDGE && pol == INTR_POLARITY_LOW) ||
319             (trig == INTR_TRIGGER_LEVEL && pol == INTR_POLARITY_HIGH)) {
320                 printf(
321                 "atpic: Mismatched config for IRQ%u: trigger %s, polarity %s\n",
322                     vector, trig == INTR_TRIGGER_EDGE ? "edge" : "level",
323                     pol == INTR_POLARITY_HIGH ? "high" : "low");
324                 return (EINVAL);
325         }
326
327         /* If there is no change, just return. */
328         if (ai->at_trigger == trig)
329                 return (0);
330
331         /*
332          * Certain IRQs can never be level/lo, so don't try to set them
333          * that way if asked.  At least some ELCR registers ignore setting
334          * these bits as well.
335          */
336         if ((vector == 0 || vector == 1 || vector == 2 || vector == 13) &&
337             trig == INTR_TRIGGER_LEVEL) {
338                 if (bootverbose)
339                         printf(
340                 "atpic: Ignoring invalid level/low configuration for IRQ%u\n",
341                             vector);
342                 return (EINVAL);
343         }
344         if (!elcr_found) {
345                 if (bootverbose)
346                         printf("atpic: No ELCR to configure IRQ%u as %s\n",
347                             vector, trig == INTR_TRIGGER_EDGE ? "edge/high" :
348                             "level/low");
349                 return (ENXIO);
350         }
351         if (bootverbose)
352                 printf("atpic: Programming IRQ%u as %s\n", vector,
353                     trig == INTR_TRIGGER_EDGE ? "edge/high" : "level/low");
354         mtx_lock_spin(&icu_lock);
355         elcr_write_trigger(atpic_vector(isrc), trig);
356         ai->at_trigger = trig;
357         mtx_unlock_spin(&icu_lock);
358         return (0);
359 }
360
361 static void
362 atpic_assign_cpu(struct intsrc *isrc, u_int apic_id)
363 {
364
365         /*
366          * 8259A's are only used in UP in which case all interrupts always
367          * go to the sole CPU and this function shouldn't even be called.
368          */
369         panic("%s: bad cookie", __func__);
370 }
371
372 static void
373 i8259_init(struct atpic *pic, int slave)
374 {
375         int imr_addr;
376
377         /* Reset the PIC and program with next four bytes. */
378         mtx_lock_spin(&icu_lock);
379         outb(pic->at_ioaddr, ICW1_RESET | ICW1_IC4);
380         imr_addr = pic->at_ioaddr + ICU_IMR_OFFSET;
381
382         /* Start vector. */
383         outb(imr_addr, pic->at_intbase);
384
385         /*
386          * Setup slave links.  For the master pic, indicate what line
387          * the slave is configured on.  For the slave indicate
388          * which line on the master we are connected to.
389          */
390         if (slave)
391                 outb(imr_addr, ICU_SLAVEID);
392         else
393                 outb(imr_addr, IRQ_MASK(ICU_SLAVEID));
394
395         /* Set mode. */
396         if (slave)
397                 outb(imr_addr, SLAVE_MODE);
398         else
399                 outb(imr_addr, MASTER_MODE);
400
401         /* Set interrupt enable mask. */
402         outb(imr_addr, *pic->at_imen);
403
404         /* Reset is finished, default to IRR on read. */
405         outb(pic->at_ioaddr, OCW3_SEL | OCW3_RR);
406
407         /* OCW2_L1 sets priority order to 3-7, 0-2 (com2 first). */
408         if (!slave)
409                 outb(pic->at_ioaddr, OCW2_R | OCW2_SL | OCW2_L1);
410         mtx_unlock_spin(&icu_lock);
411 }
412
413 void
414 atpic_startup(void)
415 {
416         struct atpic_intsrc *ai;
417         int i;
418
419         /* Start off with all interrupts disabled. */
420         imen = 0xffff;
421         i8259_init(&atpics[MASTER], 0);
422         i8259_init(&atpics[SLAVE], 1);
423         atpic_enable_source((struct intsrc *)&atintrs[ICU_SLAVEID]);
424
425         /* Install low-level interrupt handlers for all of our IRQs. */
426         for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
427                 if (i == ICU_SLAVEID)
428                         continue;
429                 ai->at_intsrc.is_count = &ai->at_count;
430                 ai->at_intsrc.is_straycount = &ai->at_straycount;
431                 setidt(((struct atpic *)ai->at_intsrc.is_pic)->at_intbase +
432                     ai->at_irq, ai->at_intr, SDT_SYSIGT, SEL_KPL, 0);
433         }
434
435         /*
436          * Look for an ELCR.  If we find one, update the trigger modes.
437          * If we don't find one, assume that IRQs 0, 1, 2, and 13 are
438          * edge triggered and that everything else is level triggered.
439          * We only use the trigger information to reprogram the ELCR if
440          * we have one and as an optimization to avoid masking edge
441          * triggered interrupts.  For the case that we don't have an ELCR,
442          * it doesn't hurt to mask an edge triggered interrupt, so we
443          * assume level trigger for any interrupt that we aren't sure is
444          * edge triggered.
445          */
446         if (elcr_found) {
447                 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
448                         ai->at_trigger = elcr_read_trigger(i);
449         } else {
450                 for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++)
451                         switch (i) {
452                         case 0:
453                         case 1:
454                         case 2:
455                         case 8:
456                         case 13:
457                                 ai->at_trigger = INTR_TRIGGER_EDGE;
458                                 break;
459                         default:
460                                 ai->at_trigger = INTR_TRIGGER_LEVEL;
461                                 break;
462                         }
463         }
464 }
465
466 static void
467 atpic_init(void *dummy __unused)
468 {
469         struct atpic_intsrc *ai;
470         int i;
471
472         /*
473          * Register our PICs, even if we aren't going to use any of their
474          * pins so that they are suspended and resumed.
475          */
476         if (intr_register_pic(&atpics[0].at_pic) != 0 ||
477             intr_register_pic(&atpics[1].at_pic) != 0)
478                 panic("Unable to register ATPICs");
479
480         /*
481          * If any of the ISA IRQs have an interrupt source already, then
482          * assume that the APICs are being used and don't register any
483          * of our interrupt sources.  This makes sure we don't accidentally
484          * use mixed mode.  The "accidental" use could otherwise occur on
485          * machines that route the ACPI SCI interrupt to a different ISA
486          * IRQ (at least one machines routes it to IRQ 13) thus disabling
487          * that APIC ISA routing and allowing the ATPIC source for that IRQ
488          * to leak through.  We used to depend on this feature for routing
489          * IRQ0 via mixed mode, but now we don't use mixed mode at all.
490          */
491         for (i = 0; i < NUM_ISA_IRQS; i++)
492                 if (intr_lookup_source(i) != NULL)
493                         return;
494
495         /* Loop through all interrupt sources and add them. */
496         for (i = 0, ai = atintrs; i < NUM_ISA_IRQS; i++, ai++) {
497                 if (i == ICU_SLAVEID)
498                         continue;
499                 intr_register_source(&ai->at_intsrc);
500         }
501 }
502 SYSINIT(atpic_init, SI_SUB_INTR, SI_ORDER_SECOND + 1, atpic_init, NULL);
503
504 void
505 atpic_handle_intr(u_int vector, struct trapframe *frame)
506 {
507         struct intsrc *isrc;
508
509         KASSERT(vector < NUM_ISA_IRQS, ("unknown int %u\n", vector));
510         isrc = &atintrs[vector].at_intsrc;
511
512         /*
513          * If we don't have an event, see if this is a spurious
514          * interrupt.
515          */
516         if (isrc->is_event == NULL && (vector == 7 || vector == 15)) {
517                 int port, isr;
518
519                 /*
520                  * Read the ISR register to see if IRQ 7/15 is really
521                  * pending.  Reset read register back to IRR when done.
522                  */
523                 port = ((struct atpic *)isrc->is_pic)->at_ioaddr;
524                 mtx_lock_spin(&icu_lock);
525                 outb(port, OCW3_SEL | OCW3_RR | OCW3_RIS);
526                 isr = inb(port);
527                 outb(port, OCW3_SEL | OCW3_RR);
528                 mtx_unlock_spin(&icu_lock);
529                 if ((isr & IRQ_MASK(7)) == 0)
530                         return;
531         }
532         intr_execute_handlers(isrc, frame);
533 }
534
535 #ifdef DEV_ISA
536 /*
537  * Bus attachment for the ISA PIC.
538  */
539 static struct isa_pnp_id atpic_ids[] = {
540         { 0x0000d041 /* PNP0000 */, "AT interrupt controller" },
541         { 0 }
542 };
543
544 static int
545 atpic_probe(device_t dev)
546 {
547         int result;
548         
549         result = ISA_PNP_PROBE(device_get_parent(dev), dev, atpic_ids);
550         if (result <= 0)
551                 device_quiet(dev);
552         return (result);
553 }
554
555 /*
556  * We might be granted IRQ 2, as this is typically consumed by chaining
557  * between the two PIC components.  If we're using the APIC, however,
558  * this may not be the case, and as such we should free the resource.
559  * (XXX untested)
560  *
561  * The generic ISA attachment code will handle allocating any other resources
562  * that we don't explicitly claim here.
563  */
564 static int
565 atpic_attach(device_t dev)
566 {
567         struct resource *res;
568         int rid;
569
570         /* Try to allocate our IRQ and then free it. */
571         rid = 0;
572         res = bus_alloc_resource_any(dev, SYS_RES_IRQ, &rid, 0);
573         if (res != NULL)
574                 bus_release_resource(dev, SYS_RES_IRQ, rid, res);
575         return (0);
576 }
577
578 static device_method_t atpic_methods[] = {
579         /* Device interface */
580         DEVMETHOD(device_probe,         atpic_probe),
581         DEVMETHOD(device_attach,        atpic_attach),
582         DEVMETHOD(device_detach,        bus_generic_detach),
583         DEVMETHOD(device_shutdown,      bus_generic_shutdown),
584         DEVMETHOD(device_suspend,       bus_generic_suspend),
585         DEVMETHOD(device_resume,        bus_generic_resume),
586         { 0, 0 }
587 };
588
589 static driver_t atpic_driver = {
590         "atpic",
591         atpic_methods,
592         1,              /* no softc */
593 };
594
595 static devclass_t atpic_devclass;
596
597 DRIVER_MODULE(atpic, isa, atpic_driver, atpic_devclass, 0, 0);
598 DRIVER_MODULE(atpic, acpi, atpic_driver, atpic_devclass, 0, 0);
599
600 /*
601  * Return a bitmap of the current interrupt requests.  This is 8259-specific
602  * and is only suitable for use at probe time.
603  */
604 intrmask_t
605 isa_irq_pending(void)
606 {
607         u_char irr1;
608         u_char irr2;
609
610         irr1 = inb(IO_ICU1);
611         irr2 = inb(IO_ICU2);
612         return ((irr2 << 8) | irr1);
613 }
614 #endif /* DEV_ISA */