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

📄 ni5010.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	netif_start_queue(dev);			if (NI5010_DEBUG) show_registers(dev); 	PRINTK((KERN_DEBUG "%s: open successful\n", dev->name));     	return 0;}static void reset_receiver(struct net_device *dev){	int ioaddr = dev->base_addr;		PRINTK3((KERN_DEBUG "%s: resetting receiver\n", dev->name));	outw(0, IE_GP);		/* Receive packet at start of buffer */	outb(0xff, EDLC_RCLR);	/* Clear all pending rcv interrupts */	outb(0, IE_MMODE);	/* Put EDLC to rcv buffer */	outb(MM_EN_RCV, IE_MMODE); /* Enable rcv */	outb(0xff, EDLC_RMASK);	/* Enable all rcv interrupts */}static void ni5010_timeout(struct net_device *dev){	printk(KERN_WARNING "%s: transmit timed out, %s?\n", dev->name,		   tx_done(dev) ? "IRQ conflict" : "network cable problem");	/* Try to restart the adaptor. */	/* FIXME: Give it a real kick here */	chipset_init(dev, 1);	dev->trans_start = jiffies;	netif_wake_queue(dev);}static int ni5010_send_packet(struct sk_buff *skb, struct net_device *dev){	int length = ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN;	PRINTK2((KERN_DEBUG "%s: entering ni5010_send_packet\n", dev->name));	/*          * Block sending	 */		netif_stop_queue(dev);	hardware_send_packet(dev, (unsigned char *)skb->data, length);	dev->trans_start = jiffies;	dev_kfree_skb (skb);	return 0;}/*  * The typical workload of the driver: * Handle the network interface interrupts.  */static void  ni5010_interrupt(int irq, void *dev_id, struct pt_regs *regs){	struct net_device *dev = dev_id;	struct ni5010_local *lp;	int ioaddr, status;	int xmit_was_error = 0;	PRINTK2((KERN_DEBUG "%s: entering ni5010_interrupt\n", dev->name));	ioaddr = dev->base_addr;	lp = (struct ni5010_local *)dev->priv;		status = inb(IE_ISTAT); 	PRINTK3((KERN_DEBUG "%s: IE_ISTAT = %#02x\n", dev->name, status));		        if ((status & IS_R_INT) == 0) ni5010_rx(dev);        if ((status & IS_X_INT) == 0) {                xmit_was_error = process_xmt_interrupt(dev);        }        if ((status & IS_DMA_INT) == 0) {                PRINTK((KERN_DEBUG "%s: DMA complete (???)\n", dev->name));                outb(0, IE_DMA_RST); /* Reset DMA int */        }	if (!xmit_was_error) 		reset_receiver(dev); 	return;}static void dump_packet(void *buf, int len){	int i;		printk(KERN_DEBUG "Packet length = %#4x\n", len);	for (i = 0; i < len; i++){		if (i % 16 == 0) printk(KERN_DEBUG "%#4.4x", i);		if (i % 2 == 0) printk(" ");		printk("%2.2x", ((unsigned char *)buf)[i]);		if (i % 16 == 15) printk("\n");	}	printk("\n");		return;}/* We have a good packet, get it out of the buffer. */static void ni5010_rx(struct net_device *dev){	struct ni5010_local *lp = (struct ni5010_local *)dev->priv;	int ioaddr = dev->base_addr;	unsigned char rcv_stat;	struct sk_buff *skb;		PRINTK2((KERN_DEBUG "%s: entering ni5010_rx()\n", dev->name)); 		rcv_stat = inb(EDLC_RSTAT);	PRINTK3((KERN_DEBUG "%s: EDLC_RSTAT = %#2x\n", dev->name, rcv_stat)); 		if ( (rcv_stat & RS_VALID_BITS) != RS_PKT_OK) {		PRINTK((KERN_INFO "%s: receive error.\n", dev->name));		lp->stats.rx_errors++;		if (rcv_stat & RS_RUNT) lp->stats.rx_length_errors++;		if (rcv_stat & RS_ALIGN) lp->stats.rx_frame_errors++;		if (rcv_stat & RS_CRC_ERR) lp->stats.rx_crc_errors++;		if (rcv_stat & RS_OFLW) lp->stats.rx_fifo_errors++;        	outb(0xff, EDLC_RCLR); /* Clear the interrupt */		return;	}	        outb(0xff, EDLC_RCLR);  /* Clear the interrupt */	lp->i_pkt_size = inw(IE_RCNT);	if (lp->i_pkt_size > ETH_FRAME_LEN || lp->i_pkt_size < 10 ) {		PRINTK((KERN_DEBUG "%s: Packet size error, packet size = %#4.4x\n", 			dev->name, lp->i_pkt_size));		lp->stats.rx_errors++;		lp->stats.rx_length_errors++;		return;	}	/* Malloc up new buffer. */	skb = dev_alloc_skb(lp->i_pkt_size + 3);	if (skb == NULL) {		printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n", dev->name);		lp->stats.rx_dropped++;		return;	}		skb->dev = dev;	skb_reserve(skb, 2);		/* Read packet into buffer */        outb(MM_MUX, IE_MMODE); /* Rcv buffer to system bus */	outw(0, IE_GP);	/* Seek to beginning of packet */	insb(IE_RBUF, skb_put(skb, lp->i_pkt_size), lp->i_pkt_size); 		if (NI5010_DEBUG >= 4) 		dump_packet(skb->data, skb->len); 			skb->protocol = eth_type_trans(skb,dev);	netif_rx(skb);	lp->stats.rx_packets++;	lp->stats.rx_bytes += lp->i_pkt_size;	PRINTK2((KERN_DEBUG "%s: Received packet, size=%#4.4x\n", 		dev->name, lp->i_pkt_size));	}static int process_xmt_interrupt(struct net_device *dev){	struct ni5010_local *lp = (struct ni5010_local *)dev->priv;	int ioaddr = dev->base_addr;	int xmit_stat;	PRINTK2((KERN_DEBUG "%s: entering process_xmt_interrupt\n", dev->name));	xmit_stat = inb(EDLC_XSTAT);	PRINTK3((KERN_DEBUG "%s: EDLC_XSTAT = %2.2x\n", dev->name, xmit_stat));		outb(0, EDLC_XMASK);	/* Disable xmit IRQ's */	outb(0xff, EDLC_XCLR);	/* Clear all pending xmit IRQ's */		if (xmit_stat & XS_COLL){                printk("ether collision\n"); /* FIXME: remove */		PRINTK((KERN_DEBUG "%s: collision detected, retransmitting\n", 			dev->name));		outw(NI5010_BUFSIZE - lp->o_pkt_size, IE_GP);		/* outb(0, IE_MMODE); */ /* xmt buf on sysbus FIXME: needed ? */		outb(MM_EN_XMT | MM_MUX, IE_MMODE);		outb(XM_ALL, EDLC_XMASK); /* Enable xmt IRQ's */		lp->stats.collisions++;		return 1;	}	/* FIXME: handle other xmt error conditions */	lp->stats.tx_packets++;	lp->stats.tx_bytes += lp->o_pkt_size;	netif_wake_queue(dev);				PRINTK2((KERN_DEBUG "%s: sent packet, size=%#4.4x\n", 		dev->name, lp->o_pkt_size));	return 0;}/* The inverse routine to ni5010_open(). */static int ni5010_close(struct net_device *dev){	int ioaddr = dev->base_addr;	PRINTK2((KERN_DEBUG "%s: entering ni5010_close\n", dev->name));#ifdef jumpered_interrupts		free_irq(dev->irq, NULL);#endif	/* Put card in held-RESET state */	outb(0, IE_MMODE);	outb(RS_RESET, EDLC_RESET);	netif_stop_queue(dev);		PRINTK((KERN_DEBUG "%s: %s closed down\n", dev->name, boardname));	return 0;}/* Get the current statistics.	This may be called with the card open or   closed. */static struct net_device_stats *ni5010_get_stats(struct net_device *dev){	struct ni5010_local *lp = (struct ni5010_local *)dev->priv;	PRINTK2((KERN_DEBUG "%s: entering ni5010_get_stats\n", dev->name));		if (NI5010_DEBUG) show_registers(dev);		/* cli(); */	/* Update the statistics from the device registers. */	/* We do this in the interrupt handler */	/* sti(); */	return &lp->stats;}/* Set or clear the multicast filter for this adaptor.   num_addrs == -1      Promiscuous mode, receive all packets   num_addrs == 0       Normal mode, clear multicast list   num_addrs > 0        Multicast mode, receive normal and MC packets, and do                        best-effort filtering.*/static void ni5010_set_multicast_list(struct net_device *dev){	short ioaddr = dev->base_addr;  	PRINTK2((KERN_DEBUG "%s: entering set_multicast_list\n", dev->name));	if (dev->flags&IFF_PROMISC || dev->flags&IFF_ALLMULTI) {		dev->flags |= IFF_PROMISC;		outb(RMD_PROMISC, EDLC_RMODE); /* Enable promiscuous mode */		PRINTK((KERN_DEBUG "%s: Entering promiscuous mode\n", dev->name));	} else if (dev->mc_list) {		/* Sorry, multicast not supported */		PRINTK((KERN_DEBUG "%s: No multicast, entering broadcast mode\n", dev->name));		outb(RMD_BROADCAST, EDLC_RMODE);	} else {		PRINTK((KERN_DEBUG "%s: Entering broadcast mode\n", dev->name));		outb(RMD_BROADCAST, EDLC_RMODE);  /* Disable promiscuous mode, use normal mode */	}}static void hardware_send_packet(struct net_device *dev, char *buf, int length){	struct ni5010_local *lp = (struct ni5010_local *)dev->priv;	int ioaddr = dev->base_addr;	unsigned long flags;	unsigned int buf_offs;	PRINTK2((KERN_DEBUG "%s: entering hardware_send_packet\n", dev->name));	        if (length > ETH_FRAME_LEN) {                PRINTK((KERN_WARNING "%s: packet too large, not possible\n",                        dev->name));                return;        }	if (NI5010_DEBUG) show_registers(dev);	if (inb(IE_ISTAT) & IS_EN_XMT) {		PRINTK((KERN_WARNING "%s: sending packet while already transmitting, not possible\n", 			dev->name));		return;	}		if (NI5010_DEBUG > 3) dump_packet(buf, length);        buf_offs = NI5010_BUFSIZE - length;        lp->o_pkt_size = length;	save_flags(flags);		cli();	outb(0, EDLC_RMASK);	/* Mask all receive interrupts */	outb(0, IE_MMODE);	/* Put Xmit buffer on system bus */	outb(0xff, EDLC_RCLR);	/* Clear out pending rcv interrupts */	outw(buf_offs, IE_GP); /* Point GP at start of packet */	outsb(IE_XBUF, buf, length); /* Put data in buffer */	outw(buf_offs, IE_GP); /* Rewrite where packet starts */	/* should work without that outb() (Crynwr used it) */	/*outb(MM_MUX, IE_MMODE);*/ /* Xmt buffer to EDLC bus */	outb(MM_EN_XMT | MM_MUX, IE_MMODE); /* Begin transmission */	outb(XM_ALL, EDLC_XMASK); /* Cause interrupt after completion or fail */	restore_flags(flags);	netif_wake_queue(dev);		if (NI5010_DEBUG) show_registers(dev);	}static void chipset_init(struct net_device *dev, int startp){	/* FIXME: Move some stuff here */	PRINTK3((KERN_DEBUG "%s: doing NOTHING in chipset_init\n", dev->name));}static void show_registers(struct net_device *dev){	int ioaddr = dev->base_addr;		PRINTK3((KERN_DEBUG "%s: XSTAT %#2.2x\n", dev->name, inb(EDLC_XSTAT)));	PRINTK3((KERN_DEBUG "%s: XMASK %#2.2x\n", dev->name, inb(EDLC_XMASK)));	PRINTK3((KERN_DEBUG "%s: RSTAT %#2.2x\n", dev->name, inb(EDLC_RSTAT)));	PRINTK3((KERN_DEBUG "%s: RMASK %#2.2x\n", dev->name, inb(EDLC_RMASK)));	PRINTK3((KERN_DEBUG "%s: RMODE %#2.2x\n", dev->name, inb(EDLC_RMODE)));	PRINTK3((KERN_DEBUG "%s: XMODE %#2.2x\n", dev->name, inb(EDLC_XMODE)));	PRINTK3((KERN_DEBUG "%s: ISTAT %#2.2x\n", dev->name, inb(IE_ISTAT)));}#ifdef MODULEstatic struct net_device dev_ni5010;static int io;static int irq;MODULE_PARM(io, "i");MODULE_PARM(irq, "i");int init_module(void){	int result;		PRINTK2((KERN_DEBUG "%s: entering init_module\n", boardname));	/*	if(io <= 0 || irq == 0){	   	printk(KERN_WARNING "%s: Autoprobing not allowed for modules.\n", boardname);		printk(KERN_WARNING "%s: Set symbols 'io' and 'irq'\n", boardname);	   	return -EINVAL;	}	*/	if (io <= 0){		printk(KERN_WARNING "%s: Autoprobing for modules is hazardous, trying anyway..\n", boardname);	}	PRINTK2((KERN_DEBUG "%s: init_module irq=%#2x, io=%#3x\n", boardname, irq, io));        dev_ni5010.irq=irq;        dev_ni5010.base_addr=io;	dev_ni5010.init=ni5010_probe;        if ((result = register_netdev(&dev_ni5010)) != 0) {        	PRINTK((KERN_WARNING "%s: register_netdev returned %d.\n",         		boardname, result));                return -EIO;        }        return 0;}voidcleanup_module(void){	PRINTK2((KERN_DEBUG "%s: entering cleanup_module\n", boardname));        unregister_netdev(&dev_ni5010);	release_region(dev_ni5010.base_addr, NI5010_IO_EXTENT);	if (dev_ni5010.priv != NULL){	        kfree(dev_ni5010.priv);	        dev_ni5010.priv = NULL;	}}#endif /* MODULE *//* * Local variables: *  compile-command: "gcc -D__KERNEL__ -I/usr/src/linux/net/inet -Wall -Wstrict-prototypes -O6 -m486 -c ni5010.c" *  version-control: t *  kept-new-versions: 5 *  tab-width: 4 * End: */

⌨️ 快捷键说明

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