lkml.org 
[lkml]   [2006]   [Feb]   [17]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    /
    Date
    From
    SubjectRe: 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, &sector);
    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, &sector);
    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, &sector);
    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/

    \
     
     \ /
      Last update: 2006-02-17 22:28    [W:0.161 / U:0.492 seconds]
    ©2003-2016 Jasper Spaans. hosted at Digital OceanAdvertise on this site