Diff below is mostly a rewrite of vgafb_pci_probe() to determine the
memory and mmio regions based on previously initialized BAR structures.
But it also includes the glue to attach drm(4) to vgafb(4).

It reuses the following functions from vga(4), the last three are
required by any drm(4) driver:
        - vga_pci_bar_init()
        - vga_pci_bar_info()
        - vga_pci_bar_map()
        - vga_pci_bar_unmap()

I kept amd64's major numbers for agp/drm, is that ok?

I've been running this for weeks now, tested with and without drm.

Ok?

Martin


Index: conf/files.macppc
===================================================================
RCS file: /cvs/src/sys/arch/macppc/conf/files.macppc,v
retrieving revision 1.65
diff -u -p -r1.65 files.macppc
--- conf/files.macppc   15 Nov 2011 22:27:53 -0000      1.65
+++ conf/files.macppc   21 Aug 2012 08:23:53 -0000
@@ -250,7 +250,7 @@ include "dev/rasops/files.rasops"
 include "dev/wsfont/files.wsfont"
 
 # VGA framebuffer
-device vgafb: wsemuldisplaydev, rasops8, rasops16, rasops32
+device vgafb: wsemuldisplaydev, rasops8, rasops16, rasops32, drmdev
 file   arch/macppc/pci/vgafb.c                         vgafb & vgafb_pci
 
 # Generic VGA Framebuffer version
Index: macppc/conf.c
===================================================================
RCS file: /cvs/src/sys/arch/macppc/macppc/conf.c,v
retrieving revision 1.47
diff -u -p -r1.47 conf.c
--- macppc/conf.c       6 Apr 2012 15:10:40 -0000       1.47
+++ macppc/conf.c       21 Aug 2012 09:51:19 -0000
@@ -119,6 +119,8 @@ cdev_decl(nnpfs_dev);
 
 #include "apm.h"
 #include "bthub.h"
+#include "drm.h"
+cdev_decl(drm);
 
 #include "wsmux.h"
 
@@ -243,6 +245,12 @@ struct cdevsw cdevsw[] = {
        cdev_vscsi_init(NVSCSI,vscsi),  /* 83: vscsi */
        cdev_disk_init(1,diskmap),      /* 84: disk mapper */
        cdev_pppx_init(NPPPX,pppx),     /* 85: pppx */
+#ifdef NAGP
+       cdev_agp_init(NAGP,agp),        /* 86: agp */
+#else
+       cdev_notdef(),
+#endif
+       cdev_drm_init(NDRM,drm),        /* 87: drm */
 };
 int nchrdev = nitems(cdevsw);
 
Index: pci//vgafb_pci.c
n===================================================================
RCS file: /cvs/src/sys/arch/macppc/pci/vgafb_pci.c,v
retrieving revision 1.25
diff -u -p -r1.25 vgafb_pci.c
--- pci//vgafb_pci.c    21 Jun 2012 10:08:16 -0000      1.25
+++ pci//vgafb_pci.c    21 Aug 2012 08:34:44 -0000
@@ -50,22 +50,41 @@
 #include <arch/macppc/pci/vgafbvar.h>
 #include <arch/macppc/pci/vgafb_pcivar.h>
 
-#define PCI_VENDORID(x) ((x) & 0xFFFF)
-#define PCI_CHIPID(x)   (((x) >> 16) & 0xFFFF)
+#include "drm.h"
+
+#define DEBUG_VGAFB
+
+#ifdef DEBUG_VGAFB
+#define DPRINTF(x...)  do { printf(x); } while (0);
+#else
+#define DPRINTF(x...)
+#endif
 
 struct vgafb_pci_softc {
        struct device sc_dev; 
  
-       pcitag_t sc_pcitag;             /* PCI tag, in case we need it. */
        struct vgafb_config *sc_vc;     /* VGA configuration */ 
+
+       struct pci_attach_args pa;
+       struct vga_pci_bar *bars[VGA_PCI_MAX_BARS];
 };
 
-int vgafb_pci_probe(struct pci_attach_args *pa, int id, u_int32_t *ioaddr,
-    u_int32_t *iosize, u_int32_t *memaddr, u_int32_t *memsize,
-    u_int32_t *cacheable, u_int32_t *mmioaddr, u_int32_t *mmiosize);
 int    vgafb_pci_match(struct device *, void *, void *);
 void   vgafb_pci_attach(struct device *, struct device *, void *);
 
+#if NDRM > 0
+int    drmsubmatch(struct device *, void *, void *);
+#endif
+
+void   vgafb_pci_mem_init(struct vgafb_pci_softc *, uint32_t *, uint32_t *,
+           uint32_t *, uint32_t *);
+
+void   vga_pci_bar_init(struct vgafb_pci_softc *, struct pci_attach_args *);
+struct vga_pci_bar *vga_pci_bar_info(struct vgafb_pci_softc *, int);
+struct vga_pci_bar *vga_pci_bar_map(struct vgafb_pci_softc *, int,
+           bus_size_t, int);
+void   vga_pci_bar_unmap(struct vga_pci_bar*);
+
 struct cfattach vgafb_pci_ca = {
        sizeof(struct vgafb_pci_softc), (cfmatch_t)vgafb_pci_match, 
vgafb_pci_attach,
 };
@@ -73,149 +92,75 @@ struct cfattach vgafb_pci_ca = {
 pcitag_t vgafb_pci_console_tag;
 struct vgafb_config vgafb_pci_console_vc;
 
-#if 0
-#define DEBUG_VGAFB
-#endif
-
-int
-vgafb_pci_probe(struct pci_attach_args *pa, int id, u_int32_t *ioaddr,
-    u_int32_t *iosize, u_int32_t *memaddr, u_int32_t *memsize,
-    u_int32_t *cacheable, u_int32_t *mmioaddr, u_int32_t *mmiosize)
-{
-       bus_addr_t addr;
-       bus_size_t size;
-       int tcacheable;
-       pci_chipset_tag_t pc = pa->pa_pc;
-       int retval;
+void
+vgafb_pci_mem_init(struct vgafb_pci_softc *dev, uint32_t *memaddr,
+    uint32_t *memsize, uint32_t *mmioaddr, uint32_t *mmiosize)
+{
+       struct vga_pci_bar *bar;
        int i;
 
-       *iosize   = 0x0;
        *memsize  = 0x0;
        *mmiosize = 0x0;
-       for (i = PCI_MAPREG_START; i <= PCI_MAPREG_PPB_END; i += 4) {
-#ifdef DEBUG_VGAFB
-               printf("vgafb confread %x %x\n",
-                       i, pci_conf_read(pc, pa->pa_tag, i));
-#endif
-               /* need to check more than just two base addresses? */
-               if (PCI_MAPREG_TYPE(pci_conf_read(pc, pa->pa_tag, i)) ==
-                   PCI_MAPREG_TYPE_IO) {
-                       retval = pci_io_find(pc, pa->pa_tag, i,
-                               &addr, &size);
-                       if (retval != 0) {
-                               continue;
-                       }
-#ifdef DEBUG_VGAFB
-       printf("vgafb_pci_probe: io %x addr %x size %x\n", i, addr, size);
-#endif
-                       if (*iosize == 0) {
-                               *ioaddr = addr;
-                               *iosize = size;
-                       }
 
-               } else {
-                       retval = pci_mem_find(pc, pa->pa_tag, i,
-                               &addr, &size, &tcacheable);
-                       if (retval != 0) {
-                               continue;
-                       }
-#ifdef DEBUG_VGAFB
-       printf("vgafb_pci_probe: mem %x addr %x size %x\n", i, addr, size);
-#endif
-                       if (size == 0 || addr == 0) {
+       for (i = 0; i < VGA_PCI_MAX_BARS; i++) {
+               bar = dev->bars[i];
+               if (bar == NULL)
+                       continue;
+
+               DPRINTF("\nvgafb: 0x%04x: BAR ", bar->addr);
+
+               switch (PCI_MAPREG_TYPE(bar->maptype)) {
+               case PCI_MAPREG_TYPE_IO:
+                       DPRINTF("io ");
+                       break;
+               case PCI_MAPREG_TYPE_MEM:
+                       if (bar->base == 0 || bar->maxsize == 0) {
                                /* ignore this entry */
                        } else if (*memsize == 0) {
                                /*
                                 * first memory slot found goes into memory,
                                 * this is for the case of no mmio
                                 */
-                               *memaddr = addr;
-                               *memsize = size;
-                               *cacheable = tcacheable;
+                               *memaddr = bar->base;
+                               *memsize = bar->maxsize;
                        } else {
                                /*
-                                * Oh, we have a second 'memory' 
+                                * Oh, we have a second 'memory'
                                 * region, is this region the vga memory
                                 * or mmio, we guess that memory is
                                 * the larger of the two.
-                                */ 
-                                if (*memaddr >= size) {
+                                */
+                                if (*memsize >= bar->maxsize) {
                                        /* this is the mmio */
-                                       *mmioaddr = addr;
-                                       /* ATI driver maps 0x80000 mmio, grr */
-                                       if (size < 0x80000) {
-                                               size = 0x80000;
-                                       }
-                                       *mmiosize = size;
+                                       *mmioaddr = bar->base;
+                                       *mmiosize = bar->maxsize;
                                 } else {
                                        /* this is the memory */
                                        *mmioaddr = *memaddr;
-                                       *memaddr = addr;
                                        *mmiosize = *memsize;
-                                       *memsize = size;
-                                       *cacheable = tcacheable;
-                                       /* ATI driver maps 0x80000 mmio, grr */
-                                       if (*mmiosize < 0x80000) {
-                                               *mmiosize = 0x80000;
-                                       }
+                                       *memaddr = bar->base;
+                                       *memsize = bar->maxsize;
                                 }
                        }
+                       DPRINTF("mem ");
+                       break;
                }
-       }
-#ifdef DEBUG_VGAFB
-       printf("vgafb_pci_probe: id %x ioaddr %x, iosize %x, memaddr %x,\n 
memsize %x, mmioaddr %x, mmiosize %x\n",
-               id, *ioaddr, *iosize, *memaddr, *memsize, *mmioaddr, *mmiosize);
-#endif
-       if (*iosize == 0) {
-               if (id == 0) {
-#ifdef powerpc
-                       /* this is only used if on openfirmware system and
-                        * the device does not have a iobase config register,
-                        * eg CirrusLogic 5434 VGA.  (they hardcode iobase to 0
-                        * thus giving standard PC addresses for the registers) 
-                        */
-                       int s;
-                       u_int32_t sizedata;
-
-                       /*
-                        * Open Firmware (yuck) shuts down devices before
-                        * entering a program so we need to bring them back
-                        * 'online' to respond to bus accesses... so far
-                        * this is true on the power.4e.
-                        */
-                       s = splhigh();
-                       sizedata = pci_conf_read(pc, pa->pa_tag,
-                               PCI_COMMAND_STATUS_REG);
-                       sizedata |= (PCI_COMMAND_MASTER_ENABLE |
-                                    PCI_COMMAND_IO_ENABLE |
-                                    PCI_COMMAND_PARITY_ENABLE |
-                                    PCI_COMMAND_SERR_ENABLE);
-                       pci_conf_write(pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
-                               sizedata);
-                       splx(s);
 
-#endif
-                       /* if this is the first card, allow it
-                        * to be accessed in vga iospace
-                        */
-                       *ioaddr = 0;
-                       *iosize = 0x10000; /* 64k, good as any */
+               if (bar->maptype == PCI_MAPREG_MEM_TYPE_64BIT) {
+                       DPRINTF("64bit");
+                       i++;
                } else {
-                       /* iospace not available, assume 640x480, pray */
-                       *ioaddr = 0;
-                       *iosize = 0;
+                       DPRINTF("addr: 0x%08x/0x%08x", bar->base, bar->maxsize);
                }
        }
-#ifdef DEBUG_VGAFB
-       printf("vgafb_pci_probe: id %x ioaddr %x, iosize %x, memaddr %x,\n 
memsize %x, mmioaddr %x, mmiosize %x\n",
-               id, *ioaddr, *iosize, *memaddr, *memsize, *mmioaddr, *mmiosize);
-#endif
-       
-       /* io and mmio spaces are not required to attach */
-       if (/* *iosize == 0 || */ *memsize == 0 /* || *mmiosize == 0 */)
-               return (0);
 
-       return (1);
+       /* ATI driver maps 0x80000 mmio, grr */
+       if (*mmiosize > 0 && *mmiosize < 0x80000) {
+               *mmiosize = 0x80000;
+       }
+
+       DPRINTF("\nvgafb: memaddr %x, memsize %x, mmioaddr %x, mmiosize %x",
+           *memaddr, *memsize, *mmioaddr, *mmiosize);
 }
 
 int
@@ -251,17 +196,14 @@ vgafb_pci_attach(struct device *parent, 
        struct pci_attach_args *pa = aux;
        struct vgafb_pci_softc *sc = (struct vgafb_pci_softc *)self;
        struct vgafb_config *vc;
-       u_int32_t memaddr, memsize, cacheable;
-       u_int32_t ioaddr, iosize;
+       u_int32_t memaddr, memsize;
        u_int32_t mmioaddr, mmiosize;
        int console;
-       static int id = 0;
-       int myid;
+       pcireg_t reg;
 
-       myid = id;
 
-       vgafb_pci_probe(pa, myid, &ioaddr, &iosize,
-               &memaddr, &memsize, &cacheable, &mmioaddr, &mmiosize);
+       vga_pci_bar_init(sc, pa);
+       vgafb_pci_mem_init(sc, &memaddr, &memsize, &mmioaddr, &mmiosize);
 
 
        console = (!bcmp(&pa->pa_tag, &vgafb_pci_console_tag, 
sizeof(pa->pa_tag)));
@@ -275,6 +217,14 @@ vgafb_pci_attach(struct device *parent, 
                vgafb_init(pa->pa_iot, pa->pa_memt, vc,
                    memaddr, memsize, mmioaddr, mmiosize);
        }
+
+       /*
+        * Enable bus master; X might need this for accelerated graphics.
+        */
+       reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+       reg |= PCI_COMMAND_MASTER_ENABLE;
+       pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, reg);
+
        vc->vc_mmap = vgafb_mmap;
        vc->vc_ioctl = vgafb_ioctl;
        vc->membase = memaddr;
@@ -282,16 +232,139 @@ vgafb_pci_attach(struct device *parent, 
        vc->mmiobase = mmioaddr;
        vc->mmiosize = mmiosize;
 
-       sc->sc_pcitag = pa->pa_tag;
-
-       if (iosize == 0)
-               printf (", no io");
-
        if (mmiosize != 0)
                printf (", mmio");
 
        printf("\n");
 
        vgafb_wsdisplay_attach(self, vc, console);
-       id++;
+
+#if NDRM > 0
+       config_found_sm(self, aux, NULL, drmsubmatch);
+#endif
 }
+
+/*
+ * Prepare dev->bars to be used for information. we do this at startup
+ * so we can do the whole array at once, dealing with 64-bit BARs correctly.
+ */
+void
+vga_pci_bar_init(struct vgafb_pci_softc *dev, struct pci_attach_args *pa)
+{
+       pcireg_t type;
+       int addr = PCI_MAPREG_START, i = 0;
+       memcpy(&dev->pa, pa, sizeof(dev->pa));
+
+       while (i < VGA_PCI_MAX_BARS) {
+               dev->bars[i] = malloc(sizeof((*dev->bars[i])), M_DEVBUF,
+                   M_NOWAIT | M_ZERO);
+               if (dev->bars[i] == NULL) {
+                       return;
+               }
+
+               dev->bars[i]->addr = addr;
+
+               type = dev->bars[i]->maptype = pci_mapreg_type(pa->pa_pc,
+                   pa->pa_tag, addr);
+               if (pci_mapreg_info(pa->pa_pc, pa->pa_tag, addr,
+                   dev->bars[i]->maptype, &dev->bars[i]->base,
+                   &dev->bars[i]->maxsize, &dev->bars[i]->flags) != 0) {
+                       free(dev->bars[i], M_DEVBUF);
+                       dev->bars[i] = NULL;
+               }
+
+               if (type == PCI_MAPREG_MEM_TYPE_64BIT) {
+                       addr += 8;
+                       i += 2;
+               } else {
+                       addr += 4;
+                       i++;
+               }
+       }
+}
+
+/*
+ * Get the vga_pci_bar struct for the address in question. returns NULL if
+ * invalid BAR is passed.
+ */
+struct vga_pci_bar*
+vga_pci_bar_info(struct vgafb_pci_softc *dev, int no)
+{
+       if (dev == NULL || no >= VGA_PCI_MAX_BARS)
+               return (NULL);
+       return (dev->bars[no]);
+}
+
+/*
+ * map the BAR in question, returning the vga_pci_bar struct in case any more
+ * processing needs to be done. Returns NULL on failure. Can be called multiple
+ * times.
+ */
+struct vga_pci_bar*
+vga_pci_bar_map(struct vgafb_pci_softc *dev, int addr, bus_size_t size,
+    int busflags)
+{
+       struct vga_pci_bar *bar = NULL;
+       int i;
+
+       if (dev == NULL)
+               return (NULL);
+
+       for (i = 0; i < VGA_PCI_MAX_BARS; i++) {
+               if (dev->bars[i] && dev->bars[i]->addr == addr) {
+                       bar = dev->bars[i];
+                       break;
+               }
+       }
+       if (bar == NULL) {
+               printf("vga_pci_bar_map: given invalid address 0x%x\n", addr);
+               return (NULL);
+       }
+
+       if (bar->mapped == 0) {
+               if (pci_mapreg_map(&dev->pa, bar->addr, bar->maptype,
+                   bar->flags | busflags, &bar->bst, &bar->bsh, NULL,
+                   &bar->size, size)) {
+                       printf("vga_pci_bar_map: can't map bar 0x%x\n", addr);
+                       return (NULL);
+               }
+       }
+
+       bar->mapped++;
+       return (bar);
+}
+
+/*
+ * "unmap" the BAR referred to by argument. If more than one place has mapped 
it
+ * we just decrement the reference counter so nothing untoward happens.
+ */
+void
+vga_pci_bar_unmap(struct vga_pci_bar *bar)
+{
+       if (bar != NULL && bar->mapped != 0) {
+               if (--bar->mapped == 0)
+                       bus_space_unmap(bar->bst, bar->bsh, bar->size);
+       }
+}
+
+#if NDRM > 0
+int
+drmsubmatch(struct device *parent, void *match, void *aux)
+{
+       struct cfdata *cf = match;
+       struct cfdriver *cd;
+       size_t len = 0;
+       char *sm;
+
+       cd = cf->cf_driver;
+
+       /* is this a *drm device? */
+       len = strlen(cd->cd_name);
+       sm = cd->cd_name + len - 3;
+       if (strncmp(sm, "drm", 3) == 0)
+               return ((*cf->cf_attach->ca_match)(parent, match, aux));
+
+       return (0);
+}
+#endif
+
Index: pci//vgafb_pcivar.h
===================================================================
RCS file: /cvs/src/sys/arch/macppc/pci/vgafb_pcivar.h,v
retrieving revision 1.6
diff -u -p -r1.6 vgafb_pcivar.h
--- pci//vgafb_pcivar.h 21 Jun 2012 10:08:16 -0000      1.6
+++ pci//vgafb_pcivar.h 21 Aug 2012 08:22:40 -0000
@@ -36,6 +36,21 @@
             (PCI_CLASS(class) == PCI_CLASS_PREHISTORIC &&              \
              PCI_SUBCLASS(class) == PCI_SUBCLASS_PREHISTORIC_VGA)) ? 1 : 0)
 
+#define VGA_PCI_MAX_BARS 6
+
+struct vga_pci_bar {
+       int             addr;
+       u_int           mapped;
+       pcireg_t        maptype;
+       bus_addr_t      base;
+       bus_size_t      size;
+       bus_size_t      maxsize;
+       bus_space_tag_t bst;
+       bus_space_handle_t bsh;
+       int             flags;
+       void            *vaddr;
+};
+
 extern pcitag_t vgafb_pci_console_tag;
 
 /* XXX */

Reply via email to