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