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 + -
显示快捷键?