diff options
author | H. Peter Anvin <hpa@linux.intel.com> | 2010-07-01 12:47:02 -0700 |
---|---|---|
committer | H. Peter Anvin <hpa@linux.intel.com> | 2010-07-01 12:47:02 -0700 |
commit | 4d98f51f96a841bd80438e25d1630cb91a9e4d7f (patch) | |
tree | f522bd40834336412a304dd1fb897b5e30e865aa | |
parent | c575dbc5133e30c7b8f57202417696c87ec2e4fb (diff) | |
parent | 564a590beb7a686a10f8a0f1279cf83328af18e5 (diff) | |
download | syslinux-4d98f51f96a841bd80438e25d1630cb91a9e4d7f.tar.gz syslinux-4d98f51f96a841bd80438e25d1630cb91a9e4d7f.tar.xz syslinux-4d98f51f96a841bd80438e25d1630cb91a9e4d7f.zip |
Merge branch 'master' of ssh://terminus.zytor.com/pub/git/syslinux/syslinux
-rw-r--r-- | NEWS | 3 | ||||
-rw-r--r-- | core/fs/diskio.c | 124 |
2 files changed, 72 insertions, 55 deletions
@@ -7,6 +7,9 @@ Changes in 4.01: low memory. * SYSLINUX/EXTLINUX: fix handing of disk read retries in EDD mode. + * ISOLINUX: change the initialization sequence to avoid + problems with certain (old) BIOSes. Special thanks to + Helmut Hullen for invaluable debugging support. Changes in 4.00: * Major code base changes; all filesystem rewritten in C. diff --git a/core/fs/diskio.c b/core/fs/diskio.c index 176c5bcc..fb53109e 100644 --- a/core/fs/diskio.c +++ b/core/fs/diskio.c @@ -76,6 +76,9 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf, __intcall(0x13, &ireg, &oreg); if (!(oreg.eflags.l & EFLAGS_CF)) break; + + dprintf("CHS: error AX = %04x\n", oreg.eax.w[0]); + if (retry--) continue; @@ -87,7 +90,8 @@ static int chs_rdwr_sectors(struct disk *disk, void *buf, ireg.eax.b[0] = chunk; continue; } else { - printf("CHS: Error %s sector %llu (%u/%u/%u)\n", + printf("CHS: Error %04x %s sector %llu (%u/%u/%u)\n", + oreg.eax.w[0], is_write ? "writing" : "reading", lba, c, h, s+1); } @@ -176,6 +180,9 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf, __intcall(0x13, &ireg, &oreg); if (!(oreg.eflags.l & EFLAGS_CF)) break; + + dprintf("EDD: error AX = %04x\n", oreg.eax.w[0]); + if (retry--) continue; @@ -188,7 +195,8 @@ static int edd_rdwr_sectors(struct disk *disk, void *buf, } /*** XXX: Consider falling back to CHS here?! ***/ - printf("EDD: Error %s sector %llu\n", + printf("EDD: Error %04x %s sector %llu\n", + oreg.eax.w[0], is_write ? "writing" : "reading", lba); return done; /* Failure */ @@ -259,68 +267,73 @@ struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start, static struct disk disk; static __lowmem struct edd_disk_params edd_params; com32sys_t ireg, oreg; - bool ebios = cdrom; - int sector_size = cdrom ? 2048 : 512; - unsigned int hard_max_transfer = ebios ? 127 : 63; + bool ebios; + int sector_size; + unsigned int hard_max_transfer; memset(&ireg, 0, sizeof ireg); - - /* Get EBIOS support */ - ireg.eax.b[1] = 0x41; - ireg.ebx.w[0] = 0x55aa; ireg.edx.b[0] = devno; - ireg.eflags.b[0] = 0x3; /* CF set */ - __intcall(0x13, &ireg, &oreg); - - if (cdrom || (!(oreg.eflags.l & EFLAGS_CF) && - oreg.ebx.w[0] == 0xaa55 && (oreg.ecx.b[0] & 1))) { + if (cdrom) { + /* + * The query functions don't work right on some CD-ROM stacks. + * Known affected systems: ThinkPad T22, T23. + */ + sector_size = 2048; ebios = true; - hard_max_transfer = 127; - - /* Query EBIOS parameters */ - edd_params.len = sizeof edd_params; - - ireg.eax.b[1] = 0x48; - ireg.ds = SEG(&edd_params); - ireg.esi.w[0] = OFFS(&edd_params); - __intcall(0x13, &ireg, &oreg); - - if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.b[1] == 0) { - if (edd_params.len < sizeof edd_params) - memset((char *)&edd_params + edd_params.len, 0, - sizeof edd_params - edd_params.len); - - /* - * Note: filter impossible sector sizes. Some BIOSes - * are known to report incorrect sector size information - * (usually 512 rather than 2048) for CD-ROMs, so at least - * for now ignore the reported sector size if booted via - * El Torito. - * - * Known affected systems: ThinkPad T22, T23. - */ - if (!cdrom && - edd_params.sector_size >= 512 && - is_power_of_2(edd_params.sector_size)) - sector_size = edd_params.sector_size; + hard_max_transfer = 32; + } else { + sector_size = 512; + ebios = false; + hard_max_transfer = 63; + + /* CBIOS parameters */ + disk.h = bsHeads; + disk.s = bsSecPerTrack; + + if ((int8_t)devno < 0) { + /* Get hard disk geometry from BIOS */ + + ireg.eax.b[1] = 0x08; + __intcall(0x13, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF)) { + disk.h = oreg.edx.b[1] + 1; + disk.s = oreg.ecx.b[0] & 63; + } } - } - - /* CBIOS parameters */ - disk.h = bsHeads; - disk.s = bsSecPerTrack; - if ((int8_t)devno < 0) { - /* Get hard disk geometry from BIOS */ + /* Get EBIOS support */ + ireg.eax.b[1] = 0x41; + ireg.ebx.w[0] = 0x55aa; + ireg.eflags.b[0] = 0x3; /* CF set */ - ireg.eax.b[1] = 0x08; __intcall(0x13, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF) && + oreg.ebx.w[0] == 0xaa55 && (oreg.ecx.b[0] & 1)) { + ebios = true; + hard_max_transfer = 127; + + /* Query EBIOS parameters */ + edd_params.len = sizeof edd_params; + + ireg.eax.b[1] = 0x48; + ireg.ds = SEG(&edd_params); + ireg.esi.w[0] = OFFS(&edd_params); + __intcall(0x13, &ireg, &oreg); + + if (!(oreg.eflags.l & EFLAGS_CF) && oreg.eax.b[1] == 0) { + if (edd_params.len < sizeof edd_params) + memset((char *)&edd_params + edd_params.len, 0, + sizeof edd_params - edd_params.len); - if (!(oreg.eflags.l & EFLAGS_CF)) { - disk.h = oreg.edx.b[1] + 1; - disk.s = oreg.ecx.b[0] & 63; + if (edd_params.sector_size >= 512 && + is_power_of_2(edd_params.sector_size)) + sector_size = edd_params.sector_size; + } } + } disk.disk_number = devno; @@ -335,8 +348,9 @@ struct disk *disk_init(uint8_t devno, bool cdrom, sector_t part_start, disk.maxtransfer = MaxTransfer; - dprintf("disk %02x cdrom %d type %d sector %u/%u offset %llu\n", - devno, cdrom, ebios, sector_size, disk.sector_shift, part_start); + dprintf("disk %02x cdrom %d type %d sector %u/%u offset %llu limit %u\n", + devno, cdrom, ebios, sector_size, disk.sector_shift, + part_start, disk.maxtransfer); return &disk; } |