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

📄 tulip.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 5 页
字号:
    /* 0x60000000 = no interrupt on completion */    tx_ring[0].length = cpu_to_le32(0x60000000 | s);    tx_ring[0].status = cpu_to_le32(0x80000000);    /* Point to transmit descriptor */    outl((u32)&tx_ring[0], ioaddr + CSR4);    /* Enable Tx */    outl(csr6 | 0x00002000, ioaddr + CSR6);    /* immediate transmit demand */    outl(0, ioaddr + CSR1);    to = currticks() + TX_TIME_OUT;    while ((tx_ring[0].status & 0x80000000) && (currticks() < to))        /* wait */ ;    if (currticks() >= to) {        printf ("TX Timeout!\n");    }    /* Disable Tx */    outl(csr6 & ~0x00002000, ioaddr + CSR6);}/*********************************************************************//* eth_poll - Wait for a frame                                       *//*********************************************************************/static int tulip_poll(struct nic *nic){#ifdef TULIP_DEBUG_WHERE    whereami("tulip_poll\n");#endif    /* no packet waiting. packet still owned by NIC */    if (rx_ring[tp->cur_rx].status & 0x80000000)        return 0;#ifdef TULIP_DEBUG_WHERE    whereami("tulip_poll got one\n");#endif    nic->packetlen = (rx_ring[tp->cur_rx].status & 0x3FFF0000) >> 16;    /* if we get a corrupted packet. throw it away and move on */    if (rx_ring[tp->cur_rx].status & 0x00008000) {	/* return the descriptor and buffer to receive ring */        rx_ring[tp->cur_rx].status = 0x80000000;	tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE;        return 0;    }    /* copy packet to working buffer */    memcpy(nic->packet, rxb + tp->cur_rx * BUFLEN, nic->packetlen);    /* return the descriptor and buffer to receive ring */    rx_ring[tp->cur_rx].status = 0x80000000;    tp->cur_rx = (++tp->cur_rx) % RX_RING_SIZE;    return 1;}/*********************************************************************//* eth_disable - Disable the interface                               *//*********************************************************************/static void tulip_disable(struct nic *nic){#ifdef TULIP_DEBUG_WHERE    whereami("tulip_disable\n");#endif    /* disable interrupts */    outl(0x00000000, ioaddr + CSR7);    /* Stop the chip's Tx and Rx processes. */    outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);    /* Clear the missed-packet counter. */    (volatile unsigned long)inl(ioaddr + CSR8);}/*********************************************************************//* eth_probe - Look for an adapter                                   *//*********************************************************************/struct nic *tulip_probe(struct nic *nic, unsigned short *io_addrs,                        struct pci_device *pci){    u32 i, l1, l2;    u8  chip_rev;    u8 ee_data[EEPROM_SIZE];    unsigned short sum;    int chip_idx;    static unsigned char last_phys_addr[ETH_ALEN] = {0x00, 'L', 'i', 'n', 'u', 'x'};    if (io_addrs == 0 || *io_addrs == 0)        return 0;    ioaddr         = *io_addrs;    /* point to private storage */    tp = &tpx;    tp->vendor_id  = pci->vendor;    tp->dev_id     = pci->dev_id;    tp->nic_name   = pci->name;    tp->if_port = 0;    tp->default_port = 0;    adjust_pci_device(pci);    /* disable interrupts */    outl(0x00000000, ioaddr + CSR7);    /* Stop the chip's Tx and Rx processes. */    outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);    /* Clear the missed-packet counter. */    (volatile unsigned long)inl(ioaddr + CSR8);    printf("\n");                /* so we start on a fresh line */#ifdef TULIP_DEBUG_WHERE    whereami("tulip_probe\n");#endif#ifdef TULIP_DEBUG    if (tulip_debug > 1)	printf ("%s: Looking for Tulip Chip: Vendor=%hX  Device=%hX\n", tp->nic_name,		tp->vendor_id, tp->dev_id);#endif    /* Figure out which chip we're dealing with */    i = 0;    chip_idx = -1;      while (pci_id_tbl[i].name) {        if ( (((u32) tp->dev_id << 16) | tp->vendor_id) ==              (pci_id_tbl[i].id.pci & pci_id_tbl[i].id.pci_mask) ) {            chip_idx = pci_id_tbl[i].drv_flags;            break;        }        i++;    }    if (chip_idx == -1) {        printf ("%s: Unknown Tulip Chip: Vendor=%hX  Device=%hX\n", tp->nic_name,                tp->vendor_id, tp->dev_id);        return 0;    }    tp->pci_id_idx = i;    tp->flags = tulip_tbl[chip_idx].flags;#ifdef TULIP_DEBUG    if (tulip_debug > 1) {	printf ("%s: tp->pci_id_idx == %d,  name == %s\n", tp->nic_name, 		tp->pci_id_idx, pci_id_tbl[tp->pci_id_idx].name);	printf ("%s: chip_idx == %d, name == %s\n", tp->nic_name, chip_idx, 		tulip_tbl[chip_idx].chip_name);    }#endif      /* Bring the 21041/21143 out of sleep mode.       Caution: Snooze mode does not work with some boards! */    if (tp->flags & HAS_PWRDWN)        pcibios_write_config_dword(pci->bus, pci->devfn, 0x40, 0x00000000);    if (inl(ioaddr + CSR5) == 0xFFFFFFFF) {        printf("%s: The Tulip chip at %X is not functioning.\n",               tp->nic_name, ioaddr);        return 0;    }       pcibios_read_config_byte(pci->bus, pci->devfn, PCI_REVISION, &chip_rev);    printf("%s: [chip: %s] rev %d at %hX\n", tp->nic_name,           tulip_tbl[chip_idx].chip_name, chip_rev, ioaddr);    printf("%s: Vendor=%hX  Device=%hX", tp->nic_name, tp->vendor_id, tp->dev_id);    if (chip_idx == DC21041  &&  inl(ioaddr + CSR9) & 0x8000) {        printf(" 21040 compatible mode.");        chip_idx = DC21040;    }    printf("\n");    /* The SROM/EEPROM interface varies dramatically. */    sum = 0;    if (chip_idx == DC21040) {        outl(0, ioaddr + CSR9);         /* Reset the pointer with a dummy write. */        for (i = 0; i < ETH_ALEN; i++) {            int value, boguscnt = 100000;            do                value = inl(ioaddr + CSR9);            while (value < 0  && --boguscnt > 0);            nic->node_addr[i] = value;            sum += value & 0xff;        }    } else if (chip_idx == LC82C168) {        for (i = 0; i < 3; i++) {            int value, boguscnt = 100000;            outl(0x600 | i, ioaddr + 0x98);            do                value = inl(ioaddr + CSR9);            while (value < 0  && --boguscnt > 0);            put_unaligned(le16_to_cpu(value), ((u16*)nic->node_addr) + i);            sum += value & 0xffff;        }    } else if (chip_idx == COMET) {        /* No need to read the EEPROM. */        put_unaligned(inl(ioaddr + 0xA4), (u32 *)nic->node_addr);        put_unaligned(inl(ioaddr + 0xA8), (u16 *)(nic->node_addr + 4));        for (i = 0; i < ETH_ALEN; i ++)            sum += nic->node_addr[i];    } else {        /* A serial EEPROM interface, we read now and sort it out later. */        int sa_offset = 0;        int ee_addr_size = read_eeprom(ioaddr, 0xff, 8) & 0x40000 ? 8 : 6;        for (i = 0; i < sizeof(ee_data)/2; i++)            ((u16 *)ee_data)[i] =                le16_to_cpu(read_eeprom(ioaddr, i, ee_addr_size));        /* DEC now has a specification (see Notes) but early board makers           just put the address in the first EEPROM locations. */        /* This does  memcmp(eedata, eedata+16, 8) */        for (i = 0; i < 8; i ++)            if (ee_data[i] != ee_data[16+i])                sa_offset = 20;        if (ee_data[0] == 0xff  &&  ee_data[1] == 0xff &&  ee_data[2] == 0) {            sa_offset = 2;              /* Grrr, damn Matrox boards. */        }        for (i = 0; i < ETH_ALEN; i ++) {            nic->node_addr[i] = ee_data[i + sa_offset];            sum += ee_data[i + sa_offset];        }    }    /* Lite-On boards have the address byte-swapped. */    if ((nic->node_addr[0] == 0xA0  ||  nic->node_addr[0] == 0xC0)        &&  nic->node_addr[1] == 0x00)        for (i = 0; i < ETH_ALEN; i+=2) {            char tmp = nic->node_addr[i];            nic->node_addr[i] = nic->node_addr[i+1];            nic->node_addr[i+1] = tmp;        }    if (sum == 0  || sum == ETH_ALEN*0xff) {        printf("%s: EEPROM not present!\n", tp->nic_name);        for (i = 0; i < ETH_ALEN-1; i++)            nic->node_addr[i] = last_phys_addr[i];        nic->node_addr[i] = last_phys_addr[i] + 1;    }    for (i = 0; i < ETH_ALEN; i++)        last_phys_addr[i] = nic->node_addr[i];    printf("%s: %! at ioaddr %hX\n", tp->nic_name, nic->node_addr, ioaddr);    tp->chip_id = chip_idx;    tp->revision = chip_rev;    tp->csr0 = csr0;    /* BugFixes: The 21143-TD hangs with PCI Write-and-Invalidate cycles.       And the ASIX must have a burst limit or horrible things happen. */    if (chip_idx == DC21143  &&  chip_rev == 65)        tp->csr0 &= ~0x01000000;    else if (tp->flags & IS_ASIX)        tp->csr0 |= 0x2000;    if (media_cap[tp->default_port] & MediaIsMII) {        u16 media2advert[] = { 0x20, 0x40, 0x03e0, 0x60, 0x80, 0x100, 0x200 };        tp->mii_advertise = media2advert[tp->default_port - 9];        tp->mii_advertise |= (tp->flags & HAS_8023X); /* Matching bits! */    }    /* This is logically part of the probe routine, but too complex       to write inline. */    if (tp->flags & HAS_MEDIA_TABLE) {        memcpy(tp->eeprom, ee_data, sizeof(tp->eeprom));        parse_eeprom(nic);    }    start_link(nic);    /* reset the device and make ready for tx and rx of packets */    tulip_reset(nic);    nic->reset    = tulip_reset;    nic->poll     = tulip_poll;    nic->transmit = tulip_transmit;    nic->disable  = tulip_disable;    /* give the board a chance to reset before returning */    tulip_wait(4*TICKS_PER_SEC);    return nic;}static void start_link(struct nic *nic){    int i;#ifdef TULIP_DEBUG_WHERE    whereami("start_link\n");#endif    if ((tp->flags & ALWAYS_CHECK_MII) ||        (tp->mtable  &&  tp->mtable->has_mii) ||        ( ! tp->mtable  &&  (tp->flags & HAS_MII))) {        unsigned int phy, phy_idx;        if (tp->mtable  &&  tp->mtable->has_mii) {            for (i = 0; i < tp->mtable->leafcount; i++)                if (tp->mtable->mleaf[i].media == 11) {                    tp->cur_index = i;                    tp->saved_if_port = tp->if_port;                    select_media(nic, 2);                    tp->if_port = tp->saved_if_port;                    break;                }        }        /* Find the connected MII xcvrs. */        for (phy = 0, phy_idx = 0; phy < 32 && phy_idx < sizeof(tp->phys);             phy++) {            int mii_status = mdio_read(nic, phy, 1);            if ((mii_status & 0x8301) == 0x8001 ||                ((mii_status & 0x8000) == 0  && (mii_status & 0x7800) != 0)) {                int mii_reg0 = mdio_read(nic, phy, 0);                int mii_advert = mdio_read(nic, phy, 4);                int to_advert;                if (tp->mii_advertise)                    to_advert = tp->mii_advertise;                else if (tp->advertising[phy_idx])                    to_advert = tp->advertising[phy_idx];                else                    /* Leave unchanged. */                    tp->mii_advertise = to_advert = mii_advert;                tp->phys[phy_idx++] = phy;                printf("%s:  MII transceiver %d config %hX status %hX advertising %hX.\n",                       tp->nic_name, phy, mii_reg0, mii_status, mii_advert);                                /* Fixup for DLink with miswired PHY. */                if (mii_advert != to_advert) {                    printf("%s:  Advertising %hX on PHY %d previously advertising %hX.\n",                           tp->nic_name, to_advert, phy, mii_advert);                    mdio_write(nic, phy, 4, to_advert);                }                                /* Enable autonegotiation: some boards default to off. */                mdio_write(nic, phy, 0, mii_reg0 |                           (tp->full_duplex ? 0x1100 : 0x1000) |                           (media_cap[tp->default_port]&MediaIs100 ? 0x2000:0));            }        }        tp->mii_cnt = phy_idx;        if (tp->mtable  &&  tp->mtable->has_mii  &&  phy_idx == 0) {            printf("%s: ***WARNING***: No MII transceiver found!\n",                   tp->nic_name);            tp->phys[0] = 1;        }    }    /* Reset the xcvr interface and turn on heartbeat. */    switch (tp->chip_id) {

⌨️ 快捷键说明

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