ne2000core.java

来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 672 行 · 第 1/2 页

JAVA
672
字号
		rx_crc_errors += getReg(NE_P0_CNTR1);
		rx_missed_errors += getReg(NE_P0_CNTR2);
	}

	/**
	 * Process an interrupt caused by an overrun in the receive buffer
	 */
	private void processOverrunInterrupt() {
		log.debug("Receive buffer overrun on " + flags.getName());

		// Was a transmit active?
		final boolean wasInTx = ((getReg(NE_P0_CR) & NE_CR_TXP) != 0);

		// Stop all activity
		setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STP);
		rx_overruns++;

		// Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total
		try {
			Thread.sleep(10);
		} catch (InterruptedException ex) {
			// Ignore
		}

		// Reset RBCR[01] back to zero as per magic incantation.
		setReg(NE_P0_RBCR0, 0);
		setReg(NE_P0_RBCR1, 0);

		// See if any Tx was interrupted or not. According to NS, this
		// step is vital, and skipping it will cause no end of havoc.
		final boolean mustResend;
		if (wasInTx) {
			final int isr = getReg(NE_P0_ISR);
			final boolean txCompleted =
				((isr & (NE_ISR_TXE | NE_ISR_PTX)) != 0);
			mustResend = !txCompleted;
		} else {
			mustResend = false;
		}

		// Have to enter loopback mode and then restart the NIC before
		// you are allowed to slurp packets up off the ring.
		setReg(NE_P0_TCR, NE_TXOFF);
		setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA);

		// Clear the Rx ring of all the debris, and ack the interrupt.
		processReceiveInterrupt();
		setReg(NE_P0_ISR, NE_ISR_OVW);

		// Leave loopback mode, and resend any packet that got stopped
		setReg(NE_P0_TCR, NE_TXCONFIG);
		if (mustResend) {
			setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA | NE_CR_TXP);
		}
	}

	/**
	 * Process an interrupt caused by a received frame with no errors.
	 * Page 0 is assumed!
	 */
	private void processReceiveInterrupt() {
		//log.debug("Receive on " + flags.getName());

		// Get receive status
		boolean rc;
		do {
			rc = readPacket();
		} while (rc);
	}

	/**
	 * Read a single packet from the receive buffer
	 * @return true on succesfull packet read, false otherwise
	 */
	private boolean readPacket() {

		final int rsr = getReg(NE_P0_RSR);
		if ((rsr & (NE_RSR_PRX | NE_RSR_MPA)) == 0) {
			log.debug("No valid packet, rsr=0x" + NumberUtils.hex(rsr, 2));
			// Not valid packet
			return false;
		}

		// Where to start reading?
		int next = getReg(NE_P0_BOUND) + 1;
		if (next >= rx_end) {
			next = rx_start;
		}
		setReg(NE_P0_CR, NE_CR_PS1);
		int curr = getReg(NE_P1_CURR);
		setReg(NE_P0_CR, NE_CR_PS0);
		if (curr == next) {
			//log.debug("No valid packet, curr==next, rsr=0x" + NumberUtils.hex(rsr, 2) + ", curr=0x" + NumberUtils.hex(curr, 2));
			return false;
		}

		// Get the packet header
		final Ne2000PacketHeader hdr = getHeader(next);
		//log.debug("curr=0x" + NumberUtils.hex(curr, 2) + ", next=0x" + NumberUtils.hex(next, 2) + ", hdr=" + hdr);
		final int len = hdr.getLength();
		final byte[] bbuf = new byte[len + 1]; // +1, to allow 16-bit transfer

		// Where should we start reading
		final int nicAddr = (next << 8) + 4;
		// First page also contains 4-byte header

		if ((nicAddr + len) > (rx_end << 8)) {
			// Packet is wrapper over the end of the receive buffer
			// Get first part
			final int len1 = (rx_end << 8) - nicAddr;
			getNicData(nicAddr, bbuf, 0, len1);
			// Get second part
			final int len2 = len - len1;
			final int nicAddr2 = (rx_start << 8);
			getNicData(nicAddr2, bbuf, len1, len2);
		} else {
			// We can get the buffer in a single action
			getNicData(nicAddr, bbuf, 0, len);
		}
		final SocketBuffer buf = new SocketBuffer(bbuf, 0, len);

		// Calculate the next bound value
		final int nextBound = hdr.getNextPacketPage() - 1;
		// Set the next bound value
		if (nextBound < rx_start) {
			setReg(NE_P0_BOUND, rx_end - 1);
		} else {
			setReg(NE_P0_BOUND, nextBound);
		}

		//log.debug("curr=" + curr + ", next=" + next + ", nextBound=" + nextBound + ", length=" + len + ", hdr.next=" + hdr.getNextPacketPage());

		// Process the packet
		try {
			driver.onReceive(buf);
		} catch (NetworkException ex) {
			log.error("Error in onReceive", ex);
		}
		//log.debug("Received packet length:" + buf.getSize() + ", src:" + srcAddr + ", dst:" + dstAddr + ", data:\n" + NumberUtils.hex(buf.getBuffer(), buf.getBufferOffset(), buf.getSize()));
		return true;
	}

	/**
	 * Process an interrupt caused by a transmitted frame with no errors.
	 */
	private void processTransmitInterrupt() {
		tx_active = false;
		notifyAll();
		//log.debug("Transmit success on " + flags.getName());
	}

	/**
	 * Process an interrupt caused by an error in transmitting a frame 
	 */
	private void processTransmitErrorInterrupt() {
		tx_active = false;
		notifyAll();
		log.debug("Transmit error on " + flags.getName());
	}

	/**
	 * Reset the device
	 */
	private void reset() {
		// Trigger reset
		io.outPortByte(iobase + NE_RESET, io.inPortByte(iobase + NE_RESET));
		while ((io.inPortByte(iobase + NE_P0_ISR) & NE_ISR_RST) == 0) {
			Thread.yield();
		}
		// Reset Interrupt flags
		io.outPortByte(iobase + NE_P0_ISR, 0xff);
	}

	/**
	 * Read data from the NIC 
	 * @param nicSrcAddress
	 * @param dst
	 * @param length
	 */
	private void getNicData(
		int nicSrcAddress,
		byte[] dst,
		int dstOffset,
		int length) {

		if (flags.is16bit()) {
			length = (length + 1) & ~1;
		}

		setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA);
		setReg(NE_P0_RSAR0, nicSrcAddress & 0xFF);
		setReg(NE_P0_RSAR1, (nicSrcAddress >> 8) & 0xFF);
		setReg(NE_P0_RBCR0, length & 0xFF);
		setReg(NE_P0_RBCR1, (length >> 8) & 0xFF);
		setReg(NE_P0_CR, NE_CR_RREAD | NE_CR_PS0 | NE_CR_STA);

		if (flags.is16bit()) {
			for (int i = 0; i < length; i += 2) {
				final int v = io.inPortWord(iobase + NE_DATA);
				dst[dstOffset + i + 0] = (byte) (v & 0xFF);
				dst[dstOffset + i + 1] = (byte) ((v >> 8) & 0xFF);
			}
		} else {
			for (int i = 0; i < length; i += 2) {
				final int v = io.inPortByte(iobase + NE_DATA);
				dst[dstOffset + i] = (byte)v;
			}
		}
		setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA);
	}

	/**
	 * Read data from the NIC
	 * @param skbuf
	 * @param skbufOffset 
	 * @param nicDstAddress
	 * @param length
	 */
	protected void setNicData(
		SocketBuffer skbuf,
		int skbufOffset,
		int nicDstAddress,
		int length) {

		final int origLength = length;
		if (flags.is16bit()) {
			length = (length + 1) & ~1;
		}

		setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA);
		setReg(NE_P0_RSAR0, nicDstAddress & 0xFF);
		setReg(NE_P0_RSAR1, (nicDstAddress >> 8) & 0xFF);
		setReg(NE_P0_RBCR0, length & 0xFF);
		setReg(NE_P0_RBCR1, (length >> 8) & 0xFF);
		setReg(NE_P0_CR, NE_CR_RWRITE | NE_CR_PS0 | NE_CR_STA);

		if (flags.is16bit()) {
			int i;
			for (i = 0; (i+1) < origLength; i += 2) {
				//final int v0 = src[srcOffset + i + 0] & 0xFF;
				//final int v1 = src[srcOffset + i + 1] & 0xFF;
				final int v0 = skbuf.get(skbufOffset + i + 0);
				final int v1 = skbuf.get(skbufOffset + i + 1);
				io.outPortWord(iobase + NE_DATA, (v1 << 8) | v0);
			}
			if (i < origLength) {
				// The last byte
				final int v0 = skbuf.get(skbufOffset + i + 0);
				io.outPortWord(iobase + NE_DATA, v0);
			}
		} else {
			for (int i = 0; i < length; i++) {
				io.outPortByte(iobase + NE_DATA, skbuf.get(skbufOffset + i));
			}
		}
		setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA);
	}

	/**
	 * Read a packet header starting at a given page
	 * @param page
	 */
	private Ne2000PacketHeader getHeader(int page) {
		final byte[] buf = new byte[4];
		getNicData(page << 8, buf, 0, buf.length);
		return new Ne2000PacketHeader(buf, 0);
	}

	/**
	 * Gets the value of a register
	 * @param reg
	 */
	private int getReg(int reg) {
		return io.inPortByte(iobase + reg);
	}

	/**
	 * Gets the value of a register
	 * @param reg
	 * @param value
	 */
	private void setReg(int reg, int value) {
		io.outPortByte(iobase + reg, value);
	}

	/**
	 * Gets the ethernet address of this device.
	 */
	public final HardwareAddress getHwAddress() {
		return hwAddress;
	}

	/**
	 * Figure out the start page of the NIC's memory and the size of this memory
	 */
	private int probeNicMemoryStart() throws DriverException {
		final SocketBuffer testBuf = new SocketBuffer();
		final byte[] testData =
			new byte[] {
				(byte)0x23,
				(byte)0x34,
				(byte)0x56,
				(byte)0xf3,
				(byte)0x72,
				(byte)0xa6,
				(byte)0xe2,
				(byte)0xa1,
				(byte)0x23,
				(byte)0x34,
				(byte)0x56,
				(byte)0xf3,
				(byte)0x72,
				(byte)0xa6,
				(byte)0xe2,
				(byte)0xa1 };
		final byte[] returnData = new byte[testData.length];
		testBuf.append(testData, 0, testData.length);

		for (int page = 0; page < 256; page += 16) {
			setNicData(testBuf, 0, (page << 8), testData.length);
			getNicData((page << 8), returnData, 0, testData.length);

			if (Arrays.equals(testData, returnData)) {
				//log.debug("Found start page " + page);
				return page;
			}

			//log.debug("Got (on page " + page + "): " + NumberUtils.hex(returnData, 0, returnData.length));

		}
		throw new DriverException(
			"Cannot find NIC memory of " + flags.getName());
	}

}

⌨️ 快捷键说明

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