1 /*        $NetBSD: ioapic.c,v 1.66 2022/10/06 06:42:46 msaitoh Exp $  */
2 
3 /*-
4  * Copyright (c) 2000, 2009 The NetBSD Foundation, Inc.
5  * All rights reserved.
6  *
7  * This code is derived from software contributed to The NetBSD Foundation
8  * by RedBack Networks Inc, and by Andrew Doran.
9  *
10  * Author: Bill Sommerfeld
11  *
12  * Redistribution and use in source and binary forms, with or without
13  * modification, are permitted provided that the following conditions
14  * are met:
15  * 1. Redistributions of source code must retain the above copyright
16  *    notice, this list of conditions and the following disclaimer.
17  * 2. Redistributions in binary form must reproduce the above copyright
18  *    notice, this list of conditions and the following disclaimer in the
19  *    documentation and/or other materials provided with the distribution.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
22  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
23  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
25  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31  * POSSIBILITY OF SUCH DAMAGE.
32  */
33 
34 /*
35  * Copyright (c) 1999 Stefan Grefen
36  *
37  * Redistribution and use in source and binary forms, with or without
38  * modification, are permitted provided that the following conditions
39  * are met:
40  * 1. Redistributions of source code must retain the above copyright
41  *    notice, this list of conditions and the following disclaimer.
42  * 2. Redistributions in binary form must reproduce the above copyright
43  *    notice, this list of conditions and the following disclaimer in the
44  *    documentation and/or other materials provided with the distribution.
45  * 3. All advertising materials mentioning features or use of this software
46  *    must display the following acknowledgement:
47  *      This product includes software developed by the NetBSD
48  *      Foundation, Inc. and its contributors.
49  * 4. Neither the name of The NetBSD Foundation nor the names of its
50  *    contributors may be used to endorse or promote products derived
51  *    from this software without specific prior written permission.
52  *
53  * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND ANY
54  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
55  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
56  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR AND CONTRIBUTORS BE LIABLE
57  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
58  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
59  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
60  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
61  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
62  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
63  * SUCH DAMAGE.
64  */
65 
66 #include <sys/cdefs.h>
67 __KERNEL_RCSID(0, "$NetBSD: ioapic.c,v 1.66 2022/10/06 06:42:46 msaitoh Exp $");
68 
69 #include "opt_ddb.h"
70 
71 #include <sys/param.h>
72 #include <sys/systm.h>
73 #include <sys/device.h>
74 #include <sys/malloc.h>
75 #include <sys/kernel.h>
76 #include <sys/bus.h>
77 
78 #include <uvm/uvm_extern.h>
79 
80 #include <machine/isa_machdep.h> /* XXX intrhand */
81 #include <machine/i82093reg.h>
82 #include <machine/i82093var.h>
83 #include <machine/i82489reg.h>
84 #include <machine/i82489var.h>
85 #include <machine/i8259.h>
86 #include <machine/mpbiosvar.h>
87 #include <machine/pio.h>
88 #include <machine/pmap.h>
89 #include <machine/lock.h>
90 
91 #include "acpica.h"
92 #include "opt_mpbios.h"
93 #include "opt_acpi.h"
94 
95 #if !defined(MPBIOS) && NACPICA == 0
96 #error "ioapic needs at least one of the MPBIOS or ACPI options"
97 #endif
98 
99 /*
100  * XXX locking
101  */
102 
103 int     ioapic_match(device_t, cfdata_t, void *);
104 void    ioapic_attach(device_t, device_t, void *);
105 
106 extern int x86_mem_add_mapping(bus_addr_t, bus_size_t,
107     int, bus_space_handle_t *); /* XXX XXX */
108 
109 void ioapic_hwmask(struct pic *, int);
110 void ioapic_hwunmask(struct pic *, int);
111 bool ioapic_trymask(struct pic *, int);
112 static void ioapic_addroute(struct pic *, struct cpu_info *, int, int, int);
113 static void ioapic_delroute(struct pic *, struct cpu_info *, int, int, int);
114 
115 struct ioapic_softc *ioapics; /* head of linked list */
116 int nioapics = 0;             /* number attached */
117 static int ioapic_vecbase;
118 
119 static inline u_long
ioapic_lock(struct ioapic_softc * sc)120 ioapic_lock(struct ioapic_softc *sc)
121 {
122           u_long flags;
123 
124           flags = x86_read_psl();
125           x86_disable_intr();
126           __cpu_simple_lock(&sc->sc_pic.pic_lock);
127           return flags;
128 }
129 
130 static inline void
ioapic_unlock(struct ioapic_softc * sc,u_long flags)131 ioapic_unlock(struct ioapic_softc *sc, u_long flags)
132 {
133           __cpu_simple_unlock(&sc->sc_pic.pic_lock);
134           x86_write_psl(flags);
135 }
136 
137 #ifndef _IOAPIC_CUSTOM_RW
138 /*
139  * Register read/write routines.
140  */
141 static inline  uint32_t
ioapic_read_ul(struct ioapic_softc * sc,int regid)142 ioapic_read_ul(struct ioapic_softc *sc, int regid)
143 {
144           uint32_t val;
145 
146           *(sc->sc_reg) = regid;
147           val = *sc->sc_data;
148 
149           return val;
150 }
151 
152 static inline  void
ioapic_write_ul(struct ioapic_softc * sc,int regid,uint32_t val)153 ioapic_write_ul(struct ioapic_softc *sc, int regid, uint32_t val)
154 {
155           *(sc->sc_reg) = regid;
156           *(sc->sc_data) = val;
157 }
158 #endif /* !_IOAPIC_CUSTOM_RW */
159 
160 static inline uint32_t
ioapic_read(struct ioapic_softc * sc,int regid)161 ioapic_read(struct ioapic_softc *sc, int regid)
162 {
163           uint32_t val;
164           u_long flags;
165 
166           flags = ioapic_lock(sc);
167           val = ioapic_read_ul(sc, regid);
168           ioapic_unlock(sc, flags);
169           return val;
170 }
171 
172 static inline  void
ioapic_write(struct ioapic_softc * sc,int regid,int val)173 ioapic_write(struct ioapic_softc *sc, int regid, int val)
174 {
175           u_long flags;
176 
177           flags = ioapic_lock(sc);
178           ioapic_write_ul(sc, regid, val);
179           ioapic_unlock(sc, flags);
180 }
181 
182 struct ioapic_softc *
ioapic_find(int apicid)183 ioapic_find(int apicid)
184 {
185           struct ioapic_softc *sc;
186 
187           if (apicid == MPS_ALL_APICS) {          /* XXX mpbios-specific */
188                     /*
189                      * XXX kludge for all-ioapics interrupt support
190                      * on single ioapic systems
191                      */
192                     if (nioapics <= 1)
193                               return ioapics;
194                     panic("unsupported: all-ioapics interrupt with >1 ioapic");
195           }
196 
197           for (sc = ioapics; sc != NULL; sc = sc->sc_next)
198                     if (sc->sc_pic.pic_apicid == apicid)
199                               return sc;
200 
201           return NULL;
202 }
203 
204 /*
205  * For the case the I/O APICs were configured using ACPI, there must
206  * be an option to match global ACPI interrupts with APICs.
207  */
208 struct ioapic_softc *
ioapic_find_bybase(int vec)209 ioapic_find_bybase(int vec)
210 {
211           struct ioapic_softc *sc;
212 
213           for (sc = ioapics; sc != NULL; sc = sc->sc_next) {
214                     if (vec >= sc->sc_pic.pic_vecbase &&
215                         vec < (sc->sc_pic.pic_vecbase + sc->sc_apic_sz))
216                               return sc;
217           }
218 
219           return NULL;
220 }
221 
222 static inline void
ioapic_add(struct ioapic_softc * sc)223 ioapic_add(struct ioapic_softc *sc)
224 {
225           struct ioapic_softc **scp;
226 
227           sc->sc_next = NULL;
228 
229           for (scp = &ioapics; *scp != NULL; scp = &(*scp)->sc_next)
230                     ;
231           *scp = sc;
232           nioapics++;
233 }
234 
235 void
ioapic_print_redir(struct ioapic_softc * sc,const char * why,int pin)236 ioapic_print_redir(struct ioapic_softc *sc, const char *why, int pin)
237 {
238           uint32_t redirlo = ioapic_read(sc, IOAPIC_REDLO(pin));
239           uint32_t redirhi = ioapic_read(sc, IOAPIC_REDHI(pin));
240 
241           apic_format_redir(device_xname(sc->sc_dev), why, pin,
242               APIC_VECTYPE_IOAPIC, redirhi, redirlo);
243 }
244 
245 CFATTACH_DECL_NEW(ioapic, sizeof(struct ioapic_softc),
246     ioapic_match, ioapic_attach, NULL, NULL);
247 
248 int
ioapic_match(device_t parent,cfdata_t match,void * aux)249 ioapic_match(device_t parent, cfdata_t match, void *aux)
250 {
251 
252           return 1;
253 }
254 
255 /*
256  * can't use bus_space_xxx as we don't have a bus handle ...
257  */
258 void
ioapic_attach(device_t parent,device_t self,void * aux)259 ioapic_attach(device_t parent, device_t self, void *aux)
260 {
261           struct ioapic_softc *sc = device_private(self);
262           struct apic_attach_args *aaa = (struct apic_attach_args *)aux;
263           int apic_id;
264           uint32_t ver_sz;
265           int i;
266 
267           sc->sc_dev = self;
268           sc->sc_flags = aaa->flags;
269           sc->sc_pic.pic_apicid = aaa->apic_id;
270           sc->sc_pic.pic_name = device_xname(self);
271           sc->sc_pic.pic_ioapic = sc;
272 
273           aprint_naive("\n");
274 
275           if (ioapic_find(aaa->apic_id) != NULL) {
276                     aprint_error(": duplicate apic id (ignored)\n");
277                     return;
278           }
279 
280           aprint_verbose(": pa 0x%jx", (uintmax_t)aaa->apic_address);
281 #ifndef _IOAPIC_CUSTOM_RW
282           {
283           bus_space_handle_t bh;
284 
285           if (x86_mem_add_mapping(aaa->apic_address, PAGE_SIZE, 0, &bh) != 0) {
286                     aprint_error(": map failed\n");
287                     return;
288           }
289           sc->sc_reg = (volatile uint32_t *)(bh + IOAPIC_REG);
290           sc->sc_data = (volatile uint32_t *)(bh + IOAPIC_DATA);
291           }
292 #endif
293           sc->sc_pa = aaa->apic_address;
294 
295           sc->sc_pic.pic_type = PIC_IOAPIC;
296           __cpu_simple_lock_init(&sc->sc_pic.pic_lock);
297           sc->sc_pic.pic_hwmask = ioapic_hwmask;
298           sc->sc_pic.pic_hwunmask = ioapic_hwunmask;
299           sc->sc_pic.pic_addroute = ioapic_addroute;
300           sc->sc_pic.pic_delroute = ioapic_delroute;
301           sc->sc_pic.pic_trymask = ioapic_trymask;
302           sc->sc_pic.pic_edge_stubs = ioapic_edge_stubs;
303           sc->sc_pic.pic_level_stubs = ioapic_level_stubs;
304           sc->sc_pic.pic_intr_get_devname = x86_intr_get_devname;
305           sc->sc_pic.pic_intr_get_assigned = x86_intr_get_assigned;
306           sc->sc_pic.pic_intr_get_count = x86_intr_get_count;
307 
308           apic_id = (ioapic_read(sc, IOAPIC_ID) & IOAPIC_ID_MASK)
309               >> IOAPIC_ID_SHIFT;
310           ver_sz = ioapic_read(sc, IOAPIC_VER);
311 
312           if (ver_sz == 0xffffffff) {
313                     aprint_error(": failed to read version/size\n");
314                     goto out;
315           }
316 
317           ioapic_add(sc);
318 
319           sc->sc_apic_vers = (ver_sz & IOAPIC_VER_MASK) >> IOAPIC_VER_SHIFT;
320           sc->sc_apic_sz = (ver_sz & IOAPIC_MAX_MASK) >> IOAPIC_MAX_SHIFT;
321           sc->sc_apic_sz++;
322 
323           if (aaa->apic_vecbase != -1)
324                     sc->sc_pic.pic_vecbase = aaa->apic_vecbase;
325           else {
326                     /*
327                      * XXX this assumes ordering of ioapics in the table.
328                      * Only needed for broken BIOS workaround (see mpbios.c)
329                      */
330                     sc->sc_pic.pic_vecbase = ioapic_vecbase;
331                     ioapic_vecbase += sc->sc_apic_sz;
332           }
333 
334           if (mp_verbose) {
335                     printf(", %s mode",
336                         aaa->flags & IOAPIC_PICMODE ? "PIC" : "virtual wire");
337           }
338 
339           aprint_verbose(", version 0x%x, %d pins", sc->sc_apic_vers,
340               sc->sc_apic_sz);
341           aprint_normal("\n");
342 
343           sc->sc_pins = malloc(sizeof(struct ioapic_pin) * sc->sc_apic_sz,
344               M_DEVBUF, M_WAITOK);
345 
346           for (i = 0; i < sc->sc_apic_sz; i++) {
347                     uint32_t redlo, redhi;
348 
349                     sc->sc_pins[i].ip_next = NULL;
350                     sc->sc_pins[i].ip_map = NULL;
351                     sc->sc_pins[i].ip_vector = 0;
352                     sc->sc_pins[i].ip_type = IST_NONE;
353 
354                     /* Mask all pins by default. */
355                     redlo = IOAPIC_REDLO_MASK;
356                     /*
357                      * ISA interrupts are connect to pin 0-15 and
358                      * edge triggered on high, which is the default.
359                      *
360                      * Expect all other interrupts to be PCI-like
361                      * level triggered on low.
362                      */
363                     if (i >= 16)
364                               redlo |= IOAPIC_REDLO_LEVEL | IOAPIC_REDLO_ACTLO;
365                     redhi = (cpu_info_primary.ci_cpuid << IOAPIC_REDHI_DEST_SHIFT);
366                     ioapic_write(sc, IOAPIC_REDHI(i), redhi);
367                     ioapic_write(sc, IOAPIC_REDLO(i), redlo);
368           }
369 
370           /*
371            * In case the APIC is not initialized to the correct ID
372            * do it now.
373            * Maybe we should record the original ID for interrupt
374            * mapping later ...
375            */
376           if (apic_id != sc->sc_pic.pic_apicid) {
377                     aprint_debug_dev(sc->sc_dev,
378                         "apid is misconfigured (%d != %d)\n",
379                         apic_id, sc->sc_pic.pic_apicid);
380 
381                     ioapic_write(sc, IOAPIC_ID,
382                         (ioapic_read(sc, IOAPIC_ID) & ~IOAPIC_ID_MASK)
383                         | (sc->sc_pic.pic_apicid << IOAPIC_ID_SHIFT));
384 
385                     apic_id = (ioapic_read(sc, IOAPIC_ID) & IOAPIC_ID_MASK)
386                         >> IOAPIC_ID_SHIFT;
387 
388                     if (apic_id != sc->sc_pic.pic_apicid)
389                               aprint_error_dev(sc->sc_dev,
390                                   "can't remap apid from %d to %d\n",
391                                   apic_id, sc->sc_pic.pic_apicid);
392                     else
393                               aprint_debug_dev(sc->sc_dev, "remapped to apic %d\n",
394                                   sc->sc_pic.pic_apicid);
395           }
396 
397  out:
398           if (!pmf_device_register(self, NULL, NULL))
399                     aprint_error_dev(self, "couldn't establish power handler\n");
400 
401 #if 0
402           /* output of this was boring. */
403           if (mp_verbose)
404                     for (i = 0; i < sc->sc_apic_sz; i++)
405                               ioapic_print_redir(sc, "boot", i);
406 #endif
407 }
408 
409 static void
apic_set_redir(struct ioapic_softc * sc,int pin,int idt_vec,struct cpu_info * ci)410 apic_set_redir(struct ioapic_softc *sc, int pin, int idt_vec,
411                  struct cpu_info *ci)
412 {
413           uint32_t redlo;
414           uint32_t redhi;
415           int delmode;
416           struct ioapic_pin *pp;
417           struct mp_intr_map *map;
418 
419           pp = &sc->sc_pins[pin];
420           map = pp->ip_map;
421           redlo = map == NULL ? IOAPIC_REDLO_MASK : map->redir;
422           redhi = 0;
423           delmode = (redlo & IOAPIC_REDLO_DEL_MASK) >> IOAPIC_REDLO_DEL_SHIFT;
424 
425           if (delmode == IOAPIC_REDLO_DEL_FIXED ||
426               delmode == IOAPIC_REDLO_DEL_LOPRI) {
427                     if (pp->ip_type == IST_NONE) {
428                               redlo |= IOAPIC_REDLO_MASK;
429                     } else {
430                               redhi = (ci->ci_cpuid << IOAPIC_REDHI_DEST_SHIFT);
431                               redlo |= (idt_vec & 0xff);
432                               redlo |= IOAPIC_REDLO_DEL_FIXED
433                                   << IOAPIC_REDLO_DEL_SHIFT;
434                               redlo &= ~IOAPIC_REDLO_DSTMOD;
435 
436                               /* XXX derive this bit from BIOS info */
437                               if (pp->ip_type == IST_LEVEL)
438                                         redlo |= IOAPIC_REDLO_LEVEL;
439                               else
440                                         redlo &= ~IOAPIC_REDLO_LEVEL;
441                               if ((map != NULL)
442                                   && ((map->flags & 3) == MPS_INTPO_DEF)) {
443                                         if (pp->ip_type == IST_LEVEL)
444                                                   redlo |= IOAPIC_REDLO_ACTLO;
445                                         else
446                                                   redlo &= ~IOAPIC_REDLO_ACTLO;
447                               }
448                     }
449           }
450           ioapic_write(sc, IOAPIC_REDHI(pin), redhi);
451           ioapic_write(sc, IOAPIC_REDLO(pin), redlo);
452           if (mp_verbose)
453                     ioapic_print_redir(sc, "int", pin);
454 }
455 
456 /*
457  * Throw the switch and enable interrupts..
458  */
459 
460 void
ioapic_enable(void)461 ioapic_enable(void)
462 {
463           if (ioapics == NULL)
464                     return;
465 
466           i8259_setmask(0xffff);
467 
468           if (ioapics->sc_flags & IOAPIC_PICMODE) {
469                     aprint_debug_dev(ioapics->sc_dev,
470                                          "writing to IMCR to disable pics\n");
471                     outb(IMCR_ADDR, IMCR_REGISTER);
472                     outb(IMCR_DATA, IMCR_APIC);
473           }
474 }
475 
476 void
ioapic_reenable(void)477 ioapic_reenable(void)
478 {
479           int p, apic_id;
480           struct ioapic_softc *sc;
481 
482           if (ioapics == NULL)
483                     return;
484 
485           aprint_normal("%s reenabling\n", device_xname(ioapics->sc_dev));
486 
487           for (sc = ioapics; sc != NULL; sc = sc->sc_next) {
488                     apic_id = (ioapic_read(sc, IOAPIC_ID) & IOAPIC_ID_MASK)
489                         >> IOAPIC_ID_SHIFT;
490                     if (apic_id != sc->sc_pic.pic_apicid) {
491                               ioapic_write(sc, IOAPIC_ID,
492                                   (ioapic_read(sc, IOAPIC_ID) & ~IOAPIC_ID_MASK)
493                                   | (sc->sc_pic.pic_apicid << IOAPIC_ID_SHIFT));
494                     }
495 
496                     for (p = 0; p < sc->sc_apic_sz; p++)
497                               apic_set_redir(sc, p, sc->sc_pins[p].ip_vector,
498                                             sc->sc_pins[p].ip_cpu);
499           }
500 
501           ioapic_enable();
502 }
503 
504 void
ioapic_hwmask(struct pic * pic,int pin)505 ioapic_hwmask(struct pic *pic, int pin)
506 {
507           uint32_t redlo;
508           struct ioapic_softc *sc = pic->pic_ioapic;
509           u_long flags;
510 
511           flags = ioapic_lock(sc);
512           redlo = ioapic_read_ul(sc, IOAPIC_REDLO(pin));
513           redlo |= IOAPIC_REDLO_MASK;
514           redlo &= ~IOAPIC_REDLO_RIRR;
515           ioapic_write_ul(sc, IOAPIC_REDLO(pin), redlo);
516           ioapic_unlock(sc, flags);
517 }
518 
519 bool
ioapic_trymask(struct pic * pic,int pin)520 ioapic_trymask(struct pic *pic, int pin)
521 {
522           uint32_t redlo;
523           struct ioapic_softc *sc = pic->pic_ioapic;
524           u_long flags;
525           bool rv;
526 
527           /* Mask it. */
528           flags = ioapic_lock(sc);
529           redlo = ioapic_read_ul(sc, IOAPIC_REDLO(pin));
530           redlo |= IOAPIC_REDLO_MASK;
531           ioapic_write_ul(sc, IOAPIC_REDLO(pin), redlo);
532 
533           /* If pending, unmask and abort. */
534           redlo = ioapic_read_ul(sc, IOAPIC_REDLO(pin));
535           if ((redlo & (IOAPIC_REDLO_RIRR | IOAPIC_REDLO_DELSTS)) != 0) {
536                     redlo &= ~IOAPIC_REDLO_MASK;
537                     ioapic_write_ul(sc, IOAPIC_REDLO(pin), redlo);
538                     rv = false;
539           } else {
540                     rv = true;
541           }
542           ioapic_unlock(sc, flags);
543           return rv;
544 }
545 
546 void
ioapic_hwunmask(struct pic * pic,int pin)547 ioapic_hwunmask(struct pic *pic, int pin)
548 {
549           uint32_t redlo;
550           struct ioapic_softc *sc = pic->pic_ioapic;
551           u_long flags;
552 
553           flags = ioapic_lock(sc);
554           redlo = ioapic_read_ul(sc, IOAPIC_REDLO(pin));
555           redlo &= ~(IOAPIC_REDLO_MASK | IOAPIC_REDLO_RIRR);
556           ioapic_write_ul(sc, IOAPIC_REDLO(pin), redlo);
557           ioapic_unlock(sc, flags);
558 }
559 
560 static void
ioapic_addroute(struct pic * pic,struct cpu_info * ci,int pin,int idtvec,int type)561 ioapic_addroute(struct pic *pic, struct cpu_info *ci, int pin,
562                     int idtvec, int type)
563 {
564           struct ioapic_softc *sc = pic->pic_ioapic;
565           struct ioapic_pin *pp;
566 
567           pp = &sc->sc_pins[pin];
568           pp->ip_type = type;
569           pp->ip_vector = idtvec;
570           pp->ip_cpu = ci;
571           apic_set_redir(sc, pin, idtvec, ci);
572 }
573 
574 static void
ioapic_delroute(struct pic * pic,struct cpu_info * ci,int pin,int idtvec,int type)575 ioapic_delroute(struct pic *pic, struct cpu_info *ci, int pin,
576     int idtvec, int type)
577 {
578 
579           ioapic_hwmask(pic, pin);
580 }
581 
582 #ifdef DDB
583 void ioapic_dump(void);
584 void ioapic_dump_raw(void);
585 
586 void
ioapic_dump(void)587 ioapic_dump(void)
588 {
589           struct ioapic_softc *sc;
590           struct ioapic_pin *ip;
591           int p;
592 
593           for (sc = ioapics; sc != NULL; sc = sc->sc_next) {
594                     for (p = 0; p < sc->sc_apic_sz; p++) {
595                               ip = &sc->sc_pins[p];
596                               if (ip->ip_type != IST_NONE)
597                                         ioapic_print_redir(sc, "dump", p);
598                     }
599           }
600 }
601 
602 void
ioapic_dump_raw(void)603 ioapic_dump_raw(void)
604 {
605           struct ioapic_softc *sc;
606           int i;
607           uint32_t reg;
608 
609           for (sc = ioapics; sc != NULL; sc = sc->sc_next) {
610                     printf("Register dump of %s\n", device_xname(sc->sc_dev));
611                     i = 0;
612                     do {
613                               if (i % 0x08 == 0)
614                                         printf("%02x", i);
615                               reg = ioapic_read(sc, i);
616                               printf(" %08x", (u_int)reg);
617                               if (++i % 0x08 == 0)
618                                         printf("\n");
619                     } while (i < IOAPIC_REDTBL + (sc->sc_apic_sz * 2));
620           }
621 }
622 #endif
623