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