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

📄 cops.c

📁 linux-2.6.15.6
💻 C
📖 第 1 页 / 共 3 页
字号:
	if(board==DAYNA)		printk("%s: %s at %#3x, using IRQ %d, in Dayna mode.\n", 			dev->name, cardname, ioaddr, dev->irq);	if(board==TANGENT) {		if(dev->irq)			printk("%s: %s at %#3x, IRQ %d, in Tangent mode\n", 				dev->name, cardname, ioaddr, dev->irq);		else			printk("%s: %s at %#3x, using polled IO, in Tangent mode.\n", 				dev->name, cardname, ioaddr);	}        return 0;err_out:	release_region(ioaddr, COPS_IO_EXTENT);	return retval;}static int __init cops_irq (int ioaddr, int board){       /*         * This does not use the IRQ to determine where the IRQ is. We just         * assume that when we get a correct status response that it's the IRQ.         * This really just verifies the IO port but since we only have access         * to such a small number of IRQs (5, 4, 3) this is not bad.         * This will probably not work for more than one card.         */        int irqaddr=0;        int i, x, status;        if(board==DAYNA)        {                outb(0, ioaddr+DAYNA_RESET);                inb(ioaddr+DAYNA_RESET);                mdelay(333);        }        if(board==TANGENT)        {                inb(ioaddr);                outb(0, ioaddr);                outb(0, ioaddr+TANG_RESET);        }        for(i=0; cops_irqlist[i] !=0; i++)        {                irqaddr = cops_irqlist[i];                for(x = 0xFFFF; x>0; x --)    /* wait for response */                {                        if(board==DAYNA)                        {                                status = (inb(ioaddr+DAYNA_CARD_STATUS)&3);                                if(status == 1)                                        return irqaddr;                        }                        if(board==TANGENT)                        {                                if((inb(ioaddr+TANG_CARD_STATUS)& TANG_TX_READY) !=0)                                        return irqaddr;                        }                }        }        return 0;       /* no IRQ found */}/* * Open/initialize the board. This is called (in the current kernel) * sometime after booting when the 'ifconfig' program is run. */static int cops_open(struct net_device *dev){    struct cops_local *lp = netdev_priv(dev);	if(dev->irq==0)	{		/*		 * I don't know if the Dayna-style boards support polled 		 * operation.  For now, only allow it for Tangent.		 */		if(lp->board==TANGENT)	/* Poll 20 times per second */		{		    init_timer(&cops_timer);		    cops_timer.function = cops_poll;		    cops_timer.data 	= (unsigned long)dev;		    cops_timer.expires 	= jiffies + HZ/20;		    add_timer(&cops_timer);		} 		else 		{			printk(KERN_WARNING "%s: No irq line set\n", dev->name);			return -EAGAIN;		}	}	cops_jumpstart(dev);	/* Start the card up. */	netif_start_queue(dev);        return 0;}/* *	This allows for a dynamic start/restart of the entire card. */static int cops_jumpstart(struct net_device *dev){	struct cops_local *lp = netdev_priv(dev);	/*         *      Once the card has the firmware loaded and has acquired         *      the nodeid, if it is reset it will lose it all.         */        cops_reset(dev,1);	/* Need to reset card before load firmware. */        cops_load(dev);		/* Load the firmware. */	/*	 *	If atalkd already gave us a nodeid we will use that	 *	one again, else we wait for atalkd to give us a nodeid	 *	in cops_ioctl. This may cause a problem if someone steals	 *	our nodeid while we are resetting.	 */		if(lp->nodeid == 1)		cops_nodeid(dev,lp->node_acquire);	return 0;}static void tangent_wait_reset(int ioaddr){	int timeout=0;	while(timeout++ < 5 && (inb(ioaddr+TANG_CARD_STATUS)&TANG_TX_READY)==0)		mdelay(1);   /* Wait 1 second */}/* *      Reset the LocalTalk board. */static void cops_reset(struct net_device *dev, int sleep){        struct cops_local *lp = netdev_priv(dev);        int ioaddr=dev->base_addr;        if(lp->board==TANGENT)        {                inb(ioaddr);		/* Clear request latch. */                outb(0,ioaddr);		/* Clear the TANG_TX_READY flop. */                outb(0, ioaddr+TANG_RESET);	/* Reset the adapter. */		tangent_wait_reset(ioaddr);                outb(0, ioaddr+TANG_CLEAR_INT);        }        if(lp->board==DAYNA)        {                outb(0, ioaddr+DAYNA_RESET);	/* Assert the reset port */                inb(ioaddr+DAYNA_RESET);	/* Clear the reset */                if(sleep)                {                        long snap=jiffies;			/* Let card finish initializing, about 1/3 second */	                while(jiffies-snap<HZ/3)                                schedule();                }                else                        mdelay(333);        }	netif_wake_queue(dev);	return;}static void cops_load (struct net_device *dev){        struct ifreq ifr;        struct ltfirmware *ltf= (struct ltfirmware *)&ifr.ifr_ifru;        struct cops_local *lp = netdev_priv(dev);        int ioaddr=dev->base_addr;	int length, i = 0;        strcpy(ifr.ifr_name,"lt0");        /* Get card's firmware code and do some checks on it. */#ifdef CONFIG_COPS_DAYNA                if(lp->board==DAYNA)        {                ltf->length=sizeof(ffdrv_code);                ltf->data=ffdrv_code;        }        else#endif        #ifdef CONFIG_COPS_TANGENT        if(lp->board==TANGENT)        {                ltf->length=sizeof(ltdrv_code);                ltf->data=ltdrv_code;        }        else#endif	{		printk(KERN_INFO "%s; unsupported board type.\n", dev->name);		return;	}	        /* Check to make sure firmware is correct length. */        if(lp->board==DAYNA && ltf->length!=5983)        {                printk(KERN_WARNING "%s: Firmware is not length of FFDRV.BIN.\n", dev->name);                return;        }        if(lp->board==TANGENT && ltf->length!=2501)        {                printk(KERN_WARNING "%s: Firmware is not length of DRVCODE.BIN.\n", dev->name);                return;        }        if(lp->board==DAYNA)        {                /*                 *      We must wait for a status response                 *      with the DAYNA board.                 */                while(++i<65536)                {                       if((inb(ioaddr+DAYNA_CARD_STATUS)&3)==1)                                break;                }                if(i==65536)                        return;        }        /*         *      Upload the firmware and kick. Byte-by-byte works nicely here.         */	i=0;        length = ltf->length;        while(length--)        {                outb(ltf->data[i], ioaddr);                i++;        }	if(cops_debug > 1)		printk("%s: Uploaded firmware - %d bytes of %d bytes.\n", 			dev->name, i, ltf->length);        if(lp->board==DAYNA) 	/* Tell Dayna to run the firmware code. */                outb(1, ioaddr+DAYNA_INT_CARD);	else			/* Tell Tang to run the firmware code. */		inb(ioaddr);        if(lp->board==TANGENT)        {                tangent_wait_reset(ioaddr);                inb(ioaddr);	/* Clear initial ready signal. */        }        return;}/* * 	Get the LocalTalk Nodeid from the card. We can suggest *	any nodeid 1-254. The card will try and get that exact *	address else we can specify 0 as the nodeid and the card *	will autoprobe for a nodeid. */static int cops_nodeid (struct net_device *dev, int nodeid){	struct cops_local *lp = netdev_priv(dev);	int ioaddr = dev->base_addr;	if(lp->board == DAYNA)        {        	/* Empty any pending adapter responses. */                while((inb(ioaddr+DAYNA_CARD_STATUS)&DAYNA_TX_READY)==0)                {			outb(0, ioaddr+COPS_CLEAR_INT);	/* Clear interrupts. */        		if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST)                		cops_rx(dev);	/* Kick any packets waiting. */			schedule();                }                outb(2, ioaddr);       	/* Output command packet length as 2. */                outb(0, ioaddr);                outb(LAP_INIT, ioaddr);	/* Send LAP_INIT command byte. */                outb(nodeid, ioaddr);  	/* Suggest node address. */        }	if(lp->board == TANGENT)        {                /* Empty any pending adapter responses. */                while(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)                {			outb(0, ioaddr+COPS_CLEAR_INT);	/* Clear interrupt. */                	cops_rx(dev);          	/* Kick out packets waiting. */			schedule();                }		/* Not sure what Tangent does if nodeid picked is used. */                if(nodeid == 0)	         		/* Seed. */                	nodeid = jiffies&0xFF;		/* Get a random try */                outb(2, ioaddr);        		/* Command length LSB */                outb(0, ioaddr);       			/* Command length MSB */                outb(LAP_INIT, ioaddr); 		/* Send LAP_INIT byte */                outb(nodeid, ioaddr); 		  	/* LAP address hint. */                outb(0xFF, ioaddr);     		/* Int. level to use */        }	lp->node_acquire=0;		/* Set nodeid holder to 0. */        while(lp->node_acquire==0)	/* Get *True* nodeid finally. */	{		outb(0, ioaddr+COPS_CLEAR_INT);	/* Clear any interrupt. */		if(lp->board == DAYNA)		{                	if((inb(ioaddr+DAYNA_CARD_STATUS)&0x03)==DAYNA_RX_REQUEST)                		cops_rx(dev);	/* Grab the nodeid put in lp->node_acquire. */		}		if(lp->board == TANGENT)		{				if(inb(ioaddr+TANG_CARD_STATUS)&TANG_RX_READY)                                cops_rx(dev);   /* Grab the nodeid put in lp->node_acquire. */		}		schedule();	}	if(cops_debug > 1)		printk(KERN_DEBUG "%s: Node ID %d has been acquired.\n", 			dev->name, lp->node_acquire);	lp->nodeid=1;	/* Set got nodeid to 1. */        return 0;}/* *	Poll the Tangent type cards to see if we have work. */ static void cops_poll(unsigned long ltdev){	int ioaddr, status;	int boguscount = 0;	struct net_device *dev = (struct net_device *)ltdev;	del_timer(&cops_timer);	if(dev == NULL)		return;	/* We've been downed */	ioaddr = dev->base_addr;	do {		status=inb(ioaddr+TANG_CARD_STATUS);		if(status & TANG_RX_READY)			cops_rx(dev);

⌨️ 快捷键说明

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