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 + -
显示快捷键?