コード例 #1
0
void pnic_lnk_change(struct net_device *dev, int csr5)
{
	struct tulip_private *tp = netdev_priv(dev);
	void __iomem *ioaddr = tp->base_addr;
	int phy_reg = ioread32(ioaddr + 0xB8);

	if (tulip_debug > 1)
		netdev_dbg(dev, "PNIC link changed state %08x, CSR5 %08x\n",
			   phy_reg, csr5);
	if (ioread32(ioaddr + CSR5) & TPLnkFail) {
		iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7);
		/* If we use an external MII, then we mustn't use the
		 * internal negotiation.
		 */
		if (tulip_media_cap[dev->if_port] & MediaIsMII)
			return;
		if (! tp->nwayset || time_after(jiffies, dev_trans_start(dev) + 1*HZ)) {
			tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff);
			iowrite32(tp->csr6, ioaddr + CSR6);
			iowrite32(0x30, ioaddr + CSR12);
			iowrite32(0x0201F078, ioaddr + 0xB8); /* Turn on autonegotiation. */
			dev->trans_start = jiffies;
		}
	} else if (ioread32(ioaddr + CSR5) & TPLnkPass) {
		if (tulip_media_cap[dev->if_port] & MediaIsMII) {
			spin_lock(&tp->lock);
			tulip_check_duplex(dev);
			spin_unlock(&tp->lock);
		} else {
			pnic_do_nway(dev);
		}
		iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7);
	}
}
コード例 #2
0
void pnic_lnk_change(struct net_device *dev, int csr5)
{
    struct tulip_private *tp = netdev_priv(dev);
    void __iomem *ioaddr = tp->base_addr;
    int phy_reg = ioread32(ioaddr + 0xB8);

    if (tulip_debug > 1)
        printk(KERN_DEBUG "%s: PNIC link changed state %8.8x, CSR5 %8.8x.\n",
               dev->name, phy_reg, csr5);
    if (ioread32(ioaddr + CSR5) & TPLnkFail) {
        iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkFail) | TPLnkPass, ioaddr + CSR7);

        if (tulip_media_cap[dev->if_port] & MediaIsMII)
            return;
        if (! tp->nwayset  ||  time_after(jiffies, dev->trans_start + 1*HZ)) {
            tp->csr6 = 0x00420000 | (tp->csr6 & 0x0000fdff);
            iowrite32(tp->csr6, ioaddr + CSR6);
            iowrite32(0x30, ioaddr + CSR12);
            iowrite32(0x0201F078, ioaddr + 0xB8);
            dev->trans_start = jiffies;
        }
    } else if (ioread32(ioaddr + CSR5) & TPLnkPass) {
        if (tulip_media_cap[dev->if_port] & MediaIsMII) {
            spin_lock(&tp->lock);
            tulip_check_duplex(dev);
            spin_unlock(&tp->lock);
        } else {
            pnic_do_nway(dev);
        }
        iowrite32((ioread32(ioaddr + CSR7) & ~TPLnkPass) | TPLnkFail, ioaddr + CSR7);
    }
}
コード例 #3
0
void pnic_timer(unsigned long data)
{
	struct net_device *dev = (struct net_device *)data;
	struct tulip_private *tp = netdev_priv(dev);
	void __iomem *ioaddr = tp->base_addr;
	int next_tick = 60*HZ;

	if(!ioread32(ioaddr + CSR7)) {
		/* the timer was called due to a work overflow
		 * in the interrupt handler. Skip the connection
		 * checks, the nic is definitively speaking with
		 * his link partner.
		 */
		goto too_good_connection;
	}

	if (tulip_media_cap[dev->if_port] & MediaIsMII) {
		spin_lock_irq(&tp->lock);
		if (tulip_check_duplex(dev) > 0)
			next_tick = 3*HZ;
		spin_unlock_irq(&tp->lock);
	} else {
		int csr12 = ioread32(ioaddr + CSR12);
		int new_csr6 = tp->csr6 & ~0x40C40200;
		int phy_reg = ioread32(ioaddr + 0xB8);
		int csr5 = ioread32(ioaddr + CSR5);

		if (tulip_debug > 1)
			netdev_dbg(dev, "PNIC timer PHY status %08x, %s CSR5 %08x\n",
				   phy_reg, medianame[dev->if_port], csr5);
		if (phy_reg & 0x04000000) {	/* Remote link fault */
			iowrite32(0x0201F078, ioaddr + 0xB8);
			next_tick = 1*HZ;
			tp->nwayset = 0;
		} else if (phy_reg & 0x78000000) { /* Ignore baseT4 */
			pnic_do_nway(dev);
			next_tick = 60*HZ;
		} else if (csr5 & TPLnkFail) { /* 100baseTx link beat */
			if (tulip_debug > 1)
				netdev_dbg(dev, "%s link beat failed, CSR12 %04x, CSR5 %08x, PHY %03x\n",
					   medianame[dev->if_port],
					   csr12,
					   ioread32(ioaddr + CSR5),
					   ioread32(ioaddr + 0xB8));
			next_tick = 3*HZ;
			if (tp->medialock) {
			} else if (tp->nwayset  &&  (dev->if_port & 1)) {
				next_tick = 1*HZ;
			} else if (dev->if_port == 0) {
				dev->if_port = 3;
				iowrite32(0x33, ioaddr + CSR12);
				new_csr6 = 0x01860000;
				iowrite32(0x1F868, ioaddr + 0xB8);
			} else {
				dev->if_port = 0;
				iowrite32(0x32, ioaddr + CSR12);
				new_csr6 = 0x00420000;
				iowrite32(0x1F078, ioaddr + 0xB8);
			}
			if (tp->csr6 != new_csr6) {
				tp->csr6 = new_csr6;
				/* Restart Tx */
				tulip_restart_rxtx(tp);
				dev->trans_start = jiffies;
				if (tulip_debug > 1)
					dev_info(&dev->dev,
						 "Changing PNIC configuration to %s %s-duplex, CSR6 %08x\n",
						 medianame[dev->if_port],
						 tp->full_duplex ? "full" : "half",
						 new_csr6);
			}
		}
	}
too_good_connection:
	mod_timer(&tp->timer, RUN_AT(next_tick));
	if(!ioread32(ioaddr + CSR7)) {
		if (tulip_debug > 1)
			dev_info(&dev->dev, "sw timer wakeup\n");
		disable_irq(dev->irq);
		tulip_refill_rx(dev);
		enable_irq(dev->irq);
		iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
	}
}
コード例 #4
0
ファイル: tulip_core.c プロジェクト: ChunHungLiu/xenomai
static void tulip_up(/*RTnet*/struct rtnet_device *rtdev)
{
	struct tulip_private *tp = (struct tulip_private *)rtdev->priv;
	long ioaddr = rtdev->base_addr;
	int i;

	/* Wake the chip from sleep/snooze mode. */
	tulip_set_power_state (tp, 0, 0);

	/* On some chip revs we must set the MII/SYM port before the reset!? */
	if (tp->mii_cnt  ||  (tp->mtable  &&  tp->mtable->has_mii))
		outl(0x00040000, ioaddr + CSR6);

	/* Reset the chip, holding bit 0 set at least 50 PCI cycles. */
	outl(0x00000001, ioaddr + CSR0);
	udelay(100);

	/* Deassert reset.
	   Wait the specified 50 PCI cycles after a reset by initializing
	   Tx and Rx queues and the address filter list. */
	outl(tp->csr0, ioaddr + CSR0);
	udelay(100);

	if (tulip_debug > 1)
		printk(KERN_DEBUG "%s: tulip_up(), irq==%d.\n", rtdev->name, rtdev->irq);

	outl(tp->rx_ring_dma, ioaddr + CSR3);
	outl(tp->tx_ring_dma, ioaddr + CSR4);
	tp->cur_rx = tp->cur_tx = 0;
	tp->dirty_rx = tp->dirty_tx = 0;

	if (tp->flags & MC_HASH_ONLY) {
		u32 addr_low = cpu_to_le32(get_unaligned((u32 *)rtdev->dev_addr));
		u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(rtdev->dev_addr+4)));
		if (tp->chip_id == AX88140) {
			outl(0, ioaddr + CSR13);
			outl(addr_low,  ioaddr + CSR14);
			outl(1, ioaddr + CSR13);
			outl(addr_high, ioaddr + CSR14);
		} else if (tp->flags & COMET_MAC_ADDR) {
			outl(addr_low,  ioaddr + 0xA4);
			outl(addr_high, ioaddr + 0xA8);
			outl(0, ioaddr + 0xAC);
			outl(0, ioaddr + 0xB0);
		}
	} else {
		/* This is set_rx_mode(), but without starting the transmitter. */
		u16 *eaddrs = (u16 *)rtdev->dev_addr;
		u16 *setup_frm = &tp->setup_frame[15*6];
		dma_addr_t mapping;

		/* 21140 bug: you must add the broadcast address. */
		memset(tp->setup_frame, 0xff, sizeof(tp->setup_frame));
		/* Fill the final entry of the table with our physical address. */
		*setup_frm++ = eaddrs[0]; *setup_frm++ = eaddrs[0];
		*setup_frm++ = eaddrs[1]; *setup_frm++ = eaddrs[1];
		*setup_frm++ = eaddrs[2]; *setup_frm++ = eaddrs[2];

		mapping = pci_map_single(tp->pdev, tp->setup_frame,
					 sizeof(tp->setup_frame),
					 PCI_DMA_TODEVICE);
		tp->tx_buffers[tp->cur_tx].skb = NULL;
		tp->tx_buffers[tp->cur_tx].mapping = mapping;

		/* Put the setup frame on the Tx list. */
		tp->tx_ring[tp->cur_tx].length = cpu_to_le32(0x08000000 | 192);
		tp->tx_ring[tp->cur_tx].buffer1 = cpu_to_le32(mapping);
		tp->tx_ring[tp->cur_tx].status = cpu_to_le32(DescOwned);

		tp->cur_tx++;
	}

	tp->saved_if_port = rtdev->if_port;
	if (rtdev->if_port == 0)
		rtdev->if_port = tp->default_port;

	/* Allow selecting a default media. */
	i = 0;
	if (tp->mtable == NULL)
		goto media_picked;
	if (rtdev->if_port) {
		int looking_for = tulip_media_cap[rtdev->if_port] & MediaIsMII ? 11 :
			(rtdev->if_port == 12 ? 0 : rtdev->if_port);
		for (i = 0; i < tp->mtable->leafcount; i++)
			if (tp->mtable->mleaf[i].media == looking_for) {
				printk(KERN_INFO "%s: Using user-specified media %s.\n",
					   rtdev->name, medianame[rtdev->if_port]);
				goto media_picked;
			}
	}
	if ((tp->mtable->defaultmedia & 0x0800) == 0) {
		int looking_for = tp->mtable->defaultmedia & MEDIA_MASK;
		for (i = 0; i < tp->mtable->leafcount; i++)
			if (tp->mtable->mleaf[i].media == looking_for) {
				printk(KERN_INFO "%s: Using EEPROM-set media %s.\n",
					   rtdev->name, medianame[looking_for]);
				goto media_picked;
			}
	}
	/* Start sensing first non-full-duplex media. */
	for (i = tp->mtable->leafcount - 1;
		 (tulip_media_cap[tp->mtable->mleaf[i].media] & MediaAlwaysFD) && i > 0; i--)
		;
media_picked:

	tp->csr6 = 0;
	tp->cur_index = i;
	tp->nwayset = 0;

	if (rtdev->if_port) {
		if (tp->chip_id == DC21143  &&
		    (tulip_media_cap[rtdev->if_port] & MediaIsMII)) {
			/* We must reset the media CSRs when we force-select MII mode. */
			outl(0x0000, ioaddr + CSR13);
			outl(0x0000, ioaddr + CSR14);
			outl(0x0008, ioaddr + CSR15);
		}
		tulip_select_media(rtdev, 1);
	} else if (tp->chip_id == DC21041) {
		rtdev->if_port = 0;
		tp->nway = tp->mediasense = 1;
		tp->nwayset = tp->lpar = 0;
		outl(0x00000000, ioaddr + CSR13);
		outl(0xFFFFFFFF, ioaddr + CSR14);
		outl(0x00000008, ioaddr + CSR15); /* Listen on AUI also. */
		tp->csr6 = 0x80020000;
		if (tp->sym_advertise & 0x0040)
			tp->csr6 |= FullDuplex;
		outl(tp->csr6, ioaddr + CSR6);
		outl(0x0000EF01, ioaddr + CSR13);

	} else if (tp->chip_id == DC21142) {
		if (tp->mii_cnt) {
			tulip_select_media(rtdev, 1);
			if (tulip_debug > 1)
				printk(KERN_INFO "%s: Using MII transceiver %d, status %4.4x.\n",
					   rtdev->name, tp->phys[0], tulip_mdio_read(rtdev, tp->phys[0], 1));
			outl(csr6_mask_defstate, ioaddr + CSR6);
			tp->csr6 = csr6_mask_hdcap;
			rtdev->if_port = 11;
			outl(0x0000, ioaddr + CSR13);
			outl(0x0000, ioaddr + CSR14);
		} else
			t21142_start_nway(rtdev);
	} else if (tp->chip_id == PNIC2) {
		/* for initial startup advertise 10/100 Full and Half */
		tp->sym_advertise = 0x01E0;
		/* enable autonegotiate end interrupt */
		outl(inl(ioaddr+CSR5)| 0x00008010, ioaddr + CSR5);
		outl(inl(ioaddr+CSR7)| 0x00008010, ioaddr + CSR7);
		pnic2_start_nway(rtdev);
	} else if (tp->chip_id == LC82C168  &&  ! tp->medialock) {
		if (tp->mii_cnt) {
			rtdev->if_port = 11;
			tp->csr6 = 0x814C0000 | (tp->full_duplex ? 0x0200 : 0);
			outl(0x0001, ioaddr + CSR15);
		} else if (inl(ioaddr + CSR5) & TPLnkPass)
			pnic_do_nway(rtdev);
		else {
			/* Start with 10mbps to do autonegotiation. */
			outl(0x32, ioaddr + CSR12);
			tp->csr6 = 0x00420000;
			outl(0x0001B078, ioaddr + 0xB8);
			outl(0x0201B078, ioaddr + 0xB8);
		}
	} else if ((tp->chip_id == MX98713 || tp->chip_id == COMPEX9881)
			   && ! tp->medialock) {
		rtdev->if_port = 0;
		tp->csr6 = 0x01880000 | (tp->full_duplex ? 0x0200 : 0);
		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
	} else if (tp->chip_id == MX98715 || tp->chip_id == MX98725) {
		/* Provided by BOLO, Macronix - 12/10/1998. */
		rtdev->if_port = 0;
		tp->csr6 = 0x01a80200;
		outl(0x0f370000 | inw(ioaddr + 0x80), ioaddr + 0x80);
		outl(0x11000 | inw(ioaddr + 0xa0), ioaddr + 0xa0);
	} else if (tp->chip_id == COMET) {
		/* Enable automatic Tx underrun recovery. */
		outl(inl(ioaddr + 0x88) | 1, ioaddr + 0x88);
		rtdev->if_port = tp->mii_cnt ? 11 : 0;
		tp->csr6 = 0x00040000;
	} else if (tp->chip_id == AX88140) {
		tp->csr6 = tp->mii_cnt ? 0x00040100 : 0x00000100;
	} else
		tulip_select_media(rtdev, 1);

	/* Start the chip's Tx to process setup frame. */
	tulip_stop_rxtx(tp);
	barrier();
	udelay(5);
	outl(tp->csr6 | TxOn, ioaddr + CSR6);

	/* Enable interrupts by setting the interrupt mask. */
	outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR5);
	outl(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
	tulip_start_rxtx(tp);
	outl(0, ioaddr + CSR2);		/* Rx poll demand */

	if (tulip_debug > 2) {
		printk(KERN_DEBUG "%s: Done tulip_up(), CSR0 %8.8x, CSR5 %8.8x CSR6 %8.8x.\n",
			   rtdev->name, inl(ioaddr + CSR0), inl(ioaddr + CSR5),
			   inl(ioaddr + CSR6));
	}
}
コード例 #5
0
void pnic_timer(unsigned long data)
{
    struct net_device *dev = (struct net_device *)data;
    struct tulip_private *tp = netdev_priv(dev);
    void __iomem *ioaddr = tp->base_addr;
    int next_tick = 60*HZ;

    if(!ioread32(ioaddr + CSR7)) {

        goto too_good_connection;
    }

    if (tulip_media_cap[dev->if_port] & MediaIsMII) {
        spin_lock_irq(&tp->lock);
        if (tulip_check_duplex(dev) > 0)
            next_tick = 3*HZ;
        spin_unlock_irq(&tp->lock);
    } else {
        int csr12 = ioread32(ioaddr + CSR12);
        int new_csr6 = tp->csr6 & ~0x40C40200;
        int phy_reg = ioread32(ioaddr + 0xB8);
        int csr5 = ioread32(ioaddr + CSR5);

        if (tulip_debug > 1)
            printk(KERN_DEBUG "%s: PNIC timer PHY status %8.8x, %s "
                   "CSR5 %8.8x.\n",
                   dev->name, phy_reg, medianame[dev->if_port], csr5);
        if (phy_reg & 0x04000000) {
            iowrite32(0x0201F078, ioaddr + 0xB8);
            next_tick = 1*HZ;
            tp->nwayset = 0;
        } else if (phy_reg & 0x78000000) {
            pnic_do_nway(dev);
            next_tick = 60*HZ;
        } else if (csr5 & TPLnkFail) {
            if (tulip_debug > 1)
                printk(KERN_DEBUG "%s: %s link beat failed, CSR12 %4.4x, "
                       "CSR5 %8.8x, PHY %3.3x.\n",
                       dev->name, medianame[dev->if_port], csr12,
                       ioread32(ioaddr + CSR5), ioread32(ioaddr + 0xB8));
            next_tick = 3*HZ;
            if (tp->medialock) {
            } else if (tp->nwayset  &&  (dev->if_port & 1)) {
                next_tick = 1*HZ;
            } else if (dev->if_port == 0) {
                dev->if_port = 3;
                iowrite32(0x33, ioaddr + CSR12);
                new_csr6 = 0x01860000;
                iowrite32(0x1F868, ioaddr + 0xB8);
            } else {
                dev->if_port = 0;
                iowrite32(0x32, ioaddr + CSR12);
                new_csr6 = 0x00420000;
                iowrite32(0x1F078, ioaddr + 0xB8);
            }
            if (tp->csr6 != new_csr6) {
                tp->csr6 = new_csr6;

                tulip_restart_rxtx(tp);
                dev->trans_start = jiffies;
                if (tulip_debug > 1)
                    printk(KERN_INFO "%s: Changing PNIC configuration to %s "
                           "%s-duplex, CSR6 %8.8x.\n",
                           dev->name, medianame[dev->if_port],
                           tp->full_duplex ? "full" : "half", new_csr6);
            }
        }
    }
too_good_connection:
    mod_timer(&tp->timer, RUN_AT(next_tick));
    if(!ioread32(ioaddr + CSR7)) {
        if (tulip_debug > 1)
            printk(KERN_INFO "%s: sw timer wakeup.\n", dev->name);
        disable_irq(dev->irq);
        tulip_refill_rx(dev);
        enable_irq(dev->irq);
        iowrite32(tulip_tbl[tp->chip_id].valid_intrs, ioaddr + CSR7);
    }
}