diff options
author | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-09-25 14:02:59 +0000 |
---|---|---|
committer | cinap_lenrek <cinap_lenrek@felloff.net> | 2022-09-25 14:02:59 +0000 |
commit | 6abe569ec8f47ba14c3dcd5d5214e7b7a020bf7a (patch) | |
tree | 11b4770d01246d44f350182d5e3043fa378b1052 /sys/src/9/port | |
parent | 0294abd5646dc9966cd98ac920b17aea3de3f57f (diff) |
devpci: provide a #$ device for PCI config access
We want to provide userspace PCI config space
access on platforms that have PCI, but do not
have ISA bus.
For this, provide a stripped down version of
devpnp, wiht only the pci support that can then
be used by pi4 (bcm64) and reform (imx8) kernels.
Diffstat (limited to 'sys/src/9/port')
-rw-r--r-- | sys/src/9/port/devpci.c | 267 | ||||
-rw-r--r-- | sys/src/9/port/portmkfile | 2 |
2 files changed, 268 insertions, 1 deletions
diff --git a/sys/src/9/port/devpci.c b/sys/src/9/port/devpci.c new file mode 100644 index 000000000..ae64b7183 --- /dev/null +++ b/sys/src/9/port/devpci.c @@ -0,0 +1,267 @@ +/* + * This is a stripped down copy of port/devpnp.c, + * with the ISA PNP stripped out, only providing + * access to PCI configuration space. + */ +#include "u.h" +#include "../port/lib.h" +#include "mem.h" +#include "dat.h" +#include "fns.h" +#include "../port/pci.h" +#include "../port/error.h" + +enum { + Qtopdir = 0, + + Qpcidir, + Qpcictl, + Qpciraw, +}; + +#define TYPE(q) ((ulong)(q).path & 0x0F) +#define QID(c, t) (((c)<<4)|(t)) + +static Dirtab topdir[] = { + ".", { Qtopdir, 0, QTDIR }, 0, 0555, + "pci", { Qpcidir, 0, QTDIR }, 0, 0555, +}; + +static Dirtab pcidir[] = { + ".", { Qpcidir, 0, QTDIR }, 0, 0555, + "ctl", { Qpcictl, 0, 0 }, 0, 0666, +}; + +extern Dev pcidevtab; + +static int +pcigen(Chan *c, int t, int tbdf, Dir *dp) +{ + Qid q; + + q = (Qid){BUSBDF(tbdf)|t, 0, 0}; + switch(t) { + case Qpcictl: + snprint(up->genbuf, sizeof up->genbuf, "%d.%d.%dctl", + BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); + devdir(c, q, up->genbuf, 0, eve, 0444, dp); + return 1; + case Qpciraw: + snprint(up->genbuf, sizeof up->genbuf, "%d.%d.%draw", + BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf)); + devdir(c, q, up->genbuf, 128, eve, 0660, dp); + return 1; + } + return -1; +} + +static int +pcidirgen(Chan *c, char *, Dirtab*, int, int s, Dir *dp) +{ + Qid q; + Pcidev *p; + int tbdf; + + switch(TYPE(c->qid)){ + case Qtopdir: + if(s == DEVDOTDOT){ + q = (Qid){QID(0, Qtopdir), 0, QTDIR}; + snprint(up->genbuf, sizeof up->genbuf, "#%C", pcidevtab.dc); + devdir(c, q, up->genbuf, 0, eve, 0555, dp); + return 1; + } + return devgen(c, nil, topdir, nelem(topdir), s, dp); + case Qpcidir: + if(s == DEVDOTDOT){ + q = (Qid){QID(0, Qtopdir), 0, QTDIR}; + snprint(up->genbuf, sizeof up->genbuf, "#%C", pcidevtab.dc); + devdir(c, q, up->genbuf, 0, eve, 0555, dp); + return 1; + } + p = pcimatch(nil, 0, 0); + while(s >= 2 && p != nil) { + p = pcimatch(p, 0, 0); + s -= 2; + } + if(p == nil) + return -1; + return pcigen(c, s+Qpcictl, p->tbdf, dp); + case Qpcictl: + case Qpciraw: + tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); + p = pcimatchtbdf(tbdf); + if(p == nil) + return -1; + return pcigen(c, TYPE(c->qid), tbdf, dp); + default: + break; + } + return -1; +} + +static Chan* +pciattach(char *spec) +{ + return devattach(pcidevtab.dc, spec); +} + +Walkqid* +pciwalk(Chan* c, Chan *nc, char** name, int nname) +{ + return devwalk(c, nc, name, nname, (Dirtab *)0, 0, pcidirgen); +} + +static int +pcistat(Chan* c, uchar* dp, int n) +{ + return devstat(c, dp, n, (Dirtab *)0, 0L, pcidirgen); +} + +static Chan* +pciopen(Chan *c, int omode) +{ + c = devopen(c, omode, (Dirtab*)0, 0, pcidirgen); + switch(TYPE(c->qid)){ + default: + break; + } + return c; +} + +static void +pciclose(Chan*) +{ +} + +static long +pciread(Chan *c, void *va, long n, vlong offset) +{ + ulong x; + Pcidev *p; + char buf[256], *ebuf, *w; + char *a = va; + int i, tbdf, r; + + switch(TYPE(c->qid)){ + case Qtopdir: + case Qpcidir: + return devdirread(c, a, n, (Dirtab *)0, 0L, pcidirgen); + case Qpcictl: + tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); + p = pcimatchtbdf(tbdf); + if(p == nil) + error(Egreg); + ebuf = buf+sizeof buf-1; /* -1 for newline */ + w = seprint(buf, ebuf, "%.2x.%.2x.%.2x %.4x/%.4x %3d", + p->ccrb, p->ccru, p->ccrp, p->vid, p->did, p->intl); + for(i=0; i<nelem(p->mem); i++){ + if(p->mem[i].size == 0) + continue; + w = seprint(w, ebuf, " %d:%.8llux %lld", i, + p->mem[i].bar, p->mem[i].size); + } + *w++ = '\n'; + *w = '\0'; + return readstr(offset, a, n, buf); + case Qpciraw: + tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); + p = pcimatchtbdf(tbdf); + if(p == nil) + error(Egreg); + if(offset > 256) + return 0; + if(n+offset > 256) + n = 256-offset; + r = offset; + if(!(r & 3) && n == 4){ + x = pcicfgr32(p, r); + PBIT32(a, x); + return 4; + } + if(!(r & 1) && n == 2){ + x = pcicfgr16(p, r); + PBIT16(a, x); + return 2; + } + for(i = 0; i < n; i++){ + x = pcicfgr8(p, r); + PBIT8(a, x); + a++; + r++; + } + return i; + default: + error(Egreg); + } + return n; +} + +static long +pciwrite(Chan *c, void *va, long n, vlong offset) +{ + Pcidev *p; + ulong x; + char buf[256]; + uchar *a; + int i, r, tbdf; + + if(n >= sizeof(buf)) + n = sizeof(buf)-1; + a = va; + strncpy(buf, va, n); + buf[n] = 0; + + switch(TYPE(c->qid)){ + case Qpciraw: + tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((ulong)c->qid.path); + p = pcimatchtbdf(tbdf); + if(p == nil) + error(Egreg); + if(offset > 256) + return 0; + if(n+offset > 256) + n = 256-offset; + r = offset; + if(!(r & 3) && n == 4){ + x = GBIT32(a); + pcicfgw32(p, r, x); + return 4; + } + if(!(r & 1) && n == 2){ + x = GBIT16(a); + pcicfgw16(p, r, x); + return 2; + } + for(i = 0; i < n; i++){ + x = GBIT8(a); + pcicfgw8(p, r, x); + a++; + r++; + } + return i; + default: + error(Egreg); + } + return n; +} + +Dev pcidevtab = { + '$', + "pci", + + devreset, + devinit, + devshutdown, + pciattach, + pciwalk, + pcistat, + pciopen, + devcreate, + pciclose, + pciread, + devbread, + pciwrite, + devbwrite, + devremove, + devwstat, +}; diff --git a/sys/src/9/port/portmkfile b/sys/src/9/port/portmkfile index aae30db94..bdf049e86 100644 --- a/sys/src/9/port/portmkfile +++ b/sys/src/9/port/portmkfile @@ -113,4 +113,4 @@ devether.$O ethersink.$O: ../port/etherif.h ../port/netif.h wifi.$O: ../port/etherif.h ../port/netif.h ../port/wifi.h /sys/include/libsec.h wifi.$O: ../ip/ip.h ../ip/ipv6.h ethermii.$O: ../port/ethermii.h -pci.$O devpnp.$O usbxhci.$O: ../port/pci.h +pci.$O devpnp.$O devpci.$O usbxhci.$O: ../port/pci.h |