⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 floppycontroller.java

📁 JPC: x86 PC Hardware Emulator. 牛津大学开发的一个纯JAVA的x86系统结构硬件模拟器。
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
/*    JPC: A x86 PC Hardware Emulator for a pure Java Virtual Machine    Release Version 2.0    A project from the Physics Dept, The University of Oxford    Copyright (C) 2007 Isis Innovation Limited    This program is free software; you can redistribute it and/or modify    it under the terms of the GNU General Public License version 2 as published by    the Free Software Foundation.    This program is distributed in the hope that it will be useful,    but WITHOUT ANY WARRANTY; without even the implied warranty of    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the    GNU General Public License for more details.    You should have received a copy of the GNU General Public License along    with this program; if not, write to the Free Software Foundation, Inc.,    51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.     Details (including contact information) can be found at:     www.physics.ox.ac.uk/jpc*/package org.jpc.emulator.peripheral;import org.jpc.emulator.motherboard.*;import org.jpc.support.*;import org.jpc.emulator.*;import java.io.*;public class FloppyController implements IOPortCapable, DMATransferCapable, HardwareComponent {    /* Will always be a fixed parameter for us */    private static final int SECTOR_LENGTH = 512;    private static final int SECTOR_SIZE_CODE = 2; // Sector size code    /* Floppy disk drive emulation */    private static final int CONTROL_ACTIVE = 0x01; /* XXX: suppress that */    private static final int CONTROL_RESET  = 0x02;    private static final int CONTROL_SLEEP  = 0x04; /* XXX: suppress that */    private static final int CONTROL_BUSY   = 0x08; /* dma transfer in progress */    private static final int CONTROL_INTERRUPT   = 0x10;    private static final int DIRECTION_WRITE   = 0;    private static final int DIRECTION_READ    = 1;    private static final int DIRECTION_SCANE   = 2;    private static final int DIRECTION_SCANL   = 3;    private static final int DIRECTION_SCANH   = 4;    private static final int STATE_COMMAND    = 0x00;    private static final int STATE_STATUS = 0x01;    private static final int STATE_DATA   = 0x02;    private static final int STATE_STATE  = 0x03;    private static final int STATE_MULTI  = 0x10;    private static final int STATE_SEEK   = 0x20;    private static final int STATE_FORMAT = 0x40;    private static final byte CONTROLLER_VERSION = (byte)0x90; /* Intel 82078 Controller */    private static final int INTERRUPT_LEVEL = 6;    private static final int DMA_CHANNEL = 2;    private static final int IOPORT_BASE = 0x3f0;    private boolean drivesUpdated;    private Timer resultTimer;    private Clock clock;    private int state;    private boolean dmaEnabled;    private int currentDrive;    private int bootSelect;    /* Command FIFO */    private byte[] fifo;    private int dataOffset;    private int dataLength;    private int dataState;    private int dataDirection;    private int interruptStatus;    private byte eot; // last wanted sector    /* State kept only to be returned back */    /* Timers state */    private byte timer0;    private byte timer1;    /* precompensation */    private byte preCompensationTrack;    private byte config;    private byte lock;    /* Power down config */    private byte pwrd;    /* Drives */    private FloppyDrive[] drives;    private InterruptController irqDevice;    private DMAController dma;    public FloppyController()    {	ioportRegistered = false;	drives = new FloppyDrive[2];		config = (byte)0x60; /* Implicit Seek, polling & fifo enabled */	state = CONTROL_ACTIVE;       		fifo = new byte[SECTOR_LENGTH];    }    public void dumpState(DataOutput output) throws IOException    {        output.writeInt(state);        output.writeBoolean(dmaEnabled);        output.writeInt(currentDrive);        output.writeInt(bootSelect);        output.writeInt(fifo.length);        output.write(fifo,0,fifo.length);        output.writeInt(dataOffset);        output.writeInt(dataLength);        output.writeInt(dataState);        output.writeInt(dataDirection);        output.writeInt(interruptStatus);        output.writeByte(eot);        output.writeByte(timer0);        output.writeByte(timer1);        output.writeByte(preCompensationTrack);        output.writeByte(config);        output.writeByte(lock);        output.writeByte(pwrd);        drives[0].dumpState(output);        drives[1].dumpState(output);        resultTimer.dumpState(output);    }    public void loadState(DataInput input) throws IOException    {        drivesUpdated = false;        ioportRegistered = false;        state = input.readInt();        dmaEnabled = input.readBoolean();        currentDrive = input.readInt();        bootSelect = input.readInt();        int len = input.readInt();//be careful        fifo = new byte[len];        input.readFully(fifo,0,len);        dataOffset = input.readInt();        dataLength = input.readInt();        dataState = input.readInt();        dataDirection = input.readInt();        interruptStatus = input.readInt();        eot = input.readByte();        timer0 = input.readByte();        timer1 = input.readByte();        preCompensationTrack = input.readByte();        config = input.readByte();        lock = input.readByte();        pwrd = input.readByte();        drives[0].loadState(input);        drives[1].loadState(input);        resultTimer.loadState(input);        ioportRegistered = false; //make sure the drives aren't reset when driveset is passed in.     }    public void timerCallback()    {	stopTransfer((byte)0x00, (byte)0x00, (byte)0x00);    }    public int getDriveType(int number)    {	return drives[number].drive;    }    public int[] ioPortsRequested()    {	return new int[]{IOPORT_BASE + 1, IOPORT_BASE + 2, IOPORT_BASE + 3, IOPORT_BASE + 4, IOPORT_BASE + 5, IOPORT_BASE + 7};    }    public int ioPortReadByte(int address)    {	switch(address & 0x07) {	case 0x01:	    return readStatusB();	case 0x02:	    return readDOR();	case 0x03:	    return readTape();	case 0x04:	    return readMainStatus();	case 0x05:	    return readData();	case 0x07:	    return readDirection();	default:	    return 0xff;	}    }    public int ioPortReadWord(int address)    {	return (ioPortReadByte(address) & 0xff) | ((ioPortReadByte(address + 1) << 8) & 0xff00);    }    public int ioPortReadLong(int address)    {	return (ioPortReadWord(address) & 0xffff) | ((ioPortReadWord(address + 2) << 16) & 0xffff0000);    }    public void ioPortWriteByte(int address, int data)    {	switch(address & 0x07) {	case 0x02:	    writeDOR(data);	    break;	case 0x03:	    writeTape(data);	    break;	case 0x04:	    writeRate(data);	    break;	case 0x05:	    writeData(data);	    break;	default:	    break;	}    }    public void ioPortWriteWord(int address, int data)    {	ioPortWriteByte(address, data & 0xff);	ioPortWriteByte(address + 1, (data >>> 8) & 0xff);    }    public void ioPortWriteLong(int address, int data)    {	ioPortWriteWord(address, data & 0xffff);	ioPortWriteWord(address + 2, (data >>> 16) & 0xffff);    }    private void reset(boolean doIRQ)    {	resetIRQ();	currentDrive = 0;	dataOffset = 0;	dataLength = 0;	dataState = STATE_COMMAND;	dataDirection = DIRECTION_WRITE;	drives[0].reset();	drives[1].reset();	resetFIFO();	if (doIRQ)	    raiseIRQ(0xc0);    }    private void raiseIRQ(int status)    {	if (~(state & CONTROL_INTERRUPT) != 0) {	    irqDevice.setIRQ(INTERRUPT_LEVEL, 1);	    state |= CONTROL_INTERRUPT;	}	interruptStatus = status;    }    private void resetFIFO()    {	dataDirection = DIRECTION_WRITE;	dataOffset = 0;	dataState = (dataState & ~STATE_STATE) | STATE_COMMAND;    }    private void resetIRQ()    {	irqDevice.setIRQ(INTERRUPT_LEVEL, 0);	state &= ~CONTROL_INTERRUPT;    }    private int readStatusB()    {	return 0;    }    private int readDOR()    {	int retval = 0;		/* Drive motors state indicators */	if ((getDrive(0).driveFlags & FloppyDrive.MOTOR_ON) != 0) 	    retval |= 1 << 5;	if ((getDrive(1).driveFlags & FloppyDrive.MOTOR_ON) != 0) 	    retval |= 1 << 4;	/* DMA enable */	retval |= dmaEnabled ?  1 << 3 : 0;	/* Reset indicator */	retval |= (state & CONTROL_RESET) == 0 ? 1 << 2 : 0;	/* Selected drive */	retval |= currentDrive;		return retval;    }    private int readTape()    {	/* Disk boot selection indicator */	return bootSelect << 2;	/* Tape indicators: never allowed */    }    private int readMainStatus()    {	int retval = 0;		state &= ~(CONTROL_SLEEP | CONTROL_RESET);	if ((state & CONTROL_BUSY) == 0) {	    /* Data transfer allowed */	    retval |= 0x80;	    /* Data transfer direction indicator */	    if (dataDirection == DIRECTION_READ)		retval |= 0x40;	}	/* Should handle 0x20 for SPECIFY command */	/* Command busy indicator */	if ((dataState & STATE_STATE) == STATE_DATA || (dataState & STATE_STATE) == STATE_STATUS)	    retval |= 0x10;		return retval;    }        private int readData()    {	FloppyDrive drive;	drive = getCurrentDrive();	state &= ~CONTROL_SLEEP;	if ((dataState & STATE_STATE) == STATE_COMMAND) {	    System.err.println("fdc >> can't read data in COMMAND state");	    return 0;	}	int offset = dataOffset;	if ((dataState & STATE_STATE) == STATE_DATA) {	    offset %= SECTOR_LENGTH;	    if (offset == 0) {		int length = Math.min(dataLength - dataOffset, SECTOR_LENGTH);		drive.read(drive.currentSector(), fifo, length);	    }	}	int retval = fifo[offset];	if (++dataOffset == dataLength) {	    dataOffset = 0;	    /* Switch from transfer mode to status mode	     * then from status mode to command mode	     */	    if ((dataState & STATE_STATE) == STATE_DATA) {		stopTransfer((byte)0x20, (byte)0x00, (byte)0x00);	    } else {		resetFIFO();		resetIRQ();	    }	}		return retval;    }    private int readDirection()    {	int retval = 0;	if (((getDrive(0).driveFlags & FloppyDrive.REVALIDATE) != 0) || ((getDrive(1).driveFlags & FloppyDrive.REVALIDATE) != 0))	    retval |= 0x80;	getDrive(0).driveFlags &= ~FloppyDrive.REVALIDATE;	getDrive(1).driveFlags &= ~FloppyDrive.REVALIDATE;		return retval;    }    private void writeDOR(int data)    {	/* Reset mode */	if (((state & CONTROL_RESET) != 0) && ((data & 0x04) == 0))	    return;	/* Drive motors state indicators */	if ((data & 0x20) != 0)	    getDrive(1).start();	else	    getDrive(1).stop();	if ((data & 0x10) != 0)	    getDrive(0).start();	else	    getDrive(0).stop();	/* DMA enable */	/* Reset */	if ((data & 0x04) == 0) {	    if ((state & CONTROL_RESET) == 0) {		state |= CONTROL_RESET;	    }	} else {	    if ((state & CONTROL_RESET) != 0) {		reset(true);		state &= ~(CONTROL_RESET | CONTROL_SLEEP);	    }	}	/* Selected drive */	currentDrive = data & 1;    }    private void writeTape(int data)    {	/* Reset mode */	if ((state & CONTROL_RESET) != 0)	    return;	/* Disk boot selection indicator */	bootSelect = (data >>> 2) & 1;	/* Tape indicators: never allow */    }    private void writeRate(int data)    {	/* Reset mode */	if ((state & CONTROL_RESET) != 0)            return;	/* Reset: autoclear */	if ((data & 0x80) != 0) {	    state |= CONTROL_RESET;	    reset(true);	    state &= ~CONTROL_RESET;	}	if ((data & 0x40) != 0) {	    state |= CONTROL_SLEEP;	    reset(true);	}	//precomp = (data >>> 2) & 0x07;    }    private void writeData(int data)    {	FloppyDrive drive = getCurrentDrive();	/* Reset Mode */	if ((state & CONTROL_RESET) != 0) {	    System.err.println("fdc >> floppy controller in RESET state!");	    return;	}	state &= ~CONTROL_SLEEP;	if ((dataState & STATE_STATE) == STATE_STATUS) {	    System.err.println("fdc >> can't write data in status mode");	    return;	}	/* Is it write command time? */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -