-
Notifications
You must be signed in to change notification settings - Fork 0
Resource Management
How JNode drivers claim and release hardware resources (IRQ, I/O, DMA, memory) to avoid conflicts and enable device access.
JNode provides a platform-independent resource management framework under core/src/core/org/jnode/system/resource/. Drivers use ResourceManager to claim exclusive access to hardware resources before performing I/O operations. The framework prevents conflicts by tracking allocations in linked lists and throwing ResourceNotFreeException on duplicate claims.
The resource system covers four hardware resource types:
-
I/O ports — ISA/PCI port ranges for device registers, accessed via
inPortByte/Word/DwordandoutPortByte/Word/Dword -
IRQ lines — Hardware interrupt request lines with optional sharing, dispatched via
IRQThreadtoIRQHandlercallbacks - DMA channels — x86 DMA controller channels 0-7 with address/page register setup and transfer modes
- Memory regions — MMIO regions and buffer memory with hierarchical child resource support
| Class / File | Role |
|---|---|
Resource.java |
Base interface; defines getOwner(), release(), getParent()
|
ResourceOwner.java |
Identifies who owns a resource; SYSTEM singleton for kernel, SimpleResourceOwner for drivers |
IOResource.java |
I/O port access; getStartPort(), getLength(), raw inPort*()/outPort*() methods |
IRQResource.java |
Interrupt handling; getIRQ(), isShared()
|
IRQHandler.java |
Callback interface; handleInterrupt(int irq) — runs with interrupts disabled |
DMAResource.java |
DMA channel; setup(), enable(), getLength(), MODE_READ/MODE_WRITE
|
MemoryResource.java |
Memory region access; read/write primitives (getInt, setByte, etc.), child resource support |
ResourceManager.java |
Main entry point; bound in InitialNaming as ResourceManager.class; claim*() methods |
DMAManager.java |
DMA channel allocation interface; claimDMAChannel()
|
ResourceNotFreeException.java |
Thrown when a resource is already claimed |
ResourcePermission.java |
Java Security permission for resource access |
ResourceManagerImpl.java (org.jnode.vm) |
Main implementation; singleton with initialize()
|
IOResourceImpl.java (org.jnode.vm) |
I/O port resource implementation; extends Region with static linked list tracking |
IRQManager.java (org.jnode.vm.scheduler) |
IRQ handler registration and dispatch; claimIRQ() creates IRQThread
|
X86IRQManager.java (org.jnode.vm.x86) |
x86 IRQ manager; integrates with PIC8259A for EOI (End Of Interrupt) |
DMAPlugin.java (org.jnode.system.x86) |
x86 DMA plugin; manages channels 0-7, pre-creates channel 4 as cascade |
DMA.java (org.jnode.system.x86) |
x86 DMA controller access; address/page register I/O, 16MB address limit |
X86DMAChannel.java (org.jnode.system.x86) |
Per-channel DMA implementation; delegates to DMAPlugin |
DMAConstants.java (org.jnode.system.x86) |
I/O port addresses for both DMA controllers, mode constants, page registers |
IRQThread.java (org.jnode.vm.scheduler) |
Thread that waits for IRQ signal, dispatches to registered handlers |
MemoryScanner.java |
Scans physical memory for device information |
1. Driver obtains ResourceManager from InitialNaming
└─ InitialNaming.get(ResourceManager.class)
2. Driver claims resource
└─ ResourceManager.claimIOResource(owner, startPort, length)
└─ ResourceManager.claimIRQ(owner, irq, handler, shared)
└─ ResourceManager.claimMemoryResource(owner, start, size, mode)
└─ DMAManager.claimDMAChannel(owner, dmanr)
└─ Throws ResourceNotFreeException if already in use
3. Driver uses resource via interface methods
└─ IOResource: outPortByte(port, value)
└─ IRQResource: handler invoked on interrupt (keep short!)
└─ MemoryResource: setInt(offset, value), copy(src, dst, size)
└─ DMAResource: setup(memory, len, mode), enable()
4. Driver releases resource
└─ resource.release()
└─ Resource removed from global tracking list
└─ Memory child resources cascade release to parent
IOResourceImpl extends Region and maintains a static linked list of all claimed port ranges. The claim operation synchronizes access and validates port ranges with testPort().
ResourceManager rm = (ResourceManager) InitialNaming.get(ResourceManager.class);
IOResource io = rm.claimIOResource(this, 0x3F8, 8);
io.outPortByte(0, (byte) 0x55); // Write to port 0x3F8
// ... use the port ...
io.release();IRQManager (in org.jnode.vm.scheduler) manages IRQ handler registration. When claimIRQ() is called, it either creates a new IRQThread (starts the thread) or adds the handler to an existing thread if sharing is allowed. Supports shared IRQs by maintaining a list of handlers per IRQ line. When an interrupt fires, IRQManager.dispatchInterrupts() signals the appropriate IRQThread which calls all registered handlers.
X86IRQManager extends IRQManager and integrates with PIC8259A for End Of Interrupt (EOI) signaling. The abstract eoi(int irq) method is implemented by the x86 subclass.
IRQResource irq = rm.claimIRQ(this, 12, new IRQHandler() {
public void handleInterrupt(int irq) {
// handle the interrupt — keep this short!
}
}, false);
int irqNum = irq.getIRQ(); // returns 12
irq.release();The x86 DMA system uses two cascaded 8237 DMA controllers:
- Controller 1: Channels 0-3, I/O ports 0x00-0x0F (address/count) and 0x80-0x83 (page registers)
- Controller 2: Channels 4-7, I/O ports 0xC0-0xCF (address/count) and 0x84-0x86,0x89-0x8A (page registers)
Channel 4 is reserved as the cascade channel (connects controller 2 to controller 1). Channels 0-3 are 8-bit; channels 5-7 are 16-bit.
The DMAPlugin (org.jnode.system.x86) pre-creates channel 4 as cascade at startup. DMA transfers are limited to the lower 16MB of physical memory (addressed via page registers + 8-bit address registers = 24-bit physical address).
DMAManager dmaManager = (DMAManager) InitialNaming.get(DMAManager.NAME);
DMAResource dma = dmaManager.claimDMAChannel(this, 2);
MemoryResource buf = rm.asMemoryResource(byteArray);
dma.setup(buf, 1024, DMAResource.MODE_READ);
dma.enable();
// ... DMA transfers ...
dma.release();MemoryResourceImpl supports hierarchical parent-child relationships. Child resources are allocated from free sub-regions of the parent. Release cascades: children must be released before the parent (enforced by parent tracking). claimChildResource() supports alignment and overlap options.
MemoryResource mmio = rm.claimMemoryResource(this, 0xFED00000L, 0x10000, ResourceManager.MEMMODE_NORMAL);
// Read a 32-bit register at offset 0x10
int val = mmio.getInt(0x10);
// Claim a sub-region (child)
MemoryResource child = mmio.claimChildResource(0x1000, 0x100);
child.release(); // release child first
mmio.release(); // then release parentEvery claim requires a ResourceOwner to identify the consumer. Use SimpleResourceOwner for one-off drivers or define a custom class.
ResourceOwner owner = new SimpleResourceOwner("MyDeviceDriver");
IOResource io = rm.claimIOResource(owner, startPort, length);ResourceOwner.SYSTEM is reserved for kernel-level resources.
-
IRQ handler brevity:
IRQHandler.handleInterrupt()runs with interrupts disabled. Keep it as short as possible — signal a thread, set a flag, or push data to a queue. Never block or perform long I/O. - Memory child release order: Children must be released before their parent. The parent tracks children and the release will throw if children remain.
- DMA channel 4 is reserved: Do not claim channel 4 — it's the cascading channel for the secondary DMA controller.
- 8-bit vs 16-bit DMA: Channels 0-3 are 8-bit (channels 0-3 use DMA controller 1); channels 5-7 are 16-bit (use controller 2). Claiming a 16-bit operation on an 8-bit channel will fail.
- DMA 16MB limit: Physical addresses above 16MB cannot be used for DMA without bounce buffering, as page registers provide only 8 bits of the 24-bit address.
-
Shared IRQ caveat:
isShared()only reports whether sharing was requested at claim time. Actual sharing depends on hardware and wiring. -
SecurityManager checks:
ResourceManagerImplchecksIOPORTS_PERMandMEMSCAN_PERMbefore granting access if aSecurityManageris installed. -
Static resource lists:
IOResourceImpluses a static linked list to track allocations. This means I/O port claims persist across isolate boundaries. -
InitialNaming binding:
ResourceManageris bound asResourceManager.classinInitialNaming, not as a string key. -
Port range validation:
IOResourceImpl.testPort()throwsIndexOutOfBoundsExceptionif an out-of-range port is accessed — the port must be within[startPort, startPort + length). -
IRQ thread creation:
IRQManager.claimIRQ()creates and starts a newIRQThreadsynchronously. The first claim for an IRQ will block briefly while the thread starts.
- Driver-Framework — Parent hub page for device driver architecture
- Interrupt-Handling — How hardware IRQs are dispatched through the IDT, PIC/APIC to handlers
- Bus-Drivers — PCI and USB bus drivers that allocate IRQ/IO/DMA resources
- Architecture — System overview and subsystem interactions