📄 rtl8019.java
字号:
// skb->protocol=eth_type_trans(skb,dev); // netif_rx(skb); // dev->last_rx = jiffies; /* rx_packets++; rx_bytes += pkt_len; if ((pkt_stat & ENRSR_PHY)!=0) multicast++; */ } } else { /* if (ei_debug) printk(KERN_DEBUG "%s: bogus packet: status=%#2x nxpg=%#2x size=%d\n", dev->name, rx_frame_status, rx_frame_next, rx_frame_count); */ rx_errors++; /* NB: The NIC counts CRC, frame and missed errors. */ /* if ((pkt_stat & ENRSR_FO)!=0) rx_fifo_errors++; */ } next_frame = rx_frame_next; /* This _should_ never happen: it's here for avoiding bad clones. */ // if the code would handle the ring buffer correct this CAN happen if (next_frame >= stop_page) { /* printk("%s: next frame inconsistency, %#2x\n", dev->name, next_frame); */ next_frame = rx_start_page; } current_page = next_frame; wr(next_frame-1, EN0_BOUNDARY); } /* We used to also ack ENISR_OVER here, but that would sometimes mask a real overrun, leaving the 8390 in a stopped state with rec'vr off. */ wr(ENISR_RX+ENISR_RX_ERR, EN0_ISR); }/** * rxOverrun - handle receiver overrun * * We have a receiver overrun: we have to kick the 8390 to get it started * again. Problem is that you have to kick it exactly as NS prescribes in * the updated datasheets, or "the NIC may act in an unpredictable manner." * This includes causing "the NIC to defer indefinitely when it is stopped * on a busy network." Ugh. * Called with lock held. Don't call this with the interrupts off or your * computer will hate you - it takes 10ms or so. */ private static void rxOverrun() { boolean was_txing, must_resend = false; /* * Record whether a Tx was in progress and then issue the * stop command. */ was_txing = (rd(E8390_CMD) & E8390_TRANS) != 0; wr(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); /* if (ei_debug > 1) printk(KERN_DEBUG "%s: Receiver overrun.\n", dev->name); */ rx_over_errors++; /* * Wait a full Tx time (1.2ms) + some guard time, NS says 1.6ms total. * Early datasheets said to poll the reset bit, but now they say that * it "is not a reliable indicator and subsequently should be ignored." * We wait at least 10ms. */ Timer.sleep(10); /* * Reset RBCR[01] back to zero as per magic incantation. */ wr(0x00, EN0_RCNTLO); wr(0x00, EN0_RCNTHI); /* * See if any Tx was interrupted or not. According to NS, this * step is vital, and skipping it will cause no end of havoc. */ if (was_txing) { boolean tx_completed = (rd(EN0_ISR) & (ENISR_TX+ENISR_TX_ERR)) != 0; if (!tx_completed) must_resend = true; } /* * Have to enter loopback mode and then restart the NIC before * you are allowed to slurp packets up off the ring. */ wr(E8390_TXOFF, EN0_TXCR); wr(E8390_NODMA + E8390_PAGE0 + E8390_START, E8390_CMD); /* * Clear the Rx ring of all the debris, and ack the interrupt. */ receive(); wr(ENISR_OVER, EN0_ISR); /* * Leave loopback mode, and resend any packet that got stopped. */ wr(E8390_TXCONFIG, EN0_TXCR); if (must_resend) wr(E8390_NODMA + E8390_PAGE0 + E8390_START + E8390_TRANS, E8390_CMD);}/** Collect the stats.*/ public static void getStats() { /* Read the counter registers, assuming we are in page 0. */ rx_frame_errors += rd(EN0_COUNTER0); rx_crc_errors += rd(EN0_COUNTER1); rx_missed_errors+= rd(EN0_COUNTER2); // return &stat; }/* * Update the given Autodin II CRC value with another data byte. */ private static int update_crc(int by, int current_crc) { int bit; int ah = 0; for (bit=0; bit<8; bit++) { int carry = (current_crc>>>31); current_crc <<= 1; ah = ((ah<<1) | carry) ^ by; ah &= 0xff; if ((ah&1) != 0) current_crc ^= 0x04C11DB7; /* CRC polynomial */ ah >>>= 1; by >>>= 1; } return current_crc; }/* * Form the 64 bit 8390 multicast table from the linked list of addresses * associated with this dev structure. */ //static inline void make_mc_bits(u8 *bits, struct net_device *dev)//{// struct dev_mc_list *dmi;//// for (dmi=dev->mc_list; dmi; dmi=dmi->next) // {// int i;// u32 crc;// if (dmi->dmi_addrlen != ETH_ALEN) // {// printk(KERN_INFO "%s: invalid multicast address length given.\n", dev->name);// continue;// }// crc = 0xffffffff; /* initial CRC value */// for (i=0; i<ETH_ALEN; i++)// crc = update_crc(dmi->dmi_addr[i], crc);// /* // * The 8390 uses the 6 most significant bits of the// * CRC to index the multicast table.// */// bits[crc>>29] |= (1<<((crc>>26)&7));// }//}/////**// * do_set_multicast_list - set/clear multicast filter// * @dev: net device for which multicast filter is adjusted// *// * Set or clear the multicast filter for this adaptor. May be called// * from a BH in 2.1.x. Must be called with lock held. // */// //static void do_set_multicast_list(struct net_device *dev)//{// int i;// struct ei_device *ei_local = (struct ei_device*)dev->priv;//// if (!(dev->flags&(IFF_PROMISC|IFF_ALLMULTI))) // {// memset(mcfilter, 0, 8);// if (dev->mc_list)// make_mc_bits(mcfilter, dev);// }// else// memset(mcfilter, 0xFF, 8); /* mcast set to accept-all *///// /* // * DP8390 manuals don't specify any magic sequence for altering// * the multicast regs on an already running card. To be safe, we// * ensure multicast mode is off prior to loading up the new hash// * table. If this proves to be not enough, we can always resort// * to stopping the NIC, loading the table and then restarting.// *// * Bug Alert! The MC regs on the SMC 83C690 (SMC Elite and SMC // * Elite16) appear to be write-only. The NS 8390 data sheet lists// * them as r/w so this is a bug. The SMC 83C790 (SMC Ultra and// * Ultra32 EISA) appears to have this bug fixed.// */// // if (netif_running(dev))// wr(E8390_RXCONFIG, EN0_RXCR);// wr(E8390_NODMA + E8390_PAGE1, E8390_CMD);// for(i = 0; i < 8; i++) // {// wr(mcfilter[i], EN1_MULT_SHIFT(i));//#ifndef BUG_83C690// if(rd(EN1_MULT_SHIFT(i))!=mcfilter[i])// printk(KERN_ERR "Multicast filter read/write mismap %d\n",i);//#endif// }// wr(E8390_NODMA + E8390_PAGE0, E8390_CMD);//// if(dev->flags&IFF_PROMISC)// wr(E8390_RXCONFIG | 0x18, EN0_RXCR);// else if(dev->flags&IFF_ALLMULTI || dev->mc_list)// wr(E8390_RXCONFIG | 0x08, EN0_RXCR);// else// wr(E8390_RXCONFIG, EN0_RXCR);// }/////*// * Called without lock held. This is invoked from user context and may// * be parallel to just about everything else. Its also fairly quick and// * not called too often. Must protect against both bh and irq users// */// //static void set_multicast_list(struct net_device *dev)//{// struct ei_device *ei_local = (struct ei_device*)dev->priv;// // do_set_multicast_list(dev);//} /*** Trigger a transmit start, assuming the length is valid. */ private static void triggerSend(int length, int start_page) { wr(E8390_NODMA+E8390_PAGE0, E8390_CMD); if ((rd(E8390_CMD) & E8390_TRANS)!=0) { // "trigger_send() called with the transmitter busy.\n", return; } wr(length & 0xff, EN0_TCNTLO); wr(length >> 8, EN0_TCNTHI); wr(start_page, EN0_TPSR); wr(E8390_NODMA+E8390_TRANS+E8390_START, E8390_CMD);wrSer('x');// wrSer(' ');// intVal(length);wrSer('\n'); }/*** initialize 8390 network card.*/ public static boolean init() { 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; boolean ret = init0(); init1(); return ret; }/*** initialize first step.*/ private static boolean init0() { int i; JopSys.wr(0x20, IO_ISA_CTRL); // isa bus reset Timer.sleep(5); JopSys.wr(0x00, IO_ISA_CTRL); // disable reset Timer.sleep(5); i = rd(0); if (i!=0x21) return false; // should be 0x21 after a 'real' reset tx_start_page = NE_START_PG; rx_start_page = NE_START_PG+TX_PAGES; stop_page = NE_STOP_PG; /* Follow National Semi's recommendations for initing the DP83902. */ wr(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); /* 0x21 */ wr(0x48, EN0_DCFG); /* 0x48 or 0x49, byte mode */ /* Clear the remote byte count registers. */ wr(0x00, EN0_RCNTLO); wr(0x00, EN0_RCNTHI); /* Set to monitor and loopback mode -- this is vital!. */ wr(E8390_RXOFF, EN0_RXCR); /* 0x20 */ wr(E8390_TXOFF, EN0_TXCR); /* 0x02 */ /* Set the transmit page and receive ring. */ wr(tx_start_page, EN0_TPSR); wr(rx_start_page, EN0_STARTPG); wr(stop_page-1, EN0_BOUNDARY); /* 3c503 says 0x3f,NS0x26*/ current_page = rx_start_page; wr(stop_page, EN0_STOPPG); /* Clear the pending interrupts and mask. */ wr(0xFF, EN0_ISR); wr(0x00, EN0_IMR); /* Read the 16 bytes of station address PROM (after initialized registers!). */ rdMem(0, buf, 32); /* DMA starting at 0x0000 */ if (buf[0x1e]!=0x42) return false; // should be in 8-Bit mode /* Clear the remote byte count registers. (again ?) */ wr(0x00, EN0_RCNTLO); wr(0x00, EN0_RCNTHI); /* Copy the station address into the DS8390 registers. */ wr(E8390_NODMA + E8390_PAGE1 + E8390_STOP, E8390_CMD); /* 0x61 */ for(i=0; i<6; i++) { wr(buf[i<<1], EN1_PHYS+i); // i*2 becaus of 8-Bit mode eth[i] = buf[i<<1];hexVal(buf[i<<1]); }wrSer('\n'); wr(rx_start_page, EN1_CURPAG); wr(E8390_NODMA+E8390_PAGE0+E8390_STOP, E8390_CMD); return true; }/*** initiate chip processing.*/ private static void init1() { // netif_start_queue(dev); tx1 = 0; tx2 = 0; txing = false; wr(0xff, EN0_ISR); wr(ENISR_ALL, EN0_IMR); // I don't like ints, or what? wr(E8390_NODMA+E8390_PAGE0+E8390_START, E8390_CMD); wr(E8390_TXCONFIG, EN0_TXCR); /* xmit on. */ /* 3c503 TechMan says rxconfig only after the NIC is started. */ wr(E8390_RXCONFIG, EN0_RXCR); /* rx on, */// TODO// do_set_multicast_list(dev); /* (re)load the mcast table */ }/* serial output for debug*/ private static final int IO_STATUS = 1; private static final int IO_UART = 2; static void wrSer(int c) { while ((JopSys.rd(IO_STATUS)&1)==0) ; JopSys.wr(c, IO_UART); } static void intVal(int val) { int i; for (i=0; i<MAX_SER-1; ++i) { serBuf[i] = val%10; val /= 10; if (val==0) break; } for (val=i; val>=0; --val) { wrSer('0'+serBuf[val]); } wrSer(' '); } static void hexVal(int val) { int i, j; if (val<16) wrSer('0'); for (i=0; i<MAX_SER-1; ++i) { j = val & 0x0f; if (j<10) { j += '0'; } else { j += 'a'-10; } serBuf[i] = j; val >>>= 4; if (val==0) break; } for (val=i; val>=0; --val) { wrSer(serBuf[val]); } wrSer(' '); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -