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

📄 cops.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 3 页
字号:
	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);			dev->tbusy = 0;			mark_bh(NET_BH);		} while(++boguscount < 20);	}	else	{		do {                       	status=inb(ioaddr+TANG_CARD_STATUS);			if(status & TANG_RX_READY)				cops_rx(dev);			if(status & TANG_TX_READY)				dev->tbusy = 0;			status=inb(ioaddr+TANG_CARD_STATUS);		} while((++boguscount < 20) &&				(status&(TANG_RX_READY|TANG_TX_READY)));	}        dev->interrupt = 0;        return;}/* *      We have a good packet(s), get it/them out of the buffers. */static void cops_rx(struct device *dev){        int pkt_len = 0;        int rsp_type = 0;        struct sk_buff *skb;        struct cops_local *lp = (struct cops_local *)dev->priv;        int ioaddr = dev->base_addr;        int boguscount = 0;        cli();  /* Disable interrupts. */        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)                {                        if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_READY)                                break;                }                if(boguscount==1000000)                {                        printk(KERN_WARNING "%s: DMA timed out.\n",dev->name);                        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_NOTICE "%s: Memory squeeze, dropping packet.\n",			dev->name);                lp->stats.rx_dropped++;                while(pkt_len--)        /* Discard packet */                        inb(ioaddr);                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 */        sti();  /* Restore interrupts. */        /* Check for bad response length */        if(pkt_len < 0 || pkt_len > MAX_LLAP_SIZE)        {		printk(KERN_NOTICE "%s: Bad packet length of %d bytes.\n", 			dev->name, pkt_len);                lp->stats.tx_errors++;                kfree_skb(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];                kfree_skb(skb);                return;        }        /* One last check to make sure we have a good packet. */        if(rsp_type != LAP_RESPONSE)        {                printk("%s: Bad packet type %d.\n", dev->name, rsp_type);                lp->stats.tx_errors++;                kfree_skb(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);        return;}/* *	Make the card transmit a LocalTalk packet. */static int cops_send_packet(struct sk_buff *skb, struct device *dev){        struct cops_local *lp = (struct cops_local *)dev->priv;        int ioaddr = dev->base_addr;        if(dev->tbusy)        {                /*                 * If we get here, some higher level has decided we are broken.                 * There should really be a "kick me" function call instead.                 */                int tickssofar = jiffies - dev->trans_start;                if(tickssofar < 5)                        return 1;		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->tbusy=0;                dev->trans_start = jiffies;        }        /*         * Block a timer-based transmit from overlapping. This could better be         * done with atomic_swap(1, dev->tbusy), but set_bit() works as well.	 */        if(test_and_set_bit(0, (void*) &dev->tbusy) != 0)                printk(KERN_WARNING "%s: Transmitter access conflict.\n",			dev->name);        else        {		cli();	/* Disable interrupts. */		if(lp->board == DAYNA)	 /* Wait for adapter transmit buffer. */			while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0);		if(lp->board == TANGENT) /* Wait for adapter transmit buffer. */			while((inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0);		/* 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);		sti();	/* 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);	dev->tbusy = 0;        return 0;}/* *	Dummy function to keep the Appletalk layer happy. */ static void set_multicast_list(struct 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 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 device *dev, struct ifreq *ifr, int cmd){        struct cops_local *lp = (struct cops_local *)dev->priv;        struct sockaddr_at *sa=(struct sockaddr_at *)&ifr->ifr_addr;        struct at_addr *aa=(struct at_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 device *dev){	struct cops_local *lp = (struct cops_local *)dev->priv;	/* If we were running polled, yank the timer.	 */	if(lp->board==TANGENT && dev->irq==0)		del_timer(&cops_timer);        dev->tbusy = 1;        dev->start = 0;#ifdef MODULE        MOD_DEC_USE_COUNT;#endif	        return 0;}/* *      Get the current statistics. *      This may be called with the card open or closed. */static struct enet_statistics *cops_get_stats(struct device *dev){        struct cops_local *lp = (struct cops_local *)dev->priv;        return &lp->stats;}#ifdef MODULEstatic char lt_name[16];static struct device cops0_dev ={	lt_name,	/* device name */        0, 0, 0, 0,        0x0, 0,  /* I/O address, IRQ */        0, 0, 0, NULL, cops_probe};MODULE_PARM(io, "i");MODULE_PARM(irq, "i");MODULE_PARM(board_type, "i");int init_module(void){        int result, err;        if(io == 0)		printk(KERN_WARNING "%s: You shouldn't autoprobe with insmod\n",			cardname);        /* Copy the parameters from insmod into the device structure. */        cops0_dev.base_addr = io;        cops0_dev.irq       = irq;	err=dev_alloc_name(&cops0_dev, "lt%d");        if(err < 0)                return err;        if((result = register_netdev(&cops0_dev)) != 0)                return result;        return 0;}void cleanup_module(void){        /* No need to check MOD_IN_USE, as sys_delete_module() checks. */	unregister_netdev(&cops0_dev);	if(cops0_dev.priv)                kfree_s(cops0_dev.priv, sizeof(struct cops_local));	if(cops0_dev.irq)		free_irq(cops0_dev.irq, &cops0_dev);        release_region(cops0_dev.base_addr, COPS_IO_EXTENT);}#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 + -