Skip to content

Commit

Permalink
staging: xgifb: copy PCI ROM properly
Browse files Browse the repository at this point in the history
Use proper helper functions to copy the PCI ROM. Also use dynamic memory
allocation. The original code mapped incorrect amount of memory and will
crash on some platforms.

Signed-off-by: Aaro Koskinen <aaro.koskinen@iki.fi>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
  • Loading branch information
Aaro Koskinen authored and Greg Kroah-Hartman committed Feb 18, 2011
1 parent 6af8172 commit 0f07d94
Showing 1 changed file with 19 additions and 42 deletions.
61 changes: 19 additions & 42 deletions drivers/staging/xgifb/XGI_main_26.c
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,8 @@ int XGIfb_accel = 0;
#define GPIOG_READ (1<<1)
int XGIfb_GetXG21DefaultLVDSModeIdx(void);

#define XGIFB_ROM_SIZE 65536

/* -------------------- Macro definitions ---------------------------- */

#undef XGIFBDEBUG
Expand Down Expand Up @@ -2881,52 +2883,26 @@ XGIINITSTATIC int __init XGIfb_setup(char *options)
return 0;
}

static unsigned char VBIOS_BUF[65535];

static unsigned char *attempt_map_rom(struct pci_dev *dev, void *copy_address)
static unsigned char *xgifb_copy_rom(struct pci_dev *dev)
{
u32 rom_size = 0;
u32 rom_address = 0;
int j;

/* Get the size of the expansion rom */
pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0xFFFFFFFF);
pci_read_config_dword(dev, PCI_ROM_ADDRESS, &rom_size);
if ((rom_size & 0x01) == 0) {
printk("No ROM\n");
return NULL;
}
void __iomem *rom_address;
unsigned char *rom_copy;
size_t rom_size;

rom_size &= 0xFFFFF800;
rom_size = (~rom_size) + 1;

rom_address = pci_resource_start(dev, 0);
if (rom_address == 0 || rom_address == 0xFFFFFFF0) {
printk("No suitable rom address found\n");
rom_address = pci_map_rom(dev, &rom_size);
if (rom_address == NULL)
return NULL;
}

printk("ROM Size is %dK, Address is %x\n", rom_size / 1024, rom_address);
rom_copy = vzalloc(XGIFB_ROM_SIZE);
if (rom_copy == NULL)
goto done;

/* Map ROM */
pci_write_config_dword(dev, PCI_ROM_ADDRESS, rom_address
| PCI_ROM_ADDRESS_ENABLE);
rom_size = min_t(size_t, rom_size, XGIFB_ROM_SIZE);
memcpy_fromio(rom_copy, rom_address, rom_size);

/* memcpy(copy_address, rom_address, rom_size); */
{
unsigned char *virt_addr = ioremap(rom_address, 0x8000000);

unsigned char *from = (unsigned char *) virt_addr;
unsigned char *to = (unsigned char *) copy_address;
for (j = 0; j < 65536 /*rom_size*/; j++)
*to++ = *from++;
}

pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);

printk("Copy is done\n");

return copy_address;
done:
pci_unmap_rom(dev, rom_address);
return rom_copy;
}

static int __devinit xgifb_probe(struct pci_dev *pdev,
Expand Down Expand Up @@ -3039,8 +3015,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,

XGIhw_ext.pDevice = NULL;
if ((xgi_video_info.chip == XG21) || (XGIfb_userom)) {
XGIhw_ext.pjVirtualRomBase = attempt_map_rom(pdev, VBIOS_BUF);

XGIhw_ext.pjVirtualRomBase = xgifb_copy_rom(pdev);
if (XGIhw_ext.pjVirtualRomBase)
printk(KERN_INFO "XGIfb: Video ROM found and mapped to %p\n", XGIhw_ext.pjVirtualRomBase);
else
Expand Down Expand Up @@ -3434,6 +3409,7 @@ static int __devinit xgifb_probe(struct pci_dev *pdev,
return 0;

error:
vfree(XGIhw_ext.pjVirtualRomBase);
vfree(XGIhw_ext.pSR);
vfree(XGIhw_ext.pCR);
framebuffer_release(fb_info);
Expand All @@ -3449,6 +3425,7 @@ static void __devexit xgifb_remove(struct pci_dev *pdev)
/* Unregister the framebuffer */
/* if (xgi_video_info.registered) { */
unregister_framebuffer(fb_info);
vfree(XGIhw_ext.pjVirtualRomBase);
framebuffer_release(fb_info);
/* } */

Expand Down

0 comments on commit 0f07d94

Please sign in to comment.