📄 eth.java
字号:
buf[i] = rd(NE_DATAPORT); }// is used in block_input and get header, do I need this? wr(ENISR_RDC, EN0_ISR); /* Ack intr. */ }/*** DMA write to card memory.* uses page numbers instead of addr!*/ private static void wrMem(int page, int[] buf, int cnt) { int i; /* We should already be in page 0, but to be safe... */ wr(E8390_PAGE0+E8390_START+E8390_NODMA, E8390_CMD);//#ifdef NE8390_RW_BUGFIX// /* Handle the read-before-write bug the same way as the// Crynwr packet driver -- the NatSemi method doesn't work.// Actually this doesn't always work either, but if you have// problems with your NEx000 this is better than nothing! *///// wr(0x42, EN0_RCNTLO);// wr(0x00, EN0_RCNTHI);// wr(0x42, EN0_RSARLO);// wr(0x00, EN0_RSARHI);// wr(E8390_RREAD+E8390_START, E8390_CMD);// /* Make certain that the dummy read has occurred. */// udelay(6);//#endif//// wr(ENISR_RDC, EN0_ISR); // one more acc ??? /* Now the normal output. */ wr(cnt & 0xff, EN0_RCNTLO); wr(cnt >>> 8, EN0_RCNTHI); wr(0x00, EN0_RSARLO); /* DMA start */ wr(page, EN0_RSARHI); wr(E8390_RWRITE+E8390_START, E8390_CMD); for(i = 0; i<cnt; ++i) { wr(buf[i], NE_DATAPORT); }/****** dma_start = jiffies; while ((rd(EN0_ISR) & ENISR_RDC) == 0) if (jiffies - dma_start > 2*HZ/100) { // 20ms printk(KERN_WARNING "%s: timeout waiting for Tx RDC.\n", dev->name); ne_reset_8390(dev); NS8390_init(dev,1); break; }*/// do I need this??? wr(ENISR_RDC, EN0_ISR); /* Ack intr. */ }/** * txTimeout - handle transmit time out condition * * Called by kernel when device never acknowledges a transmit has * completed (or failed) - i.e. never posted a Tx related interrupt. */ public static void txTimeout() { int txsr, isr; // int tickssofar = jiffies - dev->trans_start; tx_errors++; txsr = rd(EN0_TSR); isr = rd(EN0_ISR);/* printk(KERN_DEBUG "%s: Tx timed out, %s TSR=%#2x, ISR=%#2x, t=%d.\n", dev->name, (txsr & ENTSR_ABT) ? "excess collisions." : (isr) ? "lost interrupt?" : "cable problem?", txsr, isr, tickssofar);*/// if (!isr && !tx_packets) { /* The 8390 probably hasn't gotten on the cable yet. */// interface_num ^= 1; /* Try a different xcvr. */// } /* Try to restart the card. Perhaps the user has fixed something. */ init(); // netif_wake_queue(dev); } /*** Sends a packet to an 8390 network device.old ret was 0 if ok, now true if ok!*/ public static boolean startXmit(int[] buf, int length) { int send_length, output_page; wr(0x00, EN0_IMR); send_length = ETH_ZLEN < length ? length : ETH_ZLEN; /* * We have two Tx slots available for use. Find the first free * slot, and then perform some sanity checks. With two Tx bufs, * you get very close to transmitting back-to-back packets. With * only one Tx buf, the transmitter sits idle while you reload the * card, leaving a substantial gap between each transmitted packet. */ if (tx1 == 0) { output_page = tx_start_page; tx1 = send_length; } else if (tx2 == 0) { output_page = tx_start_page + TX_PAGES/2; // second buffer tx2 = send_length; } else { /* We should never get here. */ // No Tx buffers free! // netif_stop_queue(dev); wr(ENISR_ALL, EN0_IMR); tx_errors++; return false; } /* * Okay, now upload the packet and trigger a send if the transmitter * isn't already sending. If it is busy, the interrupt handler will * trigger the send later, upon receiving a Tx done interrupt. */ wrMem(output_page, buf, length); if (!txing) { txing = true; triggerSend(send_length, output_page); // dev->trans_start = jiffies; if (output_page == tx_start_page) { tx1 = -1; } else { tx2 = -1; } } /* if (tx1!=0 && tx2!=0) netif_stop_queue(dev); else netif_start_queue(dev); */ /* Turn 8390 interrupts back on. */ wr(ENISR_ALL, EN0_IMR); tx_bytes += send_length; return true;}/*** Handle the ether interface interrupts. We pull packets from* the 8390 via the card specific functions and fire them at the networking* stack. We also handle transmit completions and wake the transmit path if* neccessary. We also update the counters and do other housekeeping as* needed.*/// when will this be called on my polling version!!! public static void interrupt() { int interrupts, nr_serviced; /* Change to page 0 and read the intr status reg. */ wr(E8390_NODMA+E8390_PAGE0, E8390_CMD); // no START means STOP ? /* !!Assumption!! -- we stay in page 0. Don't break this. */ for (nr_serviced=0; (interrupts = rd(EN0_ISR)) != 0 && nr_serviced<MAX_SERVICE; ++nr_serviced) {hexVal(interrupts); /* Push the next to-transmit packet through. */ if ((interrupts & ENISR_TX)!=0) { txIntr(); } else if ((interrupts & ENISR_TX_ERR)!=0) { txErr(); } if ((interrupts & ENISR_OVER)!=0) { rxOverrun(); } else if ((interrupts & (ENISR_RX+ENISR_RX_ERR))!=0) { /* Got a good (?) packet. */ receive(); } if ((interrupts & ENISR_COUNTERS)!=0) { rx_frame_errors += rd(EN0_COUNTER0); rx_crc_errors += rd(EN0_COUNTER1); rx_missed_errors+= rd(EN0_COUNTER2); wr(ENISR_COUNTERS, EN0_ISR); /* Ack intr. */ } /* Ignore any RDC interrupts that make it back to here. */ if ((interrupts & ENISR_RDC)!=0) { wr(ENISR_RDC, EN0_ISR); } wr(E8390_NODMA+E8390_PAGE0+E8390_START, E8390_CMD); } // if (interrupts && ei_debug) // {// wr(E8390_NODMA+E8390_PAGE0+E8390_START, E8390_CMD);// if (nr_serviced >= MAX_SERVICE) // {// /* 0xFF is valid for a card removal */// if(interrupts!=0xFF)// printk(KERN_WARNING "%s: Too much work at interrupt, status %#2.2x\n",// dev->name, interrupts);// wr(ENISR_ALL, EN0_ISR); /* Ack. most intrs. */// } else {// printk(KERN_WARNING "%s: unknown interrupt %#2x\n", dev->name, interrupts);// wr(0xff, EN0_ISR); /* Ack. all intrs. */// }// } }/*** txErr - handle transmitter error** A transmitter error has happened. Most likely excess collisions (which* is a fairly normal condition). If the error is one where the Tx will* have been aborted, we try and send another one right away, instead of* letting the failed packet sit and collect dust in the Tx buffer. This* is a much better solution as it avoids kernel based Tx timeouts, and* an unnecessary card reset.**/ private static void txErr() { int txsr = rd(EN0_TSR); boolean tx_was_aborted = (txsr & (ENTSR_ABT+ENTSR_FU))!=0;/*#ifdef VERBOSE_ERROR_DUMP printk(KERN_DEBUG "%s: transmitter error (%#2x): ", dev->name, txsr); if (txsr & ENTSR_ABT) printk("excess-collisions "); if (txsr & ENTSR_ND) printk("non-deferral "); if (txsr & ENTSR_CRS) printk("lost-carrier "); if (txsr & ENTSR_FU) printk("FIFO-underrun "); if (txsr & ENTSR_CDH) printk("lost-heartbeat "); printk("\n");#endif*/ wr(ENISR_TX_ERR, EN0_ISR); /* Ack intr. */ if (tx_was_aborted) { txIntr(); } else { tx_errors++; if ((txsr & ENTSR_CRS)!=0) tx_carrier_errors++; if ((txsr & ENTSR_CDH)!=0) tx_heartbeat_errors++; if ((txsr & ENTSR_OWC)!=0) tx_window_errors++; } }/*** txIntr - transmit interrupt handler** We have finished a transmit: check for errors and then trigger the next* packet to be sent.*/ private static void txIntr() { int status = rd(EN0_TSR); wr(ENISR_TX, EN0_ISR); /* Ack intr. */ /* * There are two Tx buffers, see which one finished, and trigger * the send of another one if it exists. */ if (tx1 < 0) { tx1 = 0; if (tx2 > 0) { txing = true; triggerSend(tx2, tx_start_page + TX_PAGES/2); // second buffer // dev->trans_start = jiffies; tx2 = -1; } else { txing = false; } } else if (tx2 < 0) { tx2 = 0; if (tx1 > 0) { txing = true; triggerSend(tx1, tx_start_page); // dev->trans_start = jiffies; tx1 = -1; } else { txing = false; } } /* Minimize Tx latency: update the statistics after we restart TXing. */ if ((status & ENTSR_COL)!=0) collisions++; if ((status & ENTSR_PTX)!=0) { tx_packets++; } else { tx_errors++; if ((status & ENTSR_ABT)!=0) { tx_aborted_errors++; collisions += 16; } if ((status & ENTSR_CRS)!=0) tx_carrier_errors++; if ((status & ENTSR_FU)!=0) tx_fifo_errors++; if ((status & ENTSR_CDH)!=0) tx_heartbeat_errors++; if ((status & ENTSR_OWC)!=0) tx_window_errors++; } // netif_wake_queue(dev); }/** * We have a good packet(s), get it/them out of the buffers. * Called with lock held. */ private static void receive() { int rxing_page, this_frame, next_frame; int current_offset; int rx_pkt_count = 0; // int num_rx_pages = stop_page-rx_start_page; wrSer('r'); //while (++rx_pkt_count < 10) { { // only one packet for now!!! int pkt_len, pkt_stat; /* Get the rx page (incoming packet pointer). */ wr(E8390_NODMA+E8390_PAGE1, E8390_CMD); rxing_page = rd(EN1_CURPAG); wr(E8390_NODMA+E8390_PAGE0, E8390_CMD); /* Remove one frame from the ring. Boundary is always a page behind. */ this_frame = rd(EN0_BOUNDARY) + 1; if (this_frame >= stop_page) this_frame = rx_start_page; /* Someday we'll omit the previous, iff we never get this message. (There is at least one clone claimed to have a problem.) Keep quiet if it looks like a card removal. One problem here is that some clones crash in roughly the same way. */ /* if (ei_debug > 0 && this_frame != current_page && (this_frame!=0x0 || rxing_page!=0xFF)) printk(KERN_ERR "%s: mismatched read page pointers %2x vs %2x.\n", dev->name, this_frame, current_page); */ // no while loop! // if (this_frame == rxing_page) /* Read all the frames? */ // break; /* Done for now */ current_offset = this_frame << 8; rdMem(current_offset, buf, 4); pkt_stat = buf[0]; int rx_frame_next = buf[1]; pkt_len = (buf[3]<<8) + buf[2] - 4;// intVal(pkt_len); next_frame = this_frame + 1 + ((pkt_len+4)>>8); /* Check for bogosity warned by 3c503 book: the status byte is never written. This happened a lot during testing! This code should be cleaned up someday. *//* strange!!! if (rx_frame_next != next_frame && rx_frame_next != next_frame + 1 && rx_frame_next != next_frame - num_rx_pages && rx_frame_next != next_frame + 1 - num_rx_pages) { current_page = rxing_page; wr(current_page-1, EN0_BOUNDARY); rx_errors++; continue; }*//* I don't care for now if (pkt_len < 60 || pkt_len > 1518) { if (ei_debug) printk(KERN_DEBUG "%s: bogus packet size: %d, status=%#2x nxpg=%#2x.\n", dev->name, rx_frame_count, rx_frame_status, rx_frame_next); rx_errors++; rx_length_errors++; } else if ((pkt_stat & 0x0F) == ENRSR_RXOK) {*/ if ((pkt_stat & 0x0F) == ENRSR_RXOK) { /* no buffer available -> drop skb = dev_alloc_skb(pkt_len+2); if (skb == NULL) { if (ei_debug > 1) printk(KERN_DEBUG "%s: Couldn't allocate a sk_buff of size %d.\n", dev->name, pkt_len); rx_dropped++; break; } else */ { // whou cares about ring buffer bounderies!!!! rdMem(current_offset + 4 /* sizeof(rx_frame)*/, buf, pkt_len); // rcv_len is the 'signal' for the loop rcv_len = pkt_len;/*wrSer('\n');wrSer('p');wrSer(' ');for (int i=0; i<pkt_len; ++i) hexVal(buf[i]);wrSer('\n');*/ // skb->protocol=eth_type_trans(skb,dev);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -