📄 cs8900.java
字号:
rx_fifo_errors = 0; reset(); }/*** reset chip and set registers*/ public static void reset() { int i; resetIsa(); // 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(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, send_cmd); 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. */ // spin_unlock_irq(&lock); // if (net_debug) printk("cs89x0: Tx buffer not free!\n"); // p.setStatus(Packet.FREE);// or keep it in SND status??? return false; } /* Write ethernet header */ writeHead(p); /* Write the contents of the packet */ writeData(p); p.setStatus(Packet.FREE); 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)-14; // don't count ethernet header if ((status & RX_OK) == 0) { count_rx_errors(status); writeReg(PP_RxCFG, curr_rx_cfg | SKIP_1); // release memory on chip return; } Packet p = Packet.getPacket(Packet.FREE, Packet.ALLOC); 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); p.setStatus(Packet.RCV); // inform upper layer // netif_rx(skb); // dev->last_rx = jiffies; rx_packets++; rx_bytes += length+14; } // /* 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 + -