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

📄 cops.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
		if(status & TANG_TX_READY)			netif_wake_queue(dev);		status = inb(ioaddr+TANG_CARD_STATUS);	} while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));	/* poll 20 times per second */	cops_timer.expires = jiffies + HZ/20;	add_timer(&cops_timer);	return;}/* *      The typical workload of the driver: *      Handle the network interface interrupts. */static irqreturn_t cops_interrupt(int irq, void *dev_id, struct pt_regs * regs){        struct net_device *dev = dev_id;        struct cops_local *lp;        int ioaddr, status;        int boguscount = 0;        ioaddr = dev->base_addr;        lp = netdev_priv(dev);	if(lp->board==DAYNA)	{		do {			outb(0, ioaddr + COPS_CLEAR_INT);                       	status=inb(ioaddr+DAYNA_CARD_STATUS);                       	if((status&0x03)==DAYNA_RX_REQUEST)                       	        cops_rx(dev);                	netif_wake_queue(dev);		} while(++boguscount < 20);	}	else	{		do {                       	status=inb(ioaddr+TANG_CARD_STATUS);			if(status & TANG_RX_READY)				cops_rx(dev);			if(status & TANG_TX_READY)				netif_wake_queue(dev);			status=inb(ioaddr+TANG_CARD_STATUS);		} while((++boguscount < 20) && (status&(TANG_RX_READY|TANG_TX_READY)));	}        return IRQ_HANDLED;}/* *      We have a good packet(s), get it/them out of the buffers. */static void cops_rx(struct net_device *dev){        int pkt_len = 0;        int rsp_type = 0;        struct sk_buff *skb = NULL;        struct cops_local *lp = netdev_priv(dev);        int ioaddr = dev->base_addr;        int boguscount = 0;        unsigned long flags;	spin_lock_irqsave(&lp->lock, flags);	        if(lp->board==DAYNA)        {                outb(0, ioaddr);                /* Send out Zero length. */                outb(0, ioaddr);                outb(DATA_READ, ioaddr);        /* Send read command out. */                /* Wait for DMA to turn around. */                while(++boguscount<1000000)                {			barrier();                        if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY)                                break;                }                if(boguscount==1000000)                {                        printk(KERN_WARNING "%s: DMA timed out.\n",dev->name);			spin_unlock_irqrestore(&lp->lock, flags);                        return;                }        }        /* Get response length. */	if(lp->board==DAYNA)        	pkt_len = inb(ioaddr) & 0xFF;	else		pkt_len = inb(ioaddr) & 0x00FF;        pkt_len |= (inb(ioaddr) << 8);        /* Input IO code. */        rsp_type=inb(ioaddr);        /* Malloc up new buffer. */        skb = dev_alloc_skb(pkt_len);        if(skb == NULL)        {                printk(KERN_WARNING "%s: Memory squeeze, dropping packet.\n",			dev->name);                lp->stats.rx_dropped++;                while(pkt_len--)        /* Discard packet */                        inb(ioaddr);                spin_unlock_irqrestore(&lp->lock, flags);                return;        }        skb->dev = dev;        skb_put(skb, pkt_len);        skb->protocol = htons(ETH_P_LOCALTALK);        insb(ioaddr, skb->data, pkt_len);               /* Eat the Data */        if(lp->board==DAYNA)                outb(1, ioaddr+DAYNA_INT_CARD);         /* Interrupt the card */        spin_unlock_irqrestore(&lp->lock, flags);  /* Restore interrupts. */        /* Check for bad response length */        if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE)        {		printk(KERN_WARNING "%s: Bad packet length of %d bytes.\n", 			dev->name, pkt_len);                lp->stats.tx_errors++;                dev_kfree_skb_any(skb);                return;        }        /* Set nodeid and then get out. */        if(rsp_type == LAP_INIT_RSP)        {	/* Nodeid taken from received packet. */                lp->node_acquire = skb->data[0];                dev_kfree_skb_any(skb);                return;        }        /* One last check to make sure we have a good packet. */        if(rsp_type != LAP_RESPONSE)        {                printk(KERN_WARNING "%s: Bad packet type %d.\n", dev->name, rsp_type);                lp->stats.tx_errors++;                dev_kfree_skb_any(skb);                return;        }        skb->mac.raw    = skb->data;    /* Point to entire packet. */        skb_pull(skb,3);        skb->h.raw      = skb->data;    /* Point to data (Skip header). */        /* Update the counters. */        lp->stats.rx_packets++;        lp->stats.rx_bytes += skb->len;        /* Send packet to a higher place. */        netif_rx(skb);	dev->last_rx = jiffies;}static void cops_timeout(struct net_device *dev){        struct cops_local *lp = netdev_priv(dev);        int ioaddr = dev->base_addr;	lp->stats.tx_errors++;        if(lp->board==TANGENT)        {		if((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)               		printk(KERN_WARNING "%s: No TX complete interrupt.\n", dev->name);	}	printk(KERN_WARNING "%s: Transmit timed out.\n", dev->name);	cops_jumpstart(dev);	/* Restart the card. */	dev->trans_start = jiffies;	netif_wake_queue(dev);}/* *	Make the card transmit a LocalTalk packet. */static int cops_send_packet(struct sk_buff *skb, struct net_device *dev){        struct cops_local *lp = netdev_priv(dev);        int ioaddr = dev->base_addr;        unsigned long flags;        /*         * Block a timer-based transmit from overlapping. 	 */	 	netif_stop_queue(dev);	spin_lock_irqsave(&lp->lock, flags);	if(lp->board == DAYNA)	 /* Wait for adapter transmit buffer. */		while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0)			cpu_relax();	if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */		while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)			cpu_relax();	/* Output IO length. */	outb(skb->len, ioaddr);	if(lp->board == DAYNA)               	outb(skb->len >> 8, ioaddr);	else		outb((skb->len >> 8)&0x0FF, ioaddr);	/* Output IO code. */	outb(LAP_WRITE, ioaddr);	if(lp->board == DAYNA)	/* Check the transmit buffer again. */        	while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);	outsb(ioaddr, skb->data, skb->len);	/* Send out the data. */	if(lp->board==DAYNA)	/* Dayna requires you kick the card */		outb(1, ioaddr+DAYNA_INT_CARD);	spin_unlock_irqrestore(&lp->lock, flags);	/* Restore interrupts. */	/* Done sending packet, update counters and cleanup. */	lp->stats.tx_packets++;	lp->stats.tx_bytes += skb->len;	dev->trans_start = jiffies;	dev_kfree_skb (skb);        return 0;}/* *	Dummy function to keep the Appletalk layer happy. */ static void set_multicast_list(struct net_device *dev){        if(cops_debug >= 3)		printk("%s: set_multicast_list executed\n", dev->name);}/* *      Another Dummy function to keep the Appletalk layer happy. */ static int cops_hard_header(struct sk_buff *skb, struct net_device *dev,			    unsigned short type, void *daddr, void *saddr, 			    unsigned len){        if(cops_debug >= 3)                printk("%s: cops_hard_header executed. Wow!\n", dev->name);        return 0;}/* *      System ioctls for the COPS LocalTalk card. */ static int cops_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd){        struct cops_local *lp = netdev_priv(dev);        struct sockaddr_at *sa = (struct sockaddr_at *)&ifr->ifr_addr;        struct atalk_addr *aa = (struct atalk_addr *)&lp->node_addr;        switch(cmd)        {                case SIOCSIFADDR:			/* Get and set the nodeid and network # atalkd wants. */			cops_nodeid(dev, sa->sat_addr.s_node);			aa->s_net               = sa->sat_addr.s_net;                        aa->s_node              = lp->node_acquire;			/* Set broardcast address. */                        dev->broadcast[0]       = 0xFF;						/* Set hardware address. */                        dev->dev_addr[0]        = aa->s_node;                        dev->addr_len           = 1;                        return 0;                case SIOCGIFADDR:                        sa->sat_addr.s_net      = aa->s_net;                        sa->sat_addr.s_node     = aa->s_node;                        return 0;                default:                        return -EOPNOTSUPP;        }}/* *	The inverse routine to cops_open(). */ static int cops_close(struct net_device *dev){	struct cops_local *lp = netdev_priv(dev);	/* If we were running polled, yank the timer.	 */	if(lp->board==TANGENT && dev->irq==0)		del_timer(&cops_timer);	netif_stop_queue(dev);        return 0;}/* *      Get the current statistics. *      This may be called with the card open or closed. */static struct net_device_stats *cops_get_stats(struct net_device *dev){        struct cops_local *lp = netdev_priv(dev);        return &lp->stats;}#ifdef MODULEstatic struct net_device *cops_dev;MODULE_LICENSE("GPL");module_param(io, int, 0);module_param(irq, int, 0);module_param(board_type, int, 0);int init_module(void){	if (io == 0)		printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",			cardname);	cops_dev = cops_probe(-1);	if (IS_ERR(cops_dev))		return PTR_ERR(cops_dev);        return 0;}void cleanup_module(void){	unregister_netdev(cops_dev);	cleanup_card(cops_dev);	free_netdev(cops_dev);}#endif /* MODULE *//* * Local variables: *  compile-command: "gcc -DMODVERSIONS -DMODULE -D__KERNEL__ -Wall -Wstrict-prototypes -O2 -c cops.c" *  c-basic-offset: 4 *  c-file-offsets: ((substatement-open . 0)) * End: */

⌨️ 快捷键说明

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