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

📄 3c505.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
				default:					printk(KERN_DEBUG "%s: unknown PCB received - %2.2x\n", dev->name, adapter->irx_pcb.command);					break;				}			} else {				printk("%s: failed to read PCB on interrupt\n", dev->name);				adapter_reset(dev);			}		}	} while (icount++ < 5 && (inb_status(dev->base_addr) & (ACRF | DONE)));	prime_rx(dev);	/*	 * indicate no longer in interrupt routine	 */	dev->interrupt = 0;}/****************************************************** * * open the board * ******************************************************/static int elp_open(struct device *dev){	elp_device *adapter;	adapter = dev->priv;	if (elp_debug >= 3)		printk("%s: request to open device\n", dev->name);	/*	 * make sure we actually found the device	 */	if (adapter == NULL) {		printk("%s: Opening a non-existent physical device\n", dev->name);		return -EAGAIN;	}	/*	 * disable interrupts on the board	 */	outb_control(0, dev);	/*	 * clear any pending interrupts	 */	inb_command(dev->base_addr);	adapter_reset(dev);	/*	 * interrupt routine not entered	 */	dev->interrupt = 0;	/*	 *  transmitter not busy	 */	dev->tbusy = 0;	/*	 * no receive PCBs active	 */	adapter->rx_active = 0;	adapter->busy = 0;	adapter->send_pcb_semaphore = 0;	adapter->rx_backlog.in = 0;	adapter->rx_backlog.out = 0;	/*	 * install our interrupt service routine	 */	if (request_irq(dev->irq, &elp_interrupt, 0, "3c505", dev)) {		return -EAGAIN;	}	if (request_dma(dev->dma, "3c505")) {		printk("%s: could not allocate DMA channel\n", dev->name);		return -EAGAIN;	}	adapter->dma_buffer = (void *) dma_mem_alloc(DMA_BUFFER_SIZE);	if (!adapter->dma_buffer) {		printk("Could not allocate DMA buffer\n");	}	adapter->dmaing = 0;	/*	 * enable interrupts on the board	 */	outb_control(CMDE, dev);	/*	 * configure adapter memory: we need 10 multicast addresses, default==0	 */	if (elp_debug >= 3)		printk("%s: sending 3c505 memory configuration command\n", dev->name);	adapter->tx_pcb.command = CMD_CONFIGURE_ADAPTER_MEMORY;	adapter->tx_pcb.data.memconf.cmd_q = 10;	adapter->tx_pcb.data.memconf.rcv_q = 20;	adapter->tx_pcb.data.memconf.mcast = 10;	adapter->tx_pcb.data.memconf.frame = 20;	adapter->tx_pcb.data.memconf.rcv_b = 20;	adapter->tx_pcb.data.memconf.progs = 0;	adapter->tx_pcb.length = sizeof(struct Memconf);	adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 0;	if (!send_pcb(dev, &adapter->tx_pcb))		printk("%s: couldn't send memory configuration command\n", dev->name);	else {		int timeout = jiffies + TIMEOUT;		while (adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] == 0 && time_before(jiffies, timeout));		if (time_after_eq(jiffies, timeout))			TIMEOUT_MSG(__LINE__);	}	/*	 * configure adapter to receive broadcast messages and wait for response	 */	if (elp_debug >= 3)		printk("%s: sending 82586 configure command\n", dev->name);	adapter->tx_pcb.command = CMD_CONFIGURE_82586;	adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;	adapter->tx_pcb.length = 2;	adapter->got[CMD_CONFIGURE_82586] = 0;	if (!send_pcb(dev, &adapter->tx_pcb))		printk("%s: couldn't send 82586 configure command\n", dev->name);	else {		int timeout = jiffies + TIMEOUT;		while (adapter->got[CMD_CONFIGURE_82586] == 0 && time_before(jiffies, timeout));		if (time_after_eq(jiffies, timeout))			TIMEOUT_MSG(__LINE__);	}	/* enable burst-mode DMA */	/* outb(0x1, dev->base_addr + PORT_AUXDMA); */	/*	 * queue receive commands to provide buffering	 */	prime_rx(dev);	if (elp_debug >= 3)		printk("%s: %d receive PCBs active\n", dev->name, adapter->rx_active);	/*	 * device is now officially open!	 */	dev->start = 1;	MOD_INC_USE_COUNT;	return 0;		/* Always succeed */}/****************************************************** * * send a packet to the adapter * ******************************************************/static int send_packet(struct device *dev, struct sk_buff *skb){	elp_device *adapter = dev->priv;	unsigned long target;	unsigned long flags;	/*	 * make sure the length is even and no shorter than 60 bytes	 */	unsigned int nlen = (((skb->len < 60) ? 60 : skb->len) + 1) & (~1);	if (test_and_set_bit(0, (void *) &adapter->busy)) {		if (elp_debug >= 2)			printk("%s: transmit blocked\n", dev->name);		return FALSE;	}	adapter->stats.tx_bytes += nlen;		/*	 * send the adapter a transmit packet command. Ignore segment and offset	 * and make sure the length is even	 */	adapter->tx_pcb.command = CMD_TRANSMIT_PACKET;	adapter->tx_pcb.length = sizeof(struct Xmit_pkt);	adapter->tx_pcb.data.xmit_pkt.buf_ofs	    = adapter->tx_pcb.data.xmit_pkt.buf_seg = 0;	/* Unused */	adapter->tx_pcb.data.xmit_pkt.pkt_len = nlen;	if (!send_pcb(dev, &adapter->tx_pcb)) {		adapter->busy = 0;		return FALSE;	}	/* if this happens, we die */	if (test_and_set_bit(0, (void *) &adapter->dmaing))		printk("%s: tx: DMA %d in progress\n", dev->name, adapter->current_dma.direction);	adapter->current_dma.direction = 1;	adapter->current_dma.start_time = jiffies;	target = virt_to_bus(skb->data);	if ((target + nlen) >= MAX_DMA_ADDRESS) {		memcpy(adapter->dma_buffer, skb->data, nlen);		target = virt_to_bus(adapter->dma_buffer);	}	adapter->current_dma.skb = skb;	flags=claim_dma_lock();	disable_dma(dev->dma);	clear_dma_ff(dev->dma);	set_dma_mode(dev->dma, 0x48);	/* dma memory -> io */	set_dma_addr(dev->dma, target);	set_dma_count(dev->dma, nlen);	outb_control(adapter->hcr_val | DMAE | TCEN, dev);	enable_dma(dev->dma);	release_dma_lock(flags);		if (elp_debug >= 3)		printk("%s: DMA transfer started\n", dev->name);	return TRUE;}/****************************************************** * * start the transmitter *    return 0 if sent OK, else return 1 * ******************************************************/static int elp_start_xmit(struct sk_buff *skb, struct device *dev){	if (dev->interrupt) {		printk("%s: start_xmit aborted (in irq)\n", dev->name);		return 1;	}	check_3c505_dma(dev);	/*	 * if the transmitter is still busy, we have a transmit timeout...	 */	if (dev->tbusy) {		elp_device *adapter = dev->priv;       		int tickssofar = jiffies - dev->trans_start;		int stat;		if (tickssofar < 1000)			return 1;		stat = inb_status(dev->base_addr);		printk("%s: transmit timed out, lost %s?\n", dev->name, (stat & ACRF) ? "interrupt" : "command");		if (elp_debug >= 1)			printk("%s: status %#02x\n", dev->name, stat);		dev->trans_start = jiffies;		dev->tbusy = 0;		adapter->stats.tx_dropped++;	}	if (elp_debug >= 3)		printk("%s: request to send packet of length %d\n", dev->name, (int) skb->len);	if (test_and_set_bit(0, (void *) &dev->tbusy)) {		printk("%s: transmitter access conflict\n", dev->name);		return 1;	}	/*	 * send the packet at skb->data for skb->len	 */	if (!send_packet(dev, skb)) {		if (elp_debug >= 2) {			printk("%s: failed to transmit packet\n", dev->name);		}		dev->tbusy = 0;		return 1;	}	if (elp_debug >= 3)		printk("%s: packet of length %d sent\n", dev->name, (int) skb->len);	/*	 * start the transmit timeout	 */	dev->trans_start = jiffies;	prime_rx(dev);	return 0;}/****************************************************** * * return statistics on the board * ******************************************************/static struct net_device_stats *elp_get_stats(struct device *dev){	elp_device *adapter = (elp_device *) dev->priv;	if (elp_debug >= 3)		printk("%s: request for stats\n", dev->name);	/* If the device is closed, just return the latest stats we have,	   - we cannot ask from the adapter without interrupts */	if (!dev->start)		return &adapter->stats;	/* send a get statistics command to the board */	adapter->tx_pcb.command = CMD_NETWORK_STATISTICS;	adapter->tx_pcb.length = 0;	adapter->got[CMD_NETWORK_STATISTICS] = 0;	if (!send_pcb(dev, &adapter->tx_pcb))		printk("%s: couldn't send get statistics command\n", dev->name);	else {		int timeout = jiffies + TIMEOUT;		while (adapter->got[CMD_NETWORK_STATISTICS] == 0 && time_before(jiffies, timeout));		if (time_after_eq(jiffies, timeout)) {			TIMEOUT_MSG(__LINE__);			return &adapter->stats;		}	}	/* statistics are now up to date */	return &adapter->stats;}/****************************************************** * * close the board * ******************************************************/static int elp_close(struct device *dev){	elp_device *adapter;	adapter = dev->priv;	if (elp_debug >= 3)		printk("%s: request to close device\n", dev->name);	/* Someone may request the device statistic information even when	 * the interface is closed. The following will update the statistics	 * structure in the driver, so we'll be able to give current statistics.	 */	(void) elp_get_stats(dev);	/*	 * disable interrupts on the board	 */	outb_control(0, dev);	/*	 *  flag transmitter as busy (i.e. not available)	 */	dev->tbusy = 1;	/*	 *  indicate device is closed	 */	dev->start = 0;	/*	 * release the IRQ	 */	free_irq(dev->irq, dev);	free_dma(dev->dma);	free_pages((unsigned long) adapter->dma_buffer, __get_order(DMA_BUFFER_SIZE));	MOD_DEC_USE_COUNT;	return 0;}/************************************************************ * * Set multicast list * num_addrs==0: clear mc_list * num_addrs==-1: set promiscuous mode * num_addrs>0: set mc_list * ************************************************************/static void elp_set_mc_list(struct device *dev){	elp_device *adapter = (elp_device *) dev->priv;	struct dev_mc_list *dmi = dev->mc_list;	int i;	if (elp_debug >= 3)		printk("%s: request to set multicast list\n", dev->name);	if (!(dev->flags & (IFF_PROMISC | IFF_ALLMULTI))) {		/* send a "load multicast list" command to the board, max 10 addrs/cmd */		/* if num_addrs==0 the list will be cleared */		adapter->tx_pcb.command = CMD_LOAD_MULTICAST_LIST;		adapter->tx_pcb.length = 6 * dev->mc_count;		for (i = 0; i < dev->mc_count; i++) {			memcpy(adapter->tx_pcb.data.multicast[i], dmi->dmi_addr, 6);			dmi = dmi->next;		}		adapter->got[CMD_LOAD_MULTICAST_LIST] = 0;		if (!send_pcb(dev, &adapter->tx_pcb))			printk("%s: couldn't send set_multicast command\n", dev->name);		else {			int timeout = jiffies + TIMEOUT;			while (adapter->got[CMD_LOAD_MULTICAST_LIST] == 0 && time_before(jiffies, timeout));			if (time_after_eq(jiffies, timeout)) {				TIMEOUT_MSG(__LINE__);			}		}		if (dev->mc_count)			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD | RECV_MULTI;		else		/* num_addrs == 0 */			adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_BROAD;	} else		adapter->tx_pcb.data.configure = NO_LOOPBACK | RECV_PROMISC;	/*	 * configure adapter to receive messages (as specified above)	 * and wait for response	 */	if (elp_debug >= 3)		printk("%s: sending 82586 configure command\n", dev->name);	adapter->tx_pcb.command = CMD_CONFIGURE_82586;

⌨️ 快捷键说明

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