⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 if_ns.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 2 页
字号:
				if (interrupts & ENISR_TX) {			nsxint(sc);		}		else if (interrupts & ENISR_COUNTERS) {			/*			 * XXX - We really should be storing statistics 			 * about the interface.  For now we just drop them.			 */			/* reading resets the counters! */			(void) inb_p(port + EN0_COUNTER0);   	/* frame */		  	(void) inb_p(port + EN0_COUNTER1);	/* crc */		  	(void) inb_p(port + EN0_COUNTER2);	/* miss */			DEBUGF(printf("%s%d: acked counter interrupt.\n",				      sc->sc_name, sc->sc_unit));			outb_p(port + EN0_ISR, ENISR_COUNTERS);	/* ack intr */		}				if (interrupts & ENISR_TX_ERR) {			DEBUGF(printf("acking transmit error\n"));			outb_p(port + EN0_ISR, ENISR_TX_ERR);	/* ack intr */		}		outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0+E8390_START);	}	DEBUGF({		if (interrupts) {			printf("%s%d: unknown interrupt 0x%x",			       sc->sc_name, sc->sc_unit, interrupts);			outb_p(port + E8390_CMD,			       E8390_NODMA+E8390_PAGE0+E8390_START);			outb_p(port + EN0_ISR, 0xff);	/* ack all intrs */		}	})}/* * Process a transmit interrupt. */voidnsxint(sc)	struct nssoftc *sc;{	int port = sc->sc_port, status;	struct ifnet *ifp = &sc->sc_if;	status = inb(port + EN0_TSR);	outb_p(port + EN0_ISR, ENISR_TX);	/* ack intr */	sc->sc_txing = 0;	sc->sc_timer = 0;	sc->sc_oactive = 0;	if (sc->sc_pingpong) {		if (sc->sc_tx1 < 0) {			if (sc->sc_lasttx != 1 && sc->sc_lasttx != -1)				printf("%s%d: bogus last_tx_buffer %d,"				       "tx1 = %d\n",				       sc->sc_name, sc->sc_unit,				       sc->sc_lasttx, sc->sc_tx1);			sc->sc_tx1 = 0;			if (sc->sc_tx2 > 0) {				nsxmit(sc, sc->sc_tx2, sc->sc_txstrtpg + 6);				sc->sc_tx2 = -1;				sc->sc_lasttx = 2;			} else				sc->sc_lasttx = 20;		} else if (sc->sc_tx2 < 0) {			if (sc->sc_lasttx != 2 && sc->sc_lasttx != -2)				printf("%s%d: bogus last_tx_buffer %d,"				       "tx2 = %d\n",				       sc->sc_name, sc->sc_unit,				       sc->sc_lasttx, sc->sc_tx2);			sc->sc_tx2 = 0;			if (sc->sc_tx1 > 0) {				nsxmit(sc, sc->sc_tx1, sc->sc_txstrtpg);				sc->sc_tx1 = -1;				sc->sc_lasttx = 1;			} else				sc->sc_lasttx = 10;		} else			printf("%s%d: unexpected TX-done interrupt, "			       "lasttx = %d\n",			       sc->sc_name, sc->sc_unit, sc->sc_lasttx);	}	/*	 * Update stats.	 */	if (status & ENTSR_COL) {		if (status & ENTSR_ABT)			ifp->if_collisions += 16;		else			ifp->if_collisions += inb(port + EN0_NCR);	}	if (status & ENTSR_PTX) {		DEBUGF(printf("sent: %s%d\n", sc->sc_name, sc->sc_unit));		ifp->if_opackets++;	} else		ifp->if_oerrors++;	/*	 * Start output on interface.	 */	nsstart(sc);}/* * Process a receive interrupt. */voidnsrint(sc)	struct nssoftc *sc;{	int port = sc->sc_port;	int rxing_page, this_frame, next_frame, current_offset;	int rx_pkt_count = 0;	int num_rx_pages = sc->sc_stoppg - sc->sc_rxstrtpg;	struct nspkthdr rx_frame;	struct ifnet *ifp = &sc->sc_if;	while (++rx_pkt_count < 10) {		int pkt_len;		/*		 * Get the rx page (incoming packet pointer).		 */		outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE1);		rxing_page = inb_p(port + EN1_CURPAG);		outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0);		/*		 * Remove one frame from the ring.		 * Boundary is always a page behind.		 */		this_frame = inb_p(port + EN0_BOUNDARY) + 1;		if (this_frame >= sc->sc_stoppg)			this_frame = sc->sc_rxstrtpg;		DEBUGF({			if (this_frame != sc->sc_curpg)				printf("%s%d: mismatched read page pointers "				       "%x vs %x\n",				       sc->sc_name, sc->sc_unit,				       this_frame, sc->sc_curpg);		});		if (this_frame == rxing_page) {		  	DEBUGF(printf("this_frame = rxing_page!\n"));			break;		}		current_offset = this_frame << 8;		(*sc->sc_input)(sc, sizeof(rx_frame), (char *)&rx_frame,				current_offset);		pkt_len = rx_frame.count - sizeof(rx_frame);		next_frame = this_frame + 1 + ((pkt_len + 4) >> 8);		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) {			sc->sc_curpg = rxing_page;			outb(port + EN0_BOUNDARY, sc->sc_curpg - 1);			ifp->if_ierrors++;			DEBUGF(printf("INPUT ERROR?\n"));			continue;		}		if (pkt_len < 60 || pkt_len > 1518) {			ifp->if_ierrors++;			DEBUGF(printf("%s%d: bad packet length %d\n",				      sc->sc_name, sc->sc_unit, pkt_len));		} else if ((rx_frame.status & 0x0f) == ENRSR_RXOK) {			ipc_kmsg_t kmsg;			kmsg = net_kmsg_get();			if (kmsg == 0) {				DEBUGF(printf("%s%d: dropped packet\n",					      sc->sc_name, sc->sc_unit));				ifp->if_rcvdrops++;			} else {				int len, off;				struct ether_header *eh;				struct packet_header *pkt;				ifp->if_ipackets++;				off = current_offset + sizeof(rx_frame);				eh = ((struct ether_header *)				      (&net_kmsg(kmsg)->header[0]));				(*sc->sc_input)(sc,						sizeof(struct ether_header),						(char *)eh, off);				off += sizeof(struct ether_header);				len = pkt_len - sizeof(struct ether_header);				DEBUGF(printf("rcv: %s%d: %x:%x:%x:%x:%x:%x, "					      "len %d, type 0x%x\n",					      sc->sc_name, sc->sc_unit,					      eh->ether_shost[0],					      eh->ether_shost[1],					      eh->ether_shost[2],					      eh->ether_shost[3],					      eh->ether_shost[4],					      eh->ether_shost[5],					      len, eh->ether_type));				pkt = ((struct packet_header *)				       (&net_kmsg(kmsg)->packet[0]));				(*sc->sc_input)(sc, len, (char *)(pkt+1), off);				pkt->type = eh->ether_type;				pkt->length = len+sizeof(struct packet_header);				net_packet(ifp, kmsg, pkt->length,					   ethernet_priority(kmsg));			}		} else {			DEBUGF(printf("%s%d: bogus packet: "				      "status=0x%x nxpg=0x%x size=%d\n",				      sc->sc_name, sc->sc_unit,				      rx_frame.status, rx_frame.next,				      rx_frame.count));			ifp->if_ierrors++;		}		next_frame = rx_frame.next;		if (next_frame >= sc->sc_stoppg) {			DEBUGF(printf("%s%d: next frame inconsistency, 0x%x\n",				      sc->sc_name, sc->sc_unit, next_frame));			next_frame = sc->sc_rxstrtpg;		}		sc->sc_curpg = next_frame;		outb(port + EN0_BOUNDARY, next_frame - 1);	}	/*	 * Bug alert!  Reset ENISR_OVER to avoid spurious overruns!	 */	outb_p(port + EN0_ISR, ENISR_RX+ENISR_RX_ERR+ENISR_OVER);}/* * Handle a receive overrun condition. * * XXX - this needs to be gone over in light of the NS documentation. */voidnsrxoverrun(sc)	struct nssoftc *sc;{	int port = sc->sc_port, i;	extern unsigned delaycount;	printf("%s%d: receive overrun\n", sc->sc_name, sc->sc_unit);	/*	 * We should already be stopped and in page0, but just to be sure...	 */	outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0+E8390_STOP);	/*	 * Clear remote byte counter registers.	 */	outb_p(port + EN0_RCNTLO, 0);	outb_p(port + EN0_RCNTHI, 0);	/*	 * Wait for reset to complete.	 */	for (i = delaycount*2; i && !(inb_p(port+EN0_ISR) & ENISR_RESET); i--)		;	if (i == 0) {		printf("%s%d: reset did not complete at overrun\n",		       sc->sc_name, sc->sc_unit);		nsinit(sc);		return;	}	/*	 * Disable transmitter.	 */	outb_p(port + EN0_TXCR, E8390_TXOFF);	/*	 * Remove packets.	 */	nsrint(sc);	outb_p(port + EN0_ISR, 0xff);	outb_p(port + E8390_CMD, E8390_NODMA+E8390_PAGE0+E8390_START);	outb_p(port + EN0_TXCR, E8390_TXCONFIG);}/* * Trigger a transmit start. */voidnsxmit(sc, length, start_page)	struct nssoftc *sc;	unsigned length;	int start_page;{	int port = sc->sc_port;	sc->sc_txing = 1;	outb_p(port, E8390_NODMA+E8390_PAGE0);	if (inb_p(port) & E8390_TRANS) {		printf("%s%d: nsxmit() called with the transmitter busy\n",		       sc->sc_name, sc->sc_unit);		return;	}	outb_p(port + EN0_TCNTLO, length & 0xff);	outb_p(port + EN0_TCNTHI, (length >> 8) & 0xff);	outb_p(port + EN0_TPSR, start_page);	outb_p(port, E8390_NODMA+E8390_TRANS+E8390_START);	sc->sc_timer = 4;}#endif	/* NUL > 0 || NWD > 0 */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -