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

📄 lnc.c

📁 一款类linux的操作系统源码
💻 C
📖 第 1 页 / 共 2 页
字号:
}static buf_tlnc_get_packet(int start_of_packet, int pkt_len){    struct host_ring_entry *start;    buf_t b;    char *data, *buf_data;    int blen;    disable;    b = _bget(ETHER_PKT_LEN);    enable;    if (b == NULL) {#if _DEBUG	kprintf("lnc_get_packet: no buffers\n");#endif	return NULL;    }    blen(b) = 0;    start = sc.recv_ring + start_of_packet;    blen = RECVBUFSIZE;    data = start->buff.data;    buf_data = bstart(b);    while (start_of_packet != sc.recv_next) {	if (pkt_len < blen)	    blen = pkt_len;	bcopy(data, buf_data, blen);	pkt_len -= blen;	blen(b) += blen;	data += blen;	buf_data += blen;	start->md->md1 &= HADR;	start->md->md1 |= OWN;	start->md->md2 = -RECVBUFSIZE;	INC_MD_PTR(start_of_packet, sc.nrdre);	start = sc.recv_ring + start_of_packet;	data = start->buff.data;	blen = RECVBUFSIZE;    }    return b;}static voidlnc_rint(){    struct host_ring_entry *start, *next;    int flags, lookahead, pkt_len, start_of_packet;    /*     * The LANCE will issue a RINT interrupt when the ownership of the     * last buffer of a receive packet has been relinquished by the LANCE.     * Therefore, it can be assumed that a complete packet can be found     * before hitting buffers that are still owned by the LANCE, if not     * then there is a bug in the driver that is causing the descriptors     * to get out of sync.     */    lookahead = 0;    next = sc.recv_ring + sc.recv_next;    for (;;) {	flags = next->md->md1;	if (!(flags & STP))	    break;	/* Note start of packet */	start_of_packet = sc.recv_next;	/*	 * Find the end of the packet. Even if not data chaining, jabber	 * packets can overrun into a second descriptor.  If there is no	 * error, then the ENP flag is set in the last descriptor of the	 * packet. If there is an error then the ERR flag will be set in	 * the descriptor where the error occured.  Therefore, to find	 * the last buffer of a packet we search for either ERR or ENP.	 */	if (!(flags & (ENP | MDERR))) {	    do {		INC_MD_PTR(sc.recv_next, sc.nrdre);		next = sc.recv_ring + sc.recv_next;		flags = next->md->md1;	    } while (!(flags & (STP | OWN | ENP | MDERR)));	    if (flags & STP) {#if _DEBUG		kprintf("lnc_rint: start of packet before end of prev\n");#endif		lnc_reset(sc);		return;	    }	    if (flags & OWN) {		if (lookahead) {		    /* Looked ahead into a packet still being received */		    sc.recv_next = start_of_packet;		    break;		} else {#if _DEBUG		    kprintf("lnc_rint: end of packet not found\n");#endif		    lnc_reset(sc);		    return;		}	    }	}	pkt_len = (next->md->md3 & MCNT) - FCS_LEN;	/* Move pointer onto start of next packet */	INC_MD_PTR(sc.recv_next, sc.nrdre);	next = sc.recv_ring + sc.recv_next;	if (flags & MDERR) {	    /* Drop packet */	    while (start_of_packet != sc.recv_next) {		start = sc.recv_ring + start_of_packet;		start->md->md2 = -RECVBUFSIZE;		start->md->md1 &= HADR;		start->md->md1 |= OWN;		INC_MD_PTR(start_of_packet, sc.nrdre);	    }	} else {	    buf_t b = lnc_get_packet(start_of_packet, pkt_len);	    if (b != NULL)		netif_input(b);	}	lookahead++;    }    write_csr(CSR0, RINT | INEA);}static voidlnc_tint(){    struct host_ring_entry *next, *start;    int start_of_packet;    int lookahead;    /*     * The LANCE will write the status information for the packet it just     * tried to transmit in one of two places. If the packet was     * transmitted successfully then the status will be written into the     * last descriptor of the packet. If the transmit failed then the     * status will be written into the descriptor that was being accessed     * when the error occured and all subsequent descriptors in that     * packet will have been relinquished by the LANCE.     *     * At this point we know that sc.trans_next points to the start     * of a packet that the LANCE has just finished trying to transmit.     * We now search for a buffer with either ENP or ERR set.     */    lookahead = 0;    do {	start_of_packet = sc.trans_next;	next = sc.trans_ring + sc.trans_next;	/* Find end of packet */	if (!(next->md->md1 & (ENP | MDERR))) {	    do {		INC_MD_PTR(sc.trans_next, sc.ntdre);		next = sc.trans_ring + sc.trans_next;	    }	    while (!(next->md->md1 & (STP | OWN | ENP | MDERR)));	    if (next->md->md1 & STP) {#if _DEBUG		kprintf("lnc_tint: start of packet found before end ");		kprintf("of prevous in transmit ring\n");#endif		lnc_reset();		return;	    }	    if (next->md->md1 & OWN) {		if (lookahead) {		    /* Looked ahead into a packet still being transmitted */		    sc.trans_next = start_of_packet;		    break;		} else {#if _DEBUG		    kprintf("lnc_tint: end of packet not found\n");#endif		    lnc_reset();		    return;		}	    }	}	/*	 * Check for ERR first since other flags are irrelevant if an	 * error occurred.	 */	if (next->md->md1 & MDERR) {	    if (next->md->md3 & LCOL) {#if _DEBUG		kprintf("lnc_tint: transmit late collision\n");#endif		/* Clear TBUFF since it's not valid when LCOL set */		next->md->md3 &= ~TBUFF;	    }	    if (next->md->md3 & LCAR) {#if _DEBUG		kprintf("lnc_tint: loss of carrier during transmit\n");#endif	    }	    if (next->md->md3 & RTRY) {#if _DEBUG		kprintf("lnc_tint: retransmits failed\n");#endif		/* Clear TBUFF since it's not valid when RTRY set */		next->md->md3 &= ~TBUFF;	    }	    /*	     * TBUFF is only valid if neither LCOL nor RTRY are set.	     * We need to check UFLO after LCOL and RTRY so that we	     * know whether or not TBUFF is valid. If either are	     * set then TBUFF will have been cleared above. A	     * UFLO error will turn off the transmitter so we	     * have to reset.	     *	     */	    if (next->md->md3 & UFLO) {		/* If UFLO occured it's possibly due to TBUFF error */#if _DEBUG		if (next->md->md3 & TBUFF)		    kprintf("lnc_tint: transmit buffer error\n");		else		    kprintf("lnc_tint: transmit underflow error\n");#endif		lnc_reset();		return;	    }	    do {		INC_MD_PTR(sc.trans_next, sc.ntdre);		next = sc.trans_ring + sc.trans_next;	    } while (!(next->md->md1 & STP) &&		     (sc.trans_next != sc.next_to_send));	} else {	    INC_MD_PTR(sc.trans_next, sc.ntdre);	    next = sc.trans_ring + sc.trans_next;	}	/* Clear descriptors */	do {	    start = sc.trans_ring + start_of_packet;	    start->md->md1 &= HADR;	    sc.pending_transmits--;	    INC_MD_PTR(start_of_packet, sc.ntdre);	} while (start_of_packet != sc.trans_next);	lookahead++;    } while (sc.pending_transmits && !(next->md->md1 & OWN));    /* Clear TINT since we've dealt with all the completed transmissions */    write_csr(CSR0, TINT | INEA);    lnc_start();}static voidlnc_isr(void *params){    u_short csr0;    for (;;) {	csr0 = read_csr(CSR0);	if (!(csr0 & INTR))	    break;	/*	 * Clear interrupt flags early to avoid race conditions. The	 * controller can still set these flags even while we're in this	 * interrupt routine. If the flag is still set from the event	 * that caused this interrupt any new events will be missed.	 */	write_csr(CSR0, csr0);	if (csr0 & ERR) {	    if (csr0 & CERR) {#if _DEBUG		kprintf("lnc_isr: heartbeat error\n");#endif	    }	    if (csr0 & BABL) {#if _DEBUG		kprintf("lnc_isr: babbling\n");#endif	    }	    if (csr0 & MISS) {#if _DEBUG		kprintf("lnc_isr: missed packet\n");#endif	    }	    if (csr0 & MERR) {#if _DEBUG		kprintf("lnc_isr: memory error\n");#endif	    }	}	if (csr0 & RINT)	    lnc_rint();	if (csr0 & TINT) {	    lnc_tint();	}    }    /* XXX Hard coded for the moment */    outb(I8259_SLV_CTRL, 0x61);    outb(I8259_MSTR_CTRL, I8259_EOI_CAS);}intlnc_init(){    pci_func_t func;    ipaddr ip;    char s[20];    int ndesc;    bzero(&sc, sizeof(struct lnc_softc));    /* XXX Looking for PCI NICs only for the moment */    func = pci_lookup(PCI_VENDOR_AMD, PCI_DEVICE);    if (func == NULL) {#if _DEBUG	kprintf("lnc_init: no pci adapter found\n");#endif	return EFAIL;    }    sc.isa_dev.id_iobase = func->iobase;    sc.isa_dev.id_irq = func->irq;    if (ne2100_probe() == 0) {#if _DEBUG	kprintf("lnc_init: no NE2100 adapter found\n");#endif	return EFAIL;    }    ether2str(sc.hwaddr, s);    kprintf("lnc_init: %s iobase 0x%x irq %d hwaddr %s\n",	    ic_ident[sc.nic.ic], sc.isa_dev.id_iobase, sc.isa_dev.id_irq, s);    bcopy(sc.hwaddr, netif_primary.hwaddr, ETHER_ADDR_LEN);    netif_primary.state = NETIF_STATE_UP;    str2ip(IPADDR, &ip);    arp_insert(ARP_ENTRY_RESOLVED, ARP_TTL_INFINITE, ip, sc.hwaddr);    binitq(&(sc.sndq));    /* Stop the LANCE for initialization */    lnc_stop();    /* Enable bus mastering */    if (sc.nic.ic > PCnet_32)	pci_busmaster_enable(func->bus, func->dev, 0);    ndesc = NDESC(sc.nrdre) + NDESC(sc.ntdre);    sc.lnc_mem_size = ndesc * sizeof(struct host_ring_entry);    sc.lnc_mem_size += sizeof(struct init_block);    sc.lnc_mem_size += ndesc * sizeof(struct mds);    sc.lnc_mem_size += 8;    sc.lnc_mem_size += NDESC(sc.nrdre) * RECVBUFSIZE;    sc.lnc_mem_size += NDESC(sc.ntdre) * TRANSBUFSIZE;    sc.recv_ring = (struct host_ring_entry *) kmalloc(sc.lnc_mem_size);    if (sc.recv_ring == NULL) {#if _DEBUG	kprintf("lnc_init: could not allocate memory\n");#endif	return ENOMEM;    }    if ((u_long) sc.recv_ring + sc.lnc_mem_size >= 0x1000000) {#if _DEBUG	kprintf("lnc_init: memory allocated above 16 Mbyte limit\n");#endif	return ENOMEM;    }    bzero(sc.recv_ring, sc.lnc_mem_size);    isr_inst(IRQ2INTR(sc.isa_dev.id_irq), lnc_isr, NULL);    intr_unmask(IRQ2INTR(sc.isa_dev.id_irq));    /* Initialize LANCE controller */    lnc_reset();    return 0;}intlnc_shut(){    return ENOSYS;}intlnc_ioctl(int cmd, void *args){    return ENOSYS;}intlnc_read(buf_t * b){    return ENOSYS;}intlnc_write(buf_t * b){    disable;    benq(*b, &(sc.sndq));    enable;    lnc_start();    return 0;}

⌨️ 快捷键说明

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