rtl8139core.java

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

JAVA
695
字号
	}

	/**
	 * Release all resources
	 */
	public void release() {
		io.release();
		irq.release();
	}

	/**
	 * Transmit the given buffer
	 * 
	 * @param buf
	 * @param timeout
	 * @throws InterruptedException
	 * @throws TimeoutException
	 */
	public void transmit(SocketBuffer buf, long timeout) throws InterruptedException, TimeoutException {
		// Set the source address
		hwAddress.writeTo(buf, 6);
		//tx_active = true;

		txNumberOfPackets++;
		// Set the address of the txBuffer

		setReg32(REG_CFG9346, CFG9346_WE);

		// this should be a bug fix, but looking (in Ethereal) at the packes send
		// indicate on my card that this is not true
		// Martin
		/*
		 * if (txIndex == 0) { txBuffers[0].initialize(buf); setReg32(REG_TX_STATUS0, txFlag |
		 * buf.getSize());
		 * 
		 * txBuffers[1].initialize(buf); setReg32(REG_TX_STATUS0 + 4, txFlag | buf.getSize());
		 * 
		 * txIndex = 2; } else {
		 */
		txBuffers[txIndex].initialize(buf);

		setReg32(REG_TX_STATUS0 + 4 * txIndex, txFlag | buf.getSize());

		// Point to the next empty descriptor
		txIndex++;
		txIndex &= 3;
		//    }

		setReg32(REG_CFG9346, CFG9346_NORMAL);
	}

	/**
	 * Handle a given hardware interrupt. This method is called from the kernel with interrupts
	 * disabled. So keep and handling here as short as possible!
	 */
	public void handleInterrupt(int irq) {
		int bogusCount = 20;
		// Keep processing interrupts until there are none to process
		boolean linkChanged = false;

		while (true) {
			int status = getReg16(REG_INTR_STATUS);

			if (status == 0xffff) {
				break;
			}

			// See if anything needs servicing
			if ((status
				& (INTR_RX_OK | INTR_RX_ERR | INTR_TX_OK | INTR_TX_ERR | INTR_RX_BUF_OVRFLO | INTR_RX_FIFO_OVRFLO | INTR_TIMEOUT | INTR_SYS_ERR | INTR_RX_UNDERRUN | INTR_LEN_CHG))
				== 0) {
				break;
			}

			if ((status & INTR_RX_UNDERRUN) == INTR_RX_UNDERRUN) {
				linkChanged = (getReg16(REG_CSCR) & CSCR_LINKCHANGE) == CSCR_LINKCHANGE;
				if (linkChanged) {
					log.debug("Link changed");
				}
			}

			if ((status & INTR_RX_FIFO_OVRFLO) == INTR_RX_FIFO_OVRFLO) {
				setReg16(REG_INTR_STATUS, status | INTR_RX_BUF_OVRFLO);
			} else {
				setReg16(REG_INTR_STATUS, status);
			}

			// Process tx interrupts
			if ((status & (INTR_TX_OK | INTR_TX_ERR)) != 0) {
				txProcess(status);
			}

			// Process rx interrupts
			if ((status & (INTR_RX_OK | INTR_RX_FIFO_OVRFLO | INTR_RX_BUF_OVRFLO)) != 0) {
				rxProcess(status);
			}

			// Process the other errors
			if ((status & (INTR_RX_ERR | INTR_TX_ERR | INTR_RX_BUF_OVRFLO | INTR_RX_FIFO_OVRFLO | INTR_TIMEOUT | INTR_SYS_ERR | INTR_RX_UNDERRUN)) != 0) {
				errorInterrupt(status);

				//        log.debug(" error Interupt "+status);
			}
			if (--bogusCount < 0) {
				setReg16(REG_INTR_STATUS, 0xffff);

				break;
			}
		}
	}

	private void errorInterrupt(int status) {
		// Tally the missed packets and zero the counter
		setReg32(REG_RX_MISSED, 0);

		if ((status & (INTR_RX_UNDERRUN | INTR_RX_BUF_OVRFLO | INTR_RX_FIFO_OVRFLO | INTR_RX_ERR)) != 0) {
			//      rxErrors++;
		}
		if ((status & INTR_RX_FIFO_OVRFLO) != 0) {
			//    rxFifoOverflow++;
		}
		if ((status & INTR_RX_UNDERRUN) != 0) {
			//      rxUnderRun++;
		}
		if ((status & INTR_RX_BUF_OVRFLO) != 0) {
			//     rxBufferOverflow++;
			//      rxBufferOverflow++;
			// following is needed to clear this interrupt
			//      rxIndex = getReg16(REG_RX_BUF_CNT) % RX_BUF_SIZE;
			rxRing.setIndex(getReg16(REG_RX_BUF_CNT) % RX_BUF_SIZE);
			setReg16(REG_RX_BUF_PTR, rxRing.getIndex() - 16);

		}
		if ((status & INTR_SYS_ERR) != 0) {
		}
		if ((status & INTR_TIMEOUT) != 0) {
			//      timeoutError++;
		}
	}

	/*
	 * private void rxError(int status) {
	 */

	private void rxProcess(int status) {
		// Read all packets
		setReg32(REG_CFG9346, CFG9346_WE);

		while ((getReg8(REG_CHIPCMD) & CMD_BUFFER_EMPTY) == 0) {
			final int pktStatus = rxRing.getPktStatus();
			final int pktLen = (pktStatus >> 16);

			if (pktLen == 0xfff0) {
				break;
			}

			if ((pktStatus & (RX_ISE | RX_RUNT | RX_LONG | RX_CRC | RX_FAE)) != 0) {
				setReg8(REG_CHIPCMD, CMD_TX_ENABLE);

				// set up rx mode/configuration
				setReg32(REG_RX_CONFIG, rxConfig);

				rxRing.setIndex(getReg16(CBR));

				setReg16(CAPR, CBR);

				enableTxRx();

				setReg32(REG_RX_CONFIG, rxConfig);

				// Enable interrupts
				setReg16(REG_INTR_MASK, INTR_MASK);
				return;
			} else {
				final SocketBuffer skbuf = rxRing.getPacket(pktLen);

				try {
					if (skbuf.getSize() > 0)
						driver.onReceive(skbuf);
				} catch (NetworkException e) {
					e.printStackTrace(); //To change body of catch statement use Options | File
					// Templates.
				} finally {
				}
			}

			setReg16(CAPR, rxRing.getIndex() - 16);
		}

		setReg32(REG_CFG9346, CFG9346_NORMAL);
	}

	public void txProcess(int status) {
		while (txNumberOfPackets > 0) {
			int txStatus = getReg32(REG_TX_STATUS0 + (txPending * 4));
			// Make sure something has been transmitted
			if ((txStatus & (TX_TUN | TX_TOK | TX_TABT)) == 0) {
				return;
			}
			if ((txStatus & (TX_OWC | TX_TABT)) != 0) {
				//        txErrors++;
				if ((txStatus & TX_TABT) != 0) {
					txAborted++;
					// Setting clear abort bit will make the 8139
					// retransmit the aborted packet
					setReg32(REG_TX_CONFIG, txConfig | TCR_CLRABT);
					return;
				}
				if ((txStatus & TX_CRS) != 0) {
					//          txCarrierErrors++;
				}
				if ((txStatus & TX_OWC) != 0) {
					//		    System.out.println("TX window error");
					//          txWindowErrors++;
				}
			} else {
				if ((txStatus & TX_TUN) != 0) {
					//          txFifoErrors++;
				}
				//        txCollisions += ((txStatus & TX_NCC) >> 24);
				//        txBytes += txStatus & 0x7ff;
				//        txPackets++;
			}
			// txPendingQueue[txPending].free();
			txNumberOfPackets--;
			txPending++;
			txPending &= 3;
		}

	}

	/**
	 * Gets the first IO-Address used by the given device
	 * 
	 * @param device
	 * @param flags
	 */

	protected int getIOBase(Device device, RTL8139Flags flags) throws DriverException {
		final PCIDeviceConfig config = ((PCIDevice) device).getConfig();
		final PCIBaseAddress[] addrs = config.getBaseAddresses();

		if (addrs.length < 1) {
			throw new DriverException("Cannot find iobase: not base addresses");
		}
		if (!addrs[0].isIOSpace()) {
			throw new DriverException("Cannot find iobase: first address is not I/O");
		}
		return addrs[0].getIOBase();
	}

	/**
	 * Gets the number of IO-Addresses used by the given device
	 * 
	 * @param device
	 * @param flags
	 */
	protected int getIOLength(Device device, RTL8139Flags flags) throws DriverException {
		final PCIDeviceConfig config = ((PCIDevice) device).getConfig();
		final PCIBaseAddress[] addrs = config.getBaseAddresses();

		if (addrs.length < 1) {
			throw new DriverException("Cannot find iobase: not base addresses");
		}

		if (!addrs[0].isIOSpace()) {
			throw new DriverException("Cannot find iobase: first address is not I/O");
		}

		return addrs[0].getSize();
	}

	/**
	 * Gets the IRQ used by the given device
	 * 
	 * @param device
	 * @param flags
	 */

	protected int getIRQ(Device device, RTL8139Flags flags) throws DriverException {
		final PCIDeviceConfig config = ((PCIDevice) device).getConfig();

		return config.getInterruptLine();
	}

	/**
	 * Reads a 8-bit NIC register
	 * 
	 * @param reg
	 */
	protected final int getReg8(int reg) {
		return io.inPortByte(iobase + reg);
	}

	/**
	 * Reads a 16-bit NIC register
	 * 
	 * @param reg
	 */
	protected final int getReg16(int reg) {
		return io.inPortWord(iobase + reg);
	}

	/**
	 * Reads a 32-bit NIC register
	 * 
	 * @param reg
	 */

	protected final int getReg32(int reg) {
		return io.inPortDword(iobase + reg);
	}

	/**
	 * Writes a 8-bit NIC register
	 * 
	 * @param reg
	 * @param value
	 */

	protected final void setReg8(int reg, int value) {
		io.outPortByte(iobase + reg, value);
	}

	/**
	 * Writes a 16-bit NIC register
	 * 
	 * @param reg
	 * @param value
	 */

	protected final void setReg16(int reg, int value) {
		io.outPortWord(iobase + reg, value);
	}

	/**
	 * Writes a 32-bit NIC register
	 * 
	 * @param reg
	 * @param value
	 */

	public final void setReg32(int reg, int value) {
		io.outPortDword(iobase + reg, value);
	}
}

⌨️ 快捷键说明

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