floppydriver.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 361 行
JAVA
361 行
/*
* $Id: FloppyDriver.java,v 1.5 2003/12/21 07:52:19 epr Exp $
*/
package org.jnode.driver.floppy;
import java.io.IOException;
import org.apache.log4j.Logger;
import org.jnode.driver.Driver;
import org.jnode.driver.RemovableDeviceAPI;
import org.jnode.driver.block.BlockAlignmentSupport;
import org.jnode.driver.block.FSBlockDeviceAPI;
import org.jnode.fs.partitions.PartitionTableEntry;
import org.jnode.fs.util.CHS;
import org.jnode.fs.util.Geometry;
import org.jnode.util.TimeoutException;
/**
* Driver for a FloppyDevice (a single floppy drive)
*
* @author epr
*/
public class FloppyDriver extends Driver implements FSBlockDeviceAPI, RemovableDeviceAPI, FloppyConstants {
/** My logger */
private final Logger log = Logger.getLogger(getClass());
/** Drive number */
private int drive;
/** The controller of the floppy drive i'm a driver for */
private FloppyControllerDriver controller;
private FloppyDriveParameters dp;
private FloppyParameters fp;
private int currentSectorSize = -1;
private FloppyBlockAlignmentSupport api;
/**
* Start the device
*/
protected void startDevice() {
final FloppyDevice dev = (FloppyDevice)getDevice();
controller = dev.getFloppyControllerBus().getController();
drive = dev.getDrive();
dp = dev.getDriveParams();
fp = null;
api = new FloppyBlockAlignmentSupport(this, 512);
dev.registerAPI(RemovableDeviceAPI.class, api);
dev.registerAPI(FSBlockDeviceAPI.class, api);
}
/**
* Stop the device
*/
protected void stopDevice() {
final FloppyDevice dev = (FloppyDevice)getDevice();
dev.unregisterAPI(RemovableDeviceAPI.class);
dev.unregisterAPI(FSBlockDeviceAPI.class);
controller = null;
drive = -1;
fp = null;
dp = null;
}
/**
* @see org.jnode.driver.block.BlockDeviceAPI#flush()
*/
public void flush() {
// Nothing to do here
}
/**
* @see org.jnode.driver.block.BlockDeviceAPI#getLength()
* @return The length
* @throws IOException
*/
public long getLength() throws IOException {
testDiskChange();
return fp.getGeometry().getTotalSectors() * SECTOR_LENGTH[currentSectorSize];
}
/**
* @param devOffset
* @param dest
* @param destOffset
* @param length
* @see org.jnode.driver.block.BlockDeviceAPI#read(long, byte[], int, int)
* @throws IOException
*/
public void read(long devOffset, byte[] dest, int destOffset, int length) throws IOException {
synchronized (controller) {
testDiskChange();
final int sectorLength = SECTOR_LENGTH[currentSectorSize];
testAlignment(sectorLength, devOffset, length);
CHS chs = fp.getGeometry().getCHS(devOffset / sectorLength);
try {
while (length > 0) {
final FloppyReadSectorCommand cmd;
cmd =
new FloppyReadSectorCommand(
drive,
fp.getGeometry(),
chs,
currentSectorSize,
false,
fp.getGap1Size(),
dest,
destOffset);
controller.executeAndWait(cmd, RW_TIMEOUT);
destOffset += sectorLength;
length -= sectorLength;
chs = fp.getGeometry().NextSector(chs);
}
} catch (TimeoutException ex) {
timeout(ex, "read");
}
}
}
/**
* @param devOffset
* @param src
* @param srcOffset
* @param length
* @see org.jnode.driver.block.BlockDeviceAPI#write(long, byte[], int, int)
* @throws IOException
*/
public void write(long devOffset, byte[] src, int srcOffset, int length) throws IOException {
synchronized (controller) {
testDiskChange();
final int sectorLength = SECTOR_LENGTH[currentSectorSize];
testAlignment(sectorLength, devOffset, length);
CHS chs = fp.getGeometry().getCHS(devOffset / sectorLength);
try {
while (length > 0) {
final FloppyWriteSectorCommand cmd;
cmd =
new FloppyWriteSectorCommand(
drive,
fp.getGeometry(),
chs,
currentSectorSize,
false,
fp.getGap1Size(),
src,
srcOffset);
controller.executeAndWait(cmd, RW_TIMEOUT);
srcOffset += sectorLength;
length -= sectorLength;
chs = fp.getGeometry().NextSector(chs);
}
} catch (TimeoutException ex) {
timeout(ex, "write");
}
}
}
/**
* @see org.jnode.driver.block.FSBlockDeviceAPI#getPartitionTableEntry()
* @return The partition table entry, always null here.
*/
public PartitionTableEntry getPartitionTableEntry() {
return null; // A floppy has not partition table
}
/**
* @see org.jnode.driver.block.FSBlockDeviceAPI#getSectorSize()
* @return int
*/
public int getSectorSize() {
if (currentSectorSize < 0) {
return 512;
} else {
return SECTOR_LENGTH[currentSectorSize];
}
}
/**
* Test if the disk has been changed and/or the format of the loaded floppy
* is known. If the floppy has been changed or the format of the floppy is
* not known, try to probe its format.
*
* @throws IOException
*/
private final void testDiskChange() throws IOException {
if (controller.diskChanged(drive, true)) {
log.debug("FloppyDisk change detected");
// Disk has changed, probe for format of new disk
fp = null;
}
if (fp == null) {
log.debug("Try to probe floppy format...");
controller.resetFDC();
log.debug("seek(0)");
seek(0);
fp = probeFormat();
api.setAlignment(SECTOR_LENGTH[currentSectorSize]);
}
}
/**
* Try to determine the format of the disk in the drive
*
* @return The parameters
* @throws IOException
*/
private final FloppyParameters probeFormat() throws IOException {
final FloppyParameters[] fpList = dp.getAutodetectFormats();
final byte[] buf = new byte[512];
for (int i = 0; i < fpList.length; i++) {
final FloppyParameters fp = fpList[i];
log.debug("Trying format " + fp);
final Geometry geom = fp.getGeometry();
final int cyl = geom.getCylinders() - 1;
final int sect = geom.getSectors();
final int head = geom.getHeads() - 1;
final CHS chs0 = new CHS(cyl, head, sect);
specify(fp);
seek(cyl);
readID();
try {
final FloppyReadSectorCommand cmd =
new FloppyReadSectorCommand(
drive,
fp.getGeometry(),
chs0,
currentSectorSize,
false,
fp.getGap1Size(),
buf,
0);
controller.executeAndWait(cmd, RW_TIMEOUT);
// The read has succeeded, we found the format!
log.debug("Found floppy format: " + fp);
return fp;
} catch (TimeoutException ex) {
// Read failed, reset the controller and try the next format
controller.resetFDC();
}
}
throw new IOException("Unknown format");
}
/**
* Seek to a given cylinder
*
* @param cylinder
* @throws IOException
*/
private final void seek(int cylinder) throws IOException {
final FloppySeekCommand cmd = new FloppySeekCommand(drive, cylinder);
try {
controller.executeAndWait(cmd, SEEK_TIMEOUT);
if (controller.diskChanged(drive, false)) {
throw new IOException("Floppy not present");
}
} catch (TimeoutException ex) {
timeout(ex, "seek");
}
}
/**
* Read the ID of the disk
*
* @throws IOException
*/
private final void readID() throws IOException {
final FloppyIdCommand cmd = new FloppyIdCommand(drive);
try {
controller.executeAndWait(cmd, RW_TIMEOUT);
if (cmd.hasError()) {
throw new IOException("Error in Read ID", cmd.getError());
}
currentSectorSize = cmd.getSectorSize();
} catch (TimeoutException ex) {
timeout(ex, "readID");
}
}
/**
* Read the ID of the disk
*
* @param fp
* @throws IOException
*/
private final void specify(FloppyParameters fp) throws IOException {
final FloppyDriveParametersCommand cmd = new FloppyDriveParametersCommand(drive, dp, fp);
try {
controller.executeAndWait(cmd, RW_TIMEOUT);
if (cmd.hasError()) {
throw new IOException("Error in specify", cmd.getError());
}
} catch (TimeoutException ex) {
timeout(ex, "specify");
}
}
/**
* Test the alignment of the given parameters
*
* @param sectorLength
* @param devOffset
* @param length
* @throws IOException
*/
private final void testAlignment(int sectorLength, long devOffset, int length) throws IOException {
if ((devOffset % sectorLength) != 0) {
throw new IOException("devOffset is not sector aligned");
}
if ((length % sectorLength) != 0) {
throw new IOException("length is not sector aligned");
}
}
/**
* Process a timeout during read/write
*
* @param ex
* @param operation
* @throws IOException
*/
private final void timeout(TimeoutException ex, String operation) throws IOException {
controller.resetFDC();
fp = null;
throw new IOException("Timeout in " + operation, ex);
}
static class FloppyBlockAlignmentSupport
extends BlockAlignmentSupport
implements FSBlockDeviceAPI, RemovableDeviceAPI {
private final FSBlockDeviceAPI parentApi;
/**
* @param parentApi
* @param alignment
*/
public FloppyBlockAlignmentSupport(FSBlockDeviceAPI parentApi, int alignment) {
super(parentApi, alignment);
this.parentApi = parentApi;
}
/**
* @see org.jnode.driver.block.FSBlockDeviceAPI#getPartitionTableEntry()
* @return The partition table entry
*/
public PartitionTableEntry getPartitionTableEntry() {
return parentApi.getPartitionTableEntry();
}
/**
* @see org.jnode.driver.block.FSBlockDeviceAPI#getSectorSize()
* @return int
*/
public int getSectorSize() {
return parentApi.getSectorSize();
}
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?