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

📄 pcnet32.c

📁 linux和2410结合开发 用他可以生成2410所需的zImage文件
💻 C
📖 第 1 页 / 共 4 页
字号:
    pcnet32_dwio_write_rap,    pcnet32_dwio_reset};/* only probes for non-PCI devices, the rest are handled by pci_register_driver via pcnet32_probe_pci*/static int __init pcnet32_probe_vlbus(int cards_found){    unsigned long ioaddr = 0; // FIXME dev ? dev->base_addr: 0;    unsigned int  irq_line = 0; // FIXME dev ? dev->irq : 0;    int *port;        printk(KERN_INFO "pcnet32_probe_vlbus: cards_found=%d\n", cards_found);#ifndef __powerpc__    if (ioaddr > 0x1ff) {	if (check_region(ioaddr, PCNET32_TOTAL_SIZE) == 0)	    return pcnet32_probe1(ioaddr, irq_line, 0, 0, NULL);	else	    return -ENODEV;    } else#endif	if (ioaddr != 0)	    return -ENXIO;        /* now look for PCnet32 VLB cards */    for (port = pcnet32_portlist; *port; port++) {	unsigned long ioaddr = *port;		if ( check_region(ioaddr, PCNET32_TOTAL_SIZE) == 0) {	    /* check if there is really a pcnet chip on that ioaddr */	    if ((inb(ioaddr + 14) == 0x57) &&		(inb(ioaddr + 15) == 0x57) &&		(pcnet32_probe1(ioaddr, 0, 0, 0, NULL) == 0))		cards_found++;	}    }    return cards_found ? 0: -ENODEV;}static int __devinitpcnet32_probe_pci(struct pci_dev *pdev, const struct pci_device_id *ent){    static int card_idx;    long ioaddr;    int err = 0;    printk(KERN_INFO "pcnet32_probe_pci: found device %#08x.%#08x\n", ent->vendor, ent->device);    if ((err = pci_enable_device(pdev)) < 0) {	printk(KERN_ERR "pcnet32.c: failed to enable device -- err=%d\n", err);	return err;    }    pci_set_master(pdev);    ioaddr = pci_resource_start (pdev, 0);    printk(KERN_INFO "    ioaddr=%#08lx  resource_flags=%#08lx\n", ioaddr, pci_resource_flags (pdev, 0));    if (!ioaddr) {        printk (KERN_ERR "no PCI IO resources, aborting\n");        return -ENODEV;    }	    if (!pci_dma_supported(pdev, PCNET32_DMA_MASK)) {	printk(KERN_ERR "pcnet32.c: architecture does not support 32bit PCI busmaster DMA\n");	return -ENODEV;    }    return pcnet32_probe1(ioaddr, pdev->irq, 1, card_idx, pdev);}/* pcnet32_probe1  *  Called from both pcnet32_probe_vlbus and pcnet_probe_pci.   *  pdev will be NULL when called from pcnet32_probe_vlbus. */static int __devinitpcnet32_probe1(unsigned long ioaddr, unsigned char irq_line, int shared, int card_idx, struct pci_dev *pdev){    struct pcnet32_private *lp;    struct resource *res;    dma_addr_t lp_dma_addr;    int i,media,fdx = 0, mii = 0, fset = 0;#ifdef DO_DXSUFLO    int dxsuflo = 0;#endif    int ltint = 0;    int chip_version;    char *chipname;    struct net_device *dev;    struct pcnet32_access *a = NULL;    /* reset the chip */    pcnet32_dwio_reset(ioaddr);    pcnet32_wio_reset(ioaddr);    /* NOTE: 16-bit check is first, otherwise some older PCnet chips fail */    if (pcnet32_wio_read_csr (ioaddr, 0) == 4 && pcnet32_wio_check (ioaddr)) {	a = &pcnet32_wio;    } else {	if (pcnet32_dwio_read_csr (ioaddr, 0) == 4 && pcnet32_dwio_check(ioaddr)) {	    a = &pcnet32_dwio;	} else	    return -ENODEV;    }    chip_version = a->read_csr (ioaddr, 88) | (a->read_csr (ioaddr,89) << 16);    if (pcnet32_debug > 2)	printk(KERN_INFO "  PCnet chip version is %#x.\n", chip_version);    if ((chip_version & 0xfff) != 0x003)	return -ENODEV;    chip_version = (chip_version >> 12) & 0xffff;    switch (chip_version) {    case 0x2420:	chipname = "PCnet/PCI 79C970"; /* PCI */	break;    case 0x2430:	if (shared)	    chipname = "PCnet/PCI 79C970"; /* 970 gives the wrong chip id back */	else	    chipname = "PCnet/32 79C965"; /* 486/VL bus */	break;    case 0x2621:	chipname = "PCnet/PCI II 79C970A"; /* PCI */	fdx = 1;	break;    case 0x2623:	chipname = "PCnet/FAST 79C971"; /* PCI */	fdx = 1; mii = 1; fset = 1;	ltint = 1;	break;    case 0x2624:	chipname = "PCnet/FAST+ 79C972"; /* PCI */	fdx = 1; mii = 1; fset = 1;	break;    case 0x2625:	chipname = "PCnet/FAST III 79C973"; /* PCI */	fdx = 1; mii = 1;	break;    case 0x2626:	chipname = "PCnet/Home 79C978"; /* PCI */	fdx = 1;	/* 	 * This is based on specs published at www.amd.com.  This section	 * assumes that a card with a 79C978 wants to go into 1Mb HomePNA	 * mode.  The 79C978 can also go into standard ethernet, and there	 * probably should be some sort of module option to select the	 * mode by which the card should operate	 */	/* switch to home wiring mode */	media = a->read_bcr (ioaddr, 49);#if 0	if (pcnet32_debug > 2)	    printk(KERN_DEBUG "pcnet32: pcnet32 media value %#x.\n",  media);	media &= ~3;	media |= 1;#endif	if (pcnet32_debug > 2)	    printk(KERN_DEBUG "pcnet32: pcnet32 media reset to %#x.\n",  media);	a->write_bcr (ioaddr, 49, media);	break;    case 0x2627:	chipname = "PCnet/FAST III 79C975"; /* PCI */	fdx = 1; mii = 1;	break;    default:	printk(KERN_INFO "pcnet32: PCnet version %#x, no PCnet32 chip.\n",chip_version);	return -ENODEV;    }    /*     *	On selected chips turn on the BCR18:NOUFLO bit. This stops transmit     *	starting until the packet is loaded. Strike one for reliability, lose     *	one for latency - although on PCI this isnt a big loss. Older chips      *	have FIFO's smaller than a packet, so you can't do this.     */	     if(fset)    {	a->write_bcr(ioaddr, 18, (a->read_bcr(ioaddr, 18) | 0x0800));	a->write_csr(ioaddr, 80, (a->read_csr(ioaddr, 80) & 0x0C00) | 0x0c00);#ifdef DO_DXSUFLO	dxsuflo = 1;#endif	ltint = 1;    }        dev = init_etherdev(NULL, 0);    if(dev==NULL)	return -ENOMEM;    printk(KERN_INFO "%s: %s at %#3lx,", dev->name, chipname, ioaddr);    /* In most chips, after a chip reset, the ethernet address is read from the     * station address PROM at the base address and programmed into the     * "Physical Address Registers" CSR12-14.     * As a precautionary measure, we read the PROM values and complain if     * they disagree with the CSRs.  Either way, we use the CSR values, and     * double check that they are valid.     */    for (i = 0; i < 3; i++) {	unsigned int val;	val = a->read_csr(ioaddr, i+12) & 0x0ffff;	/* There may be endianness issues here. */	dev->dev_addr[2*i] = val & 0x0ff;	dev->dev_addr[2*i+1] = (val >> 8) & 0x0ff;    }    {	u8 promaddr[6];	for (i = 0; i < 6; i++) {	    promaddr[i] = inb(ioaddr + i);	}	if( memcmp( promaddr, dev->dev_addr, 6) )	{	    printk(" warning PROM address does not match CSR address\n");#if defined(__i386__)	    printk(KERN_WARNING "%s: Probably a Compaq, using the PROM address of", dev->name);	    memcpy(dev->dev_addr, promaddr, 6);#elif defined(__powerpc__)	    if (!is_valid_ether_addr(dev->dev_addr)		&& is_valid_ether_addr(promaddr)) {		    printk("\n" KERN_WARNING "%s: using PROM address:",			   dev->name);		    memcpy(dev->dev_addr, promaddr, 6);	    }#endif	}	    	        }    /* if the ethernet address is not valid, force to 00:00:00:00:00:00 */    if( !is_valid_ether_addr(dev->dev_addr) )	for (i = 0; i < 6; i++)	    dev->dev_addr[i]=0;    for (i = 0; i < 6; i++)	printk(" %2.2x", dev->dev_addr[i] );    if (((chip_version + 1) & 0xfffe) == 0x2624) { /* Version 0x2623 or 0x2624 */	i = a->read_csr(ioaddr, 80) & 0x0C00;  /* Check tx_start_pt */	printk("\n" KERN_INFO "    tx_start_pt(0x%04x):",i);	switch(i>>10) {	    case 0: printk("  20 bytes,"); break;	    case 1: printk("  64 bytes,"); break;	    case 2: printk(" 128 bytes,"); break;	    case 3: printk("~220 bytes,"); break;	}	i = a->read_bcr(ioaddr, 18);  /* Check Burst/Bus control */	printk(" BCR18(%x):",i&0xffff);	if (i & (1<<5)) printk("BurstWrEn ");	if (i & (1<<6)) printk("BurstRdEn ");	if (i & (1<<7)) printk("DWordIO ");	if (i & (1<<11)) printk("NoUFlow ");	i = a->read_bcr(ioaddr, 25);	printk("\n" KERN_INFO "    SRAMSIZE=0x%04x,",i<<8);	i = a->read_bcr(ioaddr, 26);	printk(" SRAM_BND=0x%04x,",i<<8);	i = a->read_bcr(ioaddr, 27);	if (i & (1<<14)) printk("LowLatRx");    }    dev->base_addr = ioaddr;    res = request_region(ioaddr, PCNET32_TOTAL_SIZE, chipname);    if (res == NULL)	return -EBUSY;        /* pci_alloc_consistent returns page-aligned memory, so we do not have to check the alignment */    if ((lp = pci_alloc_consistent(pdev, sizeof(*lp), &lp_dma_addr)) == NULL) {	release_resource(res);	return -ENOMEM;    }    memset(lp, 0, sizeof(*lp));    lp->dma_addr = lp_dma_addr;    lp->pci_dev = pdev;    printk("\n" KERN_INFO "pcnet32: pcnet32_private lp=%p lp_dma_addr=%#08x", lp, lp_dma_addr);    spin_lock_init(&lp->lock);        dev->priv = lp;    lp->name = chipname;    lp->shared_irq = shared;    lp->mii_if.full_duplex = fdx;#ifdef DO_DXSUFLO    lp->dxsuflo = dxsuflo;#endif    lp->ltint = ltint;    lp->mii = mii;    if (options[card_idx] > sizeof (options_mapping))	lp->options = PCNET32_PORT_ASEL;    else	lp->options = options_mapping[options[card_idx]];    lp->mii_if.dev = dev;    lp->mii_if.mdio_read = mdio_read;    lp->mii_if.mdio_write = mdio_write;        if (fdx && !(lp->options & PCNET32_PORT_ASEL) && full_duplex[card_idx])	lp->options |= PCNET32_PORT_FD;        if (a == NULL) {      printk(KERN_ERR "pcnet32: No access methods\n");      pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);      release_resource(res);      return -ENODEV;    }    lp->a = *a;        /* detect special T1/E1 WAN card by checking for MAC address */    if (dev->dev_addr[0] == 0x00 && dev->dev_addr[1] == 0xe0 && dev->dev_addr[2] == 0x75)	lp->options = PCNET32_PORT_FD | PCNET32_PORT_GPSI;    lp->init_block.mode = le16_to_cpu(0x0003);	/* Disable Rx and Tx. */    lp->init_block.tlen_rlen = le16_to_cpu(TX_RING_LEN_BITS | RX_RING_LEN_BITS);     for (i = 0; i < 6; i++)	lp->init_block.phys_addr[i] = dev->dev_addr[i];    lp->init_block.filter[0] = 0x00000000;    lp->init_block.filter[1] = 0x00000000;    lp->init_block.rx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, rx_ring));    lp->init_block.tx_ring = (u32)le32_to_cpu(lp->dma_addr + offsetof(struct pcnet32_private, tx_ring));        /* switch pcnet32 to 32bit mode */    a->write_bcr (ioaddr, 20, 2);    a->write_csr (ioaddr, 1, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) & 0xffff);    a->write_csr (ioaddr, 2, (lp->dma_addr + offsetof(struct pcnet32_private, init_block)) >> 16);        if (irq_line) {	dev->irq = irq_line;    }        if (dev->irq >= 2)	printk(" assigned IRQ %d.\n", dev->irq);    else {	unsigned long irq_mask = probe_irq_on();		/*	 * To auto-IRQ we enable the initialization-done and DMA error	 * interrupts. For ISA boards we get a DMA error, but VLB and PCI	 * boards will work.	 */	/* Trigger an initialization just for the interrupt. */	a->write_csr (ioaddr, 0, 0x41);	mdelay (1);		dev->irq = probe_irq_off (irq_mask);	if (dev->irq)	    printk(", probed IRQ %d.\n", dev->irq);	else {	    printk(", failed to detect IRQ line.\n");	    pci_free_consistent(lp->pci_dev, sizeof(*lp), lp, lp->dma_addr);	    release_resource(res);	    return -ENODEV;	}    }    if (pcnet32_debug > 0)	printk(KERN_INFO "%s", version);        /* The PCNET32-specific entries in the device structure. */    dev->open = &pcnet32_open;    dev->hard_start_xmit = &pcnet32_start_xmit;    dev->stop = &pcnet32_close;    dev->get_stats = &pcnet32_get_stats;    dev->set_multicast_list = &pcnet32_set_multicast_list;    dev->do_ioctl = &pcnet32_ioctl;    dev->tx_timeout = pcnet32_tx_timeout;    dev->watchdog_timeo = (HZ >> 1);    lp->next = pcnet32_dev;    pcnet32_dev = dev;    /* Fill in the generic fields of the device structure. */    ether_setup(dev);    return 0;}static intpcnet32_open(struct net_device *dev){    struct pcnet32_private *lp = dev->priv;    unsigned long ioaddr = dev->base_addr;    u16 val;    int i;    if (dev->irq == 0 ||	request_irq(dev->irq, &pcnet32_interrupt,		    lp->shared_irq ? SA_SHIRQ : 0, lp->name, (void *)dev)) {	return -EAGAIN;    }    /* Check for a valid station address */    if( !is_valid_ether_addr(dev->dev_addr) )	return -EINVAL;    /* Reset the PCNET32 */    lp->a.reset (ioaddr);    /* switch pcnet32 to 32bit mode */    lp->a.write_bcr (ioaddr, 20, 2);    if (pcnet32_debug > 1)	printk(KERN_DEBUG "%s: pcnet32_open() irq %d tx/rx rings %#x/%#x init %#x.\n",	       dev->name, dev->irq,	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, tx_ring)),	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, rx_ring)),	       (u32) (lp->dma_addr + offsetof(struct pcnet32_private, init_block)));        /* set/reset autoselect bit */    val = lp->a.read_bcr (ioaddr, 2) & ~2;    if (lp->options & PCNET32_PORT_ASEL)	val |= 2;    lp->a.write_bcr (ioaddr, 2, val);        /* handle full duplex setting */    if (lp->mii_if.full_duplex) {	val = lp->a.read_bcr (ioaddr, 9) & ~3;	if (lp->options & PCNET32_PORT_FD) {	    val |= 1;	    if (lp->options == (PCNET32_PORT_FD | PCNET32_PORT_AUI))		val |= 2;	}	lp->a.write_bcr (ioaddr, 9, val);    }        /* set/reset GPSI bit in test register */    val = lp->a.read_csr (ioaddr, 124) & ~0x10;    if ((lp->options & PCNET32_PORT_PORTSEL) == PCNET32_PORT_GPSI)	val |= 0x10;    lp->a.write_csr (ioaddr, 124, val);        if (lp->mii && !(lp->options & PCNET32_PORT_ASEL)) {	val = lp->a.read_bcr (ioaddr, 32) & ~0x38; /* disable Auto Negotiation, set 10Mpbs, HD */	if (lp->options & PCNET32_PORT_FD)	    val |= 0x10;	if (lp->options & PCNET32_PORT_100)	    val |= 0x08;	lp->a.write_bcr (ioaddr, 32, val);

⌨️ 快捷键说明

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