This source file includes following definitions.
- acpiprt_match
- acpiprt_attach
- acpiprt_getirq
- acpiprt_prt_add
- acpiprt_getminbus
- acpiprt_getpcibus
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 #include <sys/param.h>
19 #include <sys/proc.h>
20 #include <sys/signalvar.h>
21 #include <sys/systm.h>
22 #include <sys/device.h>
23 #include <sys/malloc.h>
24
25 #include <machine/bus.h>
26
27 #include <dev/acpi/acpireg.h>
28 #include <dev/acpi/acpivar.h>
29 #include <dev/acpi/acpidev.h>
30 #include <dev/acpi/amltypes.h>
31 #include <dev/acpi/dsdt.h>
32
33 #include <dev/pci/pcivar.h>
34 #include <dev/pci/ppbreg.h>
35
36 #include <machine/i82093reg.h>
37 #include <machine/i82093var.h>
38
39 #include <machine/mpbiosvar.h>
40
41 #include "ioapic.h"
42
43 int acpiprt_match(struct device *, void *, void *);
44 void acpiprt_attach(struct device *, struct device *, void *);
45 int acpiprt_getirq(union acpi_resource *crs, void *arg);
46 int acpiprt_getminbus(union acpi_resource *, void *);
47
48
49 struct acpiprt_softc {
50 struct device sc_dev;
51
52 struct acpi_softc *sc_acpi;
53 struct aml_node *sc_devnode;
54
55 int sc_bus;
56 };
57
58 struct cfattach acpiprt_ca = {
59 sizeof(struct acpiprt_softc), acpiprt_match, acpiprt_attach
60 };
61
62 struct cfdriver acpiprt_cd = {
63 NULL, "acpiprt", DV_DULL
64 };
65
66 void acpiprt_prt_add(struct acpiprt_softc *, struct aml_value *);
67 int acpiprt_getpcibus(struct acpiprt_softc *, struct aml_node *);
68
69 int
70 acpiprt_match(struct device *parent, void *match, void *aux)
71 {
72 struct acpi_attach_args *aa = aux;
73 struct cfdata *cf = match;
74
75
76 if (aa->aaa_name == NULL ||
77 strcmp(aa->aaa_name, cf->cf_driver->cd_name) != 0 ||
78 aa->aaa_table != NULL)
79 return (0);
80
81 return (1);
82 }
83
84 void
85 acpiprt_attach(struct device *parent, struct device *self, void *aux)
86 {
87 struct acpiprt_softc *sc = (struct acpiprt_softc *)self;
88 struct acpi_attach_args *aa = aux;
89 struct aml_value res;
90 int i;
91
92 sc->sc_acpi = (struct acpi_softc *)parent;
93 sc->sc_devnode = aa->aaa_node;
94 sc->sc_bus = acpiprt_getpcibus(sc, sc->sc_devnode);
95
96 printf(": bus %d (%s)", sc->sc_bus, sc->sc_devnode->parent->name);
97
98 if (aml_evalname(sc->sc_acpi, sc->sc_devnode, "_PRT", 0, NULL, &res)) {
99 printf(": no PCI interrupt routing table\n");
100 return;
101 }
102
103 if (res.type != AML_OBJTYPE_PACKAGE) {
104 printf(": _PRT is not a package\n");
105 aml_freevalue(&res);
106 return;
107 }
108
109 printf("\n");
110
111 if (sc->sc_bus == -1)
112 return;
113
114 for (i = 0; i < res.length; i++)
115 acpiprt_prt_add(sc, res.v_package[i]);
116
117 aml_freevalue(&res);
118 }
119
120 int
121 acpiprt_getirq(union acpi_resource *crs, void *arg)
122 {
123 int *irq = (int *)arg;
124 int typ;
125
126 typ = AML_CRSTYPE(crs);
127 switch (typ) {
128 case SR_IRQ:
129 *irq = ffs(aml_letohost16(crs->sr_irq.irq_mask)) - 1;
130 break;
131 case LR_EXTIRQ:
132 *irq = aml_letohost32(crs->lr_extirq.irq[0]);
133 break;
134 default:
135 printf("Unknown interrupt : %x\n", typ);
136 }
137 return (0);
138 }
139
140 void
141 acpiprt_prt_add(struct acpiprt_softc *sc, struct aml_value *v)
142 {
143 struct aml_node *node;
144 struct aml_value res, *pp;
145 u_int64_t addr;
146 int pin, irq, sta;
147 #if NIOAPIC > 0
148 struct mp_intr_map *map;
149 struct ioapic_softc *apic;
150 #endif
151 pci_chipset_tag_t pc = NULL;
152 pcitag_t tag;
153 pcireg_t reg;
154 int bus, dev, func, nfuncs;
155
156 if (v->type != AML_OBJTYPE_PACKAGE || v->length != 4) {
157 printf("invalid mapping object\n");
158 return;
159 }
160
161 addr = aml_val2int(v->v_package[0]);
162 pin = aml_val2int(v->v_package[1]);
163 if (pin > 3) {
164 return;
165 }
166
167 pp = v->v_package[2];
168 if (pp->type == AML_OBJTYPE_NAMEREF) {
169 node = aml_searchname(sc->sc_devnode, pp->v_nameref);
170 if (node == NULL) {
171 printf("Invalid device!\n");
172 return;
173 }
174 pp = node->value;
175 }
176 if (pp->type == AML_OBJTYPE_OBJREF) {
177 pp = pp->v_objref.ref;
178 }
179 if (pp->type == AML_OBJTYPE_DEVICE) {
180 node = pp->node;
181 if (aml_evalname(sc->sc_acpi, node, "_STA", 0, NULL, &res))
182 printf("no _STA method\n");
183
184 sta = aml_val2int(&res) & STA_ENABLED;
185 aml_freevalue(&res);
186 if (sta == 0)
187 return;
188
189 if (aml_evalname(sc->sc_acpi, node, "_CRS", 0, NULL, &res))
190 printf("no _CRS method\n");
191
192 if (res.type != AML_OBJTYPE_BUFFER || res.length < 6) {
193 printf("invalid _CRS object\n");
194 aml_freevalue(&res);
195 return;
196 }
197 aml_parse_resource(res.length, res.v_buffer,
198 acpiprt_getirq, &irq);
199 aml_freevalue(&res);
200 } else {
201 irq = aml_val2int(v->v_package[3]);
202 }
203
204 #ifdef ACPI_DEBUG
205 printf("%s: %s addr 0x%llx pin %d irq %d\n",
206 DEVNAME(sc), aml_nodename(pp->node), addr, pin, irq);
207 #endif
208
209 #if NIOAPIC > 0
210 if (nioapics > 0) {
211 apic = ioapic_find_bybase(irq);
212 if (apic == NULL) {
213 printf("%s: no apic found for irq %d\n", DEVNAME(sc), irq);
214 return;
215 }
216
217 map = malloc(sizeof (struct mp_intr_map), M_DEVBUF, M_NOWAIT);
218 if (map == NULL)
219 return;
220
221 memset(map, 0, sizeof *map);
222 map->ioapic = apic;
223 map->ioapic_pin = irq - apic->sc_apic_vecbase;
224 map->bus_pin = ((addr >> 14) & 0x7c) | (pin & 0x3);
225 map->redir = IOAPIC_REDLO_ACTLO | IOAPIC_REDLO_LEVEL;
226 map->redir |= (IOAPIC_REDLO_DEL_LOPRI << IOAPIC_REDLO_DEL_SHIFT);
227
228 map->ioapic_ih = APIC_INT_VIA_APIC |
229 ((apic->sc_apicid << APIC_INT_APIC_SHIFT) |
230 (map->ioapic_pin << APIC_INT_PIN_SHIFT));
231
232 apic->sc_pins[map->ioapic_pin].ip_map = map;
233
234 map->next = mp_busses[sc->sc_bus].mb_intrs;
235 mp_busses[sc->sc_bus].mb_intrs = map;
236
237 return;
238 }
239 #endif
240
241 bus = sc->sc_bus;
242 dev = ACPI_PCI_DEV(addr << 16);
243 tag = pci_make_tag(pc, bus, dev, 0);
244
245 reg = pci_conf_read(pc, tag, PCI_BHLC_REG);
246 if (PCI_HDRTYPE_MULTIFN(reg))
247 nfuncs = 8;
248 else
249 nfuncs = 1;
250
251 for (func = 0; func < nfuncs; func++) {
252 tag = pci_make_tag(pc, bus, dev, func);
253 reg = pci_conf_read(pc, tag, PCI_INTERRUPT_REG);
254 if (PCI_INTERRUPT_PIN(reg) == pin + 1) {
255 reg &= ~(PCI_INTERRUPT_LINE_MASK << PCI_INTERRUPT_LINE_SHIFT);
256 reg |= irq << PCI_INTERRUPT_LINE_SHIFT;
257 pci_conf_write(pc, tag, PCI_INTERRUPT_REG, reg);
258 }
259 }
260 }
261
262 int
263 acpiprt_getminbus(union acpi_resource *crs, void *arg)
264 {
265 int *bbn = arg;
266 int typ = AML_CRSTYPE(crs);
267
268
269 if (typ == LR_WORD && crs->lr_word.type == 2)
270 *bbn = crs->lr_word._min;
271 return 0;
272 }
273
274 int
275 acpiprt_getpcibus(struct acpiprt_softc *sc, struct aml_node *node)
276 {
277 struct aml_node *parent = node->parent;
278 struct aml_value res;
279 pci_chipset_tag_t pc = NULL;
280 pcitag_t tag;
281 pcireg_t reg;
282 int bus, dev, func, rv;
283
284 if (parent == NULL)
285 return 0;
286
287 if (aml_evalname(sc->sc_acpi, parent, "_ADR", 0, NULL, &res) == 0) {
288 bus = acpiprt_getpcibus(sc, parent);
289 dev = ACPI_PCI_DEV(aml_val2int(&res) << 16);
290 func = ACPI_PCI_FN(aml_val2int(&res) << 16);
291 aml_freevalue(&res);
292
293
294
295
296
297 if (dev >= pci_bus_maxdevs(pc, bus))
298 return (-1);
299
300 tag = pci_make_tag(pc, bus, dev, func);
301 reg = pci_conf_read(pc, tag, PCI_CLASS_REG);
302 if (PCI_CLASS(reg) == PCI_CLASS_BRIDGE &&
303 PCI_SUBCLASS(reg) == PCI_SUBCLASS_BRIDGE_PCI) {
304 reg = pci_conf_read(pc, tag, PPB_REG_BUSINFO);
305 return (PPB_BUSINFO_SECONDARY(reg));
306 }
307 }
308
309 if (aml_evalname(sc->sc_acpi, parent, "_CRS", 0, NULL, &res) == 0) {
310 rv = -1;
311 if (res.type == AML_OBJTYPE_BUFFER)
312 aml_parse_resource(res.length, res.v_buffer,
313 acpiprt_getminbus, &rv);
314 aml_freevalue(&res);
315 if (rv != -1)
316 return rv;
317 }
318 if (aml_evalname(sc->sc_acpi, parent, "_BBN", 0, NULL, &res) == 0) {
319 rv = aml_val2int(&res);
320 aml_freevalue(&res);
321 return (rv);
322 }
323
324 return (0);
325 }