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

📄 3c505.c

📁 GNU Mach 微内核源代码, 基于美国卡内基美隆大学的 Mach 研究项目
💻 C
📖 第 1 页 / 共 4 页
字号:
 * to respond to the initial interrupt. * * We run initially with interrupts turned on, but with a semaphore set * so that nobody tries to re-enter this code.  Once the first byte has * gone through, we turn interrupts off and then send the others (the * timeout is reduced to 500us). */static int send_pcb(struct device *dev, pcb_struct * pcb){	int i;	int timeout;	elp_device *adapter = dev->priv;	check_dma(dev);	if (adapter->dmaing && adapter->current_dma.direction == 0)		return FALSE;	/* Avoid contention */	if (set_bit(1, &adapter->send_pcb_semaphore)) {		if (elp_debug >= 3) {			printk("%s: send_pcb entered while threaded\n", dev->name);		}		return FALSE;	}	/*	 * load each byte into the command register and	 * wait for the HCRE bit to indicate the adapter	 * had read the byte	 */	set_hsf(dev->base_addr, 0);	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(inb_control(dev->base_addr) | 3, dev->base_addr);	/* signal end of PCB */	outb_command(2 + pcb->length, dev->base_addr);	/* now wait for the acknowledgement */	sti();	for (timeout = jiffies + 5; jiffies < timeout;) {		switch (GET_ASF(dev->base_addr)) {		case ASF_PCB_ACK:			adapter->send_pcb_semaphore = 0;			return TRUE;			break;		case ASF_PCB_NAK:			printk("%s: send_pcb got NAK\n", dev->name);			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->base_addr, 0);	/* get the command code */	timeout = jiffies + 2;	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && jiffies < timeout);	if (jiffies >= timeout) {		TIMEOUT_MSG(__LINE__);		return FALSE;	}	pcb->command = inb_command(dev->base_addr);	/* read the data length */	timeout = jiffies + 3;	while (((stat = get_status(dev->base_addr)) & ACRF) == 0 && jiffies < timeout);	if (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->base_addr, HSF_PCB_NAK);		return FALSE;	}	if (pcb->command == CMD_RECEIVE_PACKET_COMPLETE) {		if (set_bit(0, (void *) &adapter->busy)) {			if (backlog_next(adapter->rx_backlog.in) == adapter->rx_backlog.out) {				set_hsf(dev->base_addr, 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->base_addr, 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;	unsigned long target;	struct sk_buff *skb;	rlen = (len + 1) & ~1;	skb = dev_alloc_skb(rlen + 2);	adapter->current_dma.copy_flag = 0;	if (!skb) {	  printk("%s: memory squeeze, dropping packet\n", dev->name);	  target = virt_to_bus(adapter->dma_buffer);	} else {	  skb_reserve(skb, 2);	  target = virt_to_bus(skb_put(skb, rlen));	  if ((target + rlen) >= MAX_DMA_ADDRESS) {	    target = virt_to_bus(adapter->dma_buffer);	    adapter->current_dma.copy_flag = 1;	  }	}	/* if this happens, we die */	if (set_bit(0, (void *) &adapter->dmaing))		printk("%s: rx blocked, DMA in progress, dir %d\n", dev->name, adapter->current_dma.direction);	adapter->current_dma.direction = 0;	adapter->current_dma.length = rlen;	adapter->current_dma.skb = skb;	adapter->current_dma.start_time = jiffies;	outb_control(inb_control(dev->base_addr) | DIR | TCEN | DMAE, dev->base_addr);	disable_dma(dev->dma);	clear_dma_ff(dev->dma);	set_dma_mode(dev->dma, 0x04);	/* dma read */	set_dma_addr(dev->dma, target);	set_dma_count(dev->dma, rlen);	enable_dma(dev->dma);	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 = irq2dev_map[irq];	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(inb_control(dev->base_addr) & ~(DMAE | TCEN | DIR), dev->base_addr);			if (adapter->current_dma.direction) {				dev_kfree_skb(adapter->current_dma.skb, FREE_WRITE);			} else {				struct sk_buff *skb = adapter->current_dma.skb;				if (skb) {				  skb->dev = dev;				  if (adapter->current_dma.copy_flag) {				    memcpy(skb_put(skb, adapter->current_dma.length), adapter->dma_buffer, adapter->current_dma.length);				  }				  skb->protocol = eth_type_trans(skb,dev);				  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_dma(dev);		}		sti();		/*		 * receive a PCB from the adapter		 */		timeout = jiffies + 3;		while ((inb_status(dev->base_addr) & ACRF) != 0 && 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;

⌨️ 快捷键说明

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