-
Notifications
You must be signed in to change notification settings - Fork 0
IDEDisk Driver
JNode's primary IDE/ATA disk driver providing block-level access to PATA devices via LBA addressing with both PIO and DMA transfer modes.
The IDEDiskDriver is a critical JNode driver that manages Parallel ATA (PATA) disk devices. It extends the Driver class and implements the IDEDeviceAPI, providing the bridge between JNode's block device layer and hardware IDE controllers. The driver supports both 28-bit and 48-bit LBA addressing, enabling access to disks larger than 128GB.
| File | Purpose |
|---|---|
fs/src/driver/org/jnode/driver/block/ide/disk/IDEDiskDriver.java |
Main driver class |
fs/src/driver/org/jnode/driver/block/ide/disk/IDEDiskPartitionDevice.java |
Partition device representation |
fs/src/driver/org/jnode/driver/block/ide/disk/IDEDiskPartitionDriver.java |
Partition driver |
fs/src/driver/org/jnode/driver/bus/ide/IDEBus.java |
Command queue processing bus |
fs/src/driver/org/jnode/driver/bus/ide/IDEConstants.java |
ATA register definitions, commands, timeouts |
fs/src/driver/org/jnode/driver/bus/ide/command/IDERWSectorsCommand.java |
Read/write sector commands |
fs/src/driver/org/jnode/driver/bus/ide/IDEDriveDescriptor.java |
Drive identification data |
When startDevice() is called, the driver:
- Creates an
IDEDiskBus(internalBussubclass) wrapping theIDEDevice - Reads the MBR boot sector via LBA sector 0
- Creates an
IBMPartitionTablefrom the boot sector - Registers partition devices for each valid partition entry
- Handles extended partitions by iterating through chained partition tables
protected void startDevice() throws DriverException {
final IDEDevice dev = (IDEDevice) getDevice();
diskBus = new IDEDiskBus(dev);
dev.registerAPI(IDEDeviceAPI.class,
new IDEDeviceBlockAlignmentSupport<IBMPartitionTableEntry>(this, SECTOR_SIZE));
final IDEDriveDescriptor descr = dev.getDescriptor();
is48bit = descr.supports48bitAddressing();
maxSector = descr.getSectorsAddressable();
// Read boot sector, create partition table, register partitions
final byte[] bs = new byte[SECTOR_SIZE];
read(0, ByteBuffer.wrap(bs));
this.pt = factory.createIBMPartitionTable(bs, dev);
// ... register partitions
}The transfer() method handles block reads/writes with the following flow:
- Validates offset/length alignment to 512-byte sector boundaries
- Splits large transfers into chunks respecting the maximum sector count:
- 256 sectors for 28-bit addressing
- 65536 sectors for 48-bit addressing
- Creates
IDEReadSectorsCommandorIDEWriteSectorsCommandfor each chunk - Executes commands via
bus.executeAndWait()with a 10-second timeout - Handles errors by throwing
IOException
protected void transfer(long devOffset, ByteBuffer buf, boolean isWrite) throws IOException {
final long lbaStart = devOffset / SECTOR_SIZE;
final int sectors = length / SECTOR_SIZE;
final int maxSectorCount = is48bit ? MAX_SECTOR_COUNT_48 : MAX_SECTOR_COUNT_28;
while (length > 0) {
final int partSectorCount = Math.min(length / SECTOR_SIZE, maxSectorCount);
final IDERWSectorsCommand cmd = isWrite ?
new IDEWriteSectorsCommand(primary, master, is48bit, partLbaStart, partSectorCount, buf) :
new IDEReadSectorsCommand(primary, master, is48bit, partLbaStart, partSectorCount, buf);
bus.executeAndWait(cmd, IDE_DATA_XFER_TIMEOUT);
// ...
}
}IDEBus manages a QueueProcessorThread that sequentially processes IDE commands:
- Commands are added via
execute(command) - Synchronous wait via
executeAndWait(command, timeout) - IRQ handler (
handleInterrupt) signals command completion - Software reset via
softwareReset()if commands timeout
IDEConstants defines all ATA register offsets and command codes:
| Register | Offset | Purpose |
|---|---|---|
| Data | 0x1F0/0x170 | 16-bit data I/O |
| Error/Feature | 1 | Read errors, write features |
| Sector Count | 2 | Number of sectors (LBA low) |
| LBA Low | 3 | LBA bits 0-7 |
| LBA Mid | 4 | LBA bits 8-15 |
| LBA High | 5 | LBA bits 16-23 |
| Drive/Head | 6 | Drive selection, LBA bit 24-27 |
| Status/Command | 7 | Read status, write commands |
28-bit LBA: Uses Drive/Head register for LBA bits 24-27
io.setSelectReg(SEL_LBA | getSelect() | ((int)(lbaStart >> 24) & 0xF));48-bit LBA: Writes registers twice (high then low)
io.setSectorCountReg((sectorCount >> 8) & 0xFF); // high byte
io.setLbaLowReg((int)((lbaStart >> 24) & 0xFF));
// ... more high bytes ...
io.setSectorCountReg((sectorCount >> 0) & 0xFF); // low byte
io.setLbaLowReg((int)((lbaStart >> 0) & 0xFF));
// ... more low bytes ...-
Double boot sector read: The driver reads sector 0 twice as a workaround for an unknown first-read failure (
IDEDiskDriver.java:106-112). The exact cause is unclear but may relate to controller initialization. -
Partition unregistration on stop:
stopDevice()manually iterates the device manager to find and unregister partition children, rather than using a hierarchical shutdown mechanism. -
DMA mode disabled: DMA support is commented out in the codebase (
//dma = descr.supportsDMA()). The driver currently uses PIO mode exclusively, despite having DMA command definitions inIDEConstants(e.g.,CMD_READDMA,CMD_WRITEDMA). -
Command timeout handling: Timeouts result in
InterruptedIOException, but the controller may remain in a busy state, potentially affecting subsequent commands. -
No error recovery: On command errors, the driver throws an
IOExceptionwith minimal diagnostic information (just the error code).
- Block-Device-Layer — Block I/O APIs and device hierarchy
- BlockDeviceLayer — Block device abstraction layer internals
- Driver-Framework — Device driver architecture
- Filesystem-Layer — Partition tables and filesystem mounting
- Resource-Management — Hardware resource allocation
-
IDEBus — Command queue bus (see
fs/src/driver/org/jnode/driver/bus/ide/IDEBus.java)