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.
This commit is contained in:
parent
2aecc71d04
commit
8dfb7255af
|
@ -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 self, void *aux)
|
|||
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 self, void *aux)
|
|||
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 self, void *aux)
|
|||
}
|
||||
|
||||
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 self, void *aux)
|
|||
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 cmd, void *data, int flags,
|
|||
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 offset, int prot)
|
|||
(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_space_tag_t iot,
|
|||
{
|
||||
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_space_tag_t iot,
|
|||
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_space_tag_t iot,
|
|||
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_space_tag_t iot,
|
|||
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);
|
||||
|
|
Loading…
Reference in New Issue