idebus.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 423 行
JAVA
423 行
/*
* $Id: IDEBus.java,v 1.2 2003/11/29 17:20:24 gbin Exp $
*/
package org.jnode.driver.ide;
import javax.naming.NameNotFoundException;
import org.apache.log4j.Logger;
import org.jnode.driver.Bus;
import org.jnode.driver.Device;
import org.jnode.naming.InitialNaming;
import org.jnode.system.IOResource;
import org.jnode.system.IRQHandler;
import org.jnode.system.IRQResource;
import org.jnode.system.ResourceManager;
import org.jnode.system.ResourceNotFreeException;
import org.jnode.system.ResourceOwner;
import org.jnode.util.NumberUtils;
import org.jnode.util.Queue;
import org.jnode.util.QueueProcessor;
import org.jnode.util.QueueProcessorThread;
import org.jnode.util.TimeoutException;
/**
* @author epr
*/
public class IDEBus extends Bus implements IDEConstants, IRQHandler, QueueProcessor {
/** My logger */
private final Logger log = Logger.getLogger(getClass());
private IRQResource irqRes;
/** IDE Taskfile io space */
private IOResource ideIO;
/** IDE High taskfile io space */
private IOResource ideHighIO;
/** The command queue for IDE commands */
private final Queue commandQueue = new Queue();
/** The command that is currently being processed */
private IDECommand currentCommand;
/** The worker thread for the command queue */
private QueueProcessorThread queueProcessor;
private final int taskfile;
/** First port of the taskfile this command is intended for */
protected final int startPort;
/** The IRQ for this processor */
private final int irq;
/**
* Create a new instance
*/
protected IDEBus(Device parent, int taskfile)
throws IllegalArgumentException {
super(parent);
switch (taskfile) {
case 0: {
startPort = IDE0_START_PORT;
irq = IDE0_IRQ;
} break;
case 1: {
startPort = IDE1_START_PORT;
irq = IDE1_IRQ;
} break;
default: {
throw new IllegalArgumentException("Invalid taskfile " + taskfile);
}
}
this.taskfile = taskfile;
}
/**
* Add the given command to the queue of commands to be executed.
* @param command
*/
public void execute(IDECommand command) {
commandQueue.add(command);
}
/**
* Add the given command to the queue of commands to be executed and wait
* for the command to finish.
* @param command
*/
public void executeAndWait(IDECommand command)
throws InterruptedException {
execute(command);
command.waitUntilFinished();
}
/**
* Add the given command to the queue of commands to be executed and wait
* for the command to finish.
* @param command
* @param timeout Maximum time to wait
*/
public void executeAndWait(IDECommand command, long timeout)
throws InterruptedException {
execute(command);
try {
command.waitUntilFinished(timeout);
} catch (TimeoutException ex) {
// ignore
}
}
/**
* Starts this processor.
* First the IRQ handler is registers, after that a queue processor
* is initialized and started.
*/
public void start(ResourceOwner owner)
throws ResourceNotFreeException {
// Claim the IOResources
IOResource ideIO = null;
IOResource ideHighIO = null;
final ResourceManager rm;
try {
rm = (ResourceManager)InitialNaming.lookup(ResourceManager.NAME);
ideIO = rm.claimIOResource(owner, startPort, IDE_NR_PORTS);
ideHighIO = rm.claimIOResource(owner, startPort + HIGH_OFFSET, IDE_NR_HIGH_PORTS);
} catch (NameNotFoundException ex) {
throw new ResourceNotFreeException("Cannot find ResourceManager", ex);
} catch (ResourceNotFreeException ex) {
if (ideIO != null) {
ideIO.release();
}
if (ideHighIO != null) {
ideHighIO.release();
}
throw ex;
}
this.ideIO = ideIO;
this.ideHighIO = ideHighIO;
// Register the irq handler
irqRes = rm.claimIRQ(owner, irq, this, false);
// Reset the controller
setControlReg(CTR_SRST);
try {
Thread.sleep(50);
} catch (InterruptedException ex) {
/* ignore */
}
// Set the controller to interrupts enabled
setControlReg(0);
// Create and start the queue processor
queueProcessor = new QueueProcessorThread("IDE-" + taskfile, commandQueue, this);
queueProcessor.start();
}
/**
* Stop this processor.
*/
public void stop() {
queueProcessor.stopProcessor();
irqRes.release();
queueProcessor = null;
ideIO.release();
ideHighIO.release();
}
/**
* Handle the IDE interrupt.
*/
public void handleInterrupt(int irq) {
final IDECommand cmd = currentCommand;
//log.debug("IDE IRQ " + irq + " cmd=" + cmd);
if (cmd != null) {
cmd.handleIRQ(this);
if (cmd.isFinished()) {
currentCommand = null;
}
}
}
/**
* Probe for the existence of a given IDE device.
* @param master
*/
public IDEDriveDescriptor probe(boolean master)
throws InterruptedException {
log.info("Probing IDE" + taskfile + "." + (master ? "0" : "1"));
setControlReg(0); // Interrupts enabled
// First try a normal IDE Identify command
IDEIdCommand cmd = new IDEIdCommand(taskfile, master, false);
executeAndWait(cmd, IDE_TIMEOUT);
if (cmd.isFinished()) {
final IDEDriveDescriptor result = cmd.getResult();
if (result != null) {
return result;
} else {
if (!cmd.isPacketResponse()) {
// Not an ATAPI device.
return null;
}
//log.debug("result==null");
}
} else {
// Force a reset of any IRQ
final int state = getStatusReg();
// Timeout
log.debug("Timeout state=" + NumberUtils.hex(state));
return null;
}
// Clear any interrupts
getStatusReg();
// IDE Identify failed, do an ATAPI Identify
cmd = new IDEIdCommand(taskfile, master, true);
executeAndWait(cmd, IDE_TIMEOUT);
// Force a reset of any IRQ
getStatusReg();
// Good result?
if (cmd.isFinished()) {
return cmd.getResult();
}
log.debug("Probe done, return null");
// No device found
return null;
}
/**
* Gets a word from the data register
*/
protected final int getDataReg() {
return ideIO.inPortWord(startPort + RW16_DATA_OFFSET);
}
/**
* Writes a word to the data register
* @param dataWord
*/
protected final void setDataReg(int dataWord) {
ideIO.outPortWord(startPort + RW16_DATA_OFFSET, dataWord);
}
/**
* Gets the contents of the error register
*/
protected final int getErrorReg() {
return ideIO.inPortByte(startPort + R8_ERROR_OFFSET);
}
/**
* Sets the contents of the featureregister
*/
protected final void setFeatureReg(int features) {
ideIO.outPortByte(startPort + W8_FEATURE_OFFSET, features);
}
/**
* Gets the contents of the sector count register
*/
protected final int getSectorCountReg() {
return ideIO.inPortByte(startPort + RW8_SECTOR_COUNT_OFFSET);
}
/**
* Sets the sector count register
* @param sectorCount
*/
protected final void setSectorCountReg(int sectorCount) {
ideIO.outPortByte(startPort + RW8_SECTOR_COUNT_OFFSET, sectorCount);
}
/**
* Gets the contents of the sector register
*/
protected final int getSectorReg() {
return ideIO.inPortByte(startPort + RW8_SECTOR_OFFSET);
}
/**
* Gets the contents of the LBA low register
*/
protected final int getLbaLowReg() {
return ideIO.inPortByte(startPort + RW8_LBA_LOW_OFFSET);
}
/**
* Gets the contents of the LBA mid register
*/
protected final int getLbaMidReg() {
return ideIO.inPortByte(startPort + RW8_LBA_MID_OFFSET);
}
/**
* Gets the contents of the LBA high register
*/
protected final int getLbaHighReg() {
return ideIO.inPortByte(startPort + RW8_LBA_HIGH_OFFSET);
}
/**
* Sets the contents of the LBA low register
*/
protected final void setLbaLowReg(int value) {
ideIO.outPortByte(startPort + RW8_LBA_LOW_OFFSET, value);
}
/**
* Sets the contents of the LBA mid register
*/
protected final void setLbaMidReg(int value) {
ideIO.outPortByte(startPort + RW8_LBA_MID_OFFSET, value);
}
/**
* Sets the contents of the LBA high register
*/
protected final void setLbaHighReg(int value) {
ideIO.outPortByte(startPort + RW8_LBA_HIGH_OFFSET, value);
}
/**
* Sets the sector register
* @param sector
*/
protected final void setSectorReg(int sector) {
ideIO.outPortByte(startPort + RW8_SECTOR_OFFSET, sector);
}
/**
* Gets the combined cylinder value out the the cylinder LSB and MSB registers.
*/
protected final int getCylinderRegs() {
final int lsb = ideIO.inPortByte(startPort + RW8_CYLINDER_LSB_OFFSET);
final int msb = ideIO.inPortByte(startPort + RW8_CYLINDER_MSB_OFFSET);
return ((msb & 0xFF) << 8) | (lsb & 0xFF);
}
/**
* Sets the cylinder registers value (both LSB and MSB)
*/
protected final void setCylinderRegs(int cylinder) {
final int lsb = cylinder & 0xFF;
final int msb = (cylinder >> 8) & 0xFF;
ideIO.outPortByte(startPort + RW8_CYLINDER_LSB_OFFSET, lsb);
ideIO.outPortByte(startPort + RW8_CYLINDER_MSB_OFFSET, msb);
}
/**
* Gets the contents of the select register
*/
protected final int getSelectReg() {
return ideIO.inPortByte(startPort + RW8_SELECT_OFFSET);
}
/**
* Sets the select register
* @param select
*/
protected final void setSelectReg(int select) {
ideIO.outPortByte(startPort + RW8_SELECT_OFFSET, select);
}
/**
* Gets the status of the IDE controller. Any pending IRQ is reset.
*/
protected final int getStatusReg() {
return ideIO.inPortByte(startPort + R8_STATUS_OFFSET);
}
/**
* Gets the alternative status of the IDE controller.
* Any pending IRQ is NOT reset.
*/
protected final int getAltStatusReg() {
return ideHighIO.inPortByte(startPort + R8_ALTSTATUS_OFFSET);
}
/**
* Sets the command register. This also activates the IDE controller
* so always set other registers first.
* @param command
*/
protected final void setCommandReg(int command) {
ideIO.outPortByte(startPort + W8_COMMAND_OFFSET, command);
}
/**
* Sets the control register.
* @param control The new value for the control register
*/
protected final void setControlReg(int control) {
ideHighIO.outPortByte(startPort + W8_CONTROL_OFFSET, control);
}
/**
* Block the current thread until the controller is not busy anymore.
*/
protected final void waitUntilNotBusy() {
int state = ideHighIO.inPortByte(startPort + R8_ALTSTATUS_OFFSET);
while ((state & ST_BUSY) != 0) {
try {
Thread.sleep(10);
} catch (InterruptedException ex) {
// nothing special to do
}
state = ideHighIO.inPortByte(startPort + R8_ALTSTATUS_OFFSET);
}
}
/**
* @see org.jnode.util.QueueProcessor#process(java.lang.Object)
*/
public void process(Object object) throws Exception {
final IDECommand cmd = (IDECommand)object;
// Wait until the controller is not busy anymore
if ((getAltStatusReg() & ST_BUSY) == ST_BUSY) {
log.debug("<wait>");
waitUntilNotBusy();
log.debug("</wait>");
}
currentCommand = cmd;
cmd.setup(IDEBus.this);
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?