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

📄 3c505.c

📁 powerpc内核mpc8241linux系统下net驱动程序
💻 C
📖 第 1 页 / 共 4 页
字号:
	if (send_pcb_slow(dev->base_addr, pcb->command))		goto abort;	cli();	if (send_pcb_fast(dev->base_addr, pcb->length))		goto sti_abort;	for (i = 0; i < pcb->length; i++) {		if (send_pcb_fast(dev->base_addr, pcb->data.raw[i]))			goto sti_abort;	}	outb_control(adapter->hcr_val | 3, dev);	/* signal end of PCB */	outb_command(2 + pcb->length, dev->base_addr);	/* now wait for the acknowledgement */	sti();	for (timeout = jiffies + 5*HZ/100; time_before(jiffies, timeout);) {		switch (GET_ASF(dev->base_addr)) {		case ASF_PCB_ACK:			adapter->send_pcb_semaphore = 0;			return TRUE;			break;		case ASF_PCB_NAK:#ifdef ELP_DEBUG			printk(KERN_DEBUG "%s: send_pcb got NAK\n", dev->name);#endif			goto abort;			break;		}	}	if (elp_debug >= 1)		printk("%s: timeout waiting for PCB acknowledge (status %02x)\n", dev->name, inb_status(dev->base_addr));      sti_abort:	sti();      abort:	adapter->send_pcb_semaphore = 0;	return FALSE;}/***************************************************************** * * receive_pcb *   Read a PCB from the adapter * *	wait for ACRF to be non-zero        ---<---+ *	input a byte                               | *	if ASF1 and ASF2 were not both one         | *		before byte was read, loop      --->---+ *	set HSF1 and HSF2 for ack * *****************************************************************/static int receive_pcb(struct device *dev, pcb_struct * pcb){	int i, j;	int total_length;	int stat;	int timeout;	elp_device *adapter = dev->priv;	set_hsf(dev, 0);	/* get the command code */	timeout = jiffies + 2*HZ/100;	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));	if (time_after_eq(jiffies, timeout)) {		TIMEOUT_MSG(__LINE__);		return FALSE;	}	pcb->command = inb_command(dev->base_addr);	/* read the data length */	timeout = jiffies + 3*HZ/100;	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && time_before(jiffies, timeout));	if (time_after_eq(jiffies, timeout)) {		TIMEOUT_MSG(__LINE__);		printk("%s: status %02x\n", dev->name, stat);		return FALSE;	}	pcb->length = inb_command(dev->base_addr);	if (pcb->length > MAX_PCB_DATA) {		INVALID_PCB_MSG(pcb->length);		adapter_reset(dev);		return FALSE;	}	/* read the data */	cli();	i = 0;	do {		j = 0;		while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && j++ < 20000);		pcb->data.raw[i++] = inb_command(dev->base_addr);		if (i > MAX_PCB_DATA)			INVALID_PCB_MSG(i);	} while ((stat & ASF_PCB_MASK) != ASF_PCB_END && j < 20000);	sti();	if (j >= 20000) {		TIMEOUT_MSG(__LINE__);		return FALSE;	}	/* woops, the last "data" byte was really the length! */	total_length = pcb->data.raw[--i];	/* safety check total length vs data length */	if (total_length != (pcb->length + 2)) {		if (elp_debug >= 2)			printk("%s: mangled PCB received\n", dev->name);		set_hsf(dev, HSF_PCB_NAK);		return FALSE;	}	if (pcb->command == CMD_RECEIVE_PACKET_COMPLETE) {		if (test_and_set_bit(0, (void *) &adapter->busy)) {			if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) {				set_hsf(dev, HSF_PCB_NAK);				printk("%s: PCB rejected, transfer in progress and backlog full\n", dev->name);				pcb->command = 0;				return TRUE;			} else {				pcb->command = 0xff;			}		}	}	set_hsf(dev, HSF_PCB_ACK);	return TRUE;}/****************************************************** * *  queue a receive command on the adapter so we will get an *  interrupt when a packet is received. * ******************************************************/static int start_receive(struct device *dev, pcb_struct * tx_pcb){	int status;	elp_device *adapter = dev->priv;	if (elp_debug >= 3)		printk("%s: restarting receiver\n", dev->name);	tx_pcb->command = CMD_RECEIVE_PACKET;	tx_pcb->length = sizeof(struct Rcv_pkt);	tx_pcb->data.rcv_pkt.buf_seg	    = tx_pcb->data.rcv_pkt.buf_ofs = 0;		/* Unused */	tx_pcb->data.rcv_pkt.buf_len = 1600;	tx_pcb->data.rcv_pkt.timeout = 0;	/* set timeout to zero */	status = send_pcb(dev, tx_pcb);	if (status)		adapter->rx_active++;	return status;}/****************************************************** * * extract a packet from the adapter * this routine is only called from within the interrupt * service routine, so no cli/sti calls are needed * note that the length is always assumed to be even * ******************************************************/static void receive_packet(struct device *dev, int len){	int rlen;	elp_device *adapter = dev->priv;	void *target;	struct sk_buff *skb;	unsigned long flags;	rlen = (len + 1) & ~1;	skb = dev_alloc_skb(rlen + 2);	if (!skb) {		printk("%s: memory squeeze, dropping packet\n", dev->name);		target = adapter->dma_buffer;		adapter->current_dma.target = NULL;	} else {		skb_reserve(skb, 2);		target = skb_put(skb, rlen);		if (virt_to_bus(target + rlen) >= MAX_DMA_ADDRESS) {			adapter->current_dma.target = target;			target = adapter->dma_buffer;		} else {			adapter->current_dma.target = NULL;		}	}	/* if this happens, we die */	if (test_and_set_bit(0, (void *) &adapter->dmaing))		printk("%s: rx blocked, DMA in progress, dir %d\n", dev->name, adapter->current_dma.direction);	skb->dev = dev;	adapter->current_dma.direction = 0;	adapter->current_dma.length = rlen;	adapter->current_dma.skb = skb;	adapter->current_dma.start_time = jiffies;	outb_control(adapter->hcr_val | DIR | TCEN | DMAE, dev);	flags=claim_dma_lock();	disable_dma(dev->dma);	clear_dma_ff(dev->dma);	set_dma_mode(dev->dma, 0x04);	/* dma read */	set_dma_addr(dev->dma, virt_to_bus(target));	set_dma_count(dev->dma, rlen);	enable_dma(dev->dma);	release_dma_lock(flags);	if (elp_debug >= 3) {		printk("%s: rx DMA transfer started\n", dev->name);	}	if (adapter->rx_active)		adapter->rx_active--;	if (!adapter->busy)		printk("%s: receive_packet called, busy not set.\n", dev->name);}/****************************************************** * * interrupt handler * ******************************************************/static void elp_interrupt(int irq, void *dev_id, struct pt_regs *reg_ptr){	int len;	int dlen;	int icount = 0;	struct device *dev;	elp_device *adapter;	int timeout;	if (irq < 0 || irq > 15) {		printk("elp_interrupt(): illegal IRQ number found in interrupt routine (%i)\n", irq);		return;	}	dev = dev_id;	if (dev == NULL) {		printk("elp_interrupt(): irq %d for unknown device.\n", irq);		return;	}	adapter = (elp_device *) dev->priv;	if (dev->interrupt) {		printk("%s: re-entering the interrupt handler!\n", dev->name);		return;	}	dev->interrupt = 1;	do {		/*		 * has a DMA transfer finished?		 */		if (inb_status(dev->base_addr) & DONE) {			if (!adapter->dmaing) {				printk("%s: phantom DMA completed\n", dev->name);			}			if (elp_debug >= 3) {				printk("%s: %s DMA complete, status %02x\n", dev->name, adapter->current_dma.direction ? "tx" : "rx", inb_status(dev->base_addr));			}			outb_control(adapter->hcr_val & ~(DMAE | TCEN | DIR),				     dev);			if (adapter->current_dma.direction) {				dev_kfree_skb(adapter->current_dma.skb);			} else {				struct sk_buff *skb = adapter->current_dma.skb;				if (skb) {				  if (adapter->current_dma.target) {				    /* have already done the skb_put() */				    memcpy(adapter->current_dma.target, adapter->dma_buffer, adapter->current_dma.length);				  }				  skb->protocol = eth_type_trans(skb,dev);				  adapter->stats.rx_bytes += skb->len;				  netif_rx(skb);				}			}			adapter->dmaing = 0;			if (adapter->rx_backlog.in != adapter->rx_backlog.out) {				int t = adapter->rx_backlog.length[adapter->rx_backlog.out];				adapter->rx_backlog.out = backlog_next(adapter->rx_backlog.out);				if (elp_debug >= 2)					printk("%s: receiving backlogged packet (%d)\n", dev->name, t);				receive_packet(dev, t);			} else {				adapter->busy = 0;			}		} else {			/* has one timed out? */			check_3c505_dma(dev);		}		sti();		/*		 * receive a PCB from the adapter		 */		timeout = jiffies + 3*HZ/100;		while ((inb_status(dev->base_addr) & ACRF) != 0 && time_before(jiffies, timeout)) {			if (receive_pcb(dev, &adapter->irx_pcb)) {				switch (adapter->irx_pcb.command) {				case 0:					break;					/*					 * received a packet - this must be handled fast					 */				case 0xff:				case CMD_RECEIVE_PACKET_COMPLETE:					/* if the device isn't open, don't pass packets up the stack */					if (dev->start == 0)						break;					cli();					len = adapter->irx_pcb.data.rcv_resp.pkt_len;					dlen = adapter->irx_pcb.data.rcv_resp.buf_len;					if (adapter->irx_pcb.data.rcv_resp.timeout != 0) {						printk("%s: interrupt - packet not received correctly\n", dev->name);						sti();					} else {						if (elp_debug >= 3) {							sti();							printk("%s: interrupt - packet received of length %i (%i)\n", dev->name, len, dlen);							cli();						}						if (adapter->irx_pcb.command == 0xff) {							if (elp_debug >= 2)								printk("%s: adding packet to backlog (len = %d)\n", dev->name, dlen);							adapter->rx_backlog.length[adapter->rx_backlog.in] = dlen;							adapter->rx_backlog.in = backlog_next(adapter->rx_backlog.in);						} else {							receive_packet(dev, dlen);						}						sti();						if (elp_debug >= 3)							printk("%s: packet received\n", dev->name);					}					break;					/*					 * 82586 configured correctly					 */				case CMD_CONFIGURE_82586_RESPONSE:					adapter->got[CMD_CONFIGURE_82586] = 1;					if (elp_debug >= 3)						printk("%s: interrupt - configure response received\n", dev->name);					break;					/*					 * Adapter memory configuration					 */				case CMD_CONFIGURE_ADAPTER_RESPONSE:					adapter->got[CMD_CONFIGURE_ADAPTER_MEMORY] = 1;					if (elp_debug >= 3)						printk("%s: Adapter memory configuration %s.\n", dev->name,						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");					break;					/*					 * Multicast list loading					 */				case CMD_LOAD_MULTICAST_RESPONSE:					adapter->got[CMD_LOAD_MULTICAST_LIST] = 1;					if (elp_debug >= 3)						printk("%s: Multicast address list loading %s.\n", dev->name,						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");					break;					/*					 * Station address setting					 */				case CMD_SET_ADDRESS_RESPONSE:					adapter->got[CMD_SET_STATION_ADDRESS] = 1;					if (elp_debug >= 3)						printk("%s: Ethernet address setting %s.\n", dev->name,						       adapter->irx_pcb.data.failed ? "failed" : "succeeded");					break;					/*					 * received board statistics					 */				case CMD_NETWORK_STATISTICS_RESPONSE:					adapter->stats.rx_packets += adapter->irx_pcb.data.netstat.tot_recv;					adapter->stats.tx_packets += adapter->irx_pcb.data.netstat.tot_xmit;					adapter->stats.rx_crc_errors += adapter->irx_pcb.data.netstat.err_CRC;					adapter->stats.rx_frame_errors += adapter->irx_pcb.data.netstat.err_align;					adapter->stats.rx_fifo_errors += adapter->irx_pcb.data.netstat.err_ovrrun;					adapter->stats.rx_over_errors += adapter->irx_pcb.data.netstat.err_res;					adapter->got[CMD_NETWORK_STATISTICS] = 1;					if (elp_debug >= 3)						printk("%s: interrupt - statistics response received\n", dev->name);					break;					/*					 * sent a packet					 */				case CMD_TRANSMIT_PACKET_COMPLETE:					if (elp_debug >= 3)						printk("%s: interrupt - packet sent\n", dev->name);					if (dev->start == 0)						break;					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					 */

⌨️ 快捷键说明

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