lance.java
来自「纯java操作系统jnode,安装简单和操作简单的个人使用的Java操作系统」· Java 代码 · 共 315 行
JAVA
315 行
/*
* $Id: Lance.java,v 1.4 2003/12/21 08:04:06 epr Exp $
*/
package org.jnode.driver.net.lance;
import javax.naming.NameNotFoundException;
import org.apache.log4j.Logger;
import org.jnode.driver.DriverException;
import org.jnode.driver.pci.PCIBaseAddress;
import org.jnode.driver.pci.PCIDevice;
import org.jnode.driver.pci.PCIDeviceConfig;
import org.jnode.naming.InitialNaming;
import org.jnode.net.ethernet.EthernetAddress;
import org.jnode.net.ethernet.EthernetConstants;
import org.jnode.system.BootLog;
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;
/**
* @author epr
*/
public class Lance implements IRQHandler, LanceConstants, EthernetConstants {
/** My logger */
private final Logger log = Logger.getLogger(getClass());
/** Start of IO address space */
private final int iobase;
/** IO address space */
private final IOResource io;
/** IRQ */
private final IRQResource irq;
/** My ethernet address */
private final EthernetAddress hwAddress;
private final LanceFlags flags;
private final RxTxBuffer rxtxbuf;
private boolean chip16Bits = true;
/**
* Create a new instance and allocate all resources
*
* @throws ResourceNotFreeException
*/
public Lance(ResourceOwner owner, PCIDevice device, LanceFlags flags) throws ResourceNotFreeException, DriverException {
final PCIDeviceConfig config = device.getConfig();
final PCIBaseAddress[] addrs = config.getBaseAddresses();
final int irq = config.getInterruptLine();
log.debug("Found Lance IRQ: " + irq);
this.flags = flags;
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");
}
// Get the start of the IO address space
iobase = addrs[0].getIOBase();
final int iolength = addrs[0].getSize();
log.debug("Found Lance IOBase: 0x" + NumberUtils.hex(iobase) + ", length: " + iolength);
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;
}
// Load the hw address
this.hwAddress = loadHWAddress();
log.debug("Found hwaddress: " + hwAddress);
// Create rx & tx descriptor rings, initdata and databuffers
this.rxtxbuf = new RxTxBuffer(4, 4, CSR15_DRX | CSR15_DTX, 0, 0, rm);
}
/**
* Release all resources
*/
public void release() {
io.release();
irq.release();
}
/**
* Initialize this device.
*/
public void initialize() {
// reset the chip
resetDW();
reset();
chip16Bits = true;
if (getCSR(0) == 4 && check()) {
BootLog.debug("PCNet :: 16 bits chip");
chip16Bits = true;
} else {
chip16Bits = false;
if (getCSR(0) == 4 && checkDW()) {
BootLog.debug("PCNet :: 32 bits chip");
chip16Bits = false;
}
}
int chipVersion = getCSR(88) | (getCSR(89) << 16);
chipVersion = (chipVersion >> 12) & 0xffff;
String chipName;
switch (chipVersion) {
case 0x2420 :
chipName = "PCnet/PCI 79C970";
break;
case 0x2430 :
chipName = "PCnet/PCI 79C970 or PCnet/32 79C965";
break;
case 0x2621 :
chipName = "PCnet/PCI II 79C970A";
break;
case 0x2623 :
chipName = "PCnet/FAST 79C971";
break;
case 0x2624 :
chipName = "PCnet/FAST+ 79C972";
break;
case 0x2625 :
chipName = "PCnet/FAST III 79C973";
break;
case 0x2626 :
chipName = "PCnet/Home 79C978";
break;
case 0x2627 :
chipName = "PCnet/FAST III 79C970";
break;
default :
chipName = "no device !";
break;
}
BootLog.debug("Pcnet32 :: " + chipName + " at " + NumberUtils.hex(iobase));
if (flags.isAutoSelectEnabled()) {
/*
* This is 79C960 specific; Turn on auto-select of media
*/
final int current = getBCR(0x02);
setBCR(0x02, current | BCR2_ASEL);
}
final int iaddr = rxtxbuf.getInitDataAddress();
setCSR(1, iaddr & 0xFFFF);
setCSR(2, (iaddr >> 16) & 0xFFFF);
setCSR(4, CSR4_JABM | CSR4_TXSTRTM | CSR4_RCVCCOM | CSR4_MFCOM | CSR4_APAD_XMT); // Set
// Interrupt
// masks
setCSR(0, CSR0_INIT | CSR0_IENA); // Trigger INIT, Enable interrupts
// Wait for the initialization to finish
int i = 0;
while (i++ < 100) {
if ((getCSR(0) & CSR0_IDON) != 0)
break;
//Thread.yield();
}
BootLog.debug("PCNet :: Init done after " + i + " ticks.");
setCSR(0,0x0042);
// Now enable RX/TX
setCSR(15, 0);
}
/**
* Disable this device
*
*/
public void disable() {
reset();
setCSR(0, CSR0_STOP);
}
/**
* Gets the hardware address of this card.
*/
public EthernetAddress getAddress() {
return hwAddress;
}
/**
* Read the hardware address
*/
private final EthernetAddress loadHWAddress() {
final byte[] addr = new byte[ETH_ALEN];
for (int i = 0; i < addr.length; i++) {
addr[i] = (byte) io.inPortByte(iobase + R_ETH_ADDR_OFFSET + i);
}
return new EthernetAddress(addr, 0);
}
/**
* Reset the device
*/
private final void reset() {
// Read triggers a reset
io.inPortWord(iobase + RW_RESET_OFFSET);
if (flags.mustUnreset()) {
// Write only needed on NE2100, should not harm others.
io.outPortWord(iobase + RW_RESET_OFFSET, 0);
}
}
/**
* Reset the device (DW version)
*/
private final void resetDW() {
io.inPortDword(iobase + RDW_RESET_OFFSET);
}
/**
* Gets the contents of a Control and Status Register.
*
* @param csrnr
*/
private final int getCSR(int csrnr) {
if (chip16Bits) {
io.outPortWord(iobase + RW_ADDR_OFFSET, csrnr);
return io.inPortWord(iobase + RW_RDATA_OFFSET);
} else {
io.outPortDword(iobase + RDW_ADDR_OFFSET, csrnr);
return (io.inPortDword(iobase + RDW_RDATA_OFFSET) & 0xffff);
}
}
/**
* Sets the contents of a Control and Status Register.
*
* @param csrnr
*/
private final void setCSR(int csrnr, int value) {
if (chip16Bits) {
io.outPortWord(iobase + RW_ADDR_OFFSET, csrnr);
io.outPortWord(iobase + RW_RDATA_OFFSET, value);
} else {
io.outPortWord(iobase + RDW_ADDR_OFFSET, csrnr);
io.outPortWord(iobase + RDW_RDATA_OFFSET, value);
}
}
/**
* Gets the contents of a Bus Configuration Register.
*
* @param bcrnr
*/
private final int getBCR(int bcrnr) {
if (chip16Bits) {
io.outPortWord(iobase + RW_ADDR_OFFSET, bcrnr);
return io.inPortWord(iobase + RW_BDATA_OFFSET);
} else {
io.outPortWord(iobase + RDW_ADDR_OFFSET, bcrnr);
return (io.inPortWord(iobase + RDW_BDATA_OFFSET) & 0xffff);
}
}
/**
* Sets the contents of a Bus Configuration Register.
*
* @param bcrnr
* @param value
*/
private final void setBCR(int bcrnr, int value) {
if (chip16Bits) {
io.outPortWord(iobase + RW_ADDR_OFFSET, bcrnr);
io.outPortWord(iobase + RW_BDATA_OFFSET, value);
} else {
io.outPortWord(iobase + RDW_ADDR_OFFSET, bcrnr);
io.outPortWord(iobase + RDW_BDATA_OFFSET, value);
}
}
private final boolean check() {
io.outPortWord(iobase + RW_ADDR_OFFSET, 88);
return (io.inPortWord(iobase + RW_ADDR_OFFSET) == 88);
}
private final boolean checkDW() {
io.outPortWord(iobase + RDW_ADDR_OFFSET, 88);
return ((io.inPortWord(iobase + RDW_ADDR_OFFSET) & 0xffff) == 88);
}
/**
* @see org.jnode.system.IRQHandler#handleInterrupt(int)
*/
public void handleInterrupt(int irq) {
final int csr0 = getCSR(0);
setCSR(0, csr0); // This will clear the interrupt bits
log.debug("Lance IRQ, CSR0: 0x" + NumberUtils.hex(csr0));
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?