📄 cs8900.java
字号:
tx_bytes = 0; collisions = 0; rx_packets = 0; rx_bytes = 0; rx_dropped = 0; reset(); single = new CS8900(); single.start(); // kick off the thread }//// ISA bus handling// private static final int IO_CTRL = 5; private static final int IO_DATA = 6; private static final int ISA_RESET = 0x20; private static final int ISA_RD = 0x40; private static final int ISA_WR = 0x80; private static final int ISA_DIR = 0x100; // means driving out/* VHDL definition: isa_a <= din(4 downto 0); isa_reset <= din(5); isa_nior <= not din(6); isa_niow <= not din(7); isa_dir <= din(8);*//*** reset isa bus*/ private static void resetIsa() { try { Native.wr(ISA_RESET, IO_CTRL); // isa bus reset Thread.sleep(5); Native.wr(0, IO_CTRL); // disable reset Thread.sleep(5); } catch (Exception e) {}; }/*** 'ISA Bus' io read cycle 2x8 bit.*/ private static int readWord(int port) { Native.wr(port, IO_CTRL); // port Native.wr(port | ISA_RD, IO_CTRL); // nior low int ret = Native.rd(IO_DATA); // read data Native.wr(port, IO_CTRL); // nior high again ++port; Native.wr(port, IO_CTRL); // port Native.wr(port | ISA_RD, IO_CTRL); // nior low ret += Native.rd(IO_DATA)<<8; // read data Native.wr(port, IO_CTRL); // nior high again return ret; }/*** 'ISA Bus' io read cycle 2x8 bit with high byte first.*/ private static int readWordHighFirst(int port) { ++port; Native.wr(port, IO_CTRL); // addr Native.wr(port | ISA_RD, IO_CTRL); // nior low int ret = Native.rd(IO_DATA)<<8; // read data Native.wr(port, IO_CTRL); // nior high again --port; Native.wr(port, IO_CTRL); // addr Native.wr(port | ISA_RD, IO_CTRL); // nior low ret += Native.rd(IO_DATA)&0xff; // read data Native.wr(port, IO_CTRL); // nior high again return ret; }/*** 'ISA Bus' io write cycle 2x8 bit.* first low byte than high byte at higher address.*/ private static void writeWord(int port, int value) { Native.wr(value, IO_DATA); // value in buffer Native.wr(port | ISA_DIR, IO_CTRL); // port and drive value out Native.wr(port | ISA_WR | ISA_DIR, IO_CTRL); // niow low Native.wr(port | ISA_DIR, IO_CTRL); // niow high again ++port; Native.wr(value>>8, IO_DATA); // value in buffer Native.wr(port | ISA_DIR, IO_CTRL); // port and drive value out Native.wr(port | ISA_WR | ISA_DIR, IO_CTRL); // niow low Native.wr(port | ISA_DIR, IO_CTRL); // niow high again Native.wr(port, IO_CTRL); // disable dout } private static int readReg(int reg) { writeWord(ADD_PORT, reg); return readWord(DATA_PORT); } private static void writeReg(int reg, int value) { writeWord(ADD_PORT, reg); writeWord(DATA_PORT, value); }/*** write ethernet header.*/ private static void writeHead(Packet p) { int i, val; p.llh[3] = mac_hi; p.llh[4] = mac_mid; p.llh[5] = mac_low; for (i=0; i<ETH_HLEN/2; ++i) { val = p.llh[i]; Native.wr(val>>>8, IO_DATA); // value in buffer Native.wr(TX_FRAME_PORT | ISA_DIR, IO_CTRL); // port and drive value out Native.wr(TX_FRAME_PORT | ISA_WR | ISA_DIR, IO_CTRL); // niow low Native.wr(TX_FRAME_PORT | ISA_DIR, IO_CTRL); // niow high again Native.wr(val, IO_DATA); // value in buffer Native.wr(TX_FRAME_PORT+1 | ISA_DIR, IO_CTRL); // port and drive value out Native.wr(TX_FRAME_PORT+1 | ISA_WR | ISA_DIR, IO_CTRL); // niow low Native.wr(TX_FRAME_PORT+1 | ISA_DIR, IO_CTRL); // niow high again } Native.wr(TX_FRAME_PORT+1, IO_CTRL); // disable dout }/*** write tx data.*/ private static void writeData(Packet p) { int i, val; int[] buf = p.buf; int length = p.len; if ((length & 1) == 1) ++length; // even bytes val = 0; for (i=0; i<length; i+=2) { if ((i & 2) != 0) { val <<= 16; } else { val = buf[(i>>2)]; } Native.wr(val>>>24, IO_DATA); // value in buffer Native.wr(TX_FRAME_PORT | ISA_DIR, IO_CTRL); // port and drive value out Native.wr(TX_FRAME_PORT | ISA_WR | ISA_DIR, IO_CTRL); // niow low Native.wr(TX_FRAME_PORT | ISA_DIR, IO_CTRL); // niow high again Native.wr(val>>>16, IO_DATA); // value in buffer Native.wr(TX_FRAME_PORT+1 | ISA_DIR, IO_CTRL); // port and drive value out Native.wr(TX_FRAME_PORT+1 | ISA_WR | ISA_DIR, IO_CTRL); // niow low Native.wr(TX_FRAME_PORT+1 | ISA_DIR, IO_CTRL); // niow high again } Native.wr(TX_FRAME_PORT+1, IO_CTRL); // disable dout }/*** read ethernet header.*/ private static void readHead(Packet p) { int i, val; int[] buf = p.llh; for (i=0; i<ETH_HLEN/2; ++i) { // be careful: intel byte order! Native.wr(RX_FRAME_PORT, IO_CTRL); // port Native.wr(RX_FRAME_PORT | ISA_RD, IO_CTRL); // nior low val = Native.rd(IO_DATA)<<8; // read data (second byte) Native.wr(RX_FRAME_PORT, IO_CTRL); // nior high again Native.wr(RX_FRAME_PORT+1, IO_CTRL); // port Native.wr(RX_FRAME_PORT+1 | ISA_RD, IO_CTRL); // nior low buf[i] = val + Native.rd(IO_DATA); // read data (first byte) Native.wr(RX_FRAME_PORT+1, IO_CTRL); // nior high again } }/*** read rx data.*/ private static void readData(Packet p) { int i, val; int length = p.len; int[] buf = p.buf; if ((length & 1) != 0) ++length; // even bytes val = 0; for (i=0; i<length; i+=2) { Native.wr(RX_FRAME_PORT, IO_CTRL); // port Native.wr(RX_FRAME_PORT | ISA_RD, IO_CTRL); // nior low val += Native.rd(IO_DATA)<<8; // read data Native.wr(RX_FRAME_PORT, IO_CTRL); // nior high again Native.wr(RX_FRAME_PORT+1, IO_CTRL); // port Native.wr(RX_FRAME_PORT+1 | ISA_RD, IO_CTRL); // nior low val += Native.rd(IO_DATA); // read data Native.wr(RX_FRAME_PORT+1, IO_CTRL); // nior high again if ((i & 2) != 0) { buf[i>>2] = val; val = 0; } else { val <<= 16; } } if ((length & 2) != 0) { // length is not a multiple of 4 buf[length>>2] = val; } }/*** reset chip and set registers*/ private static void reset() { int i; resetIsa(); // isa reset // wait for init while((readReg(PP_SelfST) & INIT_DONE) == 0) // && jiffies - reset_start_time < 2) ; // no int, no mem and don't use iochrdy pin writeReg(PP_BusCTL, IO_CHANNEL_READY_ON); // set the Ethernet address for (i=0; i < 6/2; i++) { writeReg(PP_IA+i*2, eth[i*2] | (eth[i*2+1] << 8)); } // default value, 10BASE-T only, disabled rx, tx // set LOW_RX_SQUELCH for longer cables writeReg(PP_LineCTL, 0); // TODO check attached cable // Turn on both receive and transmit operations writeReg(PP_LineCTL, readReg(PP_LineCTL) | SERIAL_RX_ON | SERIAL_TX_ON); // Receive only error free packets addressed to this card // rx_mode = 0; writeReg(PP_RxCTL, DEF_RX_ACCEPT); curr_rx_cfg = RX_OK_ENBL | RX_CRC_ERROR_ENBL; writeReg(PP_RxCFG, curr_rx_cfg); writeReg(PP_TxCFG, TX_LOST_CRS_ENBL | TX_SQE_ERROR_ENBL | TX_OK_ENBL | TX_LATE_COL_ENBL | TX_JBR_ENBL | TX_ANY_COL_ENBL | TX_16_COL_ENBL); writeReg(PP_BufCFG, READY_FOR_TX_ENBL | RX_MISS_COUNT_OVRFLOW_ENBL | TX_COL_COUNT_OVRFLOW_ENBL | TX_UNDERRUN_ENBL); }/*** Sends a packet to an CS8900 network device.* old ret was 0 if ok, now true if ok!*/ private static void send(Packet p) { /* keep the upload from being interrupted, since we ask the chip to start transmitting before the whole packet has been completely uploaded. */ // spin_lock_irq(&lp->lock); // netif_stop_queue(dev); /* initiate a transmit sequence */ writeWord(TX_CMD_PORT, TX_AFTER_ALL); writeWord(TX_LEN_PORT, p.len+14); /* Test to see if the chip has allocated memory for the packet */ if ((readReg(PP_BusST) & READY_FOR_TX_NOW) == 0) { /* * Gasp! It hasn't. But that shouldn't happen since * we're waiting for TxOk, so return 1 and requeue this packet. */ // p.setStatus(Packet.FREE);// or keep it in SND status???Dbg.wr('^'); return; } /* Write ethernet header */ writeHead(p); /* Write the contents of the packet */ writeData(p); p.setStatus(Packet.FREE); txFree = false; // // txFree is set with an transmit event // } private static final int EVENT_MASK = 0xffc0; private static int pollRegs() { int event; event = readReg(PP_RxEvent); if ((event & EVENT_MASK)!=0) return event; event = readReg(PP_TxEvent); if ((event & EVENT_MASK)!=0) return event; event = readReg(PP_BufEvent); if ((event & EVENT_MASK)!=0) return event; return 0; }/*** The typical workload of the driver:* We have to poll the chip (in 8 Bit mode)!*/ private static void poll() { int status, mask; /* we MUST read all the events out of the ISQ, otherwise we'll never get interrupted again. As a consequence, we can't have any limit on the number of times we loop in the interrupt handler. The hardware guarantees that eventually we'll run out of events. Of course, if you're on a slow machine, and packets are arriving faster than you can read them off, you're screwed. Hasta la vista, baby! */ while ((status = pollRegs()) != 0) { mask = status & ISQ_EVENT_MASK; if (mask == ISQ_RECEIVER_EVENT) { /* Got a packet(s). */ net_rx(); } else if (mask == ISQ_TRANSMITTER_EVENT) { tx_packets++; // netif_wake_queue(dev); /* Inform upper layers. */ txFree = true; if ((status & ( TX_OK | TX_LOST_CRS | TX_SQE_ERROR | TX_LATE_COL | TX_16_COL)) != TX_OK) { ; } } else if (mask == ISQ_BUFFER_EVENT) { if ((status & READY_FOR_TX) != 0) { /* we tried to transmit a packet earlier, but inexplicably ran out of buffers. That shouldn't happen since we only ever load one packet. Shrug. Do the right thing anyway. */ // netif_wake_queue(dev); /* Inform upper layers. */ txFree = true; } if ((status & TX_UNDERRUN)!=0) { /* transmit cycle is done, although frame wasn't transmitted - this avoids having to wait for the upper layers to timeout on us, in the event of a tx underrun */ // netif_wake_queue(dev); /* Inform upper layers. */ txFree = true; } } } } /* We have a good packet(s), get it/them out of the buffers. */ private static void net_rx() { int status, length; // read high byte first: see AN181 status = readWordHighFirst(RX_FRAME_PORT); length = readWordHighFirst(RX_FRAME_PORT)-14; // don't count ethernet header if ((status & RX_OK) == 0) { writeReg(PP_RxCFG, curr_rx_cfg | SKIP_1); // release memory on chip return; } // get a free packet and set source to CS8900 Packet p = Packet.getPacket(Packet.FREE, Packet.ALLOC, single); if (p == null) { // got no free buffer!Dbg.wr('~'); rx_dropped++; writeReg(PP_RxCFG, curr_rx_cfg | SKIP_1); // release memory on chip return; } p.len = length; // read ethernet header readHead(p); // read data readData(p); // // if an ARP request we handle it here. // int i = p.llh[6]; // type field of ethernet header if (i == ETH_ARP) { // ARP type Arp.request(p, eth, ip); } else if (i == ETH_IP) { // IP type p.setStatus(Packet.RCV); // inform upper layer// OEBB testfor (i=0; i<ETH_HLEN/2; ++i) { llh[i] = p.llh[i];} } else { p.setStatus(Packet.FREE); // just drop unknown types } rx_packets++; rx_bytes += length+14; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -