diff -ur ../xorg-build/lib/libpciaccess/src/linux_devmem.c libpciaccess/src/linux_devmem.c --- ../xorg-build/lib/libpciaccess/src/linux_devmem.c 2008-11-25 06:42:15.000000000 -0500 +++ libpciaccess/src/linux_devmem.c 2008-12-05 00:34:34.000000000 -0500 @@ -125,7 +125,7 @@ size_t bytes; for (bytes = 0; bytes < rom_size; /* empty */) { - const ssize_t got = pread(fd, buffer, rom_size - bytes, + const ssize_t got = pread64(fd, buffer, rom_size - bytes, rom_base + bytes); if (got == -1) { err = errno; diff -ur ../xorg-build/lib/libpciaccess/src/linux_sysfs.c libpciaccess/src/linux_sysfs.c --- ../xorg-build/lib/libpciaccess/src/linux_sysfs.c 2008-11-25 06:42:15.000000000 -0500 +++ libpciaccess/src/linux_sysfs.c 2008-12-05 00:42:08.000000000 -0500 @@ -301,6 +301,7 @@ return err; } +#define DEBUG_READROM 1 static int pci_device_linux_sysfs_read_rom( struct pci_device * dev, void * buffer ) @@ -312,6 +313,13 @@ size_t rom_size; size_t total_bytes; +#if defined DEBUG_READROM + FILE * dbglog = fopen("/tmp/debug-read-rom.log", "a"); + setvbuf(dbglog, NULL, _IONBF, 0); +#define COND_CLOSE() if (dbglog != NULL) fclose(dbglog); +#else +#define COND_CLOSE() +#endif snprintf( name, 255, "%s/%04x:%02x:%02x.%1u/rom", SYS_BUS_PCI, @@ -319,18 +327,28 @@ dev->bus, dev->dev, dev->func ); - +#if defined DEBUG_READROM +fprintf(dbglog, "Reading ROM from %s into address %p\n", name, buffer); +#endif fd = open( name, O_RDWR ); if ( fd == -1 ) { /* If reading the ROM using sysfs fails, fall back to the old * /dev/mem based interface. */ +#if defined DEBUG_READROM +fprintf(dbglog, "Reading ROM failed, using /dev/mem\n"); +#endif +COND_CLOSE(); return pci_device_linux_devmem_read_rom(dev, buffer); } if ( fstat( fd, & st ) == -1 ) { close( fd ); +#if defined DEBUG_READROM +fprintf(dbglog, "fstat(%s) failed with errno %d\n", name, errno); +#endif +COND_CLOSE(); return errno; } @@ -338,6 +356,11 @@ if ( rom_size == 0 ) rom_size = 0x10000; +#if defined DEBUG_READROM +fprintf(dbglog, "ROM size for %s is %ld using %u\n", name, st.st_size, rom_size); +#endif + + /* This is a quirky thing on Linux. Even though the ROM and the file * for the ROM in sysfs are read-only, the string "1" must be written to * the file to enable the ROM. After the data has been read, "0" must be @@ -351,9 +374,15 @@ rom_size - total_bytes ); if ( bytes == -1 ) { err = errno; +#if defined DEBUG_READROM +fprintf(dbglog, "Reading ROM from %s failed at offset %u with errno %d\n", name, total_bytes, errno); +#endif break; } else if ( bytes == 0 ) { +#if defined DEBUG_READROM +fprintf(dbglog, "Reading ROM from %s reached 0-sized read (EOF?) at offset %u\n", name, total_bytes); +#endif break; } @@ -365,6 +394,27 @@ write( fd, "0", 1 ); close( fd ); +#if defined DEBUG_READROM + { + unsigned int a, b, c; + fprintf(dbglog, "Dump of ROM from %s (%u bytes):\n", name, total_bytes); + for (a = 0; a < total_bytes; a += 16) { + b = total_bytes - a; + if (b > 16) b = 16; + for (c = 0; c < b; c++) fprintf(dbglog, "%02x ", ((unsigned char *)buffer)[a + c]); + fprintf(dbglog, "\n"); + } + } +#endif + if (total_bytes < rom_size) { +#if defined DEBUG_READROM +struct pci_device_private *priv = (struct pci_device_private *) dev; +fprintf(dbglog, "Reading ROM failed with short read, using /dev/mem to read from 0x%Lx\n", priv->rom_base); +#endif + /* Failed to read entire ROM, falling back to /dev/mem */ + err = pci_device_linux_devmem_read_rom(dev, buffer); + } +COND_CLOSE(); return err; }