Annotation of qemu/hw/etraxfs_eth.c, revision 1.1.1.8

1.1       root        1: /*
                      2:  * QEMU ETRAX Ethernet Controller.
                      3:  *
                      4:  * Copyright (c) 2008 Edgar E. Iglesias, Axis Communications AB.
                      5:  *
                      6:  * Permission is hereby granted, free of charge, to any person obtaining a copy
                      7:  * of this software and associated documentation files (the "Software"), to deal
                      8:  * in the Software without restriction, including without limitation the rights
                      9:  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
                     10:  * copies of the Software, and to permit persons to whom the Software is
                     11:  * furnished to do so, subject to the following conditions:
                     12:  *
                     13:  * The above copyright notice and this permission notice shall be included in
                     14:  * all copies or substantial portions of the Software.
                     15:  *
                     16:  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
                     17:  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
                     18:  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
                     19:  * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
                     20:  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
                     21:  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
                     22:  * THE SOFTWARE.
                     23:  */
                     24: 
                     25: #include <stdio.h>
                     26: #include "hw.h"
                     27: #include "net.h"
                     28: #include "etraxfs.h"
                     29: 
                     30: #define D(x)
                     31: 
                     32: /* Advertisement control register. */
                     33: #define ADVERTISE_10HALF        0x0020  /* Try for 10mbps half-duplex  */
                     34: #define ADVERTISE_10FULL        0x0040  /* Try for 10mbps full-duplex  */
                     35: #define ADVERTISE_100HALF       0x0080  /* Try for 100mbps half-duplex */
                     36: #define ADVERTISE_100FULL       0x0100  /* Try for 100mbps full-duplex */
                     37: 
                     38: /* 
                     39:  * The MDIO extensions in the TDK PHY model were reversed engineered from the 
                     40:  * linux driver (PHYID and Diagnostics reg).
                     41:  * TODO: Add friendly names for the register nums.
                     42:  */
                     43: struct qemu_phy
                     44: {
                     45:        uint32_t regs[32];
                     46: 
                     47:        int link;
                     48: 
                     49:        unsigned int (*read)(struct qemu_phy *phy, unsigned int req);
                     50:        void (*write)(struct qemu_phy *phy, unsigned int req, 
                     51:                      unsigned int data);
                     52: };
                     53: 
                     54: static unsigned int tdk_read(struct qemu_phy *phy, unsigned int req)
                     55: {
                     56:        int regnum;
                     57:        unsigned r = 0;
                     58: 
                     59:        regnum = req & 0x1f;
                     60: 
                     61:        switch (regnum) {
                     62:                case 1:
                     63:                        if (!phy->link)
                     64:                                break;
                     65:                        /* MR1.  */
                     66:                        /* Speeds and modes.  */
                     67:                        r |= (1 << 13) | (1 << 14);
                     68:                        r |= (1 << 11) | (1 << 12);
                     69:                        r |= (1 << 5); /* Autoneg complete.  */
                     70:                        r |= (1 << 3); /* Autoneg able.  */
                     71:                        r |= (1 << 2); /* link.  */
                     72:                        break;
                     73:                case 5:
                     74:                        /* Link partner ability.
                     75:                           We are kind; always agree with whatever best mode
                     76:                           the guest advertises.  */
                     77:                        r = 1 << 14; /* Success.  */
                     78:                        /* Copy advertised modes.  */
                     79:                        r |= phy->regs[4] & (15 << 5);
                     80:                        /* Autoneg support.  */
                     81:                        r |= 1;
                     82:                        break;
                     83:                case 18:
                     84:                {
                     85:                        /* Diagnostics reg.  */
                     86:                        int duplex = 0;
                     87:                        int speed_100 = 0;
                     88: 
                     89:                        if (!phy->link)
                     90:                                break;
                     91: 
                     92:                        /* Are we advertising 100 half or 100 duplex ? */
                     93:                        speed_100 = !!(phy->regs[4] & ADVERTISE_100HALF);
                     94:                        speed_100 |= !!(phy->regs[4] & ADVERTISE_100FULL);
                     95: 
                     96:                        /* Are we advertising 10 duplex or 100 duplex ? */
                     97:                        duplex = !!(phy->regs[4] & ADVERTISE_100FULL);
                     98:                        duplex |= !!(phy->regs[4] & ADVERTISE_10FULL);
                     99:                        r = (speed_100 << 10) | (duplex << 11);
                    100:                }
                    101:                break;
                    102: 
                    103:                default:
                    104:                        r = phy->regs[regnum];
                    105:                        break;
                    106:        }
                    107:        D(printf("\n%s %x = reg[%d]\n", __func__, r, regnum));
                    108:        return r;
                    109: }
                    110: 
                    111: static void 
                    112: tdk_write(struct qemu_phy *phy, unsigned int req, unsigned int data)
                    113: {
                    114:        int regnum;
                    115: 
                    116:        regnum = req & 0x1f;
                    117:        D(printf("%s reg[%d] = %x\n", __func__, regnum, data));
                    118:        switch (regnum) {
                    119:                default:
                    120:                        phy->regs[regnum] = data;
                    121:                        break;
                    122:        }
                    123: }
                    124: 
                    125: static void 
                    126: tdk_init(struct qemu_phy *phy)
                    127: {
                    128:        phy->regs[0] = 0x3100;
                    129:        /* PHY Id.  */
                    130:        phy->regs[2] = 0x0300;
                    131:        phy->regs[3] = 0xe400;
                    132:        /* Autonegotiation advertisement reg.  */
                    133:        phy->regs[4] = 0x01E1;
                    134:        phy->link = 1;
                    135: 
                    136:        phy->read = tdk_read;
                    137:        phy->write = tdk_write;
                    138: }
                    139: 
                    140: struct qemu_mdio
                    141: {
                    142:        /* bus.  */
                    143:        int mdc;
                    144:        int mdio;
                    145: 
                    146:        /* decoder.  */
                    147:        enum {
                    148:                PREAMBLE,
                    149:                SOF,
                    150:                OPC,
                    151:                ADDR,
                    152:                REQ,
                    153:                TURNAROUND,
                    154:                DATA
                    155:        } state;
                    156:        unsigned int drive;
                    157: 
                    158:        unsigned int cnt;
                    159:        unsigned int addr;
                    160:        unsigned int opc;
                    161:        unsigned int req;
                    162:        unsigned int data;
                    163: 
                    164:        struct qemu_phy *devs[32];
                    165: };
                    166: 
                    167: static void 
                    168: mdio_attach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
                    169: {
                    170:        bus->devs[addr & 0x1f] = phy;
                    171: }
                    172: 
                    173: #ifdef USE_THIS_DEAD_CODE
                    174: static void 
                    175: mdio_detach(struct qemu_mdio *bus, struct qemu_phy *phy, unsigned int addr)
                    176: {
                    177:        bus->devs[addr & 0x1f] = NULL;  
                    178: }
                    179: #endif
                    180: 
                    181: static void mdio_read_req(struct qemu_mdio *bus)
                    182: {
                    183:        struct qemu_phy *phy;
                    184: 
                    185:        phy = bus->devs[bus->addr];
                    186:        if (phy && phy->read)
                    187:                bus->data = phy->read(phy, bus->req);
                    188:        else 
                    189:                bus->data = 0xffff;
                    190: }
                    191: 
                    192: static void mdio_write_req(struct qemu_mdio *bus)
                    193: {
                    194:        struct qemu_phy *phy;
                    195: 
                    196:        phy = bus->devs[bus->addr];
                    197:        if (phy && phy->write)
                    198:                phy->write(phy, bus->req, bus->data);
                    199: }
                    200: 
                    201: static void mdio_cycle(struct qemu_mdio *bus)
                    202: {
                    203:        bus->cnt++;
                    204: 
                    205:        D(printf("mdc=%d mdio=%d state=%d cnt=%d drv=%d\n",
                    206:                bus->mdc, bus->mdio, bus->state, bus->cnt, bus->drive));
                    207: #if 0
                    208:        if (bus->mdc)
                    209:                printf("%d", bus->mdio);
                    210: #endif
                    211:        switch (bus->state)
                    212:        {
                    213:                case PREAMBLE:
                    214:                        if (bus->mdc) {
                    215:                                if (bus->cnt >= (32 * 2) && !bus->mdio) {
                    216:                                        bus->cnt = 0;
                    217:                                        bus->state = SOF;
                    218:                                        bus->data = 0;
                    219:                                }
                    220:                        }
                    221:                        break;
                    222:                case SOF:
                    223:                        if (bus->mdc) {
                    224:                                if (bus->mdio != 1)
                    225:                                        printf("WARNING: no SOF\n");
                    226:                                if (bus->cnt == 1*2) {
                    227:                                        bus->cnt = 0;
                    228:                                        bus->opc = 0;
                    229:                                        bus->state = OPC;
                    230:                                }
                    231:                        }
                    232:                        break;
                    233:                case OPC:
                    234:                        if (bus->mdc) {
                    235:                                bus->opc <<= 1;
                    236:                                bus->opc |= bus->mdio & 1;
                    237:                                if (bus->cnt == 2*2) {
                    238:                                        bus->cnt = 0;
                    239:                                        bus->addr = 0;
                    240:                                        bus->state = ADDR;
                    241:                                }
                    242:                        }
                    243:                        break;
                    244:                case ADDR:
                    245:                        if (bus->mdc) {
                    246:                                bus->addr <<= 1;
                    247:                                bus->addr |= bus->mdio & 1;
                    248: 
                    249:                                if (bus->cnt == 5*2) {
                    250:                                        bus->cnt = 0;
                    251:                                        bus->req = 0;
                    252:                                        bus->state = REQ;
                    253:                                }
                    254:                        }
                    255:                        break;
                    256:                case REQ:
                    257:                        if (bus->mdc) {
                    258:                                bus->req <<= 1;
                    259:                                bus->req |= bus->mdio & 1;
                    260:                                if (bus->cnt == 5*2) {
                    261:                                        bus->cnt = 0;
                    262:                                        bus->state = TURNAROUND;
                    263:                                }
                    264:                        }
                    265:                        break;
                    266:                case TURNAROUND:
                    267:                        if (bus->mdc && bus->cnt == 2*2) {
                    268:                                bus->mdio = 0;
                    269:                                bus->cnt = 0;
                    270: 
                    271:                                if (bus->opc == 2) {
                    272:                                        bus->drive = 1;
                    273:                                        mdio_read_req(bus);
                    274:                                        bus->mdio = bus->data & 1;
                    275:                                }
                    276:                                bus->state = DATA;
                    277:                        }
                    278:                        break;
                    279:                case DATA:                      
                    280:                        if (!bus->mdc) {
                    281:                                if (bus->drive) {
                    282:                                        bus->mdio = !!(bus->data & (1 << 15));
                    283:                                        bus->data <<= 1;
                    284:                                }
                    285:                        } else {
                    286:                                if (!bus->drive) {
                    287:                                        bus->data <<= 1;
                    288:                                        bus->data |= bus->mdio;
                    289:                                }
                    290:                                if (bus->cnt == 16 * 2) {
                    291:                                        bus->cnt = 0;
                    292:                                        bus->state = PREAMBLE;
                    293:                                        if (!bus->drive)
                    294:                                                mdio_write_req(bus);
                    295:                                        bus->drive = 0;
                    296:                                }
                    297:                        }
                    298:                        break;
                    299:                default:
                    300:                        break;
                    301:        }
                    302: }
                    303: 
                    304: /* ETRAX-FS Ethernet MAC block starts here.  */
                    305: 
                    306: #define RW_MA0_LO        0x00
                    307: #define RW_MA0_HI        0x01
                    308: #define RW_MA1_LO        0x02
                    309: #define RW_MA1_HI        0x03
                    310: #define RW_GA_LO         0x04
                    311: #define RW_GA_HI         0x05
                    312: #define RW_GEN_CTRL      0x06
                    313: #define RW_REC_CTRL      0x07
                    314: #define RW_TR_CTRL       0x08
                    315: #define RW_CLR_ERR       0x09
                    316: #define RW_MGM_CTRL      0x0a
                    317: #define R_STAT           0x0b
                    318: #define FS_ETH_MAX_REGS          0x17
                    319: 
                    320: struct fs_eth
                    321: {
1.1.1.5   root      322:        NICState *nic;
                    323:        NICConf conf;
1.1       root      324:        int ethregs;
                    325: 
                    326:        /* Two addrs in the filter.  */
                    327:        uint8_t macaddr[2][6];
                    328:        uint32_t regs[FS_ETH_MAX_REGS];
                    329: 
                    330:        struct etraxfs_dma_client *dma_out;
                    331:        struct etraxfs_dma_client *dma_in;
                    332: 
                    333:        /* MDIO bus.  */
                    334:        struct qemu_mdio mdio_bus;
                    335:        unsigned int phyaddr;
                    336:        int duplex_mismatch;
                    337: 
                    338:        /* PHY.  */
                    339:        struct qemu_phy phy;
                    340: };
                    341: 
                    342: static void eth_validate_duplex(struct fs_eth *eth)
                    343: {
                    344:        struct qemu_phy *phy;
                    345:        unsigned int phy_duplex;
                    346:        unsigned int mac_duplex;
                    347:        int new_mm = 0;
                    348: 
                    349:        phy = eth->mdio_bus.devs[eth->phyaddr];
                    350:        phy_duplex = !!(phy->read(phy, 18) & (1 << 11));
                    351:        mac_duplex = !!(eth->regs[RW_REC_CTRL] & 128);
                    352: 
                    353:        if (mac_duplex != phy_duplex)
                    354:                new_mm = 1;
                    355: 
                    356:        if (eth->regs[RW_GEN_CTRL] & 1) {
                    357:                if (new_mm != eth->duplex_mismatch) {
                    358:                        if (new_mm)
                    359:                                printf("HW: WARNING "
                    360:                                       "ETH duplex mismatch MAC=%d PHY=%d\n",
                    361:                                       mac_duplex, phy_duplex);
                    362:                        else
                    363:                                printf("HW: ETH duplex ok.\n");
                    364:                }
                    365:                eth->duplex_mismatch = new_mm;
                    366:        }
                    367: }
                    368: 
                    369: static uint32_t eth_readl (void *opaque, target_phys_addr_t addr)
                    370: {
                    371:        struct fs_eth *eth = opaque;
                    372:        uint32_t r = 0;
                    373: 
                    374:        addr >>= 2;
                    375: 
                    376:        switch (addr) {
                    377:                case R_STAT:
                    378:                        r = eth->mdio_bus.mdio & 1;
                    379:                        break;
                    380:        default:
                    381:                r = eth->regs[addr];
                    382:                D(printf ("%s %x\n", __func__, addr * 4));
                    383:                break;
                    384:        }
                    385:        return r;
                    386: }
                    387: 
                    388: static void eth_update_ma(struct fs_eth *eth, int ma)
                    389: {
                    390:        int reg;
                    391:        int i = 0;
                    392: 
                    393:        ma &= 1;
                    394: 
                    395:        reg = RW_MA0_LO;
                    396:        if (ma)
                    397:                reg = RW_MA1_LO;
                    398: 
                    399:        eth->macaddr[ma][i++] = eth->regs[reg];
                    400:        eth->macaddr[ma][i++] = eth->regs[reg] >> 8;
                    401:        eth->macaddr[ma][i++] = eth->regs[reg] >> 16;
                    402:        eth->macaddr[ma][i++] = eth->regs[reg] >> 24;
1.1.1.3   root      403:        eth->macaddr[ma][i++] = eth->regs[reg + 1];
1.1.1.6   root      404:        eth->macaddr[ma][i] = eth->regs[reg + 1] >> 8;
1.1       root      405: 
                    406:        D(printf("set mac%d=%x.%x.%x.%x.%x.%x\n", ma,
                    407:                 eth->macaddr[ma][0], eth->macaddr[ma][1],
                    408:                 eth->macaddr[ma][2], eth->macaddr[ma][3],
                    409:                 eth->macaddr[ma][4], eth->macaddr[ma][5]));
                    410: }
                    411: 
                    412: static void
                    413: eth_writel (void *opaque, target_phys_addr_t addr, uint32_t value)
                    414: {
                    415:        struct fs_eth *eth = opaque;
                    416: 
                    417:        addr >>= 2;
                    418:        switch (addr)
                    419:        {
                    420:                case RW_MA0_LO:
                    421:                case RW_MA0_HI:
                    422:                        eth->regs[addr] = value;
                    423:                        eth_update_ma(eth, 0);
                    424:                        break;
                    425:                case RW_MA1_LO:
                    426:                case RW_MA1_HI:
                    427:                        eth->regs[addr] = value;
                    428:                        eth_update_ma(eth, 1);
                    429:                        break;
                    430: 
                    431:                case RW_MGM_CTRL:
                    432:                        /* Attach an MDIO/PHY abstraction.  */
                    433:                        if (value & 2)
                    434:                                eth->mdio_bus.mdio = value & 1;
                    435:                        if (eth->mdio_bus.mdc != (value & 4)) {
                    436:                                mdio_cycle(&eth->mdio_bus);
                    437:                                eth_validate_duplex(eth);
                    438:                        }
                    439:                        eth->mdio_bus.mdc = !!(value & 4);
1.1.1.6   root      440:                        eth->regs[addr] = value;
1.1       root      441:                        break;
                    442: 
                    443:                case RW_REC_CTRL:
                    444:                        eth->regs[addr] = value;
                    445:                        eth_validate_duplex(eth);
                    446:                        break;
                    447: 
                    448:                default:
                    449:                        eth->regs[addr] = value;
                    450:                        D(printf ("%s %x %x\n",
                    451:                                  __func__, addr, value));
                    452:                        break;
                    453:        }
                    454: }
                    455: 
                    456: /* The ETRAX FS has a groupt address table (GAT) which works like a k=1 bloom
                    457:    filter dropping group addresses we have not joined. The filter has 64
                    458:    bits (m). The has function is a simple nible xor of the group addr. */
                    459: static int eth_match_groupaddr(struct fs_eth *eth, const unsigned char *sa)
                    460: {
                    461:        unsigned int hsh;
                    462:        int m_individual = eth->regs[RW_REC_CTRL] & 4;
                    463:        int match;
                    464: 
                    465:        /* First bit on the wire of a MAC address signals multicast or
                    466:           physical address.  */
1.1.1.7   root      467:        if (!m_individual && !(sa[0] & 1))
1.1       root      468:                return 0;
                    469: 
                    470:        /* Calculate the hash index for the GA registers. */
                    471:        hsh = 0;
                    472:        hsh ^= (*sa) & 0x3f;
                    473:        hsh ^= ((*sa) >> 6) & 0x03;
                    474:        ++sa;
                    475:        hsh ^= ((*sa) << 2) & 0x03c;
                    476:        hsh ^= ((*sa) >> 4) & 0xf;
                    477:        ++sa;
                    478:        hsh ^= ((*sa) << 4) & 0x30;
                    479:        hsh ^= ((*sa) >> 2) & 0x3f;
                    480:        ++sa;
                    481:        hsh ^= (*sa) & 0x3f;
                    482:        hsh ^= ((*sa) >> 6) & 0x03;
                    483:        ++sa;
                    484:        hsh ^= ((*sa) << 2) & 0x03c;
                    485:        hsh ^= ((*sa) >> 4) & 0xf;
                    486:        ++sa;
                    487:        hsh ^= ((*sa) << 4) & 0x30;
                    488:        hsh ^= ((*sa) >> 2) & 0x3f;
                    489: 
                    490:        hsh &= 63;
                    491:        if (hsh > 31)
                    492:                match = eth->regs[RW_GA_HI] & (1 << (hsh - 32));
                    493:        else
                    494:                match = eth->regs[RW_GA_LO] & (1 << hsh);
                    495:        D(printf("hsh=%x ga=%x.%x mtch=%d\n", hsh,
                    496:                 eth->regs[RW_GA_HI], eth->regs[RW_GA_LO], match));
                    497:        return match;
                    498: }
                    499: 
1.1.1.5   root      500: static int eth_can_receive(VLANClientState *nc)
1.1       root      501: {
                    502:        return 1;
                    503: }
                    504: 
1.1.1.5   root      505: static ssize_t eth_receive(VLANClientState *nc, const uint8_t *buf, size_t size)
1.1       root      506: {
                    507:        unsigned char sa_bcast[6] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1.1.1.5   root      508:        struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque;
1.1       root      509:        int use_ma0 = eth->regs[RW_REC_CTRL] & 1;
                    510:        int use_ma1 = eth->regs[RW_REC_CTRL] & 2;
                    511:        int r_bcast = eth->regs[RW_REC_CTRL] & 8;
                    512: 
                    513:        if (size < 12)
1.1.1.4   root      514:                return -1;
1.1       root      515: 
                    516:        D(printf("%x.%x.%x.%x.%x.%x ma=%d %d bc=%d\n",
                    517:                 buf[0], buf[1], buf[2], buf[3], buf[4], buf[5],
                    518:                 use_ma0, use_ma1, r_bcast));
                    519:               
                    520:        /* Does the frame get through the address filters?  */
                    521:        if ((!use_ma0 || memcmp(buf, eth->macaddr[0], 6))
                    522:            && (!use_ma1 || memcmp(buf, eth->macaddr[1], 6))
                    523:            && (!r_bcast || memcmp(buf, sa_bcast, 6))
                    524:            && !eth_match_groupaddr(eth, buf))
1.1.1.4   root      525:                return size;
1.1       root      526: 
                    527:        /* FIXME: Find another way to pass on the fake csum.  */
                    528:        etraxfs_dmac_input(eth->dma_in, (void *)buf, size + 4, 1);
1.1.1.4   root      529: 
                    530:         return size;
1.1       root      531: }
                    532: 
                    533: static int eth_tx_push(void *opaque, unsigned char *buf, int len)
                    534: {
                    535:        struct fs_eth *eth = opaque;
                    536: 
                    537:        D(printf("%s buf=%p len=%d\n", __func__, buf, len));
1.1.1.5   root      538:        qemu_send_packet(&eth->nic->nc, buf, len);
1.1       root      539:        return len;
                    540: }
                    541: 
1.1.1.5   root      542: static void eth_set_link(VLANClientState *nc)
1.1       root      543: {
1.1.1.5   root      544:        struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque;
                    545:        D(printf("%s %d\n", __func__, nc->link_down));
                    546:        eth->phy.link = !nc->link_down;
1.1       root      547: }
                    548: 
1.1.1.5   root      549: static CPUReadMemoryFunc * const eth_read[] = {
1.1       root      550:        NULL, NULL,
                    551:        &eth_readl,
                    552: };
                    553: 
1.1.1.5   root      554: static CPUWriteMemoryFunc * const eth_write[] = {
1.1       root      555:        NULL, NULL,
                    556:        &eth_writel,
                    557: };
                    558: 
1.1.1.5   root      559: static void eth_cleanup(VLANClientState *nc)
1.1.1.2   root      560: {
1.1.1.5   root      561:        struct fs_eth *eth = DO_UPCAST(NICState, nc, nc)->opaque;
1.1.1.2   root      562: 
                    563:         cpu_unregister_io_memory(eth->ethregs);
                    564: 
                    565:         qemu_free(eth->dma_out);
                    566:         qemu_free(eth);
                    567: }
                    568: 
1.1.1.5   root      569: static NetClientInfo net_etraxfs_info = {
                    570:        .type = NET_CLIENT_TYPE_NIC,
                    571:        .size = sizeof(NICState),
                    572:        .can_receive = eth_can_receive,
                    573:        .receive = eth_receive,
                    574:        .cleanup = eth_cleanup,
                    575:        .link_status_changed = eth_set_link,
                    576: };
                    577: 
1.1.1.4   root      578: void *etraxfs_eth_init(NICInfo *nd, target_phys_addr_t base, int phyaddr)
1.1       root      579: {
                    580:        struct etraxfs_dma_client *dma = NULL;  
                    581:        struct fs_eth *eth = NULL;
                    582: 
                    583:        qemu_check_nic_model(nd, "fseth");
                    584: 
                    585:        dma = qemu_mallocz(sizeof *dma * 2);
                    586:        eth = qemu_mallocz(sizeof *eth);
                    587: 
                    588:        dma[0].client.push = eth_tx_push;
                    589:        dma[0].client.opaque = eth;
                    590:        dma[1].client.opaque = eth;
                    591:        dma[1].client.pull = NULL;
                    592: 
                    593:        eth->dma_out = dma;
                    594:        eth->dma_in = dma + 1;
                    595: 
                    596:        /* Connect the phy.  */
                    597:        eth->phyaddr = phyaddr & 0x1f;
                    598:        tdk_init(&eth->phy);
                    599:        mdio_attach(&eth->mdio_bus, &eth->phy, eth->phyaddr);
                    600: 
1.1.1.7   root      601:        eth->ethregs = cpu_register_io_memory(eth_read, eth_write, eth,
                    602:                                               DEVICE_NATIVE_ENDIAN);
1.1       root      603:        cpu_register_physical_memory (base, 0x5c, eth->ethregs);
                    604: 
1.1.1.8 ! root      605:        eth->conf.macaddr = nd->macaddr;
1.1.1.5   root      606:        eth->conf.vlan = nd->vlan;
                    607:        eth->conf.peer = nd->netdev;
                    608: 
                    609:        eth->nic = qemu_new_nic(&net_etraxfs_info, &eth->conf,
                    610:                                nd->model, nd->name, eth);
1.1       root      611: 
                    612:        return dma;
                    613: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.