Add the pci device
authorRonald G. Minnich <rminnich@google.com>
Mon, 3 Mar 2014 06:46:40 +0000 (22:46 -0800)
committerRonald G. Minnich <rminnich@google.com>
Mon, 3 Mar 2014 06:46:40 +0000 (22:46 -0800)
This won't compile of course.
We need to work out our pci calls so we can write the spatches.

Signed-off-by: Ronald G. Minnich <rminnich@google.com>
kern/drivers/dev/Kbuild
kern/drivers/dev/pci.c [new file with mode: 0644]

index 6dd9397..64f7829 100644 (file)
@@ -4,6 +4,7 @@ obj-y                                           += coreboot.o
 obj-y                                          += cons.o
 obj-y                                          += ether.o
 obj-y                                          += mnt.o
+#obj-y                                         += pci.o
 obj-y                                          += pipe.o
 obj-y                                          += root.o
 obj-y                                          += srv.o
diff --git a/kern/drivers/dev/pci.c b/kern/drivers/dev/pci.c
new file mode 100644 (file)
index 0000000..614583b
--- /dev/null
@@ -0,0 +1,271 @@
+/* 
+ * This file is part of the UCB release of Plan 9. It is subject to the license
+ * terms in the LICENSE file found in the top-level directory of this
+ * distribution and at http://akaros.cs.berkeley.edu/files/Plan9License. No
+ * part of the UCB release of Plan 9, including this file, may be copied,
+ * modified, propagated, or distributed except according to the terms contained
+ * in the LICENSE file.
+ */
+
+#include <vfs.h>
+#include <kfs.h>
+#include <slab.h>
+#include <kmalloc.h>
+#include <kref.h>
+#include <string.h>
+#include <stdio.h>
+#include <assert.h>
+#include <error.h>
+#include <cpio.h>
+#include <pmap.h>
+#include <smp.h>
+#include <ip.h>
+
+enum {
+       Qtopdir = 0,
+
+       Qpcidir,
+       Qpcictl,
+       Qpciraw,
+};
+
+#define TYPE(q)                ((uint32_t)(q).path & 0x0F)
+#define QID(c, t)      (((c)<<4)|(t))
+
+static struct dirtab topdir[] = {
+       {".",   { Qtopdir, 0, QTDIR },  0,      0555},
+       {"pci", { Qpcidir, 0, QTDIR },  0,      0555},
+};
+
+extern struct dev pcidevtab;
+
+static int
+pcidirgen(struct chan *c, int t, int tbdf, struct dir *dp)
+{
+       struct qid q;
+
+       q = (struct qid){BUSBDF(tbdf)|t, 0, 0};
+       switch(t) {
+       case Qpcictl:
+               snprintf(get_cur_genbuf(), GENBUF_SZ, "%d.%d.%dctl",
+                       BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
+               devdir(c, q, get_cur_genbuf(), 0, eve, 0444, dp);
+               return 1;
+       case Qpciraw:
+               snprintf(get_cur_genbuf(), GENBUF_SZ, "%d.%d.%draw",
+                       BUSBNO(tbdf), BUSDNO(tbdf), BUSFNO(tbdf));
+               devdir(c, q, get_cur_genbuf(), 128, eve, 0664, dp);
+               return 1;
+       }
+       return -1;
+}
+
+static int
+pcigen(struct chan *c, char *, struct dirtab*, int unused_int, int s, struct dir *dp)
+{
+       int tbdf;
+       Pcidev *p;
+       struct qid q;
+
+       switch(TYPE(c->qid)){
+       case Qtopdir:
+               if(s == DEVDOTDOT){
+                       q = (struct qid){QID(0, Qtopdir), 0, QTDIR};
+                       snprintf(get_cur_genbuf(), GENBUF_SZ, "#%C", pcidevtab.dc);
+                       devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
+                       return 1;
+               }
+               return devgen(c, NULL, topdir, ARRAY_SIZE(topdir), s, dp);
+       case Qpcidir:
+               if(s == DEVDOTDOT){
+                       q = (struct qid){QID(0, Qtopdir), 0, QTDIR};
+                       snprintf(get_cur_genbuf(), GENBUF_SZ, "#%C", pcidevtab.dc);
+                       devdir(c, q, get_cur_genbuf(), 0, eve, 0555, dp);
+                       return 1;
+               }
+               p = pcimatch(NULL, 0, 0);
+               while(s >= 2 && p != NULL) {
+                       p = pcimatch(p, 0, 0);
+                       s -= 2;
+               }
+               if(p == NULL)
+                       return -1;
+               return pcidirgen(c, s+Qpcictl, p->tbdf, dp);
+       case Qpcictl:
+       case Qpciraw:
+               tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((uint32_t)c->qid.path);
+               p = pcimatchtbdf(tbdf);
+               if(p == NULL)
+                       return -1;
+               return pcidirgen(c, TYPE(c->qid), tbdf, dp);
+       default:
+               break;
+       }
+       return -1;
+}
+
+static struct chan*
+pciattach(char *spec)
+{
+       return devattach(pcidevtab.dc, spec);
+}
+
+struct walkqid*
+pciwalk(struct chan* c, struct chan *nc, char** name, int nname)
+{
+       return devwalk(c, nc, name, nname, (struct dirtab *)0, 0, pcigen);
+}
+
+static long
+pcistat(struct chan* c, uint8_t* dp, long n)
+{
+       return devstat(c, dp, n, (struct dirtab *)0, 0L, pcigen);
+}
+
+static struct chan*
+pciopen(struct chan *c, int omode)
+{
+       c = devopen(c, omode, (struct dirtab*)0, 0, pcigen);
+       switch(TYPE(c->qid)){
+       default:
+               break;
+       }
+       return c;
+}
+
+static void
+pciclose(struct chan*)
+{
+}
+
+static long
+pciread(struct chan *c, void *va, long n, int64_t offset)
+{
+       char buf[256], *ebuf, *w, *a;
+       int i, tbdf, r;
+       uint32_t x;
+       Pcidev *p;
+
+       a = va;
+       switch(TYPE(c->qid)){
+       case Qtopdir:
+       case Qpcidir:
+               return devdirread(c, a, n, (struct dirtab *)0, 0L, pcigen);
+       case Qpcictl:
+               tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((uint32_t)c->qid.path);
+               p = pcimatchtbdf(tbdf);
+               if(p == NULL)
+                       error(Egreg);
+               ebuf = buf+sizeof buf-1;        /* -1 for newline */
+               w = seprintf(buf, ebuf, "%.2x.%.2x.%.2x %.4x/%.4x %3d",
+                       p->ccrb, p->ccru, p->ccrp, p->vid, p->did, p->intl);
+               for(i=0; i<ARRAY_SIZE(p->mem); i++){
+                       if(p->mem[i].size == 0)
+                               continue;
+                       w = seprintf(w, ebuf, " %d:%.8lux %d", 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((uint32_t)c->qid.path);
+               p = pcimatchtbdf(tbdf);
+               if(p == NULL)
+                       error(Egreg);
+               if(n+offset > 256)
+                       n = 256-offset;
+               if(n < 0)
+                       return 0;
+               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(struct chan *c, void *va, long n, int64_t offset)
+{
+       char buf[256];
+       uint8_t *a;
+       int i, r, tbdf;
+       uint32_t x;
+       Pcidev *p;
+
+       if(n >= sizeof(buf))
+               n = sizeof(buf)-1;
+       a = va;
+       strncpy(buf, ( char *unused_char_p_t)a, n);
+       buf[n] = 0;
+
+       switch(TYPE(c->qid)){
+       case Qpciraw:
+               tbdf = MKBUS(BusPCI, 0, 0, 0)|BUSBDF((uint32_t)c->qid.path);
+               p = pcimatchtbdf(tbdf);
+               if(p == NULL)
+                       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;
+}
+
+struct dev pcidevtab = {
+       '$',
+       "pci",
+
+       devreset,
+       devinit,
+       devshutdown,
+       pciattach,
+       pciwalk,
+       pcistat,
+       pciopen,
+       devcreate,
+       pciclose,
+       pciread,
+       devbread,
+       pciwrite,
+       devbwrite,
+       devremove,
+       devwstat,
+};