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

📄 tulip.c

📁 i386的bootloader源码grub
💻 C
📖 第 1 页 / 共 5 页
字号:
/*********************************************************************//* EEPROM Parsing Code                                               *//*********************************************************************/static void parse_eeprom(struct nic *nic){    unsigned char *p, *ee_data = tp->eeprom;    int new_advertise = 0;    int i;#ifdef TULIP_DEBUG_WHERE    whereami("parse_eeprom\n");#endif    tp->mtable = 0;    /* Detect an old-style (SA only) EEPROM layout:       memcmp(ee_data, ee_data+16, 8). */    for (i = 0; i < 8; i ++)        if (ee_data[i] != ee_data[16+i])            break;    if (i >= 8) {        /* Do a fix-up based on the vendor half of the station address. */        for (i = 0; eeprom_fixups[i].name; i++) {            if (nic->node_addr[0] == eeprom_fixups[i].addr0                &&  nic->node_addr[1] == eeprom_fixups[i].addr1                &&  nic->node_addr[2] == eeprom_fixups[i].addr2) {                if (nic->node_addr[2] == 0xE8  &&  ee_data[0x1a] == 0x55)                    i++;                /* An Accton EN1207, not an outlaw Maxtech. */                memcpy(ee_data + 26, eeprom_fixups[i].newtable,                       sizeof(eeprom_fixups[i].newtable));#ifdef TULIP_DEBUG                printf("%s: Old format EEPROM on '%s' board.\n%s: Using substitute media control info.\n",                       tp->nic_name, eeprom_fixups[i].name, tp->nic_name);#endif                break;            }        }        if (eeprom_fixups[i].name == NULL) { /* No fixup found. */#ifdef TULIP_DEBUG            printf("%s: Old style EEPROM with no media selection information.\n",                   tp->nic_name);#endif            return;        }    }    if (ee_data[19] > 1) {#ifdef TULIP_DEBUG        printf("%s:  Multiport cards (%d ports) may not work correctly.\n",                tp->nic_name, ee_data[19]);#endif    }    p = (void *)ee_data + ee_data[27];    if (ee_data[27] == 0) {             /* No valid media table. */#ifdef TULIP_DEBUG        if (tulip_debug > 1) {            printf("%s:  No Valid Media Table. ee_data[27] = %hhX\n",                    tp->nic_name, ee_data[27]);        }#endif    } else if (tp->chip_id == DC21041) {        int media = get_u16(p);        int count = p[2];        p += 3;        printf("%s: 21041 Media table, default media %hX (%s).\n",               tp->nic_name, media,               media & 0x0800 ? "Autosense" : medianame[media & 15]);        for (i = 0; i < count; i++) {            unsigned char media_block = *p++;            int media_code = media_block & MEDIA_MASK;            if (media_block & 0x40)                p += 6;            switch(media_code) {            case 0: new_advertise |= 0x0020; break;            case 4: new_advertise |= 0x0040; break;            }            printf("%s:  21041 media #%d, %s.\n",                   tp->nic_name, media_code, medianame[media_code]);        }    } else {        unsigned char csr12dir = 0;        int count;        struct mediatable *mtable;        u16 media = get_u16(p);        p += 2;        if (tp->flags & CSR12_IN_SROM)            csr12dir = *p++;        count = *p++;        tp->mtable = mtable = (struct mediatable *)&tp->media_table_storage[0];        mtable->defaultmedia = media;        mtable->leafcount = count;        mtable->csr12dir = csr12dir;        mtable->has_nonmii = mtable->has_mii = mtable->has_reset = 0;        mtable->csr15dir = mtable->csr15val = 0;        printf("%s:  EEPROM default media type %s.\n", tp->nic_name,               media & 0x0800 ? "Autosense" : medianame[media & MEDIA_MASK]);        for (i = 0; i < count; i++) {            struct medialeaf *leaf = &mtable->mleaf[i];            if ((p[0] & 0x80) == 0) { /* 21140 Compact block. */                leaf->type = 0;                leaf->media = p[0] & 0x3f;                leaf->leafdata = p;                if ((p[2] & 0x61) == 0x01)      /* Bogus, but Znyx boards do it. */                    mtable->has_mii = 1;                p += 4;            } else {                switch(leaf->type = p[1]) {                case 5:                    mtable->has_reset = i;                    leaf->media = p[2] & 0x0f;                    break;                case 1: case 3:                    mtable->has_mii = 1;                    leaf->media = 11;                    break;                case 2:                    if ((p[2] & 0x3f) == 0) {                        u32 base15 = (p[2] & 0x40) ? get_u16(p + 7) : 0x0008;                        u16 *p1 = (u16 *)(p + (p[2] & 0x40 ? 9 : 3));                        mtable->csr15dir = (get_unaligned(p1 + 0)<<16) + base15;                        mtable->csr15val = (get_unaligned(p1 + 1)<<16) + base15;                    }                    /* Fall through. */                case 0: case 4:                    mtable->has_nonmii = 1;                    leaf->media = p[2] & MEDIA_MASK;                    switch (leaf->media) {                    case 0: new_advertise |= 0x0020; break;                    case 4: new_advertise |= 0x0040; break;                    case 3: new_advertise |= 0x0080; break;                    case 5: new_advertise |= 0x0100; break;                    case 6: new_advertise |= 0x0200; break;                    }                    break;                default:                    leaf->media = 19;                }                leaf->leafdata = p + 2;                p += (p[0] & 0x3f) + 1;            }#ifdef TULIP_DEBUG            if (tulip_debug > 1  &&  leaf->media == 11) {                unsigned char *bp = leaf->leafdata;                printf("%s:  MII interface PHY %d, setup/reset sequences %d/%d long, capabilities %hhX %hhX.\n",                       tp->nic_name, bp[0], bp[1], bp[2 + bp[1]*2],                       bp[5 + bp[2 + bp[1]*2]*2], bp[4 + bp[2 + bp[1]*2]*2]);            }#endif            printf("%s:  Index #%d - Media %s (#%d) described "                   "by a %s (%d) block.\n",                   tp->nic_name, i, medianame[leaf->media], leaf->media,                   leaf->type < 6 ? block_name[leaf->type] : "UNKNOWN",                   leaf->type);        }        if (new_advertise)            tp->sym_advertise = new_advertise;    }}/*********************************************************************//* tulip_init_ring - setup the tx and rx descriptors                *//*********************************************************************/static void tulip_init_ring(struct nic *nic){    int i;#ifdef TULIP_DEBUG_WHERE    whereami("tulip_init_ring\n");#endif    tp->cur_rx = 0;    for (i = 0; i < RX_RING_SIZE; i++) {	rx_ring[i].status  = cpu_to_le32(0x80000000);	rx_ring[i].length  = cpu_to_le32(BUFLEN);	rx_ring[i].buffer1 = virt_to_le32desc(&rxb[i * BUFLEN]);	rx_ring[i].buffer2 = virt_to_le32desc(&rx_ring[i+1]);    }    /* Mark the last entry as wrapping the ring. */    rx_ring[i-1].length    = cpu_to_le32(DESC_RING_WRAP | BUFLEN);    rx_ring[i-1].buffer2   = virt_to_le32desc(&rx_ring[0]);    /* We only use 1 transmit buffer, but we use 2 descriptors so       transmit engines have somewhere to point to if they feel the need */    tx_ring[0].status  = 0x00000000;    tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);    tx_ring[0].buffer2 = virt_to_le32desc(&tx_ring[1]);    /* this descriptor should never get used, since it will never be owned       by the machine (status will always == 0) */    tx_ring[1].status  = 0x00000000;    tx_ring[1].buffer1 = virt_to_le32desc(&txb[0]);    tx_ring[1].buffer2 = virt_to_le32desc(&tx_ring[0]);    /* Mark the last entry as wrapping the ring, though this should never happen */    tx_ring[1].length  = cpu_to_le32(DESC_RING_WRAP | BUFLEN);}/*********************************************************************//* eth_reset - Reset adapter                                         *//*********************************************************************/static void tulip_reset(struct nic *nic){    int i;    unsigned long to;    u32 addr_low, addr_high;#ifdef TULIP_DEBUG_WHERE    whereami("tulip_reset\n");#endif    /* Stop Tx and RX */    outl(inl(ioaddr + CSR6) & ~0x00002002, ioaddr + CSR6);    /* 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(0x814C0000, ioaddr + CSR6);    }      /* Reset the chip, holding bit 0 set at least 50 PCI cycles. */    outl(0x00000001, ioaddr + CSR0);    tulip_wait(1);    /* turn off reset and set cache align=16lword, burst=unlimit */    outl(tp->csr0, ioaddr + CSR0);    /*  Wait the specified 50 PCI cycles after a reset */    tulip_wait(1);    /* set up transmit and receive descriptors */    tulip_init_ring(nic);    if (tp->chip_id == PNIC2) {        u32 addr_high = (nic->node_addr[1]<<8) + (nic->node_addr[0]<<0);        /* This address setting does not appear to impact chip operation?? */        outl((nic->node_addr[5]<<8) + nic->node_addr[4] +             (nic->node_addr[3]<<24) + (nic->node_addr[2]<<16),             ioaddr + 0xB0);        outl(addr_high + (addr_high<<16), ioaddr + 0xB8);    }    /* MC_HASH_ONLY boards don't support setup packets */    if (tp->flags & MC_HASH_ONLY) {        u32 addr_low = cpu_to_le32(get_unaligned((u32 *)nic->node_addr));        u32 addr_high = cpu_to_le32(get_unaligned((u16 *)(nic->node_addr+4)));	/* clear multicast hash filters and setup MAC address filters */	if (tp->flags & IS_ASIX) {            outl(0, ioaddr + CSR13);            outl(addr_low,  ioaddr + CSR14);            outl(1, ioaddr + CSR13);            outl(addr_high, ioaddr + CSR14);	    outl(2, ioaddr + CSR13);	    outl(0, ioaddr + CSR14);	    outl(3, ioaddr + CSR13);	    outl(0, ioaddr + CSR14);	} else if (tp->chip_id == COMET) {            outl(addr_low,  ioaddr + 0xA4);            outl(addr_high, ioaddr + 0xA8);            outl(0, ioaddr + 0xAC);            outl(0, ioaddr + 0xB0);	}    } else {	/* for other boards we send a setup packet to initialize	   the filters */	u32 tx_flags = 0x08000000 | 192;	/* construct perfect filter frame with mac address as first match	   and broadcast address for all others */	for (i=0; i<192; i++) 	    txb[i] = 0xFF;	txb[0] = nic->node_addr[0];	txb[1] = nic->node_addr[1];	txb[4] = nic->node_addr[2];	txb[5] = nic->node_addr[3];	txb[8] = nic->node_addr[4];	txb[9] = nic->node_addr[5];	tx_ring[0].length  = cpu_to_le32(tx_flags);	tx_ring[0].buffer1 = virt_to_le32desc(&txb[0]);	tx_ring[0].status  = cpu_to_le32(0x80000000);    }    /* Point to rx and tx descriptors */    outl((unsigned long)&rx_ring[0], ioaddr + CSR3);    outl((unsigned long)&tx_ring[0], ioaddr + CSR4);    init_media(nic);    /* set the chip's operating mode (but don't turn on xmit and recv yet) */    outl((tp->csr6 & ~0x00002002), ioaddr + CSR6);    /* send setup packet for cards that support it */    if (!(tp->flags & MC_HASH_ONLY)) {	/* enable transmit  wait for completion */	outl(tp->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 ("%s: TX Setup Timeout.\n", tp->nic_name);	}    }    if (tp->chip_id == LC82C168)	tulip_check_duplex(nic);    /* enable transmit and receive */    outl(tp->csr6 | 0x00002002, ioaddr + CSR6);}/*********************************************************************//* eth_transmit - Transmit a frame                                   *//*********************************************************************/static void tulip_transmit(struct nic *nic, const char *d, unsigned int t,                           unsigned int s, const char *p){    u16 nstype;    u32 to;    u32 csr6 = inl(ioaddr + CSR6);#ifdef TULIP_DEBUG_WHERE        whereami("tulip_transmit\n");#endif    /* Disable Tx */    outl(csr6 & ~0x00002000, ioaddr + CSR6);    memcpy(txb, d, ETH_ALEN);    memcpy(txb + ETH_ALEN, nic->node_addr, ETH_ALEN);    nstype = htons((u16) t);    memcpy(txb + 2 * ETH_ALEN, (u8 *)&nstype, 2);    memcpy(txb + ETH_HLEN, p, s);    s += ETH_HLEN;    s &= 0x0FFF;    /* pad to minimum packet size */    while (s < ETH_ZLEN)          txb[s++] = '\0';#ifdef TULIP_DEBUG    if (tulip_debug > 1)	printf("%s: sending %d bytes ethtype %hX\n", tp->nic_name, s, t);#endif            /* setup the transmit descriptor */

⌨️ 快捷键说明

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