📄 floppycontroller.java
字号:
if ((dataState & STATE_STATE) == STATE_DATA) { /* FIFO data write */ fifo[dataOffset++] = (byte)data; if (dataOffset % SECTOR_LENGTH == (SECTOR_LENGTH -1) || dataOffset == dataLength) drive.write(drive.currentSector(), fifo, SECTOR_LENGTH); /* 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); return; } if (dataOffset == 0) { /* Command */ switch (data & 0x5f) { case 0x46: case 0x4c: case 0x50: case 0x56: case 0x59: case 0x5d: dataLength = 9; enqueue(drive, data); return; default: break; } switch (data & 0x7f) { case 0x45: case 0x49: dataLength = 9; enqueue(drive, data); return; default: break; } switch (data) { case 0x03: case 0x0f: dataLength = 3; enqueue(drive, data); return; case 0x04: case 0x07: case 0x12: case 0x33: case 0x4a: dataLength = 2; enqueue(drive, data); return; case 0x08: fifo[0] = (byte)(0x20 | (drive.head << 2) | currentDrive); fifo[1] = (byte)drive.track; setFIFO(2, false); resetIRQ(); interruptStatus = 0xc0; return; case 0x0e: /* Drives position */ fifo[0] = (byte)getDrive(0).track; fifo[1] = (byte)getDrive(1).track; fifo[2] = 0; fifo[3] = 0; /* timers */ fifo[4] = timer0; fifo[5] = dmaEnabled ? (byte)(timer1 << 1) : (byte)0; fifo[6] = (byte)drive.lastSector; fifo[7] = (byte)((lock << 7) | (drive.perpendicular << 2)); fifo[8] = config; fifo[9] = preCompensationTrack; setFIFO(10, false); return; case 0x10: fifo[0] = CONTROLLER_VERSION; setFIFO(1,true); return; case 0x13: dataLength = 4; enqueue(drive, data); return; case 0x14: lock = 0; fifo[0] = 0; setFIFO(1, false); return; case 0x17: case 0x8f: case 0xcf: dataLength = 3; enqueue(drive, data); return; case 0x18: fifo[0] = 0x41; /* Stepping 1 */ setFIFO(1, false); return; case 0x2c: fifo[0] = 0; fifo[1] = 0; fifo[2] = (byte)getDrive(0).track; fifo[3] = (byte)getDrive(1).track; fifo[4] = 0; fifo[5] = 0; fifo[6] = timer0; fifo[7] = timer1; fifo[8] = (byte)drive.lastSector; fifo[9] = (byte)((lock << 7) | (drive.perpendicular << 2)); fifo[10] = config; fifo[11] = preCompensationTrack; fifo[12] = pwrd; fifo[13] = 0; fifo[14] = 0; setFIFO(15, true); return; case 0x42: dataLength = 9; enqueue(drive, data); return; case 0x4c: dataLength = 18; enqueue(drive, data); return; case 0x4d: case 0x8e: dataLength = 6; enqueue(drive, data); return; case 0x94: lock = 1; fifo[0] = 0x10; setFIFO(1, true); return; case 0xcd: dataLength = 11; enqueue(drive, data); return; default: /* Unknown command */ unimplemented(); return; } } enqueue(drive, data); } private void enqueue(FloppyDrive drive, int data) { fifo[dataOffset] = (byte)data; if (++dataOffset == dataLength) { if ((dataState & STATE_FORMAT) != 0) { formatSector(); return; } switch (fifo[0] & 0x1f) { case 0x06: startTransfer(DIRECTION_READ); return; case 0x0c: startTransferDelete(DIRECTION_READ); return; case 0x16: stopTransfer((byte)0x20, (byte)0x00, (byte)0x00); return; case 0x10: startTransfer(DIRECTION_SCANE); return; case 0x19: startTransfer(DIRECTION_SCANL); return; case 0x1d: startTransfer(DIRECTION_SCANH); return; default: break; } switch (fifo[0] & 0x3f) { case 0x05: startTransfer(DIRECTION_WRITE); return; case 0x09: startTransferDelete(DIRECTION_WRITE); return; default: break; } switch (fifo[0]) { case 0x03: timer0 = (byte)((fifo[1] >>> 4) & 0xf); timer1 = (byte)(fifo[2] >>> 1); dmaEnabled = ((fifo[2] & 1) != 1); resetFIFO(); break; case 0x04: currentDrive = fifo[1] & 1; drive = getCurrentDrive(); drive.head = ((fifo[1] >>> 2) & 1); fifo[0] = (byte)((drive.readOnly << 6) | (drive.track == 0 ? 0x10 : 0x00) | (drive.head << 2) | currentDrive | 0x28); setFIFO(1, false); break; case 0x07: currentDrive = fifo[1] & 1; drive = getCurrentDrive(); drive.recalibrate(); resetFIFO(); raiseIRQ(0x20); break; case 0x0f: currentDrive = fifo[1] & 1; drive = getCurrentDrive(); drive.start(); if (fifo[2] <= drive.track) drive.direction = 1; else drive.direction = 0; resetFIFO(); if (fifo[2] > drive.maxTrack) raiseIRQ(0x60); else { drive.track = fifo[2]; raiseIRQ(0x20); } break; case 0x12: if ((fifo[1] & 0x80) != 0) drive.perpendicular = fifo[1] & 0x7; /* No result back */ resetFIFO(); break; case 0x13: config = fifo[2]; preCompensationTrack = fifo[3]; /* No result back */ resetFIFO(); break; case 0x17: pwrd = fifo[1]; fifo[0] = fifo[1]; setFIFO(1, true); break; case 0x33: /* No result back */ resetFIFO(); break; case 0x42: System.err.println("fdc >> treat READ_TRACK command"); startTransfer(DIRECTION_READ); break; case 0x4A: /* XXX: should set main status register to busy */ drive.head = (fifo[1] >>> 2) & 1; resultTimer.setExpiry(clock.getTime() + (clock.getTickRate()/50)); break; case 0x4C: /* RESTORE */ /* Drives position */ getDrive(0).track = fifo[3]; getDrive(1).track = fifo[4]; /* timers */ timer0 = fifo[7]; timer1 = fifo[8]; drive.lastSector = fifo[9]; lock = (byte)(fifo[10] >>> 7); drive.perpendicular = (fifo[10] >>> 2) & 0xf; config = fifo[11]; preCompensationTrack = fifo[12]; pwrd = fifo[13]; resetFIFO(); break; case 0x4D: /* FORMAT_TRACK */ currentDrive = fifo[1] & 1; drive = getCurrentDrive(); dataState |= STATE_FORMAT; if ((fifo[0] & 0x80) != 0) dataState |= STATE_MULTI; else dataState &= ~STATE_MULTI; dataState &= ~STATE_SEEK; drive.bps = fifo[2] > 7 ? 0x4000 : (0x80 << fifo[2]); drive.lastSector = fifo[3]; /* Bochs BIOS is buggy and don't send format informations * for each sector. So, pretend all's done right now... */ dataState &= ~STATE_FORMAT; stopTransfer((byte)0x00, (byte)0x00, (byte)0x00); break; case (byte)0x8E: /* DRIVE_SPECIFICATION_COMMAND */ if ((fifo[dataOffset - 1] & 0x80) != 0) { /* Command parameters done */ if ((fifo[dataOffset - 1] & 0x40) != 0) { fifo[0] = fifo[1]; fifo[2] = 0; fifo[3] = 0; setFIFO(4, true); } else resetFIFO(); } else if (dataLength > 7) { /* ERROR */ fifo[0] = (byte)(0x80 | (drive.head << 2) | currentDrive); setFIFO(1, true); } break; case (byte)0x8F: /* RELATIVE_SEEK_OUT */ currentDrive = fifo[1] & 1; drive = getCurrentDrive(); drive.start(); drive.direction = 0; if (fifo[2] + drive.track >= drive.maxTrack) drive.track = drive.maxTrack - 1; else drive.track += fifo[2]; resetFIFO(); raiseIRQ(0x20); break; case (byte)0xCD: /* FORMAT_AND_WRITE */ System.err.println("fdc >> treat FORMAT_AND_WRITE command"); unimplemented(); break; case (byte)0xCF: /* RELATIVE_SEEK_IN */ currentDrive = fifo[1] & 1; drive = getCurrentDrive(); drive.start(); drive.direction = 1; if (fifo[2] > drive.track) drive.track = 0; else drive.track -= fifo[2]; resetFIFO(); /* Raise Interrupt */ raiseIRQ(0x20); break; } } } private void setFIFO(int fifoLength, boolean doIRQ) { dataDirection = DIRECTION_READ; dataLength = fifoLength; dataOffset = 0; dataState = (dataState & ~STATE_STATE) | STATE_STATUS; if (doIRQ) raiseIRQ(0x00); } private FloppyDrive getCurrentDrive() { return getDrive(currentDrive); } private FloppyDrive getDrive(int driveNumber) { return drives[driveNumber - bootSelect]; } public void setDrive(org.jpc.support.BlockDevice drive, int i) { if ((i < 0 ) || (i > drives.length -1)) return; getDrive(i).setDrive(drive); getDrive(i).revalidate(); //do we need to call revalidate() on the drive as well? } private void unimplemented() { fifo[0] = (byte)0x80; setFIFO(1, false); } private void startTransfer(int direction) { currentDrive = fifo[1] & 1; FloppyDrive drive = getCurrentDrive(); byte kt = fifo[2]; byte kh = fifo[3]; byte ks = fifo[4]; boolean didSeek = false; switch (drive.seek(0xff & kh, 0xff & kt, 0xff & ks, drive.lastSector)) { case 2: /* sect too big */ stopTransfer((byte)0x40, (byte)0x00, (byte)0x00); fifo[3] = kt; fifo[4] = kh; fifo[5] = ks; return; case 3: /* track too big */ stopTransfer((byte)0x40, (byte)0x80, (byte)0x00); fifo[3] = kt; fifo[4] = kh; fifo[5] = ks; return; case 4: /* No seek enabled */ stopTransfer((byte)0x40, (byte)0x00, (byte)0x00); fifo[3] = kt; fifo[4] = kh; fifo[5] = ks; return; case 1: didSeek = true; break; default: break; } dataDirection = direction; dataOffset = 0; dataState = (dataState & ~STATE_STATE) | STATE_DATA; if ((fifo[0] & 0x80) != 0) dataState |= STATE_MULTI; else dataState &= ~STATE_MULTI; if (didSeek) dataState |= STATE_SEEK; else dataState &= ~STATE_SEEK; if (fifo[5] == 0x00) { dataLength = fifo[8]; } else { dataLength = 128 << fifo[5]; int temp = drive.lastSector - ks + 1; if ((fifo[0] & 0x80) != 0) temp += drive.lastSector; dataLength *= temp; } eot = fifo[6]; if (dmaEnabled) { int dmaMode = 0; dmaMode = dma.getChannelMode(DMA_CHANNEL & 3); dmaMode = (dmaMode >>> 2) & 3; if (((direction == DIRECTION_SCANE || direction == DIRECTION_SCANL || direction == DIRECTION_SCANH) && dmaMode == 0) || (direction == DIRECTION_WRITE && dmaMode == 2) || (direction == DIRECTION_READ && dmaMode == 1)) { /* No access is allowed until DMA transfer has completed */ state |= CONTROL_BUSY; /* Now, we just have to wait for the DMA controller to * recall us... */ dma.holdDREQ(DMA_CHANNEL & 3); return; } else { System.err.println("fdc >> dma_mode=" + dmaMode + " direction="+ direction); } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -