📄 floppycontroller.java
字号:
/* IO based transfer: calculate len */ raiseIRQ(0x00); return; } private void stopTransfer(byte status0, byte status1, byte status2) { FloppyDrive drive = getCurrentDrive(); fifo[0] = (byte)(status0 | (drive.head << 2) | currentDrive); fifo[1] = status1; fifo[2] = status2; fifo[3] = (byte)drive.track; fifo[4] = (byte)drive.head; fifo[5] = (byte)drive.sector; fifo[6] = SECTOR_SIZE_CODE; dataDirection = DIRECTION_READ; if ((state & CONTROL_BUSY) != 0) { dma.releaseDREQ(DMA_CHANNEL & 3); state &= ~CONTROL_BUSY; } setFIFO(7, true); } private void startTransferDelete(int direction) { stopTransfer((byte)0x60, (byte)0x00, (byte)0x00); } private void formatSector() { System.err.println("Cannot Format Sector"); } private static int memcmp(byte[] a1, byte[] a2, int offset, int length) { for (int i = 0; i < length; i++) { if (a1[i] != a2[i + offset]) return a1[i] - a2[i + offset]; } return 0; } public int transferHandler(int nchan, int pos, int size) { byte status0 = 0x00, status1 = 0x00, status2 = 0x00; if ((state & CONTROL_BUSY) == 0) return 0; FloppyDrive drive = getCurrentDrive(); if ((dataDirection == DIRECTION_SCANE) || (dataDirection == DIRECTION_SCANL) || (dataDirection == DIRECTION_SCANH)) status2 = 0x04; size = Math.min(size, dataLength); if (drive.device == null) { if (dataDirection == DIRECTION_WRITE) stopTransfer((byte)0x60, (byte)0x00, (byte)0x00); else stopTransfer((byte)0x40, (byte)0x00, (byte)0x00); return 0; } int relativeOffset = dataOffset % SECTOR_LENGTH; int startOffset; for (startOffset = dataOffset; dataOffset < size;) { int length = Math.min(size - dataOffset, SECTOR_LENGTH - relativeOffset); if ((dataDirection != DIRECTION_WRITE) || (length < SECTOR_LENGTH) || (relativeOffset != 0)) { /* READ & SCAN commands and realign to a sector for WRITE */ if (drive.read(drive.currentSector(), fifo, 1) < 0) { /* Sure, image size is too small... */ for (int i = 0; i < Math.min(fifo.length, SECTOR_LENGTH); i++) fifo[i] = (byte)0x00; } } switch (dataDirection) { case DIRECTION_READ: /* READ commands */ dma.writeMemory (nchan, fifo, relativeOffset, dataOffset, length); break; case DIRECTION_WRITE: /* WRITE commands */ dma.readMemory (nchan, fifo, relativeOffset, dataOffset, length); if (drive.write(drive.currentSector(), fifo, 1) < 0) { stopTransfer((byte)0x60, (byte)0x00, (byte)0x00); return length; } break; default: /* SCAN commands */ { byte[] tempBuffer = new byte[SECTOR_LENGTH]; dma.readMemory (nchan, tempBuffer, 0, dataOffset, length); int ret = memcmp(tempBuffer, fifo, relativeOffset, length); if (ret == 0) { status2 = 0x08; length = dataOffset - startOffset; if (dataDirection == DIRECTION_SCANE || dataDirection == DIRECTION_SCANL || dataDirection == DIRECTION_SCANH) status2 = 0x08; if ((dataState & STATE_SEEK) != 0) status0 |= 0x20; dataLength -= length; // if (dataLength == 0) stopTransfer(status0, status1, status2); return length; } if ((ret < 0 && dataDirection == DIRECTION_SCANL) || (ret > 0 && dataDirection == DIRECTION_SCANH)) { status2 = 0x00; length = dataOffset - startOffset; if (dataDirection == DIRECTION_SCANE || dataDirection == DIRECTION_SCANL || dataDirection == DIRECTION_SCANH) status2 = 0x08; if ((dataState & STATE_SEEK) != 0) status0 |= 0x20; dataLength -= length; // if (dataLength == 0) stopTransfer(status0, status1, status2); return length; } } break; } dataOffset += length; relativeOffset = dataOffset % SECTOR_LENGTH; if (relativeOffset == 0) { /* Seek to next sector */ /* XXX: drive.sect >= drive.last_sect should be an error in fact */ if ((drive.sector >= drive.lastSector) || (drive.sector == eot)) { drive.sector = 1; if ((dataState & STATE_MULTI) != 0) { if ((drive.head == 0) && ((drive.flags & FloppyDrive.DOUBLE_SIDES) != 0)) { drive.head = 1; } else { drive.head = 0; drive.track++; if ((drive.flags & FloppyDrive.DOUBLE_SIDES) == 0) break; } } else { drive.track++; break; } } else { drive.sector++; } } } int length = dataOffset - startOffset; if (dataDirection == DIRECTION_SCANE || dataDirection == DIRECTION_SCANL || dataDirection == DIRECTION_SCANH) status2 = 0x08; if ((dataState & STATE_SEEK) != 0) status0 |= 0x20; dataLength -= length; // if (dataLength == 0) stopTransfer(status0, status1, status2); return length; } static class FloppyDrive { static final int DRIVE_144 = 0x00; // 1.44 MB 3"5 drive static final int DRIVE_288 = 0x01; // 2.88 MB 3"5 drive static final int DRIVE_120 = 0x02; // 1.2 MB 5"25 drive static final int DRIVE_NONE = 0x03; // No drive connected static final int MOTOR_ON = 0x01; // motor on/off static final int REVALIDATE = 0x02; // Revalidated static final int DOUBLE_SIDES = 0x01; BlockDevice device; int drive; int driveFlags; int perpendicular; int head; int track; int sector; int direction; int readWrite; int flags; int lastSector; int maxTrack; int bps; int readOnly; FloppyFormat format; public FloppyDrive(BlockDevice device) { this.device = device; drive = DRIVE_NONE; driveFlags = 0; perpendicular = 0; lastSector = 0; maxTrack = 0; } public void dumpState(DataOutput output) throws IOException { output.writeInt(drive); output.writeInt(driveFlags); output.writeByte(perpendicular); output.writeByte(head); output.writeByte(track); output.writeByte(sector); output.writeByte(direction); output.writeByte(readWrite); output.writeInt(flags); output.writeByte(lastSector); output.writeInt(maxTrack); output.writeInt(bps); output.writeInt(readOnly); } public void loadState(DataInput input) throws IOException { drive = input.readInt(); driveFlags = input.readInt(); perpendicular = input.readByte(); head = input.readByte(); track = input.readByte(); sector = input.readByte(); direction = input.readByte(); readWrite = input.readByte(); flags = input.readInt(); lastSector = input.readByte(); maxTrack = input.readInt(); bps = input.readInt(); readOnly = input.readInt(); } public void setDrive(org.jpc.support.BlockDevice drive) { device = drive; } public void start() { driveFlags |= MOTOR_ON; } public void stop() { driveFlags &= ~MOTOR_ON; } public int seek(int seekHead, int seekTrack, int seekSector, int enableSeek) { if ((seekTrack > maxTrack) || (seekHead != 0 && (flags & DOUBLE_SIDES) == 0)) return 2; if (seekSector > lastSector) return 3; int fileSector = calculateSector(seekHead, seekTrack, seekSector, lastSector); if (fileSector != currentSector()) { if (enableSeek == 0) return 4; head = seekHead; if (track != seekTrack) { track = seekTrack; sector = seekSector; return 1; } sector = seekSector; } return 0; } public int currentSector() { return calculateSector(head, track, sector, lastSector); } private static int calculateSector(int head, int track, int sector, int lastSector) { return ((((0xff & track) * 2) + (0xff & head)) * (0xff & lastSector)) + (0xff & sector) - 1; } public void recalibrate() { head = 0; track = 0; sector = 1; direction = 1; readWrite = 0; } public int read(int sector, byte[] buffer, int length) { return device.read(0xffffffffl & sector, buffer, length); } public int write(int sector, byte[] buffer, int length) { return device.write(0xffffffffl & sector, buffer, length); } public void reset() { stop(); recalibrate(); } public void revalidate() { driveFlags &= ~REVALIDATE; if (device != null && device.inserted()) { format = FloppyFormat.findFormat(device.getTotalSectors(), drive); if (format.heads() == 1) { flags &= ~DOUBLE_SIDES; } else { flags |= DOUBLE_SIDES; } maxTrack = format.tracks(); lastSector = (byte)format.sectors(); readOnly = device.readOnly() ? 0x1 : 0x0; drive = format.drive(); } else { lastSector = 0; maxTrack = 0; flags &= ~DOUBLE_SIDES; } driveFlags |= REVALIDATE; } public String toString() { return (device == null) ? "<none>" : format.toString(); } } private boolean ioportRegistered; public void reset() { irqDevice = null; clock = null; resultTimer = null; dma = null; //Really Empty? ioportRegistered = false; fifo = new byte[SECTOR_LENGTH]; config = (byte)0x60; /* Implicit Seek, polling & fifo enabled */ drives = new FloppyDrive[2]; state = CONTROL_ACTIVE; } public boolean initialised() { return ((irqDevice != null) && (clock != null) && (dma != null) && (drives[0] != null) && ioportRegistered); } public void acceptComponent(HardwareComponent component) { if ((component instanceof InterruptController) && component.initialised()) irqDevice = (InterruptController)component; if ((component instanceof Clock) && component.initialised()) { clock = (Clock)component; resultTimer = clock.newTimer(this); } if ((component instanceof IOPortHandler) && component.initialised()) { ((IOPortHandler)component).registerIOPortCapable(this); ioportRegistered = true; } if ((component instanceof DMAController) && component.initialised()) { if (((DMAController)component).isFirst()) { if (DMA_CHANNEL != -1) { dma = (DMAController)component; dmaEnabled = true; dma.registerChannel(DMA_CHANNEL & 3, this); } } } if ((component instanceof DriveSet) && component.initialised()) { drives[0] = new FloppyDrive(((DriveSet)component).getFloppyDrive(0)); drives[1] = new FloppyDrive(((DriveSet)component).getFloppyDrive(1)); //Change CB (like in hard drive) } if (initialised()) { reset(false); for (int i = 0; i < 2; i++) if (drives[i] != null) drives[i].revalidate(); } } public boolean updated() { return (irqDevice.updated() && clock.updated() && dma.updated() && drivesUpdated && ioportRegistered); } public void updateComponent(HardwareComponent component) { // if ((component instanceof Clock) && component.updated()) // { // clock = (Clock)component; // resultTimer = clock.newTimer(this); // } if ((component instanceof IOPortHandler) && component.updated()) { ((IOPortHandler)component).registerIOPortCapable(this); ioportRegistered = true; } if ((component instanceof DMAController) && component.updated()) { if (((DMAController)component).isFirst()) { if (DMA_CHANNEL != -1) { //dma = (DMAController)component; dmaEnabled = true; dma.registerChannel(DMA_CHANNEL & 3, this); } } } if ((component instanceof DriveSet) && component.updated()) { drives[0].setDrive(((DriveSet)component).getFloppyDrive(0)); drives[1].setDrive(((DriveSet)component).getFloppyDrive(1)); drivesUpdated = true; } // if (initialised()) // { // reset(false); // for (int i = 0; i < 2; i++) // if (drives[i] != null) drives[i].revalidate(); // } } public String toString() { return "Intel 82078 Floppy Controller [" + drives[0].toString() + ", " + drives[1].toString() + "]"; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -