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