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

📄 3c505.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 4 页
字号:
					switch (adapter->irx_pcb.data.xmit_resp.c_stat) {					case 0xffff:						adapter->stats.tx_aborted_errors++;						printk(KERN_INFO "%s: transmit timed out, network cable problem?\n", dev->name);						break;					case 0xfffe:						adapter->stats.tx_fifo_errors++;						printk(KERN_INFO "%s: transmit timed out, FIFO underrun\n", dev->name);						break;					}					dev->tbusy = 0;					mark_bh(NET_BH);					break;					/*					 * some unknown PCB					 */				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(0x00, dev->base_addr);	/*	 * 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;	/*	 * make sure we can find the device header given the interrupt number	 */	irq2dev_map[dev->irq] = dev;	/*	 * install our interrupt service routine	 */	if (request_irq(dev->irq, &elp_interrupt, 0, "3c505", NULL)) {		irq2dev_map[dev->irq] = NULL;		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->base_addr);	/*	 * device is now officially open!	 */	dev->start = 1;	/*	 * 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 && jiffies < timeout);		if (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 && jiffies < timeout);		if (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);	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;	/*	 * make sure the length is even and no shorter than 60 bytes	 */	unsigned int nlen = (((skb->len < 60) ? 60 : skb->len) + 1) & (~1);	if (set_bit(0, (void *) &adapter->busy)) {		if (elp_debug >= 2)			printk("%s: transmit blocked\n", dev->name);		return FALSE;	}	adapter = dev->priv;	/*	 * 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 (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;	cli();	disable_dma(dev->dma);	clear_dma_ff(dev->dma);	set_dma_mode(dev->dma, 0x08);	/* dma memory -> io */	set_dma_addr(dev->dma, target);	set_dma_count(dev->dma, nlen);	enable_dma(dev->dma);	outb_control(inb_control(dev->base_addr) | DMAE | TCEN, dev->base_addr);	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_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++;	}	/* Some upper layer thinks we've missed a tx-done interrupt */	if (skb == NULL) {		dev_tint(dev);		return 0;	}	if (skb->len <= 0)		return 0;	if (elp_debug >= 3)		printk("%s: request to send packet of length %d\n", dev->name, (int) skb->len);	if (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 enet_statistics *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 && jiffies < timeout);		if (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(0x00, dev->base_addr);	/*	 *  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, NULL);	/*	 * and we no longer have to map irq to dev either	 */	irq2dev_map[dev->irq] = 0;	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;

⌨️ 快捷键说明

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