int rawDiskRead( BVRef bvr, unsigned int secno, void *buffer, unsigned int len ) { int secs; unsigned char *cbuf = (unsigned char *)buffer; unsigned int copy_len; int rc; if ((len & (BPS-1)) != 0) { error("raw disk read not sector aligned"); return -1; } secno += bvr->part_boff; cache_valid = FALSE; while (len > 0) { secs = len / BPS; if (secs > N_CACHE_SECS) secs = N_CACHE_SECS; copy_len = secs * BPS; //printf("rdr: ebiosread(%d, %d, %d)\n", bvr->biosdev, secno, secs); if ((rc = ebiosread(bvr->biosdev, secno, secs)) != 0) { /* Ignore corrected ECC errors */ if (rc != ECC_CORRECTED_ERR) { error(" EBIOS read error: %s\n", bios_error(rc), rc); error(" Block %d Sectors %d\n", secno, secs); return rc; } } bcopy( trackbuf, cbuf, copy_len ); len -= copy_len; cbuf += copy_len; secno += secs; spinActivityIndicator(); } return 0; }
static int Biosread(int biosdev, unsigned long long secno) { static int xbiosdev; static unsigned int xsec, xnsecs; struct driveInfo di; int rc = -1; int tries = 0; int bps, divisor; if (getDriveInfo(biosdev, &di) < 0) { return -1; } // Is biosdev in El Torito no emulation mode (think bootable CD's here)? if (di.no_emulation) { bps = 2048; // Yes. Assume 2K block size since the BIOS may lie about the geometry. } else { bps = di.di.params.phys_nbps; if (bps == 0) { return -1; } } divisor = bps / BPS; // _DISK_DEBUG_DUMP("Biosread dev %x sec %d bps %d\n", biosdev, secno, bps); // Use ebiosread() when supported, otherwise revert to biosread(). if ((biosdev >= kBIOSDevTypeHardDrive) && (di.uses_ebios & EBIOS_FIXED_DISK_ACCESS)) { if (cache_valid && (biosdev == xbiosdev) && (secno >= xsec) && ((unsigned int)secno < (xsec + xnsecs))) { biosbuf = trackbuf + (BPS * (secno - xsec)); return 0; } xnsecs = N_CACHE_SECS; xsec = (secno / divisor) * divisor; cache_valid = false; while ((rc = ebiosread(biosdev, secno / divisor, xnsecs / divisor)) && (++tries < 5)) { if (rc == ECC_CORRECTED_ERR) { rc = 0; // Ignore corrected ECC errors. break; } error(" EBIOS read error: %s\n", bios_error(rc), rc); error(" Block 0x%x Sectors %d\n", secno, xnsecs); _DISK_DEBUG_SLEEP(1); } } #if LEGACY_BIOS_READ_SUPPORT else { static int xcyl, xhead; /* spc = spt * heads */ int spc = (di.di.params.phys_spt * di.di.params.phys_heads); int cyl = secno / spc; int head = (secno % spc) / di.di.params.phys_spt; int sec = secno % di.di.params.phys_spt; if (cache_valid && (biosdev == xbiosdev) && (cyl == xcyl) && (head == xhead) && ((unsigned int)sec >= xsec) && ((unsigned int)sec < (xsec + xnsecs))) { // this sector is in trackbuf cache. biosbuf = trackbuf + (BPS * (sec - xsec)); return 0; } // Cache up to a track worth of sectors, but do not cross a track boundary. xcyl = cyl; xhead = head; xsec = sec; xnsecs = ((unsigned int)(sec + N_CACHE_SECS) > di.di.params.phys_spt) ? (di.di.params.phys_spt - sec) : N_CACHE_SECS; cache_valid = false; while ((rc = biosread(biosdev, cyl, head, sec, xnsecs)) && (++tries < 5)) { if (rc == ECC_CORRECTED_ERR) { rc = 0; // Ignore corrected ECC errors. break; } error(" BIOS read error: %s\n", bios_error(rc), rc); error(" Block %d, Cyl %d Head %d Sector %d\n", secno, cyl, head, sec); _DISK_DEBUG_SLEEP(1); } } #endif // LEGACY_BIOS_READ_SUPPORT if (rc == 0) // BIOS reported success, mark sector cache as valid. { cache_valid = true; } biosbuf = trackbuf + (secno % divisor) * BPS; xbiosdev = biosdev; return rc; }
static int Biosread( int biosdev, unsigned int secno ) { static int xbiosdev, xcyl, xhead; static unsigned int xsec, xnsecs; struct driveInfo di; int rc = -1; int cyl, head, sec; int tries = 0; int bps, divisor; if (getDriveInfo(biosdev, &di) < 0) { return -1; } if (di.no_emulation) { /* Always assume 2k block size; BIOS may lie about geometry */ bps = 2048; } else { bps = di.di.params.phys_nbps; if (bps == 0) { return -1; } } divisor = bps / BPS; DEBUG_DISK(("Biosread dev %x sec %d bps %d\n", biosdev, secno, bps)); // To read the disk sectors, use EBIOS if we can. Otherwise, // revert to the standard BIOS calls. if ((biosdev >= kBIOSDevTypeHardDrive) && (di.uses_ebios & EBIOS_FIXED_DISK_ACCESS)) { if (cache_valid && (biosdev == xbiosdev) && (secno >= xsec) && ((unsigned int)secno < (xsec + xnsecs))) { biosbuf = trackbuf + (BPS * (secno - xsec)); return 0; } xnsecs = N_CACHE_SECS; xsec = (secno / divisor) * divisor; cache_valid = FALSE; while ((rc = ebiosread(biosdev, secno / divisor, xnsecs / divisor)) && (++tries < 5)) { if (rc == ECC_CORRECTED_ERR) { /* Ignore corrected ECC errors */ rc = 0; break; } error(" EBIOS read error: %s\n", bios_error(rc), rc); error(" Block %d Sectors %d\n", secno, xnsecs); sleep(1); } } else { /* spc = spt * heads */ int spc = (di.di.params.phys_spt * di.di.params.phys_heads); cyl = secno / spc; head = (secno % spc) / di.di.params.phys_spt; sec = secno % di.di.params.phys_spt; if (cache_valid && (biosdev == xbiosdev) && (cyl == xcyl) && (head == xhead) && ((unsigned int)sec >= xsec) && ((unsigned int)sec < (xsec + xnsecs))) { // this sector is in trackbuf cache biosbuf = trackbuf + (BPS * (sec - xsec)); return 0; } // Cache up to a track worth of sectors, but do not cross a // track boundary. xcyl = cyl; xhead = head; xsec = sec; xnsecs = ((unsigned int)(sec + N_CACHE_SECS) > di.di.params.phys_spt) ? (di.di.params.phys_spt - sec) : N_CACHE_SECS; cache_valid = FALSE; while ((rc = biosread(biosdev, cyl, head, sec, xnsecs)) && (++tries < 5)) { if (rc == ECC_CORRECTED_ERR) { /* Ignore corrected ECC errors */ rc = 0; break; } error(" BIOS read error: %s\n", bios_error(rc), rc); error(" Block %d, Cyl %d Head %d Sector %d\n", secno, cyl, head, sec); sleep(1); } } // If the BIOS reported success, mark the sector cache as valid. if (rc == 0) { cache_valid = TRUE; } biosbuf = trackbuf + (secno % divisor) * BPS; xbiosdev = biosdev; spinActivityIndicator(); return rc; }