Messages in this thread | | | Date | Fri, 17 Feb 2006 15:22:58 -0700 | From | "Jeff V. Merkey" <> | Subject | Re: C/H/S from user space |
| |
Here's the code to calculate that as well -- from NetWare -- with int 13 IOCTL calls and from within Windows 98. This code builds on the djgcc DOS version og GNU tools.
Jeff
#if (DOS_UTIL)
#define READ_DEVICE 0x02 #define WRITE_DEVICE 0x03 #define NO_VERIFY 0x00 #define WRITE_VERIFY 0x01
// convert cylinder/head/sector addressing to LBA
ULONG CHStoLBA(ULONG disk, LONGLONG cyl, ULONG head, ULONG sector) { register ULONG lba; ULONG heads = SystemDisk[disk]->TracksPerCylinder; ULONG sectors = SystemDisk[disk]->SectorsPerTrack;
lba = cyl * (heads * sectors); lba += (head * sectors); lba += sector; lba -= 1; // CHS is 1 relative so adjust LBA by subtracting 1
return lba;
}
// convert LBA to cylinder/head/sector addressing
ULONG LBAtoCHS(ULONG disk, ULONG lba, LONGLONG *cyl, ULONG *head, ULONG *sector) { ULONG offset; ULONG heads = SystemDisk[disk]->TracksPerCylinder; ULONG sectors = SystemDisk[disk]->SectorsPerTrack;
if (!cyl || !head || !sector) return -1;
*cyl = (lba / (heads * sectors)); offset = lba % (heads * sectors); *head = (WORD)(offset / sectors); *sector = (WORD)(offset % sectors) + 1; // sector addressing is // 1 relative so add 1 return 0; }
ULONG pReadDiskSectors(ULONG disk, ULONG StartingLBA, BYTE *Sector, ULONG sectors, ULONG readAhead) { register ULONG bps, ccode, bytes = 0; register NWDISK *NWDisk; LONGLONG cylinder; ULONG head, sector; static _go32_dpmi_registers r; #if (WINDOWS_98_UTIL) static union REGS rl; #endif
NWFSSet(&r, 0, sizeof(_go32_dpmi_registers));
NWDisk = SystemDisk[disk]; bps = NWDisk->BytesPerSector;
if ((sectors * bps) > IO_BLOCK_SIZE) return bytes;
#if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bh = 3; // locks levels 0, 1, 2 or 3 rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x4B; // lock physical volume rl.x.dx = 0; // permissions int86(0x21, &rl, &rl);
#endif
if (NWDisk->Int13Extensions) { EXT_REQUEST request;
NWFSSet(&request, 0, sizeof(EXT_REQUEST));
request.Size = sizeof(EXT_REQUEST); request.Blocks = sectors; request.TransferBuffer = (ULONG)(NWDisk->DataSegment << 16) & 0xFFFF0000; request.LBA = StartingLBA;
movedata(_my_ds(), (unsigned)&request, NWDisk->RequestSelector, 0, sizeof(EXT_REQUEST));
r.h.ah = 0x42; r.h.dl = (0x80 | (disk & 0x7F)); r.x.ds = NWDisk->RequestSegment; r.x.si = 0; r.x.ss = r.x.sp = r.x.flags = 0;
ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto ReadExit;
// error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { movedata(NWDisk->DataSelector, 0, _my_ds(), (unsigned)Sector, (sectors * bps));
bytes = (sectors * bps); goto ReadExit; } else goto ReadExit; }
movedata(NWDisk->DataSelector, 0, _my_ds(), (unsigned)Sector, (sectors * bps));
bytes = (sectors * bps); goto ReadExit; } else { ccode = LBAtoCHS(disk, StartingLBA, &cylinder, &head, §or); if (ccode) goto ReadExit;
r.h.dh = (BYTE)head; r.h.dl = (0x80 | (disk & 0x7F)); r.h.ch = (BYTE)(cylinder & 0xFF); r.h.cl = (BYTE)((cylinder & 0x0300) >> 2); r.h.cl |= (BYTE)(sector & 0x3F); r.h.ah = READ_DEVICE; r.h.al = (BYTE)sectors; r.x.es = NWDisk->DataSegment; r.x.bx = 0; r.x.ss = r.x.sp = r.x.flags = 0;
ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto ReadExit;
// error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { movedata(NWDisk->DataSelector, 0, _my_ds(), (unsigned)Sector, (sectors * bps));
bytes = (sectors * bps); goto ReadExit; } else goto ReadExit; }
movedata(NWDisk->DataSelector, 0, _my_ds(), (unsigned)Sector, (sectors * bps));
bytes = (sectors * bps); }
ReadExit:; #if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x6B; // unlock physical volume int86(0x21, &rl, &rl); #endif
return bytes;
}
ULONG pWriteDiskSectors(ULONG disk, ULONG StartingLBA, BYTE *Sector, ULONG sectors, ULONG readAhead) { register ULONG bps, ccode, bytes = 0; register NWDISK *NWDisk; LONGLONG cylinder; ULONG head, sector; static _go32_dpmi_registers r; #if (WINDOWS_98_UTIL) static union REGS rl; #endif
NWFSSet(&r, 0, sizeof(_go32_dpmi_registers));
NWDisk = SystemDisk[disk]; bps = NWDisk->BytesPerSector;
if ((sectors * bps) > IO_BLOCK_SIZE) return bytes;
#if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bh = 3; // locks levels 0, 1, 2 or 3 rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x4B; // lock physical volume rl.x.dx = 0; // permissions int86(0x21, &rl, &rl);
#endif
if (NWDisk->Int13Extensions) { EXT_REQUEST request;
NWFSSet(&request, 0, sizeof(EXT_REQUEST));
request.Size = sizeof(EXT_REQUEST); request.Blocks = sectors; request.TransferBuffer = (ULONG)(NWDisk->DataSegment << 16) & 0xFFFF0000; request.LBA = StartingLBA;
movedata(_my_ds(), (unsigned)&request, NWDisk->RequestSelector, 0, sizeof(EXT_REQUEST));
movedata(_my_ds(), (unsigned)Sector, NWDisk->DataSelector, 0, (sectors * bps));
r.h.ah = 0x43; r.h.al = NO_VERIFY; r.h.dl = (0x80 | (disk & 0x7F)); r.x.ds = NWDisk->RequestSegment; r.x.si = 0; r.x.ss = r.x.sp = r.x.flags = 0;
ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto WriteExit;
// error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { bytes = (sectors * bps); goto WriteExit; } else goto WriteExit; } bytes = (sectors * bps); goto WriteExit; } else { ccode = LBAtoCHS(disk, StartingLBA, &cylinder, &head, §or); if (ccode) goto WriteExit;
movedata(_my_ds(), (unsigned)Sector, NWDisk->DataSelector, 0, (sectors * bps));
r.h.dh = (BYTE)head; r.h.dl = (0x80 | (disk & 0x7F)); r.h.ch = (BYTE)(cylinder & 0xFF); r.h.cl = (BYTE)((cylinder & 0x0300) >> 2); r.h.cl |= (BYTE)(sector & 0x3F); r.h.ah = WRITE_DEVICE; r.h.al = (BYTE)sectors; r.x.es = NWDisk->DataSegment; r.x.bx = 0; r.x.ds = r.x.ss = r.x.sp = r.x.flags = 0;
ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto WriteExit;
// error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { bytes = (sectors * bps); goto WriteExit; } else goto WriteExit; } bytes = (sectors * bps); goto WriteExit; }
WriteExit:; #if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x6B; // unlock physical volume int86(0x21, &rl, &rl); #endif
return bytes; }
ULONG pZeroFillDiskSectors(ULONG disk, ULONG StartingLBA, ULONG sectors, ULONG readAhead) { register ULONG bps, ccode, bytes = 0; register NWDISK *NWDisk; LONGLONG cylinder; ULONG head, sector; static _go32_dpmi_registers r; #if (WINDOWS_98_UTIL) static union REGS rl; #endif
NWFSSet(&r, 0, sizeof(_go32_dpmi_registers));
NWDisk = SystemDisk[disk]; bps = NWDisk->BytesPerSector;
if ((sectors * bps) > IO_BLOCK_SIZE) return bytes;
movedata(_my_ds(), (unsigned)ZeroBuffer, NWDisk->DataSelector, 0, (sectors * bps));
#if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bh = 3; // locks levels 0, 1, 2 or 3 rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x4B; // lock physical volume rl.x.dx = 0; // permissions int86(0x21, &rl, &rl);
#endif
if (NWDisk->Int13Extensions) { EXT_REQUEST request;
NWFSSet(&request, 0, sizeof(EXT_REQUEST));
request.Size = sizeof(EXT_REQUEST); request.Blocks = sectors; request.TransferBuffer = (ULONG)(NWDisk->DataSegment << 16) & 0xFFFF0000; request.LBA = StartingLBA;
movedata(_my_ds(), (unsigned)&request, NWDisk->RequestSelector, 0, sizeof(EXT_REQUEST));
r.h.ah = 0x43; r.h.al = NO_VERIFY; r.h.dl = (0x80 | (disk & 0x7F)); r.x.ds = NWDisk->RequestSegment; r.x.si = 0; r.x.ss = r.x.sp = r.x.flags = 0;
ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto FillExit;
// error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { bytes = (sectors * bps); goto FillExit; } else goto FillExit; } bytes = (sectors * bps); goto FillExit; } else { ccode = LBAtoCHS(disk, StartingLBA, &cylinder, &head, §or); if (ccode) goto FillExit;
r.h.dh = (BYTE)head; r.h.dl = (0x80 | (disk & 0x7F)); r.h.ch = (BYTE)(cylinder & 0xFF); r.h.cl = (BYTE)((cylinder & 0x0300) >> 2); r.h.cl |= (BYTE)(sector & 0x3F); r.h.ah = 0x03; r.h.al = (BYTE)sectors; r.x.es = NWDisk->DataSegment; r.x.bx = 0; r.x.ds = r.x.ss = r.x.sp = r.x.flags = 0;
ccode = _go32_dpmi_simulate_int(0x13, &r); if (ccode) goto FillExit;
// error if carry flag is set if (r.x.flags & 1) { // if the drive reported an ECC occurred, return success if (r.h.ah == 0x11) { bytes = (sectors * bps); goto FillExit; } else goto FillExit; } bytes = (sectors * bps); goto FillExit; }
FillExit:; #if (WINDOWS_98_UTIL) rl.x.ax = 0x440D; // generic IOCTL rl.h.bl = (0x80 | (disk & 0x7F)); // dos limit is 128 drives rl.h.ch = 0x08; // device category rl.h.cl = 0x6B; // unlock physical volume int86(0x21, &rl, &rl); #endif
return bytes;
}
void ScanDiskDevices(void) { register ULONG j, i, retCode; BYTE *Sector; static union REGS r; DRIVE_INFO dinfo;
Sector = NWFSIOAlloc(IO_BLOCK_SIZE, DISKBUF_TAG); if (!Sector) { NWFSPrint("nwfs: allocation error in AddDiskDevices\n"); return; }
for (FirstValidDisk = (ULONG)-1, j = 0; j < MAX_DOS_DISKS; j++) {
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bh = 1; // locks levels 0, 1, 2 or 3 r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x4B; // lock physical volume r.x.dx = 1; // permissions r.h.cflag = 0x0001;
int86(0x21, &r, &r); #endif
// test fixed disk status r.h.ah = 0x10; // test drive status r.h.dl = (0x80 | (j & 0x7F)); // dos limit is 128 drives int86(0x13, &r, &r);
// if we got the drive status, and the drive is active, // assume the disk is valid. if ((!r.h.cflag) && (!r.h.ah)) { // now check if this device supports removable media. This // would indicate this device is a CDROM drive. If we detect // that this device supports removable meida, then do not // add it -- it's most likely a CDROM or tape device and // we should not add it.
// see if a change line is available for this device. r.h.ah = 0x15; // test drive status r.h.dl = (0x80 | (j & 0x7F)); // dos limit is 128 drives int86(0x13, &r, &r);
// 00-no drive, 01-diskette, 02-change line, 03-fixed disk if (r.h.ch == 0x02) {
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; }
if (!SystemDisk[j]) { SystemDisk[j] = (NWDISK *) NWFSAlloc(sizeof(NWDISK), NWDISK_TAG); if (!SystemDisk[j]) { NWFSPrint("nwfs: memory allocation failure in AddDiskDevices\n");
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; } NWFSSet(SystemDisk[j], 0, sizeof(NWDISK)); }
SystemDisk[j]->PhysicalDiskHandle = (void *)(0x80 | (j & 0x7F)); SystemDisk[j]->DiskNumber = j; SystemDisk[j]->Int13Extensions = Int13ExtensionsPresent(j);
SystemDisk[j]->DataSegment = __dpmi_allocate_dos_memory(PARAGRAPH_ALIGN(IO_BLOCK_SIZE), &SystemDisk[j]->DataSelector); if (SystemDisk[j]->DataSegment == (WORD) -1) { SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0;
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; }
SystemDisk[j]->DriveInfoSegment = __dpmi_allocate_dos_memory(PARAGRAPH_ALIGN(IO_BLOCK_SIZE), &SystemDisk[j]->DriveInfoSelector); if (SystemDisk[j]->DriveInfoSegment == (WORD) -1) { if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0;
SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0;
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; }
SystemDisk[j]->RequestSegment = __dpmi_allocate_dos_memory(PARAGRAPH_ALIGN(sizeof(EXT_REQUEST)), &SystemDisk[j]->RequestSelector); if (SystemDisk[j]->RequestSegment == (WORD) -1) { if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0;
if (SystemDisk[j]->DriveInfoSelector) __dpmi_free_dos_memory(SystemDisk[j]->DriveInfoSelector); SystemDisk[j]->DriveInfoSelector = 0;
SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0;
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; }
// if int 13 extensions are present, then adjust drive geometry // based on reported drive info.
if (SystemDisk[j]->Int13Extensions) { register ULONG cylinders, heads, sectors; _go32_dpmi_registers r32;
NWFSSet(&r32, 0, sizeof(_go32_dpmi_registers)); NWFSSet(&dinfo, 0, sizeof(DRIVE_INFO));
dinfo.Size = sizeof(DRIVE_INFO);
movedata(_my_ds(), (unsigned)&dinfo, SystemDisk[j]->DriveInfoSelector, 0, sizeof(DRIVE_INFO));
// get int 13 extension drive info r32.h.ah = 0x48; r32.h.dl = (0x80 | (j & 0x7F)); r32.x.si = 0; r32.x.ds = SystemDisk[j]->DriveInfoSegment;
_go32_dpmi_simulate_int(0x13, &r32);
movedata(SystemDisk[j]->DriveInfoSelector, 0, _my_ds(), (unsigned)&dinfo, sizeof(DRIVE_INFO));
// if TotalSectors is 0, then there are no drives // attached to this controller.
if (!dinfo.TotalSectors) { if (SystemDisk[j]->RequestSelector) __dpmi_free_dos_memory(SystemDisk[j]->RequestSelector); SystemDisk[j]->RequestSelector = 0;
if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0;
if (SystemDisk[j]->DriveInfoSelector) __dpmi_free_dos_memory(SystemDisk[j]->DriveInfoSelector); SystemDisk[j]->DriveInfoSelector = 0;
SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0;
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; }
r.h.ah = 0x08; // read drive parameters r.h.dl = (0x80 | (j & 0x7F));
int86(0x13, &r, &r);
if (r.h.cflag) { if (SystemDisk[j]->RequestSelector) __dpmi_free_dos_memory(SystemDisk[j]->RequestSelector); SystemDisk[j]->RequestSelector = 0;
if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0;
if (SystemDisk[j]->DriveInfoSelector) __dpmi_free_dos_memory(SystemDisk[j]->DriveInfoSelector); SystemDisk[j]->DriveInfoSelector = 0;
SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0;
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; }
// translate drive geometry based on the total sectors // reported by the Int 13 extension procedure.
heads = r.h.dh + 1; sectors = ((WORD)r.h.cl & 0x003F); cylinders = (dinfo.TotalSectors / (heads * sectors));
// make sure that cylinders are within the maximum value // allowed by the Int 13 Extended Architecture. At present, // this limit is 16 mega-tera sectors (2^64).
// assume the current IDE limits for cylinder count if (cylinders > (ULONG) 65536) { if (SystemDisk[j]->RequestSelector) __dpmi_free_dos_memory(SystemDisk[j]->RequestSelector); SystemDisk[j]->RequestSelector = 0;
if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0;
if (SystemDisk[j]->DriveInfoSelector) __dpmi_free_dos_memory(SystemDisk[j]->DriveInfoSelector); SystemDisk[j]->DriveInfoSelector = 0;
SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0;
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; }
// Use the Phoenix method of drive translation // to translate drive geometry for those drives // that exceed 1024 cylinders in size. // // Phoenix Geometry Translation Table // ----------------------------------- // // Phys Cylinders Phys Heads Trans Cyl Trans Heads Max // -------------------------------------------------------- // 1 <C<= 1024 1 <H<= 16 C = C H = H 528 MB // 1024 <C<= 2048 1 <H<= 16 C = C/2 H = H*2 1.0 GB // 2048 <C<= 4096 1 <H<= 16 C = C/4 H = H*4 2.1 GB // 4096 <C<= 8192 1 <H<= 16 C = C/8 H = H*8 4.2 GB // 8192 <C<= 16384 1 <H<= 16 C = C/16 H = H*16 8.4 GB // 16384 <C<= 32768 1 <H<= 8 C = C/32 H = H*32 8.4 GB // 32768 <C<= 65536 1 <H<= 4 C = C/64 H = H*64 8.4 GB // // LBA Assisted Translation Table // ------------------------------ // // (NOTE: The method below is an alternate method for // translating large drives that does not place any limits // on reported drive geometry. It has the disadvantage // of always assuming 63 Sectors Per Track.) // // Range Sectors Heads Cylinders // ----------------------------------------------------- // 1 MB <X< 528 MB 63 16 X/(63 * 16 * 512) // 528 MB <X< 1.0 GB 63 32 X/(63 * 32 * 512) // 1.0 GB <X< 2.1 GB 63 64 X/(63 * 64 * 512) // 2.1 GB <X< 4.2 GB 63 128 X/(63 * 128 * 512) // 4.2 GB <X< 8.4 GB 63 255 X/(63 * 255 * 512) //
// Adjust cylinder and head dimensions until this drive // presents a geometry with a cylinder count that is less // than 1024 or Heads less than or equal to 255.
if (cylinders >= 1024) { while ((heads * 2) <= 256) { heads *= 2; cylinders /= 2; if (cylinders < 1024) break; } }
if (FirstValidDisk == (ULONG)-1) FirstValidDisk = j;
SystemDisk[j]->BytesPerSector = 512; SystemDisk[j]->Cylinders = (LONGLONG) cylinders; SystemDisk[j]->TracksPerCylinder = heads; SystemDisk[j]->SectorsPerTrack = sectors; SystemDisk[j]->driveSize = (LONGLONG) (SystemDisk[j]->Cylinders * SystemDisk[j]->TracksPerCylinder * SystemDisk[j]->SectorsPerTrack * SystemDisk[j]->BytesPerSector); #if (VERBOSE) NWFSPrint("disk-%d cyl-%d head-%d sector-%d (Int 13)\n", (int)j, (int)SystemDisk[j]->Cylinders, (int)SystemDisk[j]->TracksPerCylinder, (int)SystemDisk[j]->SectorsPerTrack); #endif } else { // query the drive parameters with standard bios r.h.ah = 0x08; r.h.dl = (0x80 | (j & 0x7F));
int86(0x13, &r, &r);
if (r.h.cflag) { if (SystemDisk[j]->RequestSelector) __dpmi_free_dos_memory(SystemDisk[j]->RequestSelector); SystemDisk[j]->RequestSelector = 0;
if (SystemDisk[j]->DataSelector) __dpmi_free_dos_memory(SystemDisk[j]->DataSelector); SystemDisk[j]->DataSelector = 0;
if (SystemDisk[j]->DriveInfoSelector) __dpmi_free_dos_memory(SystemDisk[j]->DriveInfoSelector); SystemDisk[j]->DriveInfoSelector = 0;
SystemDisk[j]->PhysicalDiskHandle = 0; NWFSFree(SystemDisk[j]); SystemDisk[j] = 0;
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif continue; }
if (FirstValidDisk == (ULONG)-1) FirstValidDisk = j;
SystemDisk[j]->BytesPerSector = 512; SystemDisk[j]->Cylinders = (LONGLONG)(((WORD)((WORD)r.h.cl << 2) & 0x0300) | (WORD)r.h.ch) + 1; SystemDisk[j]->TracksPerCylinder = (r.h.dh + 1); SystemDisk[j]->SectorsPerTrack = ((WORD)r.h.cl & 0x003F); SystemDisk[j]->driveSize = (LONGLONG) (SystemDisk[j]->Cylinders * SystemDisk[j]->TracksPerCylinder * SystemDisk[j]->SectorsPerTrack * SystemDisk[j]->BytesPerSector); #if (VERBOSE) NWFSPrint("disk-%d cyl-%d head-%d sector-%d\n", (int)j, (int)SystemDisk[j]->Cylinders, (int)SystemDisk[j]->TracksPerCylinder, (int)SystemDisk[j]->SectorsPerTrack); #endif }
#if (WINDOWS_98_UTIL) r.x.ax = 0x440D; // generic IOCTL r.h.bl = (0x80 | (j & 0x7F)); // dos limit is 128 drives r.h.ch = 0x08; // device category r.h.cl = 0x6B; // unlock physical volume int86(0x21, &r, &r); #endif TotalDisks++; if (TotalDisks > MaximumDisks) MaximumDisks = TotalDisks;
retCode = ReadDiskSectors(j, 0, Sector, IO_BLOCK_SIZE / SystemDisk[j]->BytesPerSector, IO_BLOCK_SIZE / SystemDisk[j]->BytesPerSector); if (!retCode) { NWFSPrint("nwfs: disk-%d read error in ScanDiskDevices\n", (int)j); continue; }
NWFSCopy(&SystemDisk[j]->partitionSignature, &Sector[0x01FE], 2);
if (SystemDisk[j]->partitionSignature != 0xAA55) { #if (VERBOSE) NWFSPrint("nwfs: partition signature 0xAA55 not found disk(%d)\n", (int)j); #endif NWFSSet(&SystemDisk[j]->PartitionTable[0].fBootable, 0, 64); continue; } else { NWFSCopy(&SystemDisk[j]->PartitionTable[0].fBootable, &Sector[0x01BE], 64); }
// scan for Netware Partitions and detect 3.x and 4.x/5.x partition types for (i=0, SystemDisk[j]->NumberOfPartitions = 0; i < 4; i++) { if (SystemDisk[j]->PartitionTable[i].nSectorsTotal) SystemDisk[j]->NumberOfPartitions++;
if (SystemDisk[j]->PartitionTable[i].SysFlag == NETWARE_386_ID) { retCode = ReadDiskSectors(j, SystemDisk[j]->PartitionTable[i].StartLBA, Sector, IO_BLOCK_SIZE / SystemDisk[j]->BytesPerSector, IO_BLOCK_SIZE / SystemDisk[j]->BytesPerSector); if (!retCode) { NWFSPrint("nwfs: disk-%d read error in ScanDiskDevices (part)\n", (int)j); continue; }
if (!NWFSCompare(Sector, NwPartSignature, 16)) SystemDisk[j]->PartitionVersion[i] = NW4X_PARTITION; else SystemDisk[j]->PartitionVersion[i] = NW3X_PARTITION; } } } } NWFSFree(Sector); return; }
Phillip Susi wrote:
> linux-os (Dick Johnson) wrote: > >> >> Yes, it's a very good model, in fact what I've been talking about. >> However, several people who refused to read or understand, insisted >> upon obtaining the exact same C/H/S that the machine claimed to >> use when it was booted. >> > > That's because if you don't use the same geometry that the bios > reports when calculating the CHS addresses of the sectors you intend > to load, you won't be requesting the right sectors from int 13. > >> So, since Linux doesn't destroy that information remaining in >> the BIOS tables, I show how to make it available to a 'root' user. >> Observation over several machines will show that the BIOS always >> uses the same stuff for large media and, in fact, it has no choice. >> Basically, this means that the first part of the boot-code, the >> stuff that needs to be translated to fit into the int 0x13 registers, >> needs to be below 1024 cylinders, 63 sectors-track, and 256 heads. >> Trivial... even LILO was able to do that! Once the machine boots >> past the requirement to use the BIOS services, it's a CHS=NOP. >> > > Generally yes, modern large disks will get clamped at 1024 cylinders, > 255 heads, and 63 sectors. You seem to be arguing that this will > always be the case. If that is so, then the kernel doesn't need to > store these values since it is known a priori does it? But it isn't > always going to be 255/63, there are some bioses ( I forget which ) > that cap the number of heads at 240, and disks that are smaller than 8 > gigs also will have less than 255 heads. > > >
- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/
| |