]> git.lizzy.rs Git - plan9front.git/blob - sys/src/9/bcm64/pci.c
bcm64: add support for more than 1GB of ram (untested)
[plan9front.git] / sys / src / 9 / bcm64 / pci.c
1 #include "u.h"
2 #include "../port/lib.h"
3 #include "mem.h"
4 #include "dat.h"
5 #include "fns.h"
6 #include "io.h"
7
8 /* bcmstb PCIe controller registers */
9 enum{
10         RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1      = 0x0188/4,
11         RC_CFG_PRIV1_ID_VAL3                    = 0x043c/4,
12         RC_DL_MDIO_ADDR                         = 0x1100/4,
13         RC_DL_MDIO_WR_DATA                      = 0x1104/4,
14         RC_DL_MDIO_RD_DATA                      = 0x1108/4,
15         MISC_MISC_CTRL                          = 0x4008/4,
16         MISC_CPU_2_PCIE_MEM_WIN0_LO             = 0x400c/4,
17         MISC_CPU_2_PCIE_MEM_WIN0_HI             = 0x4010/4,
18         MISC_RC_BAR1_CONFIG_LO                  = 0x402c/4,
19         MISC_RC_BAR2_CONFIG_LO                  = 0x4034/4,
20         MISC_RC_BAR2_CONFIG_HI                  = 0x4038/4,
21         MISC_RC_BAR3_CONFIG_LO                  = 0x403c/4,
22         MISC_MSI_BAR_CONFIG_LO                  = 0x4044/4,
23         MISC_MSI_BAR_CONFIG_HI                  = 0x4048/4,
24         MISC_MSI_DATA_CONFIG                    = 0x404c/4,
25         MISC_EOI_CTRL                           = 0x4060/4,
26         MISC_PCIE_CTRL                          = 0x4064/4,
27         MISC_PCIE_STATUS                        = 0x4068/4,
28         MISC_REVISION                           = 0x406c/4,
29         MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT     = 0x4070/4,
30         MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI        = 0x4080/4,
31         MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI       = 0x4084/4,
32         MISC_HARD_PCIE_HARD_DEBUG               = 0x4204/4,
33
34         INTR2_CPU_BASE                          = 0x4300/4,
35         MSI_INTR2_BASE                          = 0x4500/4,
36                 INTR_STATUS = 0,
37                 INTR_SET,
38                 INTR_CLR,
39                 INTR_MASK_STATUS,
40                 INTR_MASK_SET,
41                 INTR_MASK_CLR,
42
43         EXT_CFG_INDEX                           = 0x9000/4,
44         RGR1_SW_INIT_1                          = 0x9210/4,
45         EXT_CFG_DATA                            = 0x8000/4,
46
47 };
48
49 #define MSI_TARGET_ADDR         0xFFFFFFFFCULL
50
51 static u32int *regs = (u32int*)(VIRTIO1 + 0x500000);
52
53 static Lock pcicfglock;
54 static int pcimaxbno = 0;
55 static int pcimaxdno = 0;
56 static Pcidev* pciroot;
57 static Pcidev* pcilist;
58 static Pcidev* pcitail;
59
60 typedef struct Pcisiz Pcisiz;
61 struct Pcisiz
62 {
63         Pcidev* dev;
64         int     siz;
65         int     bar;
66 };
67
68 enum
69 {
70         MaxFNO          = 7,
71         MaxUBN          = 255,
72 };
73
74 static char* bustypes[] = {
75         "CBUSI",
76         "CBUSII",
77         "EISA",
78         "FUTURE",
79         "INTERN",
80         "ISA",
81         "MBI",
82         "MBII",
83         "MCA",
84         "MPI",
85         "MPSA",
86         "NUBUS",
87         "PCI",
88         "PCMCIA",
89         "TC",
90         "VL",
91         "VME",
92         "XPRESS",
93 };
94
95 static int
96 tbdffmt(Fmt* fmt)
97 {
98         char *p;
99         int l, r;
100         uint type, tbdf;
101
102         if((p = malloc(READSTR)) == nil)
103                 return fmtstrcpy(fmt, "(tbdfconv)");
104
105         switch(fmt->r){
106         case 'T':
107                 tbdf = va_arg(fmt->args, int);
108                 if(tbdf == BUSUNKNOWN)
109                         snprint(p, READSTR, "unknown");
110                 else{
111                         type = BUSTYPE(tbdf);
112                         if(type < nelem(bustypes))
113                                 l = snprint(p, READSTR, bustypes[type]);
114                         else
115                                 l = snprint(p, READSTR, "%d", type);
116                         snprint(p+l, READSTR-l, ".%d.%d.%d",
117                                 BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
118                 }
119                 break;
120
121         default:
122                 snprint(p, READSTR, "(tbdfconv)");
123                 break;
124         }
125         r = fmtstrcpy(fmt, p);
126         free(p);
127
128         return r;
129 }
130
131 static void pcicfginit(void);
132
133 static void*
134 cfgaddr(int tbdf, int rno)
135 {
136         if(BUSBNO(tbdf) == 0 && BUSDNO(tbdf) == 0)
137                 return (uchar*)regs + rno;
138         regs[EXT_CFG_INDEX] = BUSBNO(tbdf) << 20 | BUSDNO(tbdf) << 15 | BUSFNO(tbdf) << 12;
139         coherence();
140         return ((uchar*)&regs[EXT_CFG_DATA]) + rno;
141 }
142
143 static int
144 pcicfgrw32(int tbdf, int rno, int data, int read)
145 {
146         int x = -1;
147         u32int *p;
148
149         ilock(&pcicfglock);
150         if((p = cfgaddr(tbdf, rno & ~3)) != nil){
151                 if(read)
152                         x = *p;
153                 else
154                         *p = data;
155         }
156         iunlock(&pcicfglock);
157         return x;
158 }
159 static int
160 pcicfgrw16(int tbdf, int rno, int data, int read)
161 {
162         int x = -1;
163         u16int *p;
164
165         ilock(&pcicfglock);
166         if((p = cfgaddr(tbdf, rno & ~1)) != nil){
167                 if(read)
168                         x = *p;
169                 else
170                         *p = data;
171         }
172         iunlock(&pcicfglock);
173         return x;
174 }
175 static int
176 pcicfgrw8(int tbdf, int rno, int data, int read)
177 {
178         int x = -1;
179         u8int *p;
180
181         ilock(&pcicfglock);
182         if((p = cfgaddr(tbdf, rno)) != nil){
183                 if(read)
184                         x = *p;
185                 else
186                         *p = data;
187         }
188         iunlock(&pcicfglock);
189         return x;
190 }
191
192 int
193 pcicfgr32(Pcidev* pcidev, int rno)
194 {
195         return pcicfgrw32(pcidev->tbdf, rno, 0, 1);
196 }
197 void
198 pcicfgw32(Pcidev* pcidev, int rno, int data)
199 {
200         pcicfgrw32(pcidev->tbdf, rno, data, 0);
201 }
202 int
203 pcicfgr16(Pcidev* pcidev, int rno)
204 {
205         return pcicfgrw16(pcidev->tbdf, rno, 0, 1);
206 }
207 void
208 pcicfgw16(Pcidev* pcidev, int rno, int data)
209 {
210         pcicfgrw16(pcidev->tbdf, rno, data, 0);
211 }
212 int
213 pcicfgr8(Pcidev* pcidev, int rno)
214 {
215         return pcicfgrw8(pcidev->tbdf, rno, 0, 1);
216 }
217 void
218 pcicfgw8(Pcidev* pcidev, int rno, int data)
219 {
220         pcicfgrw8(pcidev->tbdf, rno, data, 0);
221 }
222
223 Pcidev*
224 pcimatch(Pcidev* prev, int vid, int did)
225 {
226         if(prev == nil)
227                 prev = pcilist;
228         else
229                 prev = prev->list;
230
231         while(prev != nil){
232                 if((vid == 0 || prev->vid == vid)
233                 && (did == 0 || prev->did == did))
234                         break;
235                 prev = prev->list;
236         }
237         return prev;
238 }
239
240 Pcidev*
241 pcimatchtbdf(int tbdf)
242 {
243         Pcidev *pcidev;
244
245         for(pcidev = pcilist; pcidev != nil; pcidev = pcidev->list) {
246                 if(pcidev->tbdf == tbdf)
247                         break;
248         }
249         return pcidev;
250 }
251
252 static u32int
253 pcibarsize(Pcidev *p, int rno)
254 {
255         u32int v, size;
256
257         v = pcicfgrw32(p->tbdf, rno, 0, 1);
258         pcicfgrw32(p->tbdf, rno, 0xFFFFFFF0, 0);
259         size = pcicfgrw32(p->tbdf, rno, 0, 1);
260         if(v & 1)
261                 size |= 0xFFFF0000;
262         pcicfgrw32(p->tbdf, rno, v, 0);
263
264         return -(size & ~0x0F);
265 }
266
267 static int
268 pcisizcmp(void *a, void *b)
269 {
270         Pcisiz *aa, *bb;
271
272         aa = a;
273         bb = b;
274         return aa->siz - bb->siz;
275 }
276
277 static ulong
278 pcimask(ulong v)
279 {
280         ulong m;
281
282         m = BI2BY*sizeof(v);
283         for(m = 1<<(m-1); m != 0; m >>= 1) {
284                 if(m & v)
285                         break;
286         }
287
288         m--;
289         if((v & m) == 0)
290                 return v;
291
292         v |= m;
293         return v+1;
294 }
295
296 static void
297 pcibusmap(Pcidev *root, uintptr *pmema, uintptr *pioa, int wrreg)
298 {
299         Pcidev *p;
300         int ntb, i, size, rno, hole;
301         uintptr v, mema, ioa, sioa, smema, base, limit;
302         Pcisiz *table, *tptr, *mtb, *itb;
303
304         ioa = *pioa;
305         mema = *pmema;
306
307         ntb = 0;
308         for(p = root; p != nil; p = p->link)
309                 ntb++;
310
311         ntb *= (PciCIS-PciBAR0)/4;
312         table = malloc(2*ntb*sizeof(Pcisiz));
313         if(table == nil)
314                 panic("pcibusmap: can't allocate memory");
315         itb = table;
316         mtb = table+ntb;
317
318         /*
319          * Build a table of sizes
320          */
321         for(p = root; p != nil; p = p->link) {
322                 if(p->ccrb == 0x06) {
323                         if(p->ccru != 0x04 || p->bridge == nil)
324                                 continue;
325
326                         sioa = ioa;
327                         smema = mema;
328                         pcibusmap(p->bridge, &smema, &sioa, 0);
329
330                         hole = pcimask(smema-mema);
331                         if(hole < (1<<20))
332                                 hole = 1<<20;
333                         p->mema.size = hole;
334
335                         hole = pcimask(sioa-ioa);
336                         if(hole < (1<<12))
337                                 hole = 1<<12;
338
339                         p->ioa.size = hole;
340
341                         itb->dev = p;
342                         itb->bar = -1;
343                         itb->siz = p->ioa.size;
344                         itb++;
345
346                         mtb->dev = p;
347                         mtb->bar = -1;
348                         mtb->siz = p->mema.size;
349                         mtb++;
350                         continue;
351                 }
352
353                 for(i = 0; i <= 5; i++) {
354                         rno = PciBAR0 + i*4;
355                         v = pcicfgrw32(p->tbdf, rno, 0, 1);
356                         size = pcibarsize(p, rno);
357                         if(size == 0)
358                                 continue;
359
360                         p->mem[i].size = size;
361                         if(v & 1) {
362                                 itb->dev = p;
363                                 itb->bar = i;
364                                 itb->siz = size;
365                                 itb++;
366                         }
367                         else {
368                                 mtb->dev = p;
369                                 mtb->bar = i;
370                                 mtb->siz = size;
371                                 mtb++;
372
373                                 if((v & 7) == 4)
374                                         i++;
375                         }
376                 }
377         }
378
379         /*
380          * Sort both tables IO smallest first, Memory largest
381          */
382         qsort(table, itb-table, sizeof(Pcisiz), pcisizcmp);
383         tptr = table+ntb;
384         qsort(tptr, mtb-tptr, sizeof(Pcisiz), pcisizcmp);
385
386         /*
387          * Allocate IO address space on this bus
388          */
389         for(tptr = table; tptr < itb; tptr++) {
390                 hole = tptr->siz;
391                 if(tptr->bar == -1)
392                         hole = 1<<12;
393                 ioa = (ioa+hole-1) & ~(hole-1);
394
395                 p = tptr->dev;
396                 if(tptr->bar == -1)
397                         p->ioa.bar = ioa;
398                 else {
399                         p->pcr |= IOen;
400                         p->mem[tptr->bar].bar = ioa|1;
401                         if(wrreg)
402                                 pcicfgrw32(p->tbdf, PciBAR0+(tptr->bar*4), ioa|1, 0);
403                 }
404
405                 ioa += tptr->siz;
406         }
407
408         /*
409          * Allocate Memory address space on this bus
410          */
411         for(tptr = table+ntb; tptr < mtb; tptr++) {
412                 hole = tptr->siz;
413                 if(tptr->bar == -1)
414                         hole = 1<<20;
415                 mema = (mema+hole-1) & ~(hole-1);
416
417                 p = tptr->dev;
418                 if(tptr->bar == -1)
419                         p->mema.bar = mema;
420                 else {
421                         p->pcr |= MEMen;
422                         p->mem[tptr->bar].bar = mema;
423                         if(wrreg){
424                                 rno = PciBAR0+(tptr->bar*4);
425                                 if((mema >> 32) != 0){
426                                         pcicfgrw32(p->tbdf, rno, mema|4, 0);
427                                         pcicfgrw32(p->tbdf, rno+4, mema >> 32, 0);
428                                 } else {
429                                         pcicfgrw32(p->tbdf, rno, mema, 0);
430                                 }
431                         }
432                 }
433                 mema += tptr->siz;
434         }
435
436         *pmema = mema;
437         *pioa = ioa;
438         free(table);
439
440         if(wrreg == 0)
441                 return;
442
443         /*
444          * Finally set all the bridge addresses & registers
445          */
446         for(p = root; p != nil; p = p->link) {
447                 if(p->bridge == nil) {
448                         if(p->cls == 0){
449                                 p->cls = 64;
450                                 pcicfgw8(p, PciCLS, p->cls);
451                         }
452                         pcicfgrw8(p->tbdf, PciLTR, 64, 0);
453                         p->pcr |= MASen;
454                         pcicfgrw16(p->tbdf, PciPCR, p->pcr, 0);
455                         continue;
456                 }
457
458                 if(p == pciroot){
459                         base = p->mema.bar;
460                         limit = base+p->mema.size-1;
461                         regs[MISC_CPU_2_PCIE_MEM_WIN0_LO] = base;
462                         regs[MISC_CPU_2_PCIE_MEM_WIN0_HI] = base >> 32;
463                         base >>= 20, limit >>= 20;
464                         regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT] = (base & 0xFFF) << 4 | (limit & 0xFFF) << 20;
465                         regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI] = base >> 12;
466                         regs[MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI] = limit >> 12;
467                 }
468
469                 base = p->ioa.bar;
470                 limit = base+p->ioa.size-1;
471                 v = pcicfgrw32(p->tbdf, PciIBR, 0, 1);
472                 v = (v&0xFFFF0000)|(limit & 0xF000)|((base & 0xF000)>>8);
473                 pcicfgrw32(p->tbdf, PciIBR, v, 0);
474                 v = (limit & 0xFFFF0000)|(base>>16);
475                 pcicfgrw32(p->tbdf, PciIUBR, v, 0);
476
477                 base = p->mema.bar;
478                 limit = base+p->mema.size-1;
479                 v = (limit & 0xFFF00000)|((base & 0xFFF00000)>>16);
480                 pcicfgrw32(p->tbdf, PciMBR, v, 0);
481
482                 /*
483                  * Disable memory prefetch
484                  */
485                 pcicfgrw32(p->tbdf, PciPMBR, 0x0000FFFF, 0);
486                 pcicfgrw8(p->tbdf, PciLTR, 64, 0);
487
488                 /*
489                  * Enable the bridge
490                  */
491                 p->pcr |= IOen|MEMen|MASen;
492                 pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr, 0);
493
494                 sioa = p->ioa.bar;
495                 smema = p->mema.bar;
496                 pcibusmap(p->bridge, &smema, &sioa, 1);
497         }
498 }
499
500 static int
501 pcilscan(int bno, Pcidev** list, Pcidev *parent)
502 {
503         Pcidev *p, *head, *tail;
504         int dno, fno, i, hdt, l, maxfno, maxubn, rno, sbn, tbdf, ubn;
505
506         maxubn = bno;
507         head = nil;
508         tail = nil;
509         for(dno = 0; dno <= pcimaxdno; dno++){
510                 maxfno = 0;
511                 for(fno = 0; fno <= maxfno; fno++){
512                         /*
513                          * For this possible device, form the
514                          * bus+device+function triplet needed to address it
515                          * and try to read the vendor and device ID.
516                          * If successful, allocate a device struct and
517                          * start to fill it in with some useful information
518                          * from the device's configuration space.
519                          */
520                         tbdf = MKBUS(BusPCI, bno, dno, fno);
521                         l = pcicfgrw32(tbdf, PciVID, 0, 1);
522                         if(l == 0xFFFFFFFF || l == 0)
523                                 continue;
524                         p = malloc(sizeof(*p));
525                         if(p == nil)
526                                 panic("pcilscan: no memory");
527                         p->tbdf = tbdf;
528                         p->vid = l;
529                         p->did = l>>16;
530
531                         if(pcilist != nil)
532                                 pcitail->list = p;
533                         else
534                                 pcilist = p;
535                         pcitail = p;
536
537                         p->pcr = pcicfgr16(p, PciPCR);
538                         p->rid = pcicfgr8(p, PciRID);
539                         p->ccrp = pcicfgr8(p, PciCCRp);
540                         p->ccru = pcicfgr8(p, PciCCRu);
541                         p->ccrb = pcicfgr8(p, PciCCRb);
542                         p->cls = pcicfgr8(p, PciCLS);
543                         p->ltr = pcicfgr8(p, PciLTR);
544
545                         p->intl = pcicfgr8(p, PciINTL);
546
547                         /*
548                          * If the device is a multi-function device adjust the
549                          * loop count so all possible functions are checked.
550                          */
551                         hdt = pcicfgr8(p, PciHDT);
552                         if(hdt & 0x80)
553                                 maxfno = MaxFNO;
554
555                         /*
556                          * If appropriate, read the base address registers
557                          * and work out the sizes.
558                          */
559                         switch(p->ccrb) {
560                         case 0x00:              /* prehistoric */
561                         case 0x01:              /* mass storage controller */
562                         case 0x02:              /* network controller */
563                         case 0x03:              /* display controller */
564                         case 0x04:              /* multimedia device */
565                         case 0x07:              /* simple comm. controllers */
566                         case 0x08:              /* base system peripherals */
567                         case 0x09:              /* input devices */
568                         case 0x0A:              /* docking stations */
569                         case 0x0B:              /* processors */
570                         case 0x0C:              /* serial bus controllers */
571                         case 0x0D:              /* wireless controllers */
572                         case 0x0E:              /* intelligent I/O controllers */
573                         case 0x0F:              /* sattelite communication controllers */
574                         case 0x10:              /* encryption/decryption controllers */
575                         case 0x11:              /* signal processing controllers */
576                                 if((hdt & 0x7F) != 0)
577                                         break;
578                                 rno = PciBAR0;
579                                 for(i = 0; i <= 5; i++) {
580                                         p->mem[i].bar = pcicfgr32(p, rno);
581                                         p->mem[i].size = pcibarsize(p, rno);
582                                         if((p->mem[i].bar & 7) == 4 && i < 5){
583                                                 rno += 4;
584                                                 p->mem[i].bar |= (uintptr)pcicfgr32(p, rno) << 32;
585                                                 i++;
586                                         }
587                                         rno += 4;
588                                 }
589                                 break;
590
591                         case 0x05:              /* memory controller */
592                         case 0x06:              /* bridge device */
593                         default:
594                                 break;
595                         }
596
597                         p->parent = parent;
598                         if(head != nil)
599                                 tail->link = p;
600                         else
601                                 head = p;
602                         tail = p;
603                 }
604         }
605
606         *list = head;
607         for(p = head; p != nil; p = p->link){
608                 /*
609                  * Find PCI-PCI bridges and recursively descend the tree.
610                  */
611                 if(p->ccrb != 0x06 || p->ccru != 0x04)
612                         continue;
613
614                 /*
615                  * If the secondary or subordinate bus number is not
616                  * initialised try to do what the PCI BIOS should have
617                  * done and fill in the numbers as the tree is descended.
618                  * On the way down the subordinate bus number is set to
619                  * the maximum as it's not known how many buses are behind
620                  * this one; the final value is set on the way back up.
621                  */
622                 sbn = pcicfgr8(p, PciSBN);
623                 ubn = pcicfgr8(p, PciUBN);
624
625                 if(sbn == 0 || ubn == 0) {
626                         sbn = maxubn+1;
627                         /*
628                          * Make sure memory, I/O and master enables are
629                          * off, set the primary, secondary and subordinate
630                          * bus numbers and clear the secondary status before
631                          * attempting to scan the secondary bus.
632                          *
633                          * Initialisation of the bridge should be done here.
634                          */
635                         pcicfgw32(p, PciPCR, 0xFFFF0000);
636                         l = (MaxUBN<<16)|(sbn<<8)|bno;
637                         pcicfgw32(p, PciPBN, l);
638                         pcicfgw16(p, PciSPSR, 0xFFFF);
639                         maxubn = pcilscan(sbn, &p->bridge, p);
640                         l = (maxubn<<16)|(sbn<<8)|bno;
641
642                         pcicfgw32(p, PciPBN, l);
643                 }
644                 else {
645                         if(ubn > maxubn)
646                                 maxubn = ubn;
647                         pcilscan(sbn, &p->bridge, p);
648                 }
649         }
650
651         return maxubn;
652 }
653
654 static void
655 pcicfginit(void)
656 {
657         uintptr mema, ioa;
658
659         fmtinstall('T', tbdffmt);
660
661         pcilscan(0, &pciroot, nil);
662
663         /*
664          * Work out how big the top bus is
665          */
666         ioa = 0;
667         mema = 0;
668         pcibusmap(pciroot, &mema, &ioa, 0);
669
670         /*
671          * Align the windows and map it
672          */
673         ioa = 0;
674         mema = soc.pciwin;
675         pcibusmap(pciroot, &mema, &ioa, 1);
676 }
677
678 static void
679 pcilhinv(Pcidev* p)
680 {
681         int i;
682         Pcidev *t;
683
684         if(p == nil) {
685                 p = pciroot;
686                 print("bus dev type vid  did intl memory\n");
687         }
688         for(t = p; t != nil; t = t->link) {
689                 print("%d  %2d/%d %.2ux %.2ux %.2ux %.4ux %.4ux %3d  ",
690                         BUSBNO(t->tbdf), BUSDNO(t->tbdf), BUSFNO(t->tbdf),
691                         t->ccrb, t->ccru, t->ccrp, t->vid, t->did, t->intl);
692
693                 for(i = 0; i < nelem(p->mem); i++) {
694                         if(t->mem[i].size == 0)
695                                 continue;
696                         print("%d:%llux %d ", i,
697                                 (uvlong)t->mem[i].bar, t->mem[i].size);
698                 }
699                 if(t->bridge)
700                         print("->%d", BUSBNO(t->bridge->tbdf));
701                 print("\n");
702         }
703         while(p != nil) {
704                 if(p->bridge != nil)
705                         pcilhinv(p->bridge);
706                 p = p->link;
707         }
708 }
709
710 static void
711 pcihinv(Pcidev* p)
712 {
713         pcilhinv(p);
714 }
715
716 void
717 pcisetioe(Pcidev* p)
718 {
719         p->pcr |= IOen;
720         pcicfgw16(p, PciPCR, p->pcr);
721 }
722
723 void
724 pciclrioe(Pcidev* p)
725 {
726         p->pcr &= ~IOen;
727         pcicfgw16(p, PciPCR, p->pcr);
728 }
729
730 void
731 pcisetbme(Pcidev* p)
732 {
733         p->pcr |= MASen;
734         pcicfgw16(p, PciPCR, p->pcr);
735 }
736
737 void
738 pciclrbme(Pcidev* p)
739 {
740         p->pcr &= ~MASen;
741         pcicfgw16(p, PciPCR, p->pcr);
742 }
743
744 void
745 pcisetmwi(Pcidev* p)
746 {
747         p->pcr |= MemWrInv;
748         pcicfgw16(p, PciPCR, p->pcr);
749 }
750
751 void
752 pciclrmwi(Pcidev* p)
753 {
754         p->pcr &= ~MemWrInv;
755         pcicfgw16(p, PciPCR, p->pcr);
756 }
757
758 static int
759 enumcaps(Pcidev *p, int (*fmatch)(Pcidev*, int, int, int), int arg)
760 {
761         int i, r, cap, off;
762
763         /* status register bit 4 has capabilities */
764         if((pcicfgr16(p, PciPSR) & 1<<4) == 0)
765                 return -1;      
766         switch(pcicfgr8(p, PciHDT) & 0x7F){
767         default:
768                 return -1;
769         case 0:                         /* etc */
770         case 1:                         /* pci to pci bridge */
771                 off = 0x34;
772                 break;
773         case 2:                         /* cardbus bridge */
774                 off = 0x14;
775                 break;
776         }
777         for(i = 48; i--;){
778                 off = pcicfgr8(p, off);
779                 if(off < 0x40 || (off & 3))
780                         break;
781                 off &= ~3;
782                 cap = pcicfgr8(p, off);
783                 if(cap == 0xff)
784                         break;
785                 r = (*fmatch)(p, cap, off, arg);
786                 if(r < 0)
787                         break;
788                 if(r == 0)
789                         return off;
790                 off++;
791         }
792         return -1;
793 }
794
795 static int
796 matchcap(Pcidev *, int cap, int, int arg)
797 {
798         return cap != arg;
799 }
800
801 static int
802 matchhtcap(Pcidev *p, int cap, int off, int arg)
803 {
804         int mask;
805
806         if(cap != PciCapHTC)
807                 return 1;
808         if(arg == 0x00 || arg == 0x20)
809                 mask = 0xE0;
810         else
811                 mask = 0xF8;
812         cap = pcicfgr8(p, off+3);
813         return (cap & mask) != arg;
814 }
815
816 int
817 pcicap(Pcidev *p, int cap)
818 {
819         return enumcaps(p, matchcap, cap);
820 }
821
822 int
823 pcinextcap(Pcidev *pci, int offset)
824 {
825         if(offset == 0) {
826                 if((pcicfgr16(pci, PciPSR) & (1<<4)) == 0)
827                         return 0; /* no capabilities */
828                 offset = PciCAP-1;
829         }
830         return pcicfgr8(pci, offset+1) & ~3;
831 }
832
833 int
834 pcihtcap(Pcidev *p, int cap)
835 {
836         return enumcaps(p, matchhtcap, cap);
837 }
838
839 static int
840 pcigetpmrb(Pcidev* p)
841 {
842         if(p->pmrb != 0)
843                 return p->pmrb;
844         return p->pmrb = pcicap(p, PciCapPMG);
845 }
846
847 int
848 pcigetpms(Pcidev* p)
849 {
850         int pmcsr, ptr;
851
852         if((ptr = pcigetpmrb(p)) == -1)
853                 return -1;
854
855         /*
856          * Power Management Register Block:
857          *  offset 0:   Capability ID
858          *         1:   next item pointer
859          *         2:   capabilities
860          *         4:   control/status
861          *         6:   bridge support extensions
862          *         7:   data
863          */
864         pmcsr = pcicfgr16(p, ptr+4);
865
866         return pmcsr & 0x0003;
867 }
868
869 int
870 pcisetpms(Pcidev* p, int state)
871 {
872         int ostate, pmc, pmcsr, ptr;
873
874         if((ptr = pcigetpmrb(p)) == -1)
875                 return -1;
876
877         pmc = pcicfgr16(p, ptr+2);
878         pmcsr = pcicfgr16(p, ptr+4);
879         ostate = pmcsr & 0x0003;
880         pmcsr &= ~0x0003;
881
882         switch(state){
883         default:
884                 return -1;
885         case 0:
886                 break;
887         case 1:
888                 if(!(pmc & 0x0200))
889                         return -1;
890                 break;
891         case 2:
892                 if(!(pmc & 0x0400))
893                         return -1;
894                 break;
895         case 3:
896                 break;
897         }
898         pmcsr |= state;
899         pcicfgw16(p, ptr+4, pmcsr);
900
901         return ostate;
902 }
903
904 void
905 pcienable(Pcidev *p)
906 {
907         uint pcr;
908         int i;
909
910         if(p == nil)
911                 return;
912
913         pcienable(p->parent);
914
915         switch(pcisetpms(p, 0)){
916         case 1:
917                 print("pcienable %T: wakeup from D1\n", p->tbdf);
918                 break;
919         case 2:
920                 print("pcienable %T: wakeup from D2\n", p->tbdf);
921                 if(p->bridge != nil)
922                         delay(100);     /* B2: minimum delay 50ms */
923                 else
924                         delay(1);       /* D2: minimum delay 200µs */
925                 break;
926         case 3:
927                 print("pcienable %T: wakeup from D3\n", p->tbdf);
928                 delay(100);             /* D3: minimum delay 50ms */
929
930                 /* restore registers */
931                 for(i = 0; i < 6; i++)
932                         pcicfgw32(p, PciBAR0+i*4, p->mem[i].bar);
933                 pcicfgw8(p, PciINTL, p->intl);
934                 pcicfgw8(p, PciLTR, p->ltr);
935                 pcicfgw8(p, PciCLS, p->cls);
936                 pcicfgw16(p, PciPCR, p->pcr);
937                 break;
938         }
939
940         if(p->bridge != nil)
941                 pcr = IOen|MEMen|MASen;
942         else {
943                 pcr = 0;
944                 for(i = 0; i < 6; i++){
945                         if(p->mem[i].size == 0)
946                                 continue;
947                         if(p->mem[i].bar & 1)
948                                 pcr |= IOen;
949                         else
950                                 pcr |= MEMen;
951                 }
952         }
953
954         if((p->pcr & pcr) != pcr){
955                 print("pcienable %T: pcr %ux->%ux\n", p->tbdf, p->pcr, p->pcr|pcr);
956                 p->pcr |= pcr;
957                 pcicfgrw32(p->tbdf, PciPCR, 0xFFFF0000|p->pcr, 0);
958         }
959 }
960
961 void
962 pcidisable(Pcidev *p)
963 {
964         if(p == nil)
965                 return;
966         pciclrbme(p);
967 }
968
969 enum {
970         MSICtrl = 0x02, /* message control register (16 bit) */
971         MSIAddr = 0x04, /* message address register (64 bit) */
972         MSIData32 = 0x08, /* message data register for 32 bit MSI (16 bit) */
973         MSIData64 = 0x0C, /* message data register for 64 bit MSI (16 bit) */
974 };
975
976 typedef struct Pciisr Pciisr;
977 struct Pciisr {
978         void    (*f)(Ureg*, void*);
979         void    *a;
980         Pcidev  *p;
981 };
982
983 static Pciisr pciisr[32];
984 static Lock pciisrlk;
985
986 void
987 pciintrenable(int tbdf, void (*f)(Ureg*, void*), void *a)
988 {
989         int cap, ok64;
990         u32int dat;
991         u64int adr;
992         Pcidev *p;
993         Pciisr *isr;
994
995         if((p = pcimatchtbdf(tbdf)) == nil){
996                 print("pciintrenable: %T: unknown device\n", tbdf);
997                 return;
998         }
999         if((cap = pcicap(p, PciCapMSI)) < 0){
1000                 print("pciintrenable: %T: no MSI cap\n", tbdf);
1001                 return;
1002         }
1003
1004         lock(&pciisrlk);
1005         for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){
1006                 if(isr->p == p){
1007                         isr->p = nil;
1008                         regs[MSI_INTR2_BASE + INTR_MASK_SET] = 1 << (isr-pciisr);
1009                         break;
1010                 }
1011         }
1012         for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){
1013                 if(isr->p == nil){
1014                         isr->p = p;
1015                         isr->a = a;
1016                         isr->f = f;
1017                         regs[MSI_INTR2_BASE + INTR_CLR] = 1 << (isr-pciisr);
1018                         regs[MSI_INTR2_BASE + INTR_MASK_CLR] = 1 << (isr-pciisr);
1019                         break;
1020                 }
1021         }
1022         unlock(&pciisrlk);
1023
1024         if(isr >= &pciisr[nelem(pciisr)]){
1025                 print("pciintrenable: %T: out of isr slots\n", tbdf);
1026                 return;
1027         }
1028
1029         adr = MSI_TARGET_ADDR;
1030         ok64 = (pcicfgr16(p, cap + MSICtrl) & (1<<7)) != 0;
1031         pcicfgw32(p, cap + MSIAddr, adr);
1032         if(ok64) pcicfgw32(p, cap + MSIAddr + 4, adr>>32);
1033         dat = regs[MISC_MSI_DATA_CONFIG];
1034         dat = ((dat >> 16) & (dat & 0xFFFF)) | (isr-pciisr);
1035         pcicfgw16(p, cap + (ok64 ? MSIData64 : MSIData32), dat);
1036         pcicfgw16(p, cap + MSICtrl, 1);
1037 }
1038
1039 void
1040 pciintrdisable(int tbdf, void (*f)(Ureg*, void*), void *a)
1041 {
1042         Pciisr *isr;
1043
1044         lock(&pciisrlk);
1045         for(isr = pciisr; isr < &pciisr[nelem(pciisr)]; isr++){
1046                 if(isr->p != nil && isr->p->tbdf == tbdf && isr->f == f && isr->a == a){
1047                         regs[MSI_INTR2_BASE + INTR_MASK_SET] = 1 << (isr-pciisr);
1048                         isr->p = nil;
1049                         isr->f = nil;
1050                         isr->a = nil;
1051                         break;
1052                 }
1053         }
1054         unlock(&pciisrlk);
1055 }
1056
1057 static void
1058 pciinterrupt(Ureg *ureg, void*)
1059 {
1060         Pciisr *isr;
1061         u32int sts;
1062
1063         sts = regs[MSI_INTR2_BASE + INTR_STATUS];
1064         if(sts == 0)
1065                 return;
1066         regs[MSI_INTR2_BASE + INTR_CLR] = sts;
1067         for(isr = pciisr; sts != 0 && isr < &pciisr[nelem(pciisr)]; isr++, sts>>=1){
1068                 if((sts & 1) != 0 && isr->f != nil)
1069                         (*isr->f)(ureg, isr->a);
1070         }
1071         regs[MISC_EOI_CTRL] = 1;
1072 }
1073
1074 void
1075 pcilink(void)
1076 {
1077         int log2dmasize = 30;   // 1GB
1078
1079         regs[RGR1_SW_INIT_1] |= 3;
1080         delay(200);
1081         regs[RGR1_SW_INIT_1] &= ~2;
1082         regs[MISC_PCIE_CTRL] &= ~5;
1083         delay(200);
1084
1085         regs[MISC_HARD_PCIE_HARD_DEBUG] &= ~0x08000000;
1086         delay(200);
1087
1088         regs[MSI_INTR2_BASE + INTR_CLR] = -1;
1089         regs[MSI_INTR2_BASE + INTR_MASK_SET] = -1;
1090
1091         regs[MISC_CPU_2_PCIE_MEM_WIN0_LO] = 0;
1092         regs[MISC_CPU_2_PCIE_MEM_WIN0_HI] = 0;
1093         regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_LIMIT] = 0;
1094         regs[MISC_CPU_2_PCIE_MEM_WIN0_BASE_HI] = 0;
1095         regs[MISC_CPU_2_PCIE_MEM_WIN0_LIMIT_HI] = 0;
1096
1097         // SCB_ACCESS_EN, CFG_READ_UR_MODE, MAX_BURST_SIZE_128, SCB0SIZE
1098         regs[MISC_MISC_CTRL] = 1<<12 | 1<<13 | 0<<20 | (log2dmasize-15)<<27;
1099
1100         regs[MISC_RC_BAR2_CONFIG_LO] = (log2dmasize-15);
1101         regs[MISC_RC_BAR2_CONFIG_HI] = 0;
1102
1103         regs[MISC_RC_BAR1_CONFIG_LO] = 0;
1104         regs[MISC_RC_BAR3_CONFIG_LO] = 0;
1105
1106         regs[MISC_MSI_BAR_CONFIG_LO] = MSI_TARGET_ADDR | 1;
1107         regs[MISC_MSI_BAR_CONFIG_HI] = MSI_TARGET_ADDR>>32;
1108         regs[MISC_MSI_DATA_CONFIG] = 0xFFF86540;
1109         intrenable(IRQpci, pciinterrupt, nil, BUSUNKNOWN, "pci");
1110
1111         // force to GEN2
1112         regs[(0xAC + 12)/4] = (regs[(0xAC + 12)/4] & ~15) | 2;  // linkcap
1113         regs[(0xAC + 48)/4] = (regs[(0xAC + 48)/4] & ~15) | 2;  // linkctl2
1114
1115         regs[RGR1_SW_INIT_1] &= ~1;
1116         delay(500);
1117
1118         if((regs[MISC_PCIE_STATUS] & 0x30) != 0x30){
1119                 print("pcireset: phy link is down\n");
1120                 return;
1121         }
1122
1123         regs[RC_CFG_PRIV1_ID_VAL3] = 0x060400;
1124         regs[RC_CFG_VENDOR_VENDOR_SPECIFIC_REG1] &= ~0xC;
1125         regs[MISC_HARD_PCIE_HARD_DEBUG] |= 2;
1126
1127         pcicfginit();
1128         pcihinv(nil);
1129 }