ne2000core.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 672 行 · 第 1/2 页
JAVA
672 行
/*
* $Id: Ne2000Core.java,v 1.2 2003/12/21 08:04:06 epr Exp $
*/
package org.jnode.driver.net.ne2000;
import java.util.Arrays;
import javax.naming.NameNotFoundException;
import org.apache.log4j.Logger;
import org.jnode.driver.Device;
import org.jnode.driver.DriverException;
import org.jnode.driver.net.AbstractDeviceCore;
import org.jnode.driver.net.NetworkException;
import org.jnode.driver.net.ne2000.pci.Ne2000PCIDriver;
import org.jnode.naming.InitialNaming;
import org.jnode.net.HardwareAddress;
import org.jnode.net.SocketBuffer;
import org.jnode.net.ethernet.EthernetAddress;
import org.jnode.net.ethernet.EthernetConstants;
import org.jnode.system.IOResource;
import org.jnode.system.IRQHandler;
import org.jnode.system.IRQResource;
import org.jnode.system.ResourceManager;
import org.jnode.system.ResourceNotFreeException;
import org.jnode.system.ResourceOwner;
import org.jnode.util.NumberUtils;
import org.jnode.util.TimeoutException;
/**
* @author epr
*/
public abstract class Ne2000Core extends AbstractDeviceCore
implements IRQHandler, Ne2000Constants, EthernetConstants {
private static final int TX_PAGES = 6;
/** My logger */
private final Logger log = Logger.getLogger(getClass());
/** Start of IO address space */
protected final int iobase;
/** IO address space */
protected final IOResource io;
/** IRQ */
protected final IRQResource irq;
/** My ethernet address */
private final EthernetAddress hwAddress;
/** My device flags */
protected final Ne2000Flags flags;
/** Start page of NIC memory */
protected final int nic_start;
/** Start page of transmit buffer */
protected final int tx_start;
/** Start page of receive buffer */
protected final int rx_start;
/** End page of receive buffer (exclusive) */
protected final int rx_end;
/** Is a transmit action in progress? */
private boolean tx_active;
private int rx_frame_errors;
private int rx_crc_errors;
private int rx_missed_errors;
private int rx_overruns;
/** The driver we will deliver the receive packets to */
private final Ne2000PCIDriver driver;
/**
* Create a new instance
* @param owner
* @param device
* @param flags
*/
public Ne2000Core(
Ne2000PCIDriver driver,
ResourceOwner owner,
Device device,
Ne2000Flags flags)
throws ResourceNotFreeException, DriverException {
final int irq = getIRQ(device, flags);
this.driver = driver;
this.flags = flags;
this.tx_active = false;
// Get the start of the IO address space
iobase = getIOBase(device, flags);
final int iolength = getIOLength(device, flags);
final ResourceManager rm;
try {
rm = (ResourceManager)InitialNaming.lookup(ResourceManager.NAME);
} catch (NameNotFoundException ex) {
throw new DriverException("Cannot find ResourceManager");
}
this.irq = rm.claimIRQ(owner, irq, this, true);
try {
io = rm.claimIOResource(owner, iobase, iolength);
} catch (ResourceNotFreeException ex) {
this.irq.release();
throw ex;
}
// Reset the device
reset();
// Load the hw address, todo this we must first do some initialization,
// otherwise the hw address cannot be read.
setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STP); // Select page 0
setReg(NE_P0_DCR, 0x49); // Set word-wide access
setReg(NE_P0_RBCR0, 0x00); // Clear count regs
setReg(NE_P0_RBCR1, 0x00);
setReg(NE_P0_IMR, 0x00); // Mask completion irq
setReg(NE_P0_ISR, 0xff);
setReg(NE_P0_RCR, NE_RXOFF);
setReg(NE_P0_TCR, NE_TXOFF);
// Load the start page
this.nic_start = probeNicMemoryStart();
this.tx_start = nic_start;
this.rx_start = tx_start + TX_PAGES;
this.rx_end = nic_start + (flags.getMemSize() / NE_PAGESIZE);
final byte[] saprom = new byte[32];
getNicData(0, saprom, 0, 32);
if (flags.is16bit()) {
this.hwAddress =
new EthernetAddress(
saprom[0],
saprom[2],
saprom[4],
saprom[6],
saprom[8],
saprom[10]);
} else {
this.hwAddress = new EthernetAddress(saprom, 0);
}
log.debug(
"Found "
+ flags.getName()
+ " IRQ="
+ irq
+ ", IOBase=0x"
+ NumberUtils.hex(iobase)
+ ", MAC Address="
+ hwAddress);
}
/**
* Gets the first IO-Address used by the given device
* @param device
* @param flags
*/
protected abstract int getIOBase(Device device, Ne2000Flags flags)
throws DriverException;
/**
* Gets the number of IO-Addresses used by the given device
* @param device
* @param flags
*/
protected abstract int getIOLength(Device device, Ne2000Flags flags)
throws DriverException;
/**
* Gets the IRQ used by the given device
* @param device
* @param flags
*/
protected abstract int getIRQ(Device device, Ne2000Flags flags)
throws DriverException;
/**
* Initialize the device
*/
public synchronized void initialize() {
// Reset the device
reset();
// Load the hw address, todo this we must first do some initialization,
// otherwise the hw address cannot be read.
setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STP); // Select page 0
setReg(NE_P0_DCR, 0x49); // Set word-wide access
setReg(NE_P0_RBCR0, 0x00); // Clear count regs
setReg(NE_P0_RBCR1, 0x00);
setReg(NE_P0_ISR, 0xff); // Clear all interrupt flags
setReg(NE_P0_IMR, NE_ISRCONFIG);
// Setup buffer ring
setReg(NE_P0_PSTART, rx_start);
setReg(NE_P0_PSTOP, rx_end);
setReg(NE_P0_BOUND, rx_end - 1);
setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS1 | NE_CR_STP); // Select page 1
setReg(NE_P1_CURR, rx_start);
// Setup PAR0-5, MAR0-7
for (int i = 0; i < ETH_ALEN; i++) {
setReg(NE_P1_PAR0 + i, hwAddress.get(i));
}
for (int i = 0; i < ETH_ALEN; i++) {
setReg(NE_P1_MAR0 + i, 0xff);
}
// Start the receive/transmit mode
setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA); // Select page 0
setReg(NE_P0_RCR, NE_RXCONFIG);
setReg(NE_P0_TCR, NE_TXCONFIG);
log.debug(
"Start receiving..rx_start="
+ rx_start
+ ", rx_end="
+ rx_end
+ ", tx_start="
+ tx_start);
}
/**
* Disable the device
*/
public synchronized void disable() {
// Start the receive/transmit mode
setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STP); // Select page 0
setReg(NE_P0_RCR, NE_RXOFF);
setReg(NE_P0_TCR, NE_TXOFF);
}
/**
* Release all resources
*/
public synchronized void release() {
io.release();
irq.release();
}
/**
* Transmit the given buffer
* @param buf
* @param timeout
* @throws InterruptedException
* @throws TimeoutException
*/
public synchronized void transmit(SocketBuffer buf, long timeout)
throws InterruptedException, TimeoutException {
// Set the source address
hwAddress.writeTo(buf, 6);
// Wait until we can start transmitting
while (tx_active) {
wait(timeout);
}
tx_active = true;
//log.debug("Going for transmit:\n" + NumberUtils.hex(buf.getBuffer(), buf.getBufferOffset(), buf.getSize()));
final int length = buf.getSize();
setNicData(buf, 0, (tx_start << 8), length);
// Program the transmit
setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA);
setReg(NE_P0_TPSR, tx_start);
setReg(NE_P0_TBCR0, length & 0xFF);
setReg(NE_P0_TBCR1, (length >> 8) & 0xFF);
setReg(NE_P0_CR, NE_CR_TXP | NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA);
}
/**
* @see org.jnode.system.IRQHandler#handleInterrupt(int)
*/
public synchronized void handleInterrupt(int irq) {
// Get the interrupt status
setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA);
int isr;
int loops = 0;
while (((isr = getReg(NE_P0_ISR)) != 0)
&& (loops < NE_MAX_ISR_LOOPS)) {
loops++;
// Receive
if ((isr & NE_ISR_OVW) != 0) {
processOverrunInterrupt();
// Overrun interrupt is acknowledged in processOverrunInterrupt
} else if ((isr & (NE_ISR_PRX | NE_ISR_RXE)) != 0) {
processReceiveInterrupt();
setReg(NE_P0_ISR, NE_ISR_PRX | NE_ISR_RXE);
}
// Transmit
if ((isr & NE_ISR_TXE) != 0) {
processTransmitErrorInterrupt();
setReg(NE_P0_ISR, NE_ISR_PTX | NE_ISR_TXE);
} else if ((isr & NE_ISR_PTX) != 0) {
processTransmitInterrupt();
setReg(NE_P0_ISR, NE_ISR_PTX | NE_ISR_TXE);
}
// Counters
if ((isr & NE_ISR_CNT) != 0) {
processCounterInterrupt();
setReg(NE_P0_ISR, NE_ISR_CNT);
}
// Remote DMA completed, ignore
if ((isr & NE_ISR_RDC) != 0) {
setReg(NE_P0_ISR, NE_ISR_RDC);
}
// Reset start position
setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA);
}
if (isr != 0) {
setReg(NE_P0_CR, NE_CR_NODMA | NE_CR_PS0 | NE_CR_STA);
if (loops >= NE_MAX_ISR_LOOPS) {
log.error(
"Too much work in interrupt handler of "
+ flags.getName()
+ ", isr=0x"
+ NumberUtils.hex(isr, 2));
setReg(NE_P0_ISR, NE_ISRCONFIG);
} else {
log.error(
"Unknown interrupt of "
+ flags.getName()
+ ", isr=0x"
+ NumberUtils.hex(isr, 2));
setReg(NE_P0_ISR, 0xFF);
}
}
}
/**
* Process an interrupt caused by an almost overrun of the NIC counters.
*/
private void processCounterInterrupt() {
rx_frame_errors += getReg(NE_P0_CNTR0);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?