📄 ethernetcard.java
字号:
/* 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.pci.peripheral;import org.jpc.emulator.pci.*;import org.jpc.support.EthernetOutput;import org.jpc.emulator.motherboard.IOPortHandler;import java.io.*;public class EthernetCard extends AbstractPCIDevice{ //Static Device Constants private static final int MAX_ETH_FRAME_SIZE = 1514; private static final int E8390_CMD = 0x00; // The command register (for all pages) */ /* Page 0 register offsets. */ private static final int EN0_CLDALO = 0x01; // Low byte of current local dma addr RD */ private static final int EN0_STARTPG= 0x01; // Starting page of ring bfr WR */ private static final int EN0_CLDAHI = 0x02; // High byte of current local dma addr RD */ private static final int EN0_STOPPG = 0x02; // Ending page +1 of ring bfr WR */ private static final int EN0_BOUNDARY = 0x03; // Boundary page of ring bfr RD WR */ private static final int EN0_TSR = 0x04; // Transmit status reg RD */ private static final int EN0_TPSR = 0x04; // Transmit starting page WR */ private static final int EN0_NCR = 0x05; // Number of collision reg RD */ private static final int EN0_TCNTLO = 0x05; // Low byte of tx byte count WR */ private static final int EN0_FIFO = 0x06; // FIFO RD */ private static final int EN0_TCNTHI = 0x06; // High byte of tx byte count WR */ private static final int EN0_ISR = 0x07; // Interrupt status reg RD WR */ private static final int EN0_CRDALO = 0x08; // low byte of current remote dma address RD */ private static final int EN0_RSARLO = 0x08; // Remote start address reg 0 */ private static final int EN0_CRDAHI = 0x09; // high byte, current remote dma address RD */ private static final int EN0_RSARHI = 0x09; // Remote start address reg 1 */ private static final int EN0_RCNTLO = 0x0a; // Remote byte count reg WR */ private static final int EN0_RCNTHI = 0x0b; // Remote byte count reg WR */ private static final int EN0_RSR = 0x0c; // rx status reg RD */ private static final int EN0_RXCR = 0x0c; // RX configuration reg WR */ private static final int EN0_TXCR = 0x0d; // TX configuration reg WR */ private static final int EN0_COUNTER0 = 0x0d; // Rcv alignment error counter RD */ private static final int EN0_DCFG = 0x0e; // Data configuration reg WR */ private static final int EN0_COUNTER1 = 0x0e; // Rcv CRC error counter RD */ private static final int EN0_IMR = 0x0f; // Interrupt mask reg WR */ private static final int EN0_COUNTER2 = 0x0f; // Rcv missed frame error counter RD */ private static final int EN1_PHYS = 0x11; private static final int EN1_CURPAG = 0x17; private static final int EN1_MULT = 0x18; /* Register accessed at EN_CMD, the 8390 base addr. */ private static final byte E8390_STOP = (byte)0x01; // Stop and reset the chip */ private static final byte E8390_START = (byte)0x02; // Start the chip, clear reset */ private static final byte E8390_TRANS = (byte)0x04; // Transmit a frame */ private static final byte E8390_RREAD = (byte)0x08; // Remote read */ private static final byte E8390_RWRITE = (byte)0x10; // Remote write */ private static final byte E8390_NODMA = (byte)0x20; // Remote DMA */ private static final byte E8390_PAGE0 = (byte)0x00; // Select page chip registers */ private static final byte E8390_PAGE1 = (byte)0x40; // using the two high-order bits */ private static final byte E8390_PAGE2 = (byte)0x80; // Page 3 is invalid. */ /* Bits in EN0_ISR - Interrupt status register */ private static final byte ENISR_RX = (byte)0x01; // Receiver, no error */ private static final byte ENISR_TX = (byte)0x02; // Transmitter, no error */ private static final byte ENISR_RX_ERR = (byte)0x04; // Receiver, with error */ private static final byte ENISR_TX_ERR = (byte)0x08; // Transmitter, with error */ private static final byte ENISR_OVER = (byte)0x10; // Receiver overwrote the ring */ private static final byte ENISR_COUNTERS = (byte)0x20; // Counters need emptying */ private static final byte ENISR_RDC = (byte)0x40; // remote dma complete */ private static final byte ENISR_RESET = (byte)0x80; // Reset completed */ private static final byte ENISR_ALL = (byte)0x3f; // Interrupts we will enable */ /* Bits in received packet status byte and EN0_RSR*/ private static final byte ENRSR_RXOK= (byte)0x01; // Received a good packet */ private static final byte ENRSR_CRC = (byte)0x02; // CRC error */ private static final byte ENRSR_FAE = (byte)0x04; // frame alignment error */ private static final byte ENRSR_FO = (byte)0x08; // FIFO overrun */ private static final byte ENRSR_MPA = (byte)0x10; // missed pkt */ private static final byte ENRSR_PHY = (byte)0x20; // physical/multicast address */ private static final byte ENRSR_DIS = (byte)0x40; // receiver disable. set in monitor mode */ private static final byte ENRSR_DEF = (byte)0x80; // deferring */ /* Transmitted packet status, EN0_TSR. */ private static final byte ENTSR_PTX = (byte)0x01; // Packet transmitted without error */ private static final byte ENTSR_ND = (byte)0x02; // The transmit wasn't deferred. */ private static final byte ENTSR_COL = (byte)0x04; // The transmit collided at least once. */ private static final byte ENTSR_ABT = (byte)0x08; // The transmit collided 16 times, and was deferred. */ private static final byte ENTSR_CRS = (byte)0x10; // The carrier sense was lost. */ private static final byte ENTSR_FU = (byte)0x20; // A "FIFO underrun" occurred during transmit. */ private static final byte ENTSR_CDH = (byte)0x40; // The collision detect "heartbeat" signal was lost. */ private static final byte ENTSR_OWC = (byte)0x80; // There was an out-of-window collision. */ private static final int NE2000_PMEM_SIZE = (32*1024); private static final int NE2000_PMEM_START = (16*1024); private static final int NE2000_PMEM_END = (NE2000_PMEM_SIZE+NE2000_PMEM_START); private static final int NE2000_MEM_SIZE = NE2000_PMEM_END; private static boolean DEBUG = false; //Instance (State) Properties private byte command; private int start; private int stop; private byte boundary; private byte tsr; private byte tpsr; private short tcnt; private short rcnt; private int rsar; private byte rsr; private byte isr; private byte dcfg; private byte imr; private byte phys[]; /* mac address */ private byte curpag; private byte mult[]; /* multicast mask array */ private int irq; EthernetOutput outputDevice; private ByteBuffer mem; private EthernetIORegion ioRegion; public EthernetCard() { this(null); } public EthernetCard(EthernetOutput output) { setIRQIndex(16); putConfigByte(0x00, (byte)0xec); // Realtek 8029 putConfigByte(0x01, (byte)0x10); putConfigByte(0x02, (byte)0x29); putConfigByte(0x03, (byte)0x80); putConfigByte(0x0a, (byte)0x00); // ethernet network controller putConfigByte(0x0b, (byte)0x02); putConfigByte(0x0e, (byte)0x00); // header_type putConfigByte(0x3d, (byte)0x01); // interrupt pin 0 ioRegion = new EthernetIORegion(); outputDevice = output; mem = new ByteBuffer(NE2000_MEM_SIZE); phys = new byte[6]; mult = new byte[8]; this.internalReset(); //dodgy ref to this? } public void dumpState(DataOutput output) throws IOException { output.writeByte(command); output.writeInt(start); output.writeInt(stop); output.writeByte(boundary); output.writeByte(tsr); output.writeByte(tpsr); output.writeShort(tcnt); output.writeShort(rcnt); output.writeInt(rsar); output.writeByte(rsr); output.writeByte(isr); output.writeByte(dcfg); output.writeByte(imr); output.writeInt(phys.length); output.write(phys); output.writeByte(curpag); output.writeInt(mult.length); output.write(mult); output.writeInt(irq); byte[] temp = new byte[mem.size()]; output.writeInt(mem.size()); mem.get(0, temp, 0, temp.length); output.write(temp); ioRegion.dumpState(output); //dump output device //apparently this is another whole kettle of fish... so let's ignore it } public void loadState(DataInput input) throws IOException { command = input.readByte(); start = input.readInt(); stop = input.readInt(); boundary = input.readByte(); tsr = input.readByte(); tpsr = input.readByte(); tcnt = input.readShort(); rcnt = input.readShort(); rsar = input.readInt(); rsr = input.readByte(); isr = input.readByte(); dcfg = input.readByte(); imr = input.readByte(); int len = input.readInt(); phys = new byte[len]; input.readFully(phys,0,len); curpag = input.readByte(); len = input.readInt(); mult = new byte[len]; input.readFully(mult,0,len); irq = input.readInt(); len = input.readInt(); mem = new ByteBuffer(len); byte[] buffer = new byte[len]; input.readFully(buffer,0,len); mem.set(buffer,0,0,buffer.length); ioRegion.loadState(input); //load output device //apparently this is another whole kettle of fish... so let's ignore it } public void loadIOPorts(IOPortHandler ioportHandler, DataInput input) throws IOException { loadState(input); ioportHandler.registerIOPortCapable(ioRegion); } public void reset() { putConfigByte(0x00, (byte)0xec); // Realtek 8029 putConfigByte(0x01, (byte)0x10); putConfigByte(0x02, (byte)0x29); putConfigByte(0x03, (byte)0x80); putConfigByte(0x0a, (byte)0x00); // ethernet network controller putConfigByte(0x0b, (byte)0x02); putConfigByte(0x0e, (byte)0x00); // header_type putConfigByte(0x3d, (byte)0x01); // interrupt pin 0 mem = new ByteBuffer(NE2000_MEM_SIZE); phys = new byte[6]; mult = new byte[8]; internalReset(); super.reset(); } private void internalReset() { this.setISR(ENISR_RESET); mem.set(0x0e, (byte)0x57); mem.set(0x0f, (byte)0x57); for (int i = 15; i >=0; i--) { mem.set(2*i, mem.get(i)); mem.set(2*i+1, mem.get(i)); } } private void updateIRQ() { int isr = this.getISR() & this.getIMR(); if (isr != 0) this.getIRQBouncer().setIRQ(this, 0, 1); else this.getIRQBouncer().setIRQ(this, 0, 0); } private int canReceive(){return 0;} //PCIDevice Methods //IOPort Registration Aids public IORegion[] getIORegions() { return new IORegion[]{ioRegion}; } public IORegion getIORegion(int index) { if (index == 0) return ioRegion; else return null; } class EthernetIORegion implements IOPortIORegion { private int address; public EthernetIORegion() { address = -1; } public void dumpState(DataOutput output) throws IOException { output.writeInt(address); } public void loadState(DataInput input) throws IOException { address = input.readInt(); } public void acceptComponent(org.jpc.emulator.HardwareComponent component) {} public boolean initialised() {return true;} public void updateComponent(org.jpc.emulator.HardwareComponent component) {} public boolean updated() {return true;} public void reset(){} //IORegion Methods public int getAddress() { return address; } public long getSize() { return 0x100; } public int getType() { return PCI_ADDRESS_SPACE_IO; } public int getRegionNumber() { return 0; } public void setAddress(int address) { this.address = address; } //IOPortCapable Methods public void ioPortWriteByte(int address, int data) { switch(address - this.getAddress()) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: EthernetCard.this.ioPortWrite(address, (byte)data); break; case 0x10: // May do a 16 bit write, so must only narrow to short EthernetCard.this.asicIOPortWriteByte(address, (short)data); break; case 0x1f: //this.resetIOPortWrite(address); //end of reset pulse break; default: break; } } public void ioPortWriteWord(int address, int data) { switch(address - this.getAddress()) { case 0x10: case 0x11: EthernetCard.this.asicIOPortWriteWord(address, (short)data); break; default: // should do two byte access break; } } public void ioPortWriteLong(int address, int data) { switch(address - this.getAddress()) { case 0x10: case 0x11: case 0x12: case 0x13: EthernetCard.this.asicIOPortWriteLong(address, data); break; default: break; } } public int ioPortReadByte(int address) { switch(address - this.getAddress()) { case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x05: case 0x06: case 0x07: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: case 0x0e: case 0x0f: return EthernetCard.this.ioPortRead(address); case 0x10: return 0xffff & EthernetCard.this.asicIOPortReadByte(address); case 0x1f: return EthernetCard.this.resetIOPortRead(address); default: return (byte)0xff; } } public int ioPortReadWord(int address) { switch(address - this.getAddress()) { case 0x10: case 0x11: return EthernetCard.this.asicIOPortReadWord(address); default: return (short)0xffff; //should do two byte access } } public int ioPortReadLong(int address) { switch(address - this.getAddress()) { case 0x10: case 0x11: case 0x12: case 0x13: return EthernetCard.this.asicIOPortReadLong(address); default: return (int)0xffffffff; } }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -