diff options
author | Owain Ainsworth <oga@cvs.openbsd.org> | 2008-05-06 19:19:03 +0000 |
---|---|---|
committer | Owain Ainsworth <oga@cvs.openbsd.org> | 2008-05-06 19:19:03 +0000 |
commit | 0d12c3f56a9965c9c1fbab7d8a961c9e121bc885 (patch) | |
tree | 1b8da77e839c5cdd95bbfe014dc6f76d6d8f5d4c /sys | |
parent | 6326e66a01c7b4d7ac0ec2d749c33423122e90bd (diff) |
currently agp_i810 needs to map the same BAR as inteldrm, this obviously
fails.
In order to allow this, implement an API so that drm and agp can share
mappings for the BARs. Now it works as it should.
tested by many.
ok kettenis, miod said he'd look at it when it's in tree.
Diffstat (limited to 'sys')
-rw-r--r-- | sys/dev/pci/agp.c | 4 | ||||
-rw-r--r-- | sys/dev/pci/agp_i810.c | 24 | ||||
-rw-r--r-- | sys/dev/pci/agpvar.h | 4 | ||||
-rw-r--r-- | sys/dev/pci/drm/drmP.h | 23 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_bufs.c | 29 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_drv.c | 6 | ||||
-rw-r--r-- | sys/dev/pci/drm/drm_memory.c | 52 | ||||
-rw-r--r-- | sys/dev/pci/drm/i915_drv.c | 3 | ||||
-rw-r--r-- | sys/dev/pci/drm/mach64_drv.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/drm/mga_drv.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/drm/r128_drv.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/drm/radeon_drv.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/drm/savage_drv.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/drm/sis_drv.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/drm/tdfx_drv.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/drm/via_drv.c | 2 | ||||
-rw-r--r-- | sys/dev/pci/vga_pci.c | 110 | ||||
-rw-r--r-- | sys/dev/pci/vga_pcivar.h | 29 |
18 files changed, 218 insertions, 82 deletions
diff --git a/sys/dev/pci/agp.c b/sys/dev/pci/agp.c index 6c297f9031a..15f31704d45 100644 --- a/sys/dev/pci/agp.c +++ b/sys/dev/pci/agp.c @@ -1,4 +1,4 @@ -/* $OpenBSD: agp.c,v 1.20 2008/04/09 18:59:58 oga Exp $ */ +/* $OpenBSD: agp.c,v 1.21 2008/05/06 19:19:02 oga Exp $ */ /*- * Copyright (c) 2000 Doug Rabson * All rights reserved. @@ -176,6 +176,8 @@ agp_attach(struct device *parent, struct device *self, void *aux) pci_get_capability(sc->sc_pc, sc->sc_pcitag, PCI_CAP_AGP, &sc->sc_capoff, NULL); + sc->vga_softc = (struct vga_pci_softc *)parent; + printf(": "); ret = (*ap->ap_attach)(sc, pa); if (ret == 0) diff --git a/sys/dev/pci/agp_i810.c b/sys/dev/pci/agp_i810.c index 67fbb6ee66c..cb7e1c013b0 100644 --- a/sys/dev/pci/agp_i810.c +++ b/sys/dev/pci/agp_i810.c @@ -1,4 +1,4 @@ -/* $OpenBSD: agp_i810.c,v 1.34 2008/03/23 19:54:47 oga Exp $ */ +/* $OpenBSD: agp_i810.c,v 1.35 2008/05/06 19:19:02 oga Exp $ */ /* $NetBSD: agp_i810.c,v 1.15 2003/01/31 00:07:39 thorpej Exp $ */ /*- @@ -157,6 +157,7 @@ agp_i810_attach(struct agp_softc *sc, struct pci_attach_args *pa) struct agp_i810_softc *isc; struct agp_gatt *gatt; bus_addr_t mmaddr, gmaddr; + struct vga_pci_bar *map; int error; u_int memtype = 0; @@ -251,26 +252,27 @@ agp_i810_attach(struct agp_softc *sc, struct pci_attach_args *pa) return (error); } - if (isc->chiptype == CHIP_I965) - memtype = pci_mapreg_type(isc->vga_pa.pa_pc, - isc->vga_pa.pa_tag, mmaddr); - - error = pci_mapreg_map(&isc->vga_pa, mmaddr, memtype, 0, - &isc->bst, &isc->bsh, NULL, &isc->bsz, 0); - if (error != 0) { + map = vga_pci_bar_map(sc->vga_softc, mmaddr, 0, + BUS_SPACE_MAP_LINEAR); + if (map == NULL) { printf("can't map mmadr registers\n"); agp_generic_detach(sc); return (error); } + isc->bst = map->bst; + isc->bsh = map->bsh; + isc->bsz = map->size; if (isc->chiptype == CHIP_I915 || isc->chiptype == CHIP_G33) { - error = pci_mapreg_map(&isc->vga_pa, AGP_I915_GTTADR, memtype, - 0, &isc->gtt_bst, &isc->gtt_bsh, NULL, NULL, 0); - if (error != 0) { + map = vga_pci_bar_map(sc->vga_softc, AGP_I915_GTTADR, + 0, BUS_SPACE_MAP_LINEAR); + if (map == NULL) { printf("can't map gatt registers\n"); agp_generic_detach(sc); return (error); } + isc->gtt_bst = map->bst; + isc->gtt_bsh = map->bsh; } isc->initial_aperture = AGP_GET_APERTURE(sc); diff --git a/sys/dev/pci/agpvar.h b/sys/dev/pci/agpvar.h index 5c5a0de6686..8f80f7769eb 100644 --- a/sys/dev/pci/agpvar.h +++ b/sys/dev/pci/agpvar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: agpvar.h,v 1.12 2008/03/23 19:54:47 oga Exp $ */ +/* $OpenBSD: agpvar.h,v 1.13 2008/05/06 19:19:02 oga Exp $ */ /* $NetBSD: agpvar.h,v 1.4 2001/10/01 21:54:48 fvdl Exp $ */ /*- @@ -146,6 +146,8 @@ struct agp_softc { u_int32_t sc_allocated; /* amount allocated */ enum agp_acquire_state sc_state; struct agp_memory_list sc_memory; /* list of allocated memory */ + + struct vga_pci_softc *vga_softc; /* needed for shared mappings */ }; struct agp_gatt { diff --git a/sys/dev/pci/drm/drmP.h b/sys/dev/pci/drm/drmP.h index 07fd6976d4a..f93246c0e93 100644 --- a/sys/dev/pci/drm/drmP.h +++ b/sys/dev/pci/drm/drmP.h @@ -676,18 +676,6 @@ typedef struct drm_sg_mem { drm_dma_handle_t *dmah; /* Handle to PCI memory for ATI PCIGART table */ } drm_sg_mem_t; -#if defined(__NetBSD__) || defined(__OpenBSD__) -typedef struct { - int mapped; - int maptype; - bus_addr_t base; - bus_size_t size; - bus_space_handle_t bsh; - int flags; - void * vaddr; -} pci_map_data_t; -#endif - typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t; typedef struct drm_local_map { @@ -703,7 +691,7 @@ typedef struct drm_local_map { #ifdef __FreeBSD__ struct resource *bsr; #else - pci_map_data_t *bsr; + struct vga_pci_bar *bsr; #endif bus_space_tag_t bst; bus_space_handle_t bsh; @@ -832,6 +820,7 @@ struct drm_device { #endif #ifdef __OpenBSD__ dev_t kdev; /* used by uvm_mmap, this is just a placeholder */ + struct vga_pci_softc *vga_softc; #endif int if_version; /* Highest interface version set */ @@ -885,10 +874,10 @@ struct drm_device { /* Storage of resource pointers for drm_get_resource_* */ #ifdef __FreeBSD__ struct resource *pcir[DRM_MAX_PCI_RESOURCE]; + int pcirid[DRM_MAX_PCI_RESOURCE]; #else - pci_map_data_t *pcir[DRM_MAX_PCI_RESOURCE]; + struct vga_pci_bar *pcir[DRM_MAX_PCI_RESOURCE]; #endif - int pcirid[DRM_MAX_PCI_RESOURCE]; int pci_domain; int pci_bus; @@ -950,8 +939,8 @@ d_poll_t drm_poll; d_mmap_t drm_mmap; #elif defined(__NetBSD__) || defined(__OpenBSD__) int drm_probe(struct pci_attach_args *, drm_pci_id_list_t * ); -void drm_attach(struct device *kdev, struct pci_attach_args *pa, - drm_pci_id_list_t *idlist); +void drm_attach(struct device *kdev, struct device *parent, + struct pci_attach_args *pa, drm_pci_id_list_t *idlist); int drm_detach(struct device *self, int flags); int drm_activate(struct device *self, enum devact act); dev_type_ioctl(drm_ioctl); diff --git a/sys/dev/pci/drm/drm_bufs.c b/sys/dev/pci/drm/drm_bufs.c index 64e32082e22..3451b7c63f1 100644 --- a/sys/dev/pci/drm/drm_bufs.c +++ b/sys/dev/pci/drm/drm_bufs.c @@ -67,9 +67,6 @@ drm_order(unsigned long size) int drm_alloc_resource(drm_device_t *dev, int resource) { -#ifdef __OpenBSD__ -#define PCIR_BAR(x) (PCI_MAPS + (x) * 4) -#endif if (resource >= DRM_MAX_PCI_RESOURCE) { DRM_ERROR("Resource %d too large\n", resource); return 1; @@ -81,8 +78,8 @@ drm_alloc_resource(drm_device_t *dev, int resource) return 0; } - dev->pcirid[resource] = PCIR_BAR(resource); #if defined (__FreeBSD__) + dev->pcirid[resource] = PCIR_BAR(resource); dev->pcir[resource] = bus_alloc_resource_any(dev->device, SYS_RES_MEMORY, &dev->pcirid[resource], RF_SHAREABLE); @@ -92,27 +89,12 @@ drm_alloc_resource(drm_device_t *dev, int resource) return 1; } #elif defined (__OpenBSD__) - dev->pcir[resource] = malloc(sizeof(*(dev->pcir)), M_DRM, M_NOWAIT | M_ZERO); + dev->pcir[resource] = vga_pci_bar_info(dev->vga_softc, resource); + DRM_LOCK(); if (dev->pcir[resource] == NULL) { - DRM_ERROR("Couldn't allocate memory for resource 0x%x\n", resource); - DRM_LOCK(); + DRM_ERROR("Can't get bar info for resource 0x%x\n", resource); return 1; } - dev->pcir[resource]->maptype = - pci_mapreg_type(dev->pa.pa_pc, dev->pa.pa_tag, - dev->pcirid[resource]); - if(pci_mapreg_info(dev->pa.pa_pc, dev->pa.pa_tag, - dev->pcirid[resource], - dev->pcir[resource]->maptype, - &(dev->pcir[resource]->base), - &(dev->pcir[resource]->size), - &(dev->pcir[resource]->flags))) { - dev->pcir[resource]->base = 0; - dev->pcir[resource]->size = 0; - } - if(dev->pcir[resource]->maptype == PCI_MAPREG_TYPE_MEM) - dev->pcir[resource]->flags |= BUS_SPACE_MAP_LINEAR; - DRM_LOCK(); #endif return 0; @@ -141,7 +123,7 @@ drm_get_resource_len(drm_device_t *dev, unsigned int resource) #ifdef __FreeBSD__ return rman_get_size(dev->pcir[resource]); #elif defined(__NetBSD__) || defined(__OpenBSD__) - return dev->pcir[resource]->size; + return dev->pcir[resource]->maxsize; #endif } @@ -211,7 +193,6 @@ drm_addmap(drm_device_t * dev, unsigned long offset, unsigned long size, switch ( map->type ) { case _DRM_REGISTERS: - map->bst = dev->pa.pa_iot; map->handle = drm_ioremap(dev, map); if (!map->handle) { DRM_LOCK(); diff --git a/sys/dev/pci/drm/drm_drv.c b/sys/dev/pci/drm/drm_drv.c index 7eaf8358810..bb0dcc82b7c 100644 --- a/sys/dev/pci/drm/drm_drv.c +++ b/sys/dev/pci/drm/drm_drv.c @@ -267,8 +267,8 @@ drm_probe(struct pci_attach_args *pa, drm_pci_id_list_t *idlist) } void -drm_attach(struct device *kdev, struct pci_attach_args *pa, - drm_pci_id_list_t *idlist) +drm_attach(struct device *parent, struct device *kdev, + struct pci_attach_args *pa, drm_pci_id_list_t *idlist) { int unit; drm_device_t *dev; @@ -288,7 +288,9 @@ drm_attach(struct device *kdev, struct pci_attach_args *pa, dev = drm_units[unit] = (drm_device_t*)kdev; dev->unit = unit; + /* needed for pci_mapreg_* */ memcpy(&dev->pa, pa, sizeof(dev->pa)); + dev->vga_softc = (struct vga_pci_softc *)parent; dev->irq = pa->pa_intrline; dev->pci_bus = pa->pa_bus; diff --git a/sys/dev/pci/drm/drm_memory.c b/sys/dev/pci/drm/drm_memory.c index 8d3ae1d4a5f..5900b431d17 100644 --- a/sys/dev/pci/drm/drm_memory.c +++ b/sys/dev/pci/drm/drm_memory.c @@ -97,13 +97,48 @@ drm_ioremap(drm_device_t *dev, drm_local_map_t *map) #ifdef __FreeBSD__ return pmap_mapdev(map->offset, map->size); #elif defined(__NetBSD__) || defined(__OpenBSD__) - int ret; - if (!map->bst) - map->bst = dev->pa.pa_memt; - if ((ret = bus_space_map(map->bst, map->offset, map->size, - BUS_SPACE_MAP_LINEAR, &map->bsh))) { - return NULL; + struct vga_pci_bar *bar = NULL; + int i; + + DRM_DEBUG("offset: 0x%x size: 0x%x type: %d\n", map->offset, map->size, + map->type); + + if (map->type == _DRM_AGP || map->type == _DRM_FRAME_BUFFER) { + /* + * there can be multiple agp maps in the same BAR, agp also + * quite possibly isn't the same as the vga device, just try + * to map it. + */ + DRM_DEBUG("AGP map\n"); + map->bst = dev->pa.pa_memt; + if (bus_space_map(map->bst, map->offset, + map->size, BUS_SPACE_MAP_LINEAR, &map->bsh)) { + DRM_ERROR("ioremap fail\n"); + return (NULL); + } + goto done; + } else { + for (i = 0 ; i < DRM_MAX_PCI_RESOURCE; ++i) { + bar = vga_pci_bar_info(dev->vga_softc, i); + if (bar == NULL) + continue; + + if (bar->base == map->offset) { + DRM_DEBUG("REGISTERS map\n"); + map->bsr = vga_pci_bar_map(dev->vga_softc, + bar->addr, map->size, BUS_SPACE_MAP_LINEAR); + if (map->bsr == NULL) { + DRM_ERROR("ioremap fail\n"); + return (NULL); + } + map->bst = map->bsr->bst; + map->bsh = map->bsr->bsh; + goto done; + } + } } +done: + /* handles are still supposed to be kernel virtual addresses */ return bus_space_vaddr(map->bst, map->bsh); #endif } @@ -114,7 +149,10 @@ drm_ioremapfree(drm_local_map_t *map) #ifdef __FreeBSD__ pmap_unmapdev((vm_offset_t) map->handle, map->size); #elif defined(__NetBSD__) || defined(__OpenBSD__) - bus_space_unmap(map->bst, map->bsh, map->size); + if (map != NULL && map->bsr != NULL) + vga_pci_bar_unmap(map->bsr); + else + bus_space_unmap(map->bst, map->bsh, map->size); #endif } diff --git a/sys/dev/pci/drm/i915_drv.c b/sys/dev/pci/drm/i915_drv.c index 61a3ba4218b..6b9be6b8200 100644 --- a/sys/dev/pci/drm/i915_drv.c +++ b/sys/dev/pci/drm/i915_drv.c @@ -129,7 +129,6 @@ i915drm_probe(struct device *parent, void *match, void *aux) i915drm_probe(struct device *parent, struct cfdata *match, void *aux) #endif { - DRM_DEBUG("\n"); return drm_probe((struct pci_attach_args *)aux, i915_pciidlist); } @@ -141,7 +140,7 @@ i915drm_attach(struct device *parent, struct device *self, void *aux) i915_configure(dev); - drm_attach(self, pa, i915_pciidlist); + drm_attach(parent, self, pa, i915_pciidlist); } #if defined(__OpenBSD__) diff --git a/sys/dev/pci/drm/mach64_drv.c b/sys/dev/pci/drm/mach64_drv.c index 78ef1bded92..9065840850f 100644 --- a/sys/dev/pci/drm/mach64_drv.c +++ b/sys/dev/pci/drm/mach64_drv.c @@ -138,7 +138,7 @@ mach64drm_attach(struct device *parent, struct device *self, void *aux) drm_device_t *dev = (drm_device_t *)self; mach64_configure(dev); - return drm_attach(self, pa, mach64_pciidlist); + return drm_attach(parent, self, pa, mach64_pciidlist); } #if defined(__OpenBSD__) diff --git a/sys/dev/pci/drm/mga_drv.c b/sys/dev/pci/drm/mga_drv.c index 8732c31aaf5..d18a7845063 100644 --- a/sys/dev/pci/drm/mga_drv.c +++ b/sys/dev/pci/drm/mga_drv.c @@ -188,7 +188,7 @@ mgadrm_attach(struct device *parent, struct device *self, void *aux) drm_device_t *dev = (drm_device_t *)self; mga_configure(dev); - return drm_attach(self, pa, mga_pciidlist); + return drm_attach(parent, self, pa, mga_pciidlist); } #if defined(__OpenBSD__) diff --git a/sys/dev/pci/drm/r128_drv.c b/sys/dev/pci/drm/r128_drv.c index c6b32790ade..9c16396f383 100644 --- a/sys/dev/pci/drm/r128_drv.c +++ b/sys/dev/pci/drm/r128_drv.c @@ -138,7 +138,7 @@ r128drm_attach(struct device *parent, struct device *self, void *aux) drm_device_t *dev = (drm_device_t *)self; r128_configure(dev); - return drm_attach(self, pa, r128_pciidlist); + return drm_attach(parent, self, pa, r128_pciidlist); } #if defined(__OpenBSD__) diff --git a/sys/dev/pci/drm/radeon_drv.c b/sys/dev/pci/drm/radeon_drv.c index 2ccd48818bc..082a4844db5 100644 --- a/sys/dev/pci/drm/radeon_drv.c +++ b/sys/dev/pci/drm/radeon_drv.c @@ -143,7 +143,7 @@ radeondrm_attach(struct device *parent, struct device *self, void *aux) drm_device_t *dev = (drm_device_t *)self; radeon_configure(dev); - return drm_attach(self, pa, radeon_pciidlist); + return drm_attach(parent, self, pa, radeon_pciidlist); } #if defined(__OpenBSD__) diff --git a/sys/dev/pci/drm/savage_drv.c b/sys/dev/pci/drm/savage_drv.c index 557bdbb1775..585fe9a9538 100644 --- a/sys/dev/pci/drm/savage_drv.c +++ b/sys/dev/pci/drm/savage_drv.c @@ -128,7 +128,7 @@ savagedrm_attach(struct device *parent, struct device *self, void *aux) drm_device_t *dev = (drm_device_t *)self; savage_configure(dev); - return drm_attach(self, pa, savage_pciidlist); + return drm_attach(parent, self, pa, savage_pciidlist); } #if defined(__OpenBSD__) diff --git a/sys/dev/pci/drm/sis_drv.c b/sys/dev/pci/drm/sis_drv.c index a986437aac8..072e1afdd0d 100644 --- a/sys/dev/pci/drm/sis_drv.c +++ b/sys/dev/pci/drm/sis_drv.c @@ -121,7 +121,7 @@ sisdrm_attach(struct device *parent, struct device *self, void *aux) drm_device_t *dev = (drm_device_t *)self; sis_configure(dev); - return drm_attach(self, pa, sis_pciidlist); + return drm_attach(parent, self, pa, sis_pciidlist); } #if defined(__OpenBSD__) diff --git a/sys/dev/pci/drm/tdfx_drv.c b/sys/dev/pci/drm/tdfx_drv.c index 954446c475d..37bf6075c16 100644 --- a/sys/dev/pci/drm/tdfx_drv.c +++ b/sys/dev/pci/drm/tdfx_drv.c @@ -122,7 +122,7 @@ tdfxdrm_attach(struct device *parent, struct device *self, void *aux) drm_device_t *dev = (drm_device_t *)self; tdfx_configure(dev); - return drm_attach(self, pa, tdfx_pciidlist); + return drm_attach(parent, self, pa, tdfx_pciidlist); } #if defined(__OpenBSD__) diff --git a/sys/dev/pci/drm/via_drv.c b/sys/dev/pci/drm/via_drv.c index 82a2374b296..86aa2b550ec 100644 --- a/sys/dev/pci/drm/via_drv.c +++ b/sys/dev/pci/drm/via_drv.c @@ -130,7 +130,7 @@ viadrm_attach(struct device *parent, struct device *self, void *opaque) drm_device_t *dev = (drm_device_t *)self; viadrm_configure(dev); - drm_attach(self, pa, via_pciidlist); + drm_attach(parent, self, pa, via_pciidlist); } #if defined(__OpenBSD__) diff --git a/sys/dev/pci/vga_pci.c b/sys/dev/pci/vga_pci.c index 7caf597c200..b6fcceaa91e 100644 --- a/sys/dev/pci/vga_pci.c +++ b/sys/dev/pci/vga_pci.c @@ -1,4 +1,4 @@ -/* $OpenBSD: vga_pci.c,v 1.30 2008/03/16 19:00:28 oga Exp $ */ +/* $OpenBSD: vga_pci.c,v 1.31 2008/05/06 19:19:02 oga Exp $ */ /* $NetBSD: vga_pci.c,v 1.3 1998/06/08 06:55:58 thorpej Exp $ */ /* @@ -101,6 +101,7 @@ int vga_pci_match(struct device *, void *, void *); void vga_pci_attach(struct device *, struct device *, void *); paddr_t vga_pci_mmap(void* v, off_t off, int prot); +void vga_pci_bar_init(struct vga_pci_softc *, struct pci_attach_args *); #if NAGP > 0 int agpsubmatch(struct device *, void *, void *); @@ -169,9 +170,7 @@ vga_pci_attach(struct device *parent, struct device *self, void *aux) struct agpbus_attach_args aba; #endif pcireg_t reg; -#ifdef VESAFB struct vga_pci_softc *sc = (struct vga_pci_softc *)self; -#endif /* * Enable bus master; X might need this for accelerated graphics. @@ -193,6 +192,8 @@ vga_pci_attach(struct device *parent, struct device *self, void *aux) vga_common_attach(self, pa->pa_iot, pa->pa_memt, WSDISPLAY_TYPE_PCIVGA); + vga_pci_bar_init(sc, pa); + #if NAGP > 0 /* * attach agp here instead of pchb so it can share mappings @@ -373,3 +374,106 @@ vga_pci_close(void *v) { } #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 vga_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; + } + + 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 vga_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 vga_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) { + switch (bar->maptype) { + case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: + case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: + if (pci_mapreg_map(&dev->pa, bar->addr, bar->maptype, + bar->flags | busflags, &bar->bst, &bar->bsh, NULL, + &bar->size, size) == 0) + break; + default: + 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); + } +} diff --git a/sys/dev/pci/vga_pcivar.h b/sys/dev/pci/vga_pcivar.h index 44aad8df68a..47f10b4b72c 100644 --- a/sys/dev/pci/vga_pcivar.h +++ b/sys/dev/pci/vga_pcivar.h @@ -1,4 +1,4 @@ -/* $OpenBSD: vga_pcivar.h,v 1.9 2007/11/25 17:11:12 oga Exp $ */ +/* $OpenBSD: vga_pcivar.h,v 1.10 2008/05/06 19:19:02 oga Exp $ */ /* $NetBSD: vga_pcivar.h,v 1.1 1998/03/22 15:16:19 drochner Exp $ */ /* @@ -37,13 +37,26 @@ (PCI_CLASS(class) == PCI_CLASS_PREHISTORIC && \ PCI_SUBCLASS(class) == PCI_SUBCLASS_PREHISTORIC_VGA)) ? 1 : 0) +#define VGA_PCI_MAX_BARS 4 +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; +}; + struct vga_pci_softc { struct device sc_dev; -#if 0 - struct vga_config *sc_vc; /* VGA configuration */ -#endif + struct pci_attach_args pa; + struct vga_pci_bar *bars[VGA_PCI_MAX_BARS]; #ifdef VESAFB int sc_width; int sc_height; @@ -60,8 +73,12 @@ struct vga_pci_softc { #endif }; -int vga_pci_cnattach(bus_space_tag_t, bus_space_tag_t, - pci_chipset_tag_t, int, int, int); +int vga_pci_cnattach(bus_space_tag_t, bus_space_tag_t, + pci_chipset_tag_t, int, int, int); +struct vga_pci_bar *vga_pci_bar_info(struct vga_pci_softc *, int); +struct vga_pci_bar *vga_pci_bar_map(struct vga_pci_softc *, int, + bus_size_t, int); +void vga_pci_bar_unmap(struct vga_pci_bar*); #ifdef VESAFB int vesafb_find_mode(struct vga_pci_softc *, int, int, int); |