2 * This file is part of the UCB release of Plan 9. It is subject to the license
3 * terms in the LICENSE file found in the top-level directory of this
4 * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
5 * part of the UCB release of Plan 9, including this file, may be copied,
6 * modified, propagated, or distributed except according to the terms contained
33 Msiabase = 0xfee00000u,
34 Msiadest = 1<<12, /* same as 63:56 of apic vector */
35 Msiaedest = 1<<4, /* same as 55:48 of apic vector */
36 Msialowpri = 1<<3, /* redirection hint */
43 Msidmode = 1<<8, /* 3 bits; delivery mode */
48 /* msi capabilities */
49 Vmask = 1<<8, /* Vectors can be masked. Optional. */
50 Cap64 = 1<<7, /* 64-bit addresses. Optional. */
51 Mmesgmsk = 7<<4, /* Mask for # of messages allowed. See 6.8.1.3 */
52 Mmcap = 7<<1, /* # of messages the function can support. */
53 Msienable = 1<<0, /* Enable. */
54 /* msix capabilities */
60 /* Find an arbitrary capability. This should move to pci.c? */
61 int pci_cap(struct pci_device *p, int cap)
65 /* status register bit 4 has capabilities */
66 if((pcidev_read16(p, PciPSR) & 1<<4) == 0)
68 switch(pcidev_read8(p, PciHDT) & 0x7f){
72 case 1: /* pci to pci bridge */
75 case 2: /* cardbus bridge */
80 off = pcidev_read8(p, off);
81 if(off < 0x40 || (off & 3))
84 c = pcidev_read8(p, off);
94 /* Find the offset in config space of this function of the msi capability.
95 * It is defined in 6.8.1 and is variable-sized.
98 msicap(struct pci_device *p)
102 c = pci_cap(p, PciCapMSI);
108 /* Find the offset in config space of this function of the msi-x capability.
109 * It is defined in 6.8.1 and is variable-sized.
112 msixcap(struct pci_device *p)
116 c = pci_cap(p, PciCapMSIX);
123 blacklist(struct pci_device *p)
125 switch(p->ven_id<<16 | p->dev_id){
126 case 0x11ab<<16 | 0x6485:
127 case 0x8086<<16 | 0x100f:
133 /* see section 6.8.1 of the pci spec. */
134 /* Set up a single function on a single device.
135 * We need to take the vec, bust it up into bits,
136 * and put parts of it in the msi address and parts
139 int pci_msi_enable(struct pci_device *p, uint64_t vec)
142 unsigned int c, f, d, datao, lopri, dmode, logical;
144 /* Get the offset of the MSI capability
145 * in the function's config space.
152 /* read it, clear out the Mmesgmsk bits.
153 * This means that there will be no multiple
156 f = pcidev_read16(p, c + 2) & ~Mmesgmsk;
158 /* See if it's a broken device, currently
159 * there's only Marvell there.
161 if(blacklist(p) != 0)
164 /* Data begins at 8 bytes in. */
167 /* The data we write is 16 bits, scarfed
168 * in the upper 16 bits of d.
172 /* Hard to see it being anything but lopri but ... */
173 lopri = (vec & 0x700) == MTlp;
175 logical = (vec & Lm) != 0;
177 /* OK, Msiabase is fee00000, and we offset with the
178 * dest from above, lowpri, and logical.
180 printd("Write to %d %08lx \n",c + 4, Msiabase | Msiaedest * d
181 | Msialowpri * lopri | Msialogical * logical);
182 pcidev_write32(p, c + 4, Msiabase | Msiaedest * d
183 | Msialowpri * lopri | Msialogical * logical);
185 /* And even if it's 64-bit capable, we do nothing with
186 * the high order bits. If it is 64-bit we need to offset
187 * datao (data offset) by 4 (i.e. another 32 bits)
191 pcidev_write32(p, c + 8, 0);
194 /* pick up the delivery mode from the vector */
195 dmode = (vec >> 8) & 7;
197 /* the data we write to that location is a combination
198 * of things. It's not yet clear if this is a plan 9 chosen
199 * thing or a PCI spec chosen thing.
201 printd("Write data %d %04x\n", c + datao, Msidassert | Msidlogical * logical
202 | Msidmode * dmode | ((unsigned int)vec & 0xff));
203 pcidev_write16(p, c + datao, Msidassert | Msidlogical * logical
204 | Msidmode * dmode | ((unsigned int)vec & 0xff));
206 /* If we have the option of masking the vectors,
207 * blow all the masks to 0. It's a 32-bit mask.
210 pcidev_write32(p, c + datao + 4, 0);
212 /* Now write the control bits back, with the
213 * Mmesg mask (which is a power of 2) set to 0
214 * (meaning one message only).
216 printd("write @ %d %04lx\n",c + 2, f);
217 pcidev_write16(p, c + 2, f);
221 /* see section 6.8.1 of the pci spec. */
222 /* Set up a single function on a single device.
223 * We need to take the vec, bust it up into bits,
224 * and put parts of it in the msi address and parts
227 static int pci_msix_init(struct pci_device *p)
230 unsigned int c, d, datao, lopri, dmode, logical;
234 /* Get the offset of the MSI capability
235 * in the function's config space.
241 /* for this to work, we need at least one free BAR. */
242 found = pci_find_unused_bars(p, bars, 1);
244 /* we'll use one for now. */
248 f = pcidev_read16(p, c + 2);
249 printd("msix control %04x\n", f);
250 if (!(f & Msixenable)){
251 printk("msix not enabled, f is 0x%x; done\n", f);
255 /* See if it's a broken device.
257 if(blacklist(p) != 0)
260 /* alloc 8 physically contiguous pages. */
261 p->msix = get_cont_pages(8, KMALLOC_WAIT);
265 memset(p->msix, 0, 8*PAGE_SIZE);
266 /* point the bar you found to them. */
268 p->msixsize = f & Msixsize;
269 /* what do we do for 64-bit bars? Who knows? */
270 /* there's an issue here. Does it need to be 8k aligned? Hmm. */
271 pcidev_write32(p, 0x10 + p->msixbar, paddr_low32(p->msix));
272 /* set the caps to point to the bar. */
273 /* Format is offset from the msibar | which bar it is. */
274 /* table is at offset 0. */
275 pcidev_write32(p, c + 4, found);
276 /* PBA is at offset 4096 */
277 pcidev_write32(p, c + 8, found | 4*PAGE_SIZE);
278 /* that seems to be it for the config space. */
283 uint32_t addrlo, addrhi, data, vector;
286 int pci_msix_enable(struct pci_device *p, uint64_t vec)
289 struct msixentry *entry;
290 unsigned int c, d, datao, lopri, dmode, logical;
291 /* we don't call this much, so we don't mind
294 if (! p->msixready) {
295 if (pci_msix_init(p) < 0)
300 /* find an unused slot. */
301 for(i = 0, entry = p->msix; i < p->msixsize; i++, entry++)
304 if (i == p->msixsize)
307 /* The data we write is 16 bits, scarfed
308 * in the upper 16 bits of d.
310 /* The data we write is 16 bits, scarfed
311 * in the upper 16 bits of d.
317 /* Hard to see it being anything but lopri but ... */
318 lopri = (vec & 0x700) == MTlp;
320 logical = (vec & Lm) != 0;
322 /* OK, Msiabase is fee00000, and we offset with the
323 * dest from above, lowpri, and logical.
325 printd("Write to %d %08lx \n",c + 4, Msiabase | Msiaedest * d
326 | Msialowpri * lopri | Msialogical * logical);
327 entry->addrlo = Msiabase | Msiaedest * d
328 | Msialowpri * lopri | Msialogical * logical;
330 /* And even if it's 64-bit capable, we do nothing with
331 * the high order bits. If it is 64-bit we need to offset
332 * datao (data offset) by 4 (i.e. another 32 bits)
336 /* pick up the delivery mode from the vector */
337 dmode = (vec >> 8) & 7;
339 /* the data we write to that location is a combination
340 * of things. It's not yet clear if this is a plan 9 chosen
341 * thing or a PCI spec chosen thing.
343 printd("Write data @%p %04x\n", &entry->data, Msidassert | Msidlogical * logical
344 | Msidmode * dmode | ((unsigned int)vec & 0xff));
345 entry->data = Msidassert | Msidlogical * logical
346 | Msidmode * dmode | ((unsigned int)vec & 0xff);
349 /* Mask the msi function. Since 'masking' means disable it,
350 * but the parameter has a 1 for disabling it, well, it's a
351 * bit clear operation.
354 pcimsimask(struct pci_device *p, int mask)
361 f = pcidev_read16(p, c + 2);
363 pcidev_write16(p, c + 2, f & ~Msienable);
365 pcidev_write16(p, c + 2, f | Msienable);
370 void msi_mask_irq(struct irq_handler *irq_h, int apic_vector)
372 struct pci_device *p = (struct pci_device*)irq_h->dev_private;
378 f = pcidev_read16(p, c + 2);
379 pcidev_write16(p, c + 2, f & ~Msienable);
382 void msi_unmask_irq(struct irq_handler *irq_h, int apic_vector)
384 struct pci_device *p = (struct pci_device*)irq_h->dev_private;
389 f = pcidev_read16(p, c + 2);
390 pcidev_write16(p, c + 2, f | Msienable);
393 int msi_route_irq(struct irq_handler *irq_h, int apic_vector, int dest)
395 struct pci_device *p = (struct pci_device*)irq_h->dev_private;
401 printk("Not routing MSI yet, fix me!\n");