示例#1
0
void nic_isr(snic *nic) {
	uint isr;	/* Illinois Sreet Residence Hall */
	uint overload;
	if(!nic || !nic->iobase) return;    /* make sure card was initialized */
	outb_p(NIC_DMA_DISABLE | NIC_PAGE0, nic->iobase);
	overload=MAX_LOAD+1;
	while((isr=inb_p(nic->iobase+INTERRUPTSTATUS))) {
		if((--overload)<=0) break;
		if(isr & ISR_OVW)			nic_overrun(nic);
		else if(isr & (ISR_PRX | ISR_RXE))	nic_rx(nic);
		if(isr & ISR_PTX)			nic_tx(nic);
		else if(isr & ISR_TXE)			nic_tx_err(nic);
		if(isr & ISR_CNT)			nic_counters(nic);
		if(isr & ISR_RDC) outb_p(ISR_RDC, nic->iobase+ INTERRUPTSTATUS);
		outb_p(NIC_DMA_DISABLE | NIC_PAGE0 | NIC_START, nic->iobase);
	}
	if(isr) {
		outb_p(NIC_DMA_DISABLE | NIC_PAGE0 | NIC_START, nic->iobase);
		if(!overload) {
			kprintf("NE2000: Too many requests in ISR.  ISR:%X  MaxLoad:%X\n",
				isr, MAX_LOAD);
			outb_p(ISR_ALL, nic->iobase + INTERRUPTSTATUS); // clear
		} else {
			kprintf("NE2000: Unhandeled interrupt, ISR:%X\n",isr);
			outb_p(0xff, nic->iobase + INTERRUPTSTATUS);
								// Ack it anyway
		}
	}
}
示例#2
0
文件: nic.c 项目: sunank200/ATOM-OS
static int ring_ovfl(snic *nic)
{
	unsigned char isr;
	int iobase = nic->iobase;
	int i;

	outportg(0x21, iobase);
	outportg(0x0, iobase + REMOTEBYTECOUNT0);
	outportg(0x0, iobase + REMOTEBYTECOUNT1);
	
	for (i=0; i<0x7fff; i++)
	{
		isr=inportb(iobase+INTERRUPTSTATUS);

		if ((isr & 0x80) == 0) break;
	}
	
	outportg(TCR_INTERNAL_LOOPBACK, iobase + TRANSMITCONFIGURATION);
	outportg(0x22, iobase);  //?
	nic_rx(nic);
	outportg(0x10, iobase+INTERRUPTSTATUS);

	outportg(TCR_DEFAULT, iobase + TRANSMITCONFIGURATION);

	return 0;
}
示例#3
0
static void nic_hw_xmit(struct net_device *netdev)
{
    struct nic_priv *priv = netdev_priv(netdev);
    struct iphdr *iph;
    u32 *saddr, *daddr;
    struct in_device* in_dev;
    struct in_ifaddr* if_info;

    if (priv->tx_len < sizeof(struct ethhdr) + sizeof(struct iphdr)) {
        netif_info(priv, hw, netdev, "%s(#%d), too short\n",
                   __func__, __LINE__);
        return;
    }
    dump(priv->tx_buf);
    iph = (struct iphdr *)(priv->tx_buf + sizeof(struct ethhdr));
    saddr = &iph->saddr;
    daddr = &iph->daddr;

    netif_info(priv, hw, netdev, "%s(#%d), orig, src:%pI4, dst:%pI4, len:%d\n",
                __func__, __LINE__, saddr, daddr, priv->tx_len);

    in_dev = nic_dev[(netdev == nic_dev[0] ? 1 : 0)]->ip_ptr;
    if (in_dev) {
        if_info = in_dev->ifa_list;
        for (if_info = in_dev->ifa_list; if_info; if_info=if_info->ifa_next) {
#if 0
            printk("label:%s, address=%pI4\n",
               if_info->ifa_label, &if_info->ifa_address);
#endif
            *saddr = *daddr = if_info->ifa_address;
            ((u8 *)saddr)[3]++;
            netif_info(priv, hw, netdev, "%s(#%d), new, src:%pI4, dst:%pI4\n",
                        __func__, __LINE__, saddr, daddr);
            break;
        }
        if (!if_info) {
            /* drop packet */
            netdev->stats.tx_dropped++;
            netif_info(priv, hw, netdev, "%s(#%d), drop packet\n",
                        __func__, __LINE__);
            return;
        }
    }

    iph->check = 0;         /* and rebuild the checksum (ip needs it) */
    iph->check = ip_fast_csum((unsigned char *)iph, iph->ihl);

    netdev->stats.tx_packets++;
    netdev->stats.tx_bytes += priv->tx_len;

    nic_rx(nic_dev[(netdev == nic_dev[0] ? 1 : 0)], priv->tx_len, priv->tx_buf);
}
示例#4
0
文件: nic.c 项目: sunank200/ATOM-OS
// Main interrupt handling task.
void nic_isr(int irq) 
{ 
	unsigned int isr; 
	int iobase = nic.iobase; 
	int status = 0;
	struct kthread *ithr;

	// Remember the previous interrupted thread and clear its task busy bit
	ithr = (struct kthread *)current_thread;

	// Change the high level task related pointers to point to 
	// this nic thread.
	current_process = &system_process;
	current_thread = nic_intr_thread;
	current_thread->kt_schedinf.sc_state = THREAD_STATE_RUNNING;
	current_thread->kt_schedinf.sc_tqleft = TIME_QUANTUM;

	ithr->kt_schedinf.sc_state = THREAD_STATE_READY;
	ithr->kt_cr0 = get_cr0();
	gdt_table[ithr->kt_tssdesc >> 3].b &= 0xfffffdff;
	math_state_save(&ithr->kt_fps);
	math_state_restore(&nic_intr_thread->kt_fps);
	add_readyq(ithr);

	// Enable interrupts now
	sti_intr();

	_lock(&nic.busy);
	outportg(NIC_DMA_DISABLE | NIC_PAGE0, iobase); 

	while ((isr=inportb(iobase+INTERRUPTSTATUS)))
	{
		if (isr & (ISR_CNT | ISR_OVW | ISR_PTX | ISR_TXE))
		{
			if (isr & (ISR_CNT | ISR_OVW))
			{
				ring_ovfl(&nic);
				status = ETRANSMISSION;
			}
			if(isr & ISR_PTX) 
			{
				out_byte(iobase+INTERRUPTSTATUS, 0x0a);
				status = 1;
			}
			else if (isr & ISR_TXE)
			{
				out_byte(iobase+INTERRUPTSTATUS, 0x0a);
				status = ETRANSMISSION;
			}

			if (tx_wait_pkt != NULL)
			{
				tx_wait_pkt->status = status;
				event_wakeup((struct event_t *)&tx_wait_pkt->threadwait);
				tx_wait_pkt = NULL;
			}
		}
		if(isr & (ISR_PRX | ISR_RXE))
		{
			nic_rx(&nic);
		}
	}
	out_byte(iobase+INTERRUPTSTATUS, 0xff);
	outportg(IMR_DEFAULT, iobase +INTERRUPTMASK);
	unlock(&nic.busy);

	// Schedule the interrupted thread at this point.
	cli_intr();
	current_thread->kt_schedinf.sc_state = THREAD_STATE_SLEEP;
	//current_thread->kt_schedinf.sc_reccpuusage = 0;
	
	enable_irq(9); // Enable the same irq again.
	scheduler();

	return;
}