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