Hi, I've ETOOMUCHWORK'd on this for a while, but recently had access to a laptop with GM45 graphics and a serial port. It looks like the previous patches I posted were going in the right direction but with not enough detail - the attached patch gets X started fine on the laptop with commands queued through drm, however in Xorg log I get: (EE) AIGLX error: dlopen of /usr/X11R7/lib/modules/dri/i965_dri.so failed (/usr/X11R7/lib/modules/dri/i965_dri.so: Undefined symbol "driDriverApi" (symnum = 157)) Which is a userland problem that I don't know how to fix right now. However it should address both the hang and crash previously reported. Some details on the patch: * latest intel gfx cards wish to sub-map part of agp space, which netbsd drm can't do right now * patch re-implements parts of drm_netbsd_ioremap to support this * entire mapping recorded in pci_map_data, submapping in drm_local_map_t * store mapping vaddr in local_map's "handle" field * also inject some error checking + handling for drm_addmap -- Thanks, Jeremy
Index: bsd-core/drmP.h =================================================================== RCS file: /cvsroot/src/sys/external/bsd/drm/dist/bsd-core/drmP.h,v retrieving revision 1.9.10.2 diff -u -p -r1.9.10.2 drmP.h --- bsd-core/drmP.h 14 Aug 2009 21:40:49 -0000 1.9.10.2 +++ bsd-core/drmP.h 10 Jan 2010 14:16:17 -0000 @@ -650,6 +650,19 @@ typedef struct drm_sg_mem { typedef TAILQ_HEAD(drm_map_list, drm_local_map) drm_map_list_t; +#if defined(__NetBSD__) +/* XXX - moved pci_map_data_t declaration forward for use by drm_local_map_t..*/ +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 struct drm_local_map { unsigned long offset; /* Physical address (0 for SAREA)*/ unsigned long size; /* Physical size (bytes) */ @@ -667,7 +680,7 @@ typedef struct drm_local_map { bus_space_handle_t bsh; drm_dma_handle_t *dmah; #if defined(__NetBSD__) - int *cnt; + pci_map_data_t *fullmap; bus_size_t mapsize; #endif TAILQ_ENTRY(drm_local_map) link; @@ -784,18 +797,6 @@ struct drm_driver_info { /* Length for the array of resource pointers for drm_get_resource_*. */ #define DRM_MAX_PCI_RESOURCE 6 -#if defined(__NetBSD__) -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 - /** * DRM device functions structure */ Index: bsd-core/drm_bufs.c =================================================================== RCS file: /cvsroot/src/sys/external/bsd/drm/dist/bsd-core/drm_bufs.c,v retrieving revision 1.2.10.1 diff -u -p -r1.2.10.1 drm_bufs.c --- bsd-core/drm_bufs.c 20 Jun 2009 23:36:59 -0000 1.2.10.1 +++ bsd-core/drm_bufs.c 10 Jan 2010 14:16:17 -0000 @@ -159,16 +159,25 @@ int drm_addmap(struct drm_device * dev, map->size = size; map->type = type; map->flags = flags; -#ifdef __NetBSD__ - map->cnt = NULL; +#if defined(__NetBSD__) + map->fullmap = NULL; map->mapsize = 0; #endif switch (map->type) { case _DRM_REGISTERS: map->handle = drm_ioremap(dev, map); + if (map->handle == NULL) { + DRM_ERROR("drm_addmap couldn't ioremap registers with " + "base %lX, size %lX\n", + (long) offset, (long) size); + DRM_LOCK(); + return EINVAL; + } + if (!(map->flags & _DRM_WRITE_COMBINING)) break; + /* FALLTHROUGH */ case _DRM_FRAME_BUFFER: if (drm_mtrr_add(map->offset, map->size, DRM_MTRR_WC) == 0) Index: bsd-core/drm_memory.c =================================================================== RCS file: /cvsroot/src/sys/external/bsd/drm/dist/bsd-core/drm_memory.c,v retrieving revision 1.3.10.1 diff -u -p -r1.3.10.1 drm_memory.c --- bsd-core/drm_memory.c 20 Jun 2009 23:36:59 -0000 1.3.10.1 +++ bsd-core/drm_memory.c 10 Jan 2010 14:16:18 -0000 @@ -85,29 +85,45 @@ void drm_mem_uninit(void) static void * drm_netbsd_ioremap(struct drm_device *dev, drm_local_map_t *map, int wc) { + bus_space_handle_t h; int i, reg, reason; for(i = 0; i<DRM_MAX_PCI_RESOURCE; i++) { reg = PCI_MAPREG_START + i*4; if ((dev->pci_map_data[i].maptype == PCI_MAPREG_TYPE_MEM || dev->pci_map_data[i].maptype == (PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT)) && - dev->pci_map_data[i].base == map->offset && - dev->pci_map_data[i].size >= map->size) + map->offset >= dev->pci_map_data[i].base && + map->offset + map->size <= dev->pci_map_data[i].base + + dev->pci_map_data[i].size) { map->bst = dev->pa.pa_memt; - map->cnt = &(dev->pci_map_data[i].mapped); - map->mapsize = dev->pci_map_data[i].size; + map->fullmap = &(dev->pci_map_data[i]); + map->mapsize = map->size; dev->pci_map_data[i].mapped++; if (dev->pci_map_data[i].mapped > 1) { - map->bsh = dev->pci_map_data[i].bsh; - return dev->pci_map_data[i].vaddr; + if ((reason = bus_space_subregion( + dev->pa.pa_memt, + dev->pci_map_data[i].bsh, + map->offset - dev->pci_map_data[i].base, + map->size, &h)) != 0) { + DRM_DEBUG("ioremap failed to " + "bus_space_subregion: %d\n", + reason); + return NULL; + } + map->bsh = h; + map->handle = bus_space_vaddr(dev->pa.pa_memt, + h); + return map->handle; } DRM_DEBUG("ioremap%s: flags %d\n", wc ? "_wc" : "", dev->pci_map_data[i].flags); - if ((reason = bus_space_map(map->bst, map->offset, + if ((reason = bus_space_map(map->bst, + dev->pci_map_data[i].base, dev->pci_map_data[i].size, - dev->pci_map_data[i].flags, &map->bsh))) + dev->pci_map_data[i].flags, + &dev->pci_map_data[i].bsh))) { dev->pci_map_data[i].mapped--; #if NAGP_I810 > 0 /* XXX horrible kludge: agp might have mapped it */ @@ -118,13 +134,29 @@ drm_netbsd_ioremap(struct drm_device *de reason); return NULL; } - dev->pci_map_data[i].bsh = map->bsh; - dev->pci_map_data[i].vaddr = - bus_space_vaddr(map->bst, map->bsh); + + dev->pci_map_data[i].vaddr = bus_space_vaddr(map->bst, + dev->pci_map_data[i].bsh); + + /* Caller might have requested a submapping of that */ + if ((reason = bus_space_subregion( + dev->pa.pa_memt, + dev->pci_map_data[i].bsh, + map->offset - dev->pci_map_data[i].base, + map->size, &h)) != 0) { + DRM_DEBUG("ioremap failed to " + "bus_space_subregion: %d\n", + reason); + return NULL; + } + DRM_DEBUG("ioremap mem found for %lx, %lx: %p\n", map->offset, map->size, dev->agp_map_data[i].vaddr); - return dev->pci_map_data[i].vaddr; + + map->bsh = h; + map->handle = bus_space_vaddr(dev->pa.pa_memt, h); + return map->handle; } } /* failed to find a valid mapping; all hope isn't lost though */ @@ -133,7 +165,7 @@ drm_netbsd_ioremap(struct drm_device *de dev->agp_map_data[i].base == map->offset && dev->agp_map_data[i].size >= map->size) { map->bst = dev->pa.pa_memt; - map->cnt = &(dev->agp_map_data[i].mapped); + map->fullmap = &(dev->agp_map_data[i]); map->mapsize = dev->agp_map_data[i].size; dev->agp_map_data[i].mapped++; map->bsh = dev->agp_map_data[i].bsh; @@ -148,7 +180,7 @@ drm_netbsd_ioremap(struct drm_device *de dev->agp_map_data[i].size = map->size; dev->agp_map_data[i].flags = BUS_SPACE_MAP_LINEAR; dev->agp_map_data[i].maptype = PCI_MAPREG_TYPE_MEM; - map->cnt = &(dev->agp_map_data[i].mapped); + map->fullmap = &(dev->agp_map_data[i]); map->mapsize = dev->agp_map_data[i].size; DRM_DEBUG("ioremap%s: flags %d\n", wc ? "_wc" : "", @@ -201,14 +233,16 @@ void drm_ioremapfree(drm_local_map_t *ma #if defined(__FreeBSD__) pmap_unmapdev((vm_offset_t) map->handle, map->size); #elif defined(__NetBSD__) - if (map->cnt == NULL) { + if (map->fullmap == NULL) { DRM_INFO("drm_ioremapfree called for unknown map\n"); return; } - if (*(map->cnt) > 0) { - (*(map->cnt))--; - if(*(map->cnt) == 0) - bus_space_unmap(map->bst, map->bsh, map->mapsize); + + if (map->fullmap->mapped > 0) { + map->fullmap->mapped--; + if(map->fullmap->mapped == 0) + bus_space_unmap(map->bst, map->fullmap->bsh, + map->fullmap->size); } #endif } Index: shared-core/i915_dma.c =================================================================== RCS file: /cvsroot/src/sys/external/bsd/drm/dist/shared-core/i915_dma.c,v retrieving revision 1.1.1.3.10.1 diff -u -p -r1.1.1.3.10.1 i915_dma.c --- shared-core/i915_dma.c 20 Jun 2009 23:37:01 -0000 1.1.1.3.10.1 +++ shared-core/i915_dma.c 10 Jan 2010 14:16:21 -0000 @@ -864,6 +864,8 @@ int i915_driver_load(struct drm_device * ret = drm_addmap(dev, base, size, _DRM_REGISTERS, _DRM_KERNEL | _DRM_DRIVER, &dev_priv->mmio_map); + if (ret) + return ret; if (IS_GM45(dev)) dev->driver->get_vblank_counter = gm45_get_vblank_counter;
Attachment:
signature.asc
Description: OpenPGP digital signature