This source file includes following definitions.
- mp_print
- mp_match
- mpbios_map
- mpbios_unmap
- mpbios_probe
- mpbios_cksum
- mpbios_search
- mpbios_scan
- mpbios_invent
- mpbios_cpu
- mp_cfg_special_intr
- mp_cfg_pci_intr
- mp_cfg_eisa_intr
- mp_cfg_isa_intr
- mp_print_special_intr
- mp_print_pci_intr
- mp_print_isa_intr
- mp_print_eisa_intr
- mpbios_bus
- mpbios_ioapic
- mpbios_int
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106 #include "mpbios.h"
107
108 #include <sys/param.h>
109 #include <sys/systm.h>
110 #include <sys/kernel.h>
111 #include <sys/device.h>
112 #include <sys/malloc.h>
113
114 #include <uvm/uvm_extern.h>
115
116 #include <machine/specialreg.h>
117 #include <machine/cputypes.h>
118 #include <machine/cpuvar.h>
119 #include <machine/bus.h>
120 #include <machine/mpbiosreg.h>
121 #include <machine/mpbiosvar.h>
122
123 #include <machine/i82093reg.h>
124 #include <machine/i82093var.h>
125 #include <machine/i82489reg.h>
126 #include <machine/i82489var.h>
127
128 #include <dev/isa/isareg.h>
129 #include <dev/pci/pcivar.h>
130
131 #include <dev/eisa/eisavar.h>
132
133 #include "pci.h"
134
135
136 static struct mpbios_ioapic default_ioapic = {
137 2, 0, 1, IOAPICENTRY_FLAG_EN, (caddr_t)IOAPIC_BASE_DEFAULT
138 };
139
140
141 struct mpbios_baseentry {
142 u_int8_t type;
143 u_int8_t length;
144 u_int16_t count;
145 const char *name;
146 };
147
148 static const char *loc_where[] = {
149 "extended bios data area",
150 "last page of base memory",
151 "bios"
152 };
153
154 struct mp_map
155 {
156 vaddr_t baseva;
157 int vsize;
158 paddr_t pa;
159 paddr_t pg;
160 int psize;
161 };
162
163 int mp_print(void *, const char *);
164 int mp_match(struct device *, void *, void *);
165 int mpbios_cpu_start(struct cpu_info *);
166 const void *mpbios_search(struct device *, paddr_t, int,
167 struct mp_map *);
168 static __inline int mpbios_cksum(const void *, int);
169
170 void mp_cfg_special_intr(const struct mpbios_int *, u_int32_t *);
171 void mp_cfg_pci_intr(const struct mpbios_int *, u_int32_t *);
172 void mp_cfg_eisa_intr(const struct mpbios_int *, u_int32_t *);
173 void mp_cfg_isa_intr(const struct mpbios_int *, u_int32_t *);
174 void mp_print_special_intr (int);
175 void mp_print_pci_intr (int);
176 void mp_print_eisa_intr (int);
177 void mp_print_isa_intr (int);
178
179 void mpbios_cpu(const u_int8_t *, struct device *);
180 void mpbios_bus(const u_int8_t *, struct device *);
181 void mpbios_ioapic(const u_int8_t *, struct device *);
182 int mpbios_int(const u_int8_t *, struct mp_intr_map *);
183
184 const void *mpbios_map(paddr_t, int, struct mp_map *);
185 static __inline void mpbios_unmap(struct mp_map *);
186
187
188
189
190
191 static struct mp_map mp_cfg_table_map;
192 static struct mp_map mp_fp_map;
193 const struct mpbios_cth *mp_cth;
194 const struct mpbios_fps *mp_fps;
195
196 #ifdef MPVERBOSE
197 int mp_verbose = 1;
198 #else
199 int mp_verbose = 0;
200 #endif
201
202 int
203 mp_print(void *aux, const char *pnp)
204 {
205 struct cpu_attach_args * caa = (struct cpu_attach_args *) aux;
206 if (pnp)
207 printf("%s at %s:", caa->caa_name, pnp);
208 return (UNCONF);
209 }
210
211 int
212 mp_match(struct device *parent, void *cfv, void *aux)
213 {
214 struct cfdata *cf = (struct cfdata *)cfv;
215 struct cpu_attach_args * caa = (struct cpu_attach_args *) aux;
216 if (strcmp(caa->caa_name, cf->cf_driver->cd_name))
217 return 0;
218
219 return ((*cf->cf_attach->ca_match)(parent, cf, aux));
220 }
221
222
223
224
225
226 const void *
227 mpbios_map(paddr_t pa, int len, struct mp_map *handle)
228 {
229 paddr_t pgpa = trunc_page(pa);
230 paddr_t endpa = round_page(pa + len);
231 vaddr_t va = uvm_km_valloc(kernel_map, endpa - pgpa);
232 vaddr_t retva = va + (pa & PGOFSET);
233
234 handle->pa = pa;
235 handle->pg = pgpa;
236 handle->psize = len;
237 handle->baseva = va;
238 handle->vsize = endpa-pgpa;
239
240 do {
241 #if 1
242 pmap_kenter_pa(va, pgpa, VM_PROT_READ);
243 #else
244 pmap_enter(pmap_kernel(), va, pgpa, VM_PROT_READ, TRUE,
245 VM_PROT_READ);
246 #endif
247 va += NBPG;
248 pgpa += NBPG;
249 } while (pgpa < endpa);
250
251 return ((const void *)retva);
252 }
253
254 static __inline void
255 mpbios_unmap(struct mp_map *handle)
256 {
257 #if 1
258 pmap_kremove(handle->baseva, handle->vsize);
259 #else
260 pmap_extract(pmap_kernel(), handle->baseva, NULL);
261 #endif
262 uvm_km_free(kernel_map, handle->baseva, handle->vsize);
263 }
264
265
266
267
268 int
269 mpbios_probe(struct device *self)
270 {
271 paddr_t ebda, memtop;
272
273 paddr_t cthpa;
274 int cthlen;
275 const u_int8_t *mpbios_page;
276 int scan_loc;
277
278 struct mp_map t;
279
280
281
282
283
284 if (mp_busses)
285 return (0);
286
287
288
289 mpbios_page = mpbios_map(0, NBPG, &t);
290
291
292 ebda = *(const u_int16_t *)(&mpbios_page[0x40e]);
293 ebda <<= 4;
294
295 memtop = *(const u_int16_t *)(&mpbios_page[0x413]);
296 memtop <<= 10;
297
298 mpbios_page = NULL;
299 mpbios_unmap(&t);
300
301 scan_loc = 0;
302
303 if (ebda && ebda < IOM_BEGIN ) {
304 mp_fps = mpbios_search(self, ebda, 1024, &mp_fp_map);
305 if (mp_fps != NULL)
306 goto found;
307 }
308
309 scan_loc = 1;
310
311 if (memtop && memtop <= IOM_BEGIN ) {
312 mp_fps = mpbios_search(self, memtop - 1024, 1024, &mp_fp_map);
313 if (mp_fps != NULL)
314 goto found;
315 }
316
317 scan_loc = 2;
318
319 mp_fps = mpbios_search(self, BIOS_BASE, BIOS_COUNT, &mp_fp_map);
320 if (mp_fps != NULL)
321 goto found;
322
323
324 return (0);
325
326 found:
327 if (mp_verbose)
328 printf("%s: MP floating pointer found in %s at 0x%lx\n",
329 self->dv_xname, loc_where[scan_loc], mp_fp_map.pa);
330
331 if (mp_fps->pap == 0) {
332 if (mp_fps->mpfb1 == 0) {
333 printf("%s: MP fps invalid: "
334 "no default config and no configuration table\n",
335 self->dv_xname);
336
337 goto err;
338 }
339 printf("%s: MP default configuration %d\n",
340 self->dv_xname, mp_fps->mpfb1);
341 return (10);
342 }
343
344 cthpa = mp_fps->pap;
345
346 mp_cth = mpbios_map(cthpa, sizeof (*mp_cth), &mp_cfg_table_map);
347 cthlen = mp_cth->base_len;
348 mpbios_unmap(&mp_cfg_table_map);
349
350 mp_cth = mpbios_map(cthpa, cthlen, &mp_cfg_table_map);
351
352 if (mp_verbose)
353 printf("%s: MP config table at 0x%lx, %d bytes long\n",
354 self->dv_xname, cthpa, cthlen);
355
356 if (mp_cth->signature != MP_CT_SIG) {
357 printf("%s: MP signature mismatch (%x vs %x)\n",
358 self->dv_xname,
359 MP_CT_SIG, mp_cth->signature);
360 goto err;
361 }
362
363 if (mpbios_cksum(mp_cth, cthlen)) {
364 printf ("%s: MP Configuration Table checksum mismatch\n",
365 self->dv_xname);
366 goto err;
367 }
368 return (10);
369
370 err:
371 if (mp_fps) {
372 mp_fps = NULL;
373 mpbios_unmap(&mp_fp_map);
374 }
375 if (mp_cth) {
376 mp_cth = NULL;
377 mpbios_unmap(&mp_cfg_table_map);
378 }
379 return (0);
380 }
381
382
383
384
385
386
387 static __inline int
388 mpbios_cksum(const void *start, int len)
389 {
390 unsigned char res=0;
391 const char *p = start;
392 const char *end = p + len;
393
394 while (p < end)
395 res += *p++;
396
397 return res;
398 }
399
400
401
402
403
404
405
406
407
408
409 const void *
410 mpbios_search(struct device *self, paddr_t start, int count, struct mp_map *map)
411 {
412 struct mp_map t;
413
414 int i, len;
415 const struct mpbios_fps *m;
416 int end = count - sizeof(*m);
417 const u_int8_t *base = mpbios_map(start, count, &t);
418
419 if (mp_verbose)
420 printf("%s: scanning 0x%lx to 0x%lx for MP signature\n",
421 self->dv_xname, start, start + count - sizeof(*m));
422
423 for (i = 0; i <= end; i += 4) {
424 m = (struct mpbios_fps *)&base[i];
425
426 if ((m->signature == MP_FP_SIG) &&
427 ((len = m->length << 4) != 0) &&
428 mpbios_cksum(m, (m->length << 4)) == 0) {
429 mpbios_unmap(&t);
430
431 return (mpbios_map(start + i, len, map));
432 }
433 }
434 mpbios_unmap(&t);
435
436 return (0);
437 }
438
439
440
441
442
443 static struct mpbios_baseentry mp_conf[] =
444 {
445 {0, 20, 0, "cpu"},
446 {1, 8, 0, "bus"},
447 {2, 8, 0, "ioapic"},
448 {3, 8, 0, "ioint"},
449 {4, 8, 0, "lint"},
450 };
451
452 struct mp_bus *mp_busses;
453 int mp_nbus;
454 struct mp_intr_map *mp_intrs;
455 int mp_nintrs;
456
457 struct mp_bus *mp_isa_bus;
458 struct mp_bus *mp_eisa_bus;
459
460 static struct mp_bus extint_bus = {
461 "ExtINT",
462 -1,
463 mp_print_special_intr,
464 mp_cfg_special_intr,
465 0
466 };
467 static struct mp_bus smi_bus = {
468 "SMI",
469 -1,
470 mp_print_special_intr,
471 mp_cfg_special_intr,
472 0
473 };
474 static struct mp_bus nmi_bus = {
475 "NMI",
476 -1,
477 mp_print_special_intr,
478 mp_cfg_special_intr,
479 0
480 };
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497 void
498 mpbios_scan(struct device *self)
499 {
500 const u_int8_t *position, *end;
501 int count;
502 int type;
503 int intr_cnt;
504 paddr_t lapic_base;
505
506 printf("%s: Intel MP Specification ", self->dv_xname);
507
508 switch (mp_fps->spec_rev) {
509 case 1:
510 printf("(Version 1.1)\n");
511 break;
512 case 4:
513 printf("(Version 1.4)\n");
514 break;
515 default:
516 printf("(unrecognized rev %d)\n", mp_fps->spec_rev);
517 }
518
519
520
521
522
523
524
525 lapic_base = LAPIC_BASE;
526 if (mp_cth != NULL)
527 lapic_base = (paddr_t)mp_cth->apic_address;
528
529 lapic_boot_init(lapic_base);
530
531
532 if (mp_fps->mpfb1 != 0) {
533 struct mpbios_proc pe;
534
535 printf("\n%s: MP default configuration %d\n",
536 self->dv_xname, mp_fps->mpfb1);
537
538
539 pe.apic_id = cpu_number();
540 pe.cpu_flags = PROCENTRY_FLAG_EN|PROCENTRY_FLAG_BP;
541 pe.cpu_signature = cpu_info_primary.ci_signature;
542 pe.feature_flags = cpu_info_primary.ci_feature_flags;
543
544 mpbios_cpu((u_int8_t *)&pe, self);
545
546 pe.apic_id = 1 - cpu_number();
547 pe.cpu_flags = PROCENTRY_FLAG_EN;
548
549 mpbios_cpu((u_int8_t *)&pe, self);
550
551 mpbios_ioapic((u_int8_t *)&default_ioapic, self);
552
553
554 printf("%s: WARNING: interrupts not configured\n",
555 self->dv_xname);
556 panic("lazy bum");
557 return;
558 } else {
559
560
561
562
563 if (mp_cth == NULL)
564 panic("mpbios_scan: no config (can't happen?)");
565
566
567
568
569 for (count = mp_cth->entry_count,
570 position = (const u_int8_t *)mp_cth + sizeof(*mp_cth),
571 end = position + mp_cth->base_len;
572 count-- && position < end;
573 position += mp_conf[type].length) {
574
575 type = *position;
576 if (type >= MPS_MCT_NTYPES) {
577 printf("%s: unknown entry type %x"
578 " in MP config table\n",
579 self->dv_xname, type);
580 end = position;
581 break;
582 }
583 mp_conf[type].count++;
584 }
585
586
587
588
589 for (count = mp_cth->entry_count,
590 intr_cnt = 15,
591 position = (const u_int8_t *)mp_cth + sizeof(*mp_cth);
592 count-- && position < end;
593 position += mp_conf[type].length) {
594 type = *position;
595 if (type == MPS_MCT_BUS) {
596 const struct mpbios_bus *bp =
597 (const struct mpbios_bus *)position;
598 if (bp->bus_id >= mp_nbus)
599 mp_nbus = bp->bus_id + 1;
600 }
601
602
603
604
605
606
607 if ((type == MPS_MCT_IOINT) ||
608 (type == MPS_MCT_LINT)) {
609 const struct mpbios_int *ie =
610 (const struct mpbios_int *)position;
611 if (ie->dst_apic_id != MPS_ALL_APICS)
612 intr_cnt++;
613 else if (type == MPS_MCT_IOINT)
614 intr_cnt +=
615 mp_conf[MPS_MCT_IOAPIC].count;
616 else
617 intr_cnt += mp_conf[MPS_MCT_CPU].count;
618 }
619 }
620
621 mp_busses = malloc(sizeof(struct mp_bus) * mp_nbus,
622 M_DEVBUF, M_NOWAIT);
623 memset(mp_busses, 0, sizeof(struct mp_bus) * mp_nbus);
624 mp_intrs = malloc(sizeof(struct mp_intr_map) * intr_cnt,
625 M_DEVBUF, M_NOWAIT);
626
627
628 position = (const u_int8_t *)mp_cth + sizeof(*mp_cth);
629 count = mp_cth->entry_count;
630 mp_nintrs = 0;
631
632 while ((count--) && (position < end)) {
633 switch (type = *(u_char *)position) {
634 case MPS_MCT_CPU:
635 mpbios_cpu(position, self);
636 break;
637 case MPS_MCT_BUS:
638 mpbios_bus(position, self);
639 break;
640 case MPS_MCT_IOAPIC:
641 mpbios_ioapic(position, self);
642 break;
643 case MPS_MCT_IOINT:
644 case MPS_MCT_LINT:
645 if (mpbios_int(position,
646 &mp_intrs[mp_nintrs]) == 0)
647 mp_nintrs++;
648 break;
649 default:
650 printf("%s: unknown entry type %x "
651 "in MP config table\n",
652 self->dv_xname, type);
653
654 return;
655 }
656
657 (u_char*)position += mp_conf[type].length;
658 }
659 if (mp_verbose && mp_cth->ext_len)
660 printf("%s: MP WARNING: %d "
661 "bytes of extended entries not examined\n",
662 self->dv_xname, mp_cth->ext_len);
663 }
664
665 mp_fps = NULL;
666 mpbios_unmap(&mp_fp_map);
667 if (mp_cth != NULL) {
668 mp_cth = NULL;
669 mpbios_unmap(&mp_cfg_table_map);
670 }
671
672 #if NPCI > 0
673 if (pci_mode_detect() != 0)
674 mpbios_intr_fixup();
675 #endif
676 }
677
678 int
679 mpbios_invent(int irq, int type, int bus)
680 {
681 struct mp_intr_map *mip;
682 struct mpbios_int e;
683
684 e.type = MPS_MCT_IOINT;
685 e.int_type = MPS_INTTYPE_INT;
686 switch (type) {
687 case IST_EDGE:
688 e.int_flags = MPS_INT(MPS_INTPO_ACTHI, MPS_INTTR_EDGE);
689 break;
690
691 case IST_LEVEL:
692 e.int_flags = MPS_INT(MPS_INTPO_ACTLO, MPS_INTTR_LEVEL);
693 break;
694
695 case IST_NONE:
696 case IST_PULSE:
697 e.int_flags = MPS_INT(MPS_INTPO_DEF, MPS_INTTR_DEF);
698 break;
699 }
700 e.src_bus_id = bus;
701 e.src_bus_irq = irq;
702 e.dst_apic_id = mp_busses[bus].mb_intrs->ioapic->sc_apicid;
703 e.dst_apic_int = irq;
704
705 if (mpbios_int((const u_int8_t *)&e, &mp_intrs[mp_nintrs]) == 0) {
706 mip = &mp_intrs[mp_nintrs++];
707 return (mip->ioapic_ih | irq);
708 }
709
710 return irq;
711 }
712
713 void
714 mpbios_cpu(const u_int8_t *ent, struct device *self)
715 {
716 const struct mpbios_proc *entry = (const struct mpbios_proc *)ent;
717 struct cpu_attach_args caa;
718
719
720
721 if (!(entry->cpu_flags & PROCENTRY_FLAG_EN))
722 return;
723
724
725 if (entry->cpu_flags & PROCENTRY_FLAG_BP)
726 caa.cpu_role = CPU_ROLE_BP;
727 else
728 caa.cpu_role = CPU_ROLE_AP;
729
730 caa.caa_name = "cpu";
731 caa.cpu_number = entry->apic_id;
732 caa.cpu_func = &mp_cpu_funcs;
733 #if 1
734 caa.cpu_signature = entry->cpu_signature;
735
736
737
738
739
740 caa.feature_flags = entry->feature_flags;
741
742
743
744
745
746
747 if ((caa.cpu_signature & 0x00000fff) == 0) {
748 caa.cpu_signature = cpu_id;
749 caa.feature_flags = cpu_feature;
750 }
751 #endif
752
753 config_found_sm(self, &caa, mp_print, mp_match);
754 }
755
756
757
758
759
760
761
762 void
763 mp_cfg_special_intr(const struct mpbios_int *entry, u_int32_t *redir)
764 {
765
766
767
768
769
770
771 *redir &= ~IOAPIC_REDLO_DEL_MASK;
772 *redir &= ~IOAPIC_REDLO_VECTOR_MASK;
773 *redir &= ~IOAPIC_REDLO_LEVEL;
774
775 switch (entry->int_type) {
776 case MPS_INTTYPE_NMI:
777 *redir |= (IOAPIC_REDLO_DEL_NMI<<IOAPIC_REDLO_DEL_SHIFT);
778 break;
779
780 case MPS_INTTYPE_SMI:
781 *redir |= (IOAPIC_REDLO_DEL_SMI<<IOAPIC_REDLO_DEL_SHIFT);
782 break;
783 case MPS_INTTYPE_ExtINT:
784
785
786
787
788
789 *redir |= (IOAPIC_REDLO_DEL_EXTINT<<IOAPIC_REDLO_DEL_SHIFT);
790 *redir |= (IOAPIC_REDLO_MASK);
791 break;
792 default:
793 panic("unknown MPS interrupt type %d", entry->int_type);
794 }
795 }
796
797
798
799 void
800 mp_cfg_pci_intr(const struct mpbios_int *entry, u_int32_t *redir)
801 {
802 int mpspo = entry->int_flags & 0x03;
803 int mpstrig = (entry->int_flags >> 2) & 0x03;
804
805 *redir &= ~IOAPIC_REDLO_DEL_MASK;
806 switch (mpspo) {
807 case MPS_INTPO_ACTHI:
808 *redir &= ~IOAPIC_REDLO_ACTLO;
809 break;
810 case MPS_INTPO_DEF:
811 case MPS_INTPO_ACTLO:
812 *redir |= IOAPIC_REDLO_ACTLO;
813 break;
814 default:
815 panic("unknown MPS interrupt polarity %d", mpspo);
816 }
817
818 if (entry->int_type != MPS_INTTYPE_INT) {
819 mp_cfg_special_intr(entry, redir);
820 return;
821 }
822 *redir |= (IOAPIC_REDLO_DEL_LOPRI<<IOAPIC_REDLO_DEL_SHIFT);
823
824 switch (mpstrig) {
825 case MPS_INTTR_DEF:
826 case MPS_INTTR_LEVEL:
827 *redir |= IOAPIC_REDLO_LEVEL;
828 break;
829 case MPS_INTTR_EDGE:
830 *redir &= ~IOAPIC_REDLO_LEVEL;
831 break;
832 default:
833 panic("unknown MPS interrupt trigger %d", mpstrig);
834 }
835 }
836
837 void
838 mp_cfg_eisa_intr (const struct mpbios_int *entry, u_int32_t *redir)
839 {
840 int mpspo = entry->int_flags & 0x03;
841 int mpstrig = (entry->int_flags >> 2) & 0x03;
842
843 *redir &= ~IOAPIC_REDLO_DEL_MASK;
844 switch (mpspo) {
845 case MPS_INTPO_DEF:
846 case MPS_INTPO_ACTHI:
847 *redir &= ~IOAPIC_REDLO_ACTLO;
848 break;
849 case MPS_INTPO_ACTLO:
850 *redir |= IOAPIC_REDLO_ACTLO;
851 break;
852 default:
853 panic("unknown MPS interrupt polarity %d", mpspo);
854 }
855
856 if (entry->int_type != MPS_INTTYPE_INT) {
857 mp_cfg_special_intr(entry, redir);
858 return;
859 }
860 *redir |= (IOAPIC_REDLO_DEL_LOPRI<<IOAPIC_REDLO_DEL_SHIFT);
861
862 switch (mpstrig) {
863 case MPS_INTTR_LEVEL:
864 *redir |= IOAPIC_REDLO_LEVEL;
865 break;
866 case MPS_INTTR_EDGE:
867 *redir &= ~IOAPIC_REDLO_LEVEL;
868 break;
869 case MPS_INTTR_DEF:
870
871
872
873
874 if (mp_busses[entry->src_bus_id].mb_data &
875 (1<<entry->src_bus_irq)) {
876 *redir |= IOAPIC_REDLO_LEVEL;
877 } else {
878 *redir &= ~IOAPIC_REDLO_LEVEL;
879 }
880 break;
881 default:
882 panic("unknown MPS interrupt trigger %d", mpstrig);
883 }
884 }
885
886
887 void
888 mp_cfg_isa_intr(const struct mpbios_int *entry, u_int32_t *redir)
889 {
890 int mpspo = entry->int_flags & 0x03;
891 int mpstrig = (entry->int_flags >> 2) & 0x03;
892
893 *redir &= ~IOAPIC_REDLO_DEL_MASK;
894 switch (mpspo) {
895 case MPS_INTPO_DEF:
896 case MPS_INTPO_ACTHI:
897 *redir &= ~IOAPIC_REDLO_ACTLO;
898 break;
899 case MPS_INTPO_ACTLO:
900 *redir |= IOAPIC_REDLO_ACTLO;
901 break;
902 default:
903 panic("unknown MPS interrupt polarity %d", mpspo);
904 }
905
906 if (entry->int_type != MPS_INTTYPE_INT) {
907 mp_cfg_special_intr(entry, redir);
908 return;
909 }
910 *redir |= (IOAPIC_REDLO_DEL_LOPRI << IOAPIC_REDLO_DEL_SHIFT);
911
912 switch (mpstrig) {
913 case MPS_INTTR_LEVEL:
914 *redir |= IOAPIC_REDLO_LEVEL;
915 break;
916 case MPS_INTTR_DEF:
917 case MPS_INTTR_EDGE:
918 *redir &= ~IOAPIC_REDLO_LEVEL;
919 break;
920 default:
921 panic("unknown MPS interrupt trigger %d", mpstrig);
922 }
923 }
924
925
926 void
927 mp_print_special_intr(int intr)
928 {
929 }
930
931 void
932 mp_print_pci_intr(int intr)
933 {
934 printf(" device %d INT_%c", (intr >> 2) & 0x1f, 'A' + (intr & 0x3));
935 }
936
937 void
938 mp_print_isa_intr(int intr)
939 {
940 printf(" irq %d", intr);
941 }
942
943 void
944 mp_print_eisa_intr(int intr)
945 {
946 printf(" EISA irq %d", intr);
947 }
948
949
950
951 #define TAB_UNIT 4
952 #define TAB_ROUND(a) _TAB_ROUND(a, TAB_UNIT)
953
954 #define _TAB_ROUND(a,u) (((a) + (u - 1)) & ~(u - 1))
955 #define EXTEND_TAB(a,u) (!(_TAB_ROUND(a, u) == _TAB_ROUND((a + 1), u)))
956
957 void
958 mpbios_bus(const u_int8_t *ent, struct device *self)
959 {
960 const struct mpbios_bus *entry = (const struct mpbios_bus *)ent;
961 int bus_id = entry->bus_id;
962
963 printf("%s: bus %d is type %6.6s\n", self->dv_xname,
964 bus_id, entry->bus_type);
965
966 #ifdef DIAGNOSTIC
967
968
969
970
971 if (bus_id >= mp_nbus) {
972 panic("%s: bus number %d out of range?? (type %6.6s)",
973 self->dv_xname, bus_id, entry->bus_type);
974 }
975 #endif
976
977 mp_busses[bus_id].mb_intrs = NULL;
978
979 if (memcmp(entry->bus_type, "PCI ", 6) == 0) {
980 mp_busses[bus_id].mb_name = "pci";
981 mp_busses[bus_id].mb_idx = bus_id;
982 mp_busses[bus_id].mb_intr_print = mp_print_pci_intr;
983 mp_busses[bus_id].mb_intr_cfg = mp_cfg_pci_intr;
984 } else if (memcmp(entry->bus_type, "EISA ", 6) == 0) {
985 mp_busses[bus_id].mb_name = "eisa";
986 mp_busses[bus_id].mb_idx = bus_id;
987 mp_busses[bus_id].mb_intr_print = mp_print_eisa_intr;
988 mp_busses[bus_id].mb_intr_cfg = mp_cfg_eisa_intr;
989
990 mp_busses[bus_id].mb_data = inb(ELCR0) | (inb(ELCR1) << 8);
991
992 if (mp_eisa_bus)
993 printf("%s: multiple eisa busses?\n",
994 self->dv_xname);
995 else
996 mp_eisa_bus = &mp_busses[bus_id];
997 } else if (memcmp(entry->bus_type, "ISA ", 6) == 0) {
998 mp_busses[bus_id].mb_name = "isa";
999 mp_busses[bus_id].mb_idx = bus_id;
1000 mp_busses[bus_id].mb_intr_print = mp_print_isa_intr;
1001 mp_busses[bus_id].mb_intr_cfg = mp_cfg_isa_intr;
1002 if (mp_isa_bus)
1003 printf("%s: multiple isa busses?\n",
1004 self->dv_xname);
1005 else
1006 mp_isa_bus = &mp_busses[bus_id];
1007 } else {
1008 printf("%s: unsupported bus type %6.6s\n", self->dv_xname,
1009 entry->bus_type);
1010 }
1011 }
1012
1013
1014 void
1015 mpbios_ioapic(const u_int8_t *ent, struct device *self)
1016 {
1017 const struct mpbios_ioapic *entry = (const struct mpbios_ioapic *)ent;
1018 struct apic_attach_args aaa;
1019
1020
1021 if (!(entry->apic_flags & IOAPICENTRY_FLAG_EN))
1022 return;
1023
1024 aaa.aaa_name = "ioapic";
1025 aaa.apic_id = entry->apic_id;
1026 aaa.apic_version = entry->apic_version;
1027 aaa.apic_address = (u_int32_t)entry->apic_address;
1028 aaa.apic_vecbase = -1;
1029 aaa.flags = (mp_fps->mpfb2 & 0x80) ? IOAPIC_PICMODE : IOAPIC_VWIRE;
1030
1031 config_found_sm(self, &aaa, mp_print, mp_match);
1032 }
1033
1034 int
1035 mpbios_int(const u_int8_t *ent, struct mp_intr_map *mpi)
1036 {
1037 const struct mpbios_int *entry = (const struct mpbios_int *)ent;
1038 struct mpbios_int rw_entry = *entry;
1039 struct ioapic_softc *sc = NULL, *sc2;
1040
1041 struct mp_intr_map *altmpi;
1042 struct mp_bus *mpb;
1043
1044 u_int32_t id = IOAPIC_REMAPPED_ID(entry->dst_apic_id);
1045 u_int32_t pin = entry->dst_apic_int;
1046 u_int32_t bus = entry->src_bus_id;
1047 u_int32_t dev = entry->src_bus_irq;
1048 u_int32_t type = entry->int_type;
1049 u_int32_t flags = entry->int_flags;
1050
1051 rw_entry.dst_apic_id = id;
1052
1053 switch (type) {
1054 case MPS_INTTYPE_INT:
1055 mpb = &(mp_busses[bus]);
1056 break;
1057 case MPS_INTTYPE_ExtINT:
1058 mpb = &extint_bus;
1059 break;
1060 case MPS_INTTYPE_SMI:
1061 mpb = &smi_bus;
1062 break;
1063 case MPS_INTTYPE_NMI:
1064 mpb = &nmi_bus;
1065 break;
1066 }
1067 mpi->bus = mpb;
1068 mpi->bus_pin = dev;
1069
1070 mpi->ioapic_ih = APIC_INT_VIA_APIC |
1071 ((id << APIC_INT_APIC_SHIFT) | ((pin << APIC_INT_PIN_SHIFT)));
1072
1073 mpi->type = type;
1074 mpi->flags = flags;
1075 mpi->redir = 0;
1076 if (mpb->mb_intr_cfg == NULL) {
1077 printf("mpbios: can't find bus %d for apic %d pin %d\n",
1078 bus, id, pin);
1079 return (1);
1080 }
1081
1082 (*mpb->mb_intr_cfg)(&rw_entry, &mpi->redir);
1083
1084 if (entry->type == MPS_MCT_IOINT) {
1085 sc = ioapic_find(id);
1086 if (sc == NULL) {
1087 printf("mpbios: can't find ioapic %d\n", id);
1088 return (1);
1089 }
1090
1091
1092
1093
1094
1095
1096 if (pin >= sc->sc_apic_sz) {
1097 sc2 = ioapic_find_bybase(pin);
1098 if (sc2 != sc) {
1099 printf("mpbios: bad pin %d for apic %d\n",
1100 pin, id);
1101 return (1);
1102 }
1103 printf("mpbios: WARNING: pin %d for apic %d too high; "
1104 "assuming ACPI global int value\n", pin, id);
1105 pin -= sc->sc_apic_vecbase;
1106 }
1107
1108 mpi->ioapic = sc;
1109 mpi->ioapic_pin = pin;
1110
1111 altmpi = sc->sc_pins[pin].ip_map;
1112
1113 if (altmpi != NULL) {
1114 if ((altmpi->type != type) ||
1115 (altmpi->flags != flags)) {
1116 printf(
1117 "%s: conflicting map entries for pin %d\n",
1118 sc->sc_dev.dv_xname, pin);
1119 }
1120 } else {
1121 sc->sc_pins[pin].ip_map = mpi;
1122 }
1123 } else {
1124 if (pin >= 2)
1125 printf("pin %d of local apic doesn't exist!\n", pin);
1126 else {
1127 mpi->ioapic = NULL;
1128 mpi->ioapic_pin = pin;
1129 mpi->cpu_id = id;
1130 }
1131 }
1132
1133 if (mp_verbose) {
1134 printf("%s: int%d attached to %s",
1135 sc ? sc->sc_dev.dv_xname : "local apic", pin,
1136 mpb->mb_name);
1137 if (mpb->mb_idx != -1)
1138 printf("%d", mpb->mb_idx);
1139
1140 (*(mpb->mb_intr_print))(dev);
1141
1142 printf(" (type 0x%x flags 0x%x)\n", type, flags);
1143 }
1144
1145 mpi->next = mpb->mb_intrs;
1146 mpb->mb_intrs = mpi;
1147
1148 return (0);
1149 }