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

📄 floppycontroller.java

📁 JPC: x86 PC Hardware Emulator. 牛津大学开发的一个纯JAVA的x86系统结构硬件模拟器。
💻 JAVA
📖 第 1 页 / 共 3 页
字号:
	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 + -