#include #include #include #include #include "pci.h" static Pcidev* pcilist; static Pcidev* pcitail; static void pcicfginit(void) { int fd, i, j, n, bno, dno, fno; char buf[1024], *base, *s; Pcidev *p; Dir *d; if((fd = open(base = "/dev/pci", OREAD)) < 0) if((fd = open(base = "#$/pci", OREAD)) < 0) return; n = dirreadall(fd, &d); close(fd); for(i=0; itbdf = MKBUS(BusPCI, bno, dno, fno); sprint(buf, "%s/%d.%d.%draw", base, bno, dno, fno); if((p->rawfd = open(buf, ORDWR)) < 0){ free(p); continue; } sprint(buf, "%s/%d.%d.%dctl", base, bno, dno, fno); if((fd = open(buf, OREAD)) < 0){ close(p->rawfd); free(p); continue; } if((j = read(fd, buf, sizeof(buf)-1)) <= 0){ close(p->rawfd); close(fd); free(p); continue; } buf[j] = 0; close(fd); p->ccrb = strtol(buf, nil, 16); p->ccru = strtol(buf + 3, nil, 16); p->vid = strtol(buf + 9, &s, 16); p->did = strtol(s + 1, &s, 16); p->intl = strtol(s + 1, &s, 10); p->rid = pcicfgr8(p, PciRID); while(*s == ' '){ j = strtol(s+1, &s, 10); if(j < 0 || j >= nelem(p->mem)) break; p->mem[j].bar = strtoul(s+1, &s, 16); p->mem[j].size = strtoul(s+1, &s, 10); } if(pcilist != nil) pcitail->list = p; else pcilist = p; pcitail = p; } } static u64int pcicfgrw(Pcidev *pcidev, int rno, u64int data, int len, int read) { uchar buf[8]; if(read){ memset(buf, 0, sizeof(buf)); if(pread(pcidev->rawfd, buf, len, rno) != len) return -1; switch(len){ case 1: return GBIT8(buf); case 2: return GBIT16(buf); case 4: return GBIT32(buf); case 8: return GBIT64(buf); default: abort(); } } else { switch(len){ case 1: PBIT8(buf, data); break; case 2: PBIT16(buf, data); break; case 4: PBIT32(buf, data); break; case 8: PBIT64(buf, data); break; default: abort(); } if(pwrite(pcidev->rawfd, buf, len, rno) != len) return -1; } return 0; } int pcicfgr8(Pcidev* pcidev, int rno) { return pcicfgrw(pcidev, rno, 0, 1, 1); } void pcicfgw8(Pcidev* pcidev, int rno, int data) { pcicfgrw(pcidev, rno, data, 1, 0); } int pcicfgr16(Pcidev* pcidev, int rno) { return pcicfgrw(pcidev, rno, 0, 2, 1); } void pcicfgw16(Pcidev* pcidev, int rno, int data) { pcicfgrw(pcidev, rno, data, 2, 0); } u32int pcicfgr32(Pcidev* pcidev, int rno) { return pcicfgrw(pcidev, rno, 0, 4, 1); } void pcicfgw32(Pcidev* pcidev, int rno, u32int data) { pcicfgrw(pcidev, rno, data, 4, 0); } u64int pcicfgr64(Pcidev* pcidev, int rno) { return pcicfgrw(pcidev, rno, 0, 8, 1); } void pcicfgw64(Pcidev* pcidev, int rno, u64int data) { pcicfgrw(pcidev, rno, data, 8, 0); } Pcidev* pcimatch(Pcidev* prev, int vid, int did) { if(pcilist == nil) pcicfginit(); if(prev == nil) prev = pcilist; else prev = prev->list; while(prev != nil) { if(prev->vid == vid && (did == 0 || prev->did == did)) break; prev = prev->list; } return prev; }