📄 cs8900.java
字号:
Timer.init(20000000, 5); int[] e = new int[6]; e[0] = 0xaa; e[1] = 0xbb; e[2] = 0xcc; e[3] = 0xdd; e[4] = 0xee; e[5] = 0xff; init(e);Timer.sleepWd(1000); for (;;) { poll(); if (rxCnt!=0) { Dbg.intVal(rxCnt); rxCnt = 0; } } } private static int readReg(int reg) { Isa.wr(ADD_PORT, reg); Isa.wr(ADD_PORT+1, reg>>8); return Isa.rd(DATA_PORT) + (Isa.rd(DATA_PORT+1)<<8); } private static void writeReg(int reg, int value) { Isa.wr(ADD_PORT, reg); Isa.wr(ADD_PORT+1, reg>>8); Isa.wr(DATA_PORT, value); Isa.wr(DATA_PORT+1, value>>8); } private static int readWord(int port) { return Isa.rd(port) + (Isa.rd(port+1)<<8); } private static int readWordHighFirst(int port) { return (Isa.rd(port+1)<<8) + Isa.rd(port); } private static void writeWord(int port, int value) { Isa.wr(port, value); Isa.wr(port+1, value>>8); }/*** write tx data.*/ private static void writeData(int[] buf, int length) { if ((length & 1) == 1) ++length; // even bytes for (int i=0; i<length; i+=2) { Isa.wr(TX_FRAME_PORT, buf[i]); Isa.wr(TX_FRAME_PORT+1, buf[i+1]); } }/*** read rx data.*/ private static void readData(int[] buf, int length) { if ((length & 1) == 1) ++length; // even bytes for (int i=0; i<length; i+=2) { buf[i] = Isa.rd(RX_FRAME_PORT); buf[i+1] = Isa.rd(RX_FRAME_PORT+1); } }/*** allocate buffer and reset chip.*/ public static void init(int[] mac) { rxBuf = new int[BUF_LEN]; rxCnt = 0; txFree = true; eth = new int[6]; for (int i=0; i<6; ++i) eth[i] = mac[i]; tx_packets = 0; tx_bytes = 0; collisions = 0; rx_packets = 0; rx_bytes = 0; rx_dropped = 0; multicast = 0; tx_errors = 0; tx_aborted_errors = 0; tx_carrier_errors = 0; tx_fifo_errors = 0; tx_heartbeat_errors = 0; tx_window_errors = 0; rx_errors = 0; rx_over_errors = 0; rx_length_errors = 0; rx_frame_errors = 0; rx_crc_errors = 0; rx_missed_errors = 0; rx_fifo_errors = 0; reset(); }/*** reset chip and set registers*/ public static void reset() { int i; Isa.reset(); // isa reset // wait for init while((readReg(PP_SelfST) & INIT_DONE) == 0) // && jiffies - reset_start_time < 2) ; /* get the chip type */ int rev_type = readReg(PRODUCT_ID_ADD); chip_type = rev_type &~ REVISON_BITS; chip_revision = ((rev_type & REVISON_BITS) >> 8) + 'A'; /* Check the chip type and revision in order to set the correct send command CS8920 revision C and CS8900 revision F can use the faster send. */ send_cmd = TX_AFTER_381; if (chip_type == CS8900 && chip_revision >= 'F') send_cmd = TX_NOW; if (chip_type != CS8900 && chip_revision >= 'C') send_cmd = TX_NOW; // 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); send_underrun = 0; // netif_start_queue(dev); }/*** Sends a packet to an CS8900 network device.* old ret was 0 if ok, now true if ok!*/ public static boolean send(int[] buf, int length) { /* 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, send_cmd); writeWord(TX_CMD_PORT, TX_AFTER_ALL); writeWord(TX_LEN_PORT, length); /* 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. */ // spin_unlock_irq(&lock); // if (net_debug) printk("cs89x0: Tx buffer not free!\n"); return false; } /* Write the contents of the packet */ writeData(buf, length); txFree = false; // spin_unlock_irq(&lock); // dev->trans_start = jiffies; /* * We DO NOT call netif_wake_queue() here. * We also DO NOT call netif_start_queue(). * * Either of these would cause another bottom half run through * net_send_packet() before this packet has fully gone out. That causes * us to hit the "Gasp!" above and the send is rescheduled. it runs like * a dog. We just return and wait for the Tx completion interrupt handler * to restart the netdevice layer */ return true; } 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)!*/ public 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) { if ((status & TX_OK) == 0) tx_errors++; if ((status & TX_LOST_CRS) != 0) tx_carrier_errors++; if ((status & TX_SQE_ERROR) != 0) tx_heartbeat_errors++; if ((status & TX_LATE_COL) != 0) tx_window_errors++; if ((status & TX_16_COL) != 0) tx_aborted_errors++; } } 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) { send_underrun++; if (send_underrun == 3) send_cmd = TX_AFTER_381; else if (send_underrun == 6) send_cmd = TX_AFTER_ALL; /* 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; } }/* not used case ISQ_RX_MISS_EVENT: rx_missed_errors += (status >>6); break; case ISQ_TX_COL_EVENT: collisions += (status >>6); break; }*/ } } private static void count_rx_errors(int status) { rx_errors++; if ((status & RX_RUNT)!=0) rx_length_errors++; if ((status & RX_EXTRA_DATA)!=0) rx_length_errors++; if ((status & RX_CRC_ERROR)!=0) if ((status & (RX_EXTRA_DATA|RX_RUNT))==0) /* per str 172 */ rx_crc_errors++; if ((status & RX_DRIBBLE)!=0) rx_frame_errors++; } /* 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); if ((status & RX_OK) == 0) { count_rx_errors(status); return; } if (rxCnt != 0) { // buffer not free!!! rx_dropped++; return; } readData(rxBuf, length); rxCnt += length; // signal upper layer // netif_rx(skb); // dev->last_rx = jiffies; rx_packets++; rx_bytes += length; } // /* The inverse routine to net_open(). */// static int// net_close(struct net_device *dev)// {// struct net_local *lp = (struct net_local *)dev->priv;// // netif_stop_queue(dev);// // writeReg(PP_RxCFG, 0);// writeReg(PP_TxCFG, 0);// writeReg(PP_BufCFG, 0);// writeReg(PP_BusCTL, 0);// // free_irq(dev->irq, dev);// // /* Update the statistics here. */// return 0;// }// // /* Get the current statistics. This may be called with the card open or// closed. */// static struct net_device_stats *// net_get_stats(struct net_device *dev)// {// struct net_local *lp = (struct net_local *)dev->priv;// unsigned long flags;// // /* Update the statistics from the device registers. */// rx_missed_errors += (readReg(PP_RxMiss) >> 6);// collisions += (readReg(PP_TxCol) >> 6);// spin_unlock_irqrestore(&lock, flags);// // return &stats;// }// // static void set_multicast_list(struct net_device *dev)// {// struct net_local *lp = (struct net_local *)dev->priv;// unsigned long flags;// // if(dev->flags&IFF_PROMISC)// {// rx_mode = RX_ALL_ACCEPT;// }// else if((dev->flags&IFF_ALLMULTI)||dev->mc_list)// {// /* The multicast-accept list is initialized to accept-all, and we// rely on higher-level filtering for now. */// rx_mode = RX_MULTCAST_ACCEPT;// } // else// rx_mode = 0;// // writeReg(PP_RxCTL, DEF_RX_ACCEPT | rx_mode);// // /* in promiscuous mode, we accept errored packets, so we have to enable interrupts on them also */// writeReg(PP_RxCFG, curr_rx_cfg |// (rx_mode == RX_ALL_ACCEPT? (RX_CRC_ERROR_ENBL|RX_RUNT_ENBL|RX_EXTRA_DATA_ENBL) : 0));// spin_unlock_irqrestore(&lock, flags);// }// }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -