/* * Return a copy of the VBIOS ROM */ int DRM(getvbios)( DRM_IOCTL_ARGS ) { DRM_DEVICE; drm_file_t *filp_priv; drm_get_vbios_t gb; struct resource *r; unsigned char *rom; int sigok; drm_map_t *mmio = NULL; DRM_DEBUG("\n"); DRM_GET_PRIV_WITH_RETURN( filp_priv, filp ); DRM_COPY_FROM_USER_IOCTL( gb, ( drm_get_vbios_t* )data, sizeof( gb ) ); /* Input length of zero is a request for the length */ if (gb.length == 0) { DRM_DEBUG("get length\n"); gb.length = pci_resource_len( dev->pdev, PCI_ROM_RESOURCE ); DRM_COPY_TO_USER_IOCTL( (drm_get_vbios_t *)data, gb, sizeof(gb) ); DRM_DEBUG("length is %lx\n", gb.length); return 0; } DRM_FIND_MAP( mmio, pci_resource_start( dev->pdev, 2 ) ); if(!mmio) { DRM_ERROR("could not find mmio region map!\n"); return DRM_ERR(EINVAL); } DRIVER_ROMBUG(mmio); /* used to fix a bug in the ATI BIOS */ /* no need to search for the ROM, just ask the card where it is. */ r = &dev->pdev->resource[PCI_ROM_RESOURCE]; /* assign the ROM an address if it doesn't have one */ if (r->parent == NULL) pci_assign_resource(dev->pdev, PCI_ROM_RESOURCE); /* enable if needed */ if (!(r->flags & PCI_ROM_ADDRESS_ENABLE)) { u32 loc, size; pci_read_config_dword(dev->pdev, PCI_ROM_ADDRESS, &loc); pci_write_config_dword(dev->pdev, PCI_ROM_ADDRESS, ~PCI_ROM_ADDRESS_ENABLE); pci_read_config_dword(dev->pdev, PCI_ROM_ADDRESS, &size); pci_write_config_dword(dev->pdev, PCI_ROM_ADDRESS, loc); size = pci_size(loc, size, PCI_ROM_ADDRESS_MASK); DRM_DEBUG("VROM base is %08x %08x\n", loc, size ); pci_write_config_dword(dev->pdev, PCI_ROM_ADDRESS, r->start | PCI_ROM_ADDRESS_ENABLE); r->flags |= PCI_ROM_ADDRESS_ENABLE; DRM_DEBUG("Address start/end is %08lx %08lx\n", r->start, r->end ); pci_read_config_dword(dev->pdev, PCI_ROM_ADDRESS, &loc); DRM_DEBUG("VROM enable is %08x\n", loc ); } gb.length = min( gb.length, pci_resource_len( dev->pdev, PCI_ROM_RESOURCE )); rom = ioremap(r->start, r->end - r->start + 1); if (rom) { sigok = ((readb(rom) == 0x55) && (readb(rom + 1) == 0xAA)); if (sigok) DRM_COPY_TO_USER( gb.data, rom, gb.length); else DRM_DEBUG("VROM signature wrong %02x %02x\n", *(unsigned char *)rom, *((unsigned char *)rom+1) ); iounmap(rom); if (r->parent) { release_resource(r); r->flags &= ~PCI_ROM_ADDRESS_ENABLE; r->end -= r->start; r->start = 0; } /* This will disable and set address to unassigned */ pci_write_config_dword(dev->pdev, PCI_ROM_ADDRESS, 0); if (sigok) { DRM_COPY_TO_USER_IOCTL( (drm_get_vbios_t *)data, gb, sizeof(gb) ); return 0; } } else DRM_DEBUG("VROM failed to map\n"); DRM_DEBUG("Using VROM copy at C000\n"); rom = ioremap(0xC0000, r->end - r->start + 1); DRM_COPY_TO_USER( gb.data, rom, gb.length); DRM_COPY_TO_USER_IOCTL( (drm_get_vbios_t *)data, gb, sizeof(gb) ); iounmap(rom); return 0; /* DRM_DEBUG("radeonfb: ROM failed to map\n"); gb.length = 0; DRM_COPY_TO_USER_IOCTL( (drm_get_vbios_t *)data, gb, sizeof(gb) ); return -1; */ }