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

📄 ni5010.c

📁 Linux Kernel 2.6.9 for OMAP1710
💻 C
📖 第 1 页 / 共 2 页
字号:
	PRINTK3((KERN_DEBUG "%s: passed open() #3\n", dev->name));	/* Set the station address */	for(i = 0;i < 6; i++) {		outb(dev->dev_addr[i], EDLC_ADDR + i);	}		PRINTK3((KERN_DEBUG "%s: Initialising ni5010\n", dev->name)); 	outb(0, EDLC_XMASK);	/* No xmit interrupts for now */	outb(XMD_IG_PAR | XMD_T_MODE | XMD_LBC, EDLC_XMODE); 				/* Normal packet xmit mode */	outb(0xff, EDLC_XCLR);	/* Clear all pending xmit interrupts */	outb(RMD_BROADCAST, EDLC_RMODE);				/* Receive broadcast and normal packets */	reset_receiver(dev);	/* Ready ni5010 for receiving packets */		outb(0, EDLC_RESET);	/* Un-reset the ni5010 */		netif_start_queue(dev);			if (NI5010_DEBUG) ni5010_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, skb->len, length-skb->len);	dev->trans_start = jiffies;	dev_kfree_skb (skb);	return 0;}/*  * The typical workload of the driver: * Handle the network interface interrupts.  */static irqreturn_t 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 = netdev_priv(dev);		spin_lock(&lp->lock);	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); 	spin_unlock(&lp->lock);	return IRQ_HANDLED;}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 = netdev_priv(dev);	int ioaddr = dev->base_addr;	unsigned char rcv_stat;	struct sk_buff *skb;	int i_pkt_size;		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 */	i_pkt_size = inw(IE_RCNT);	if (i_pkt_size > ETH_FRAME_LEN || i_pkt_size < 10 ) {		PRINTK((KERN_DEBUG "%s: Packet size error, packet size = %#4.4x\n", 			dev->name, i_pkt_size));		lp->stats.rx_errors++;		lp->stats.rx_length_errors++;		return;	}	/* Malloc up new buffer. */	skb = dev_alloc_skb(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, i_pkt_size), i_pkt_size); 		if (NI5010_DEBUG >= 4) 		dump_packet(skb->data, skb->len); 			skb->protocol = eth_type_trans(skb,dev);	netif_rx(skb);	dev->last_rx = jiffies;	lp->stats.rx_packets++;	lp->stats.rx_bytes += i_pkt_size;	PRINTK2((KERN_DEBUG "%s: Received packet, size=%#4.4x\n", 		dev->name, i_pkt_size));	}static int process_xmt_interrupt(struct net_device *dev){	struct ni5010_local *lp = netdev_priv(dev);	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((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 = netdev_priv(dev);	PRINTK2((KERN_DEBUG "%s: entering ni5010_get_stats\n", dev->name));		if (NI5010_DEBUG) ni5010_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, int pad){	struct ni5010_local *lp = netdev_priv(dev);	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) ni5010_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 - pad;	spin_lock_irqsave(&lp->lock, flags);	lp->o_pkt_size = length + pad;	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 */	while(pad--)		outb(0, IE_XBUF);			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 */	spin_unlock_irqrestore(&lp->lock, flags);	netif_wake_queue(dev);		if (NI5010_DEBUG) ni5010_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 ni5010_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;MODULE_PARM(io, "i");MODULE_PARM(irq, "i");MODULE_PARM_DESC(io, "ni5010 I/O base address");MODULE_PARM_DESC(irq, "ni5010 IRQ number");int init_module(void){	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 = ni5010_probe(-1);	if (IS_ERR(dev_ni5010))		return PTR_ERR(dev_ni5010);        return 0;}void cleanup_module(void){	PRINTK2((KERN_DEBUG "%s: entering cleanup_module\n", boardname));	unregister_netdev(dev_ni5010);	release_region(dev_ni5010->base_addr, NI5010_IO_EXTENT);	free_netdev(dev_ni5010);}#endif /* MODULE */MODULE_LICENSE("GPL");/* * 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 + -