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

📄 3c501.c

📁 LINUX 1.0 内核c源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	outb(TX_NORM, TX_CMD);
	outb(RX_NORM, RX_CMD);
	outb(AX_OFF, AX_CMD);	/* Just trigger a false interrupt. */
#endif
	outb(AX_RX, AX_CMD);	/* Aux control, irq and receive enabled */
	dev->tbusy = 0;
	dev->trans_start = jiffies;
    }

    if (skb == NULL) {
	dev_tint(dev);
	return 0;
    }

    /* Fill in the ethernet header. */
    if (!skb->arp  &&  dev->rebuild_header(skb->data, dev)) {
	skb->dev = dev;
	arp_queue (skb);
	return 0;
    }
    skb->arp=1;

    if (skb->len <= 0)
	return 0;

    /* Avoid timer-based retransmission conflicts. */
    if (set_bit(0, (void*)&dev->tbusy) != 0)
	printk("%s: Transmitter access conflict.\n", dev->name);
    else {
	int gp_start = 0x800 - (ETH_ZLEN < skb->len ? skb->len : ETH_ZLEN);
	unsigned char *buf = skb->data;

	el_status.tx_pkt_start = gp_start;
    	el_status.collisions = 0;

	outb(AX_SYS, AX_CMD);
	inb(RX_STATUS);
	inb(TX_STATUS);
	outb(0x00, RX_BUF_CLR);	/* Set rx packet area to 0. */
	outw(gp_start, GP_LOW);
	outsb(DATAPORT,buf,skb->len);
	outw(gp_start, GP_LOW);
	outb(AX_XMIT, AX_CMD);		/* Trigger xmit.  */
	dev->trans_start = jiffies;
    }

    if (el_debug > 2)
	printk(" queued xmit.\n");
    if (skb->free)
	kfree_skb (skb, FREE_WRITE);
    return 0;
}


/* The typical workload of the driver:
   Handle the ether interface interrupts. */
static void
el_interrupt(int reg_ptr)
{
    int irq = -(((struct pt_regs *)reg_ptr)->orig_eax+2);
    /*struct device *dev = (struct device *)(irq2dev_map[irq]);*/
    struct device *dev = eldev;
    int axsr;			/* Aux. status reg. */
    short ioaddr;

    if (eldev->irq != irq) {
	printk (EL_NAME ": irq %d for unknown device\n", irq);
	return;
    }

    ioaddr = dev->base_addr;

    axsr = inb(AX_STATUS);

    if (el_debug > 3)
      printk("%s: el_interrupt() aux=%#02x", dev->name, axsr);
    if (dev->interrupt)
	printk("%s: Reentering the interrupt driver!\n", dev->name);
    dev->interrupt = 1;

    if (dev->tbusy) {
	int txsr = inb(TX_STATUS);

	if (el_debug > 6)
	    printk(" txsr=%02x gp=%04x rp=%04x", txsr, inw(GP_LOW),
		   inw(RX_LOW));

	if ((axsr & 0x80) && (txsr & TX_READY) == 0) {
	    printk("%s: Unusual interrupt during Tx, txsr=%02x axsr=%02x"
		   " gp=%03x rp=%03x.\n", dev->name, txsr, axsr,
		   inw(ioaddr + EL1_DATAPTR), inw(ioaddr + EL1_RXPTR));
	    dev->tbusy = 0;
	    mark_bh(INET_BH);
	} else if (txsr & TX_16COLLISIONS) {
	    if (el_debug)
		printk("%s: Transmit failed 16 times, ethernet jammed?\n",
		       dev->name);
	    outb(AX_SYS, AX_CMD);
	    el_status.stats.tx_aborted_errors++;
	} else if (txsr & TX_COLLISION) {	/* Retrigger xmit. */
	    if (el_debug > 6)
		printk(" retransmitting after a collision.\n");
	    outb(AX_SYS, AX_CMD);
	    outw(el_status.tx_pkt_start, GP_LOW);
	    outb(AX_XMIT, AX_CMD);
	    el_status.stats.collisions++;
	    dev->interrupt = 0;
	    return;
	} else {
	    el_status.stats.tx_packets++;
	    if (el_debug > 6)
		printk(" Tx succeeded %s\n",
		       (txsr & TX_RDY) ? "." : "but tx is busy!");
	    dev->tbusy = 0;
	    mark_bh(INET_BH);
	}
    } else {
	int rxsr = inb(RX_STATUS);
	if (el_debug > 5)
	    printk(" rxsr=%02x txsr=%02x rp=%04x", rxsr, inb(TX_STATUS),
		   inw(RX_LOW));

	/* Just reading rx_status fixes most errors. */
	if (rxsr & RX_MISSED)
	    el_status.stats.rx_missed_errors++;
	if (rxsr & RX_RUNT) {	/* Handled to avoid board lock-up. */
	    el_status.stats.rx_length_errors++;
	    if (el_debug > 5) printk(" runt.\n");
	} else if (rxsr & RX_GOOD) {
	    el_receive(eldev);
	} else {			/* Nothing?  Something is broken! */
	    if (el_debug > 2)
		printk("%s: No packet seen, rxsr=%02x **resetting 3c501***\n",
		       dev->name, rxsr);
	    el_reset(eldev);
	}
	if (el_debug > 3)
	    printk(".\n");
    }

    outb(AX_RX, AX_CMD);
    outb(0x00, RX_BUF_CLR);
    inb(RX_STATUS);		/* Be certain that interrupts are cleared. */
    inb(TX_STATUS);
    dev->interrupt = 0;
    return;
}


/* We have a good packet. Well, not really "good", just mostly not broken.
   We must check everything to see if it is good. */
static void
el_receive(struct device *dev)
{
    int sksize, pkt_len;
    struct sk_buff *skb;

    pkt_len = inw(RX_LOW);

    if (el_debug > 4)
      printk(" el_receive %d.\n", pkt_len);

    if ((pkt_len < 60)  ||  (pkt_len > 1536)) {
	if (el_debug)
	  printk("%s: bogus packet, length=%d\n", dev->name, pkt_len);
	el_status.stats.rx_over_errors++;
	return;
    }
    outb(AX_SYS, AX_CMD);

    sksize = sizeof(struct sk_buff) + pkt_len;
    skb = alloc_skb(sksize, GFP_ATOMIC);
    outw(0x00, GP_LOW);
    if (skb == NULL) {
	printk("%s: Memory squeeze, dropping packet.\n", dev->name);
	el_status.stats.rx_dropped++;
	return;
    } else {
	skb->mem_len = sksize;
	skb->mem_addr = skb;
	skb->len = pkt_len;
	skb->dev = dev;

	insb(DATAPORT, skb->data, pkt_len);

#ifdef HAVE_NETIF_RX
	    netif_rx(skb);
#else
	    skb->lock = 0;
	    if (dev_rint((unsigned char*)skb, pkt_len, IN_SKBUFF, dev) != 0) {
		kfree_skbmem(skb, sksize);
		lp->stats.rx_dropped++;
		break;
	    }
#endif
	el_status.stats.rx_packets++;
    }
    return;
}

static void 
el_reset(struct device *dev)
{
    if (el_debug> 2)
	printk("3c501 reset...");
    outb(AX_RESET, AX_CMD);	/* Reset the chip */
    outb(AX_LOOP, AX_CMD);	/* Aux control, irq and loopback enabled */
    {
	int i;
	for (i = 0; i < 6; i++)	/* Set the station address. */
	    outb(dev->dev_addr[i], el_base + i);
    }
    
    outb(0, RX_BUF_CLR);		/* Set rx packet area to 0. */
    cli();			/* Avoid glitch on writes to CMD regs */
    outb(TX_NORM, TX_CMD);		/* tx irq on done, collision */
    outb(RX_NORM, RX_CMD);	/* Set Rx commands. */
    inb(RX_STATUS);		/* Clear status. */
    inb(TX_STATUS);
    dev->interrupt = 0;
    dev->tbusy = 0;
    sti();
}

static int
el1_close(struct device *dev)
{
    int ioaddr = dev->base_addr;

    if (el_debug > 2)
	printk("%s: Shutting down ethercard at %#x.\n", dev->name, ioaddr);

    dev->tbusy = 1;
    dev->start = 0;

    /* Free and disable the IRQ. */
    free_irq(dev->irq);
    outb(AX_RESET, AX_CMD);	/* Reset the chip */
    irq2dev_map[dev->irq] = 0;

    return 0;
}

static struct enet_statistics *
el1_get_stats(struct device *dev)
{
    return &el_status.stats;
}

#ifdef HAVE_MULTICAST
/* Set or clear the multicast filter for this adaptor.
   num_addrs == -1	Promiscuous mode, receive all packets
   num_addrs == 0	Normal mode, clear multicast list
   num_addrs > 0	Multicast mode, receive normal and MC packets, and do
			best-effort filtering.
 */
static void
set_multicast_list(struct device *dev, int num_addrs, void *addrs)
{
    if (num_addrs > 0) {
	outb(RX_MULT, RX_CMD);
	inb(RX_STATUS);		/* Clear status. */
    } else if (num_addrs < 0) {
	outb(RX_PROM, RX_CMD);
	inb(RX_STATUS);
    } else {
	outb(RX_NORM, RX_CMD);
	inb(RX_STATUS);
    }
}
#endif

/*
 * Local variables:
 *  compile-command: "gcc -D__KERNEL__ -Wall -Wstrict-prototypes -O6 -fomit-frame-pointer  -m486 -c -o 3c501.o 3c501.c"
 *  kept-new-versions: 5
 * End:
 */

⌨️ 快捷键说明

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