Module Name:    src
Committed By:   bouyer
Date:           Sun Jan 26 21:22:49 UTC 2014

Modified Files:
        src/sys/dev/pci: sisfb.c

Log Message:
Complete WSDISPLAYIO_SMODE/WSDISPLAYIO_GMODE support.
In sisfb_mmap(), allow mapping the framebuffer and mmio and io registers
when in WSDISPLAYIO_MODE_MAPPED mode. This can be used by X11.


To generate a diff of this commit:
cvs rdiff -u -r1.4 -r1.5 src/sys/dev/pci/sisfb.c

Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.

Modified files:

Index: src/sys/dev/pci/sisfb.c
diff -u src/sys/dev/pci/sisfb.c:1.4 src/sys/dev/pci/sisfb.c:1.5
--- src/sys/dev/pci/sisfb.c:1.4	Fri Jan 24 12:11:40 2014
+++ src/sys/dev/pci/sisfb.c	Sun Jan 26 21:22:49 2014
@@ -24,12 +24,13 @@
  */
 
 #include <sys/cdefs.h>
-__KERNEL_RCSID(0, "$NetBSD: sisfb.c,v 1.4 2014/01/24 12:11:40 bouyer Exp $");
+__KERNEL_RCSID(0, "$NetBSD: sisfb.c,v 1.5 2014/01/26 21:22:49 bouyer Exp $");
 
 #include <sys/param.h>
 #include <sys/systm.h>
 #include <sys/device.h>
 #include <sys/bus.h>
+#include <sys/kauth.h>
 
 #include <uvm/uvm_extern.h>
 
@@ -66,9 +67,13 @@ struct sisfb {
 
 	bus_space_tag_t		 mmiot;
 	bus_space_handle_t	 mmioh;
+	bus_addr_t	 	 mmiobase;
+	bus_size_t	 	 mmiosize;
 
 	bus_space_tag_t		 iot;
 	bus_space_handle_t	 ioh;
+	bus_addr_t	 	 iobase;
+	bus_size_t	 	 iosize;
 
 	struct vcons_screen	 vcs;
 	struct wsscreen_descr	 wsd;
@@ -225,7 +230,6 @@ sisfb_attach(device_t parent, device_t s
 	struct pci_attach_args *pa = (struct pci_attach_args *)aux;
 	struct rasops_info *ri;
 	struct wsemuldisplaydev_attach_args waa;
-	bus_size_t mmiosize, iosize;
 	struct sisfb *fb;
 	int console;
 	unsigned long defattr;
@@ -258,14 +262,15 @@ sisfb_attach(device_t parent, device_t s
 			return;
 		}
 
-		if (pci_mapreg_map(pa, PCI_MAPREG_START + 4, PCI_MAPREG_TYPE_MEM,
-		    0, &fb->mmiot, &fb->mmioh, NULL, &mmiosize) != 0) {
+		if (pci_mapreg_map(pa, PCI_MAPREG_START + 4,
+		    PCI_MAPREG_TYPE_MEM, 0,
+		    &fb->mmiot, &fb->mmioh, &fb->mmiobase, &fb->mmiosize) != 0) {
 			aprint_error_dev(self, ": can't map mmio area\n");
 			goto fail1;
 		}
 
 		if (pci_mapreg_map(pa, PCI_MAPREG_START + 8, PCI_MAPREG_TYPE_IO,
-		    0, &fb->iot, &fb->ioh, NULL, &iosize) != 0) {
+		    0, &fb->iot, &fb->ioh, &fb->iobase, &fb->iosize) != 0) {
 			aprint_error_dev(self, ": can't map registers\n");
 			goto fail2;
 		}
@@ -278,7 +283,15 @@ sisfb_attach(device_t parent, device_t s
 	}
 
 	aprint_normal_dev(self, ": %dx%dx%d frame buffer\n",
-	    fb->vcs.scr_ri.ri_width, fb->vcs.scr_ri.ri_height, fb->vcs.scr_ri.ri_depth);
+	    fb->vcs.scr_ri.ri_width, fb->vcs.scr_ri.ri_height,
+	    fb->vcs.scr_ri.ri_depth);
+
+	aprint_debug_dev(self, ": fb 0x%" PRIxBUSSIZE "@0x%" PRIxBUSADDR
+	    ", mmio 0x%" PRIxBUSSIZE "@0x%" PRIxBUSADDR
+	    ", io 0x%" PRIxBUSSIZE "@0x%" PRIxBUSADDR "\n",
+	    fb->fbsize, fb->fbbase,
+	    fb->mmiosize, fb->mmiobase,
+	    fb->iosize, fb->iobase);
 
 	fb->wsd = (struct wsscreen_descr){
 		"default",
@@ -323,9 +336,9 @@ sisfb_attach(device_t parent, device_t s
 	return;
 
 fail3:
-	bus_space_unmap(fb->iot, fb->ioh, iosize);
+	bus_space_unmap(fb->iot, fb->ioh, fb->iosize);
 fail2:
-	bus_space_unmap(fb->mmiot, fb->mmioh, mmiosize);
+	bus_space_unmap(fb->mmiot, fb->mmioh, fb->mmiosize);
 fail1:
 	bus_space_unmap(fb->fbt, fb->fbh, fb->fbsize);
 }
@@ -402,7 +415,26 @@ sisfb_ioctl(void *v, void *vs, u_long cm
 			sisfb_loadcmap(fb, cm->index, cm->count);
 		return 0;
 	case WSDISPLAYIO_SMODE:
-		/* XXX */ return 0;
+		sc->sc_mode = *(uint *)data;
+		aprint_debug_dev(sc->sc_dev, ": switching to ");
+		switch(sc->sc_mode) {
+		case WSDISPLAYIO_MODE_EMUL:
+			aprint_debug("WSDISPLAYIO_MODE_EMUL\n");
+			break;
+		case WSDISPLAYIO_MODE_MAPPED:
+			aprint_debug("WSDISPLAYIO_MODE_MAPPED\n");
+			break;
+		case WSDISPLAYIO_MODE_DUMBFB:
+			aprint_debug("WSDISPLAYIO_MODE_DUMBFB\n");
+			break;
+		default:
+			aprint_debug("unknown mode %d\n", sc->sc_mode);
+			return EINVAL;
+		}
+		return 0;
+	case WSDISPLAYIO_GMODE:
+		*(uint *)data = sc->sc_mode;
+		return 0;
 	case PCI_IOC_CFGREAD:
 	case PCI_IOC_CFGWRITE:
 		return pci_devioctl(sc->sc_pc, sc->sc_pt, cmd, data, flags, l);
@@ -431,9 +463,35 @@ sisfb_mmap(void *v, void *vs, off_t offs
 	  (uintptr_t)bus_space_vaddr(fb->fbt, fb->fbh) - (uintptr_t)fb->fb_addr;
 	paddr_t pa;
 
-	if (offset >= 0 && offset < ri->ri_stride * ri->ri_height) {
-		pa = bus_space_mmap(fb->fbt, fb->fbbase, fb_offset + offset,
-		prot, BUS_SPACE_MAP_LINEAR);
+	if (sc->sc_mode != WSDISPLAYIO_MODE_MAPPED) {
+		if (offset >= 0 && offset < ri->ri_stride * ri->ri_height) {
+			pa = bus_space_mmap(fb->fbt,
+			    fb->fbbase, fb_offset + offset,
+			    prot, BUS_SPACE_MAP_LINEAR);
+			return pa;
+		}
+		return -1;
+	}
+	if (kauth_authorize_generic(kauth_cred_get(), KAUTH_GENERIC_ISSUSER,
+	    NULL) != 0) {
+		return -1;
+	}
+	if (offset >= (fb->fbbase & ~PAGE_MASK) &&
+	    offset <= ((fb->fbbase + fb->fbsize + PAGE_SIZE - 1) & ~PAGE_MASK)) {
+		pa = bus_space_mmap(fb->fbt, fb->fbbase, offset - fb->fbbase,
+		    prot, BUS_SPACE_MAP_LINEAR|BUS_SPACE_MAP_PREFETCHABLE);
+		return pa;
+	}
+	if (offset >= (fb->mmiobase & ~PAGE_MASK) &&
+	    offset <= ((fb->mmiobase + fb->mmiosize + PAGE_SIZE - 1) & ~PAGE_MASK)) {
+		pa = bus_space_mmap(fb->mmiot, fb->mmiobase, offset - fb->mmiobase,
+		    prot, BUS_SPACE_MAP_LINEAR);
+		return pa;
+	}
+	if (offset >= (fb->iobase & ~PAGE_MASK) &&
+	    offset <= ((fb->iobase + fb->iosize + PAGE_SIZE - 1) & ~PAGE_MASK)) {
+		pa = bus_space_mmap(fb->iot, fb->iobase, offset - fb->iobase,
+		    prot, BUS_SPACE_MAP_LINEAR);
 		return pa;
 	}
 	return -1;
@@ -705,10 +763,9 @@ sisfb_cnattach(bus_space_tag_t memt, bus
 {
 	long defattr;
 	struct rasops_info * const ri = &sisfbcn.vcs.scr_ri;
-	pcireg_t bar;
+	int flags;
 	int rc;
 
-
 	/* filter out unrecognized devices */
 	switch (id) {
 	default:
@@ -717,11 +774,15 @@ sisfb_cnattach(bus_space_tag_t memt, bus
 		break;
 	}
 
-	bar = pci_conf_read(pc, tag, PCI_MAPREG_START);
-	if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
-		return EINVAL;
+	if (pci_mapreg_info(pc, tag, PCI_MAPREG_START,
+	    PCI_MAPREG_TYPE_MEM,
+	    &sisfbcn.fbbase, &sisfbcn.fbsize, &flags)) {
+		printf("sisfb can't map frame buffer\n");
+		return ENODEV;
+	}
+
 	sisfbcn.fbt = memt;
-	rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
+	rc = bus_space_map(memt, sisfbcn.fbbase, sisfbcn.fbsize,
 	    BUS_SPACE_MAP_LINEAR, &sisfbcn.fbh);
 #ifdef SIS_DEBUG
 	printf("sisfb_cnattach(memt, 0x%x rc %d\n", PCI_MAPREG_MEM_ADDR(bar), rc);
@@ -729,11 +790,14 @@ sisfb_cnattach(bus_space_tag_t memt, bus
 	if (rc != 0)
 		return rc;
 
-	bar = pci_conf_read(pc, tag, PCI_MAPREG_START + 4);
-	if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_MEM)
-		return EINVAL;
+	if (pci_mapreg_info(pc, tag, PCI_MAPREG_START + 4,
+	    PCI_MAPREG_TYPE_MEM,
+	    &sisfbcn.mmiobase, &sisfbcn.mmiosize, &flags)) {
+		printf("sisfb can't map mem space\n");
+		return ENODEV;
+	}
 	sisfbcn.mmiot = memt;
-	rc = bus_space_map(memt, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
+	rc = bus_space_map(memt, sisfbcn.mmiobase, sisfbcn.mmiosize,
 	    BUS_SPACE_MAP_LINEAR, &sisfbcn.mmioh);
 #ifdef SIS_DEBUG
 	printf("sisfb_cnattach(memt2, 0x%x rc %d\n", PCI_MAPREG_MEM_ADDR(bar), rc);
@@ -741,11 +805,14 @@ sisfb_cnattach(bus_space_tag_t memt, bus
 	if (rc != 0)
 		return rc;
 
-	bar = pci_conf_read(pc, tag, PCI_MAPREG_START + 8);
-	if (PCI_MAPREG_TYPE(bar) != PCI_MAPREG_TYPE_IO)
-		return EINVAL;
+	if (pci_mapreg_info(pc, tag, PCI_MAPREG_START + 8,
+	    PCI_MAPREG_TYPE_IO,
+	    &sisfbcn.iobase, &sisfbcn.iosize, &flags)) {
+		printf("sisfb can't map mem space\n");
+		return ENODEV;
+	}
 	sisfbcn.iot = iot;
-	rc = bus_space_map(iot, PCI_MAPREG_MEM_ADDR(bar), 1 /* XXX */,
+	rc = bus_space_map(iot, sisfbcn.iobase, sisfbcn.iosize,
 	    0, &sisfbcn.ioh);
 #ifdef SIS_DEBUG
 	printf("sisfb_cnattach(iot, 0x%x rc %d\n", PCI_MAPREG_MEM_ADDR(bar), rc);

Reply via email to