~ahs3/+junk/cq-qemu

« back to all changes in this revision

Viewing changes to hw/xgmac.c

  • Committer: Al Stone
  • Date: 2012-02-09 01:17:20 UTC
  • Revision ID: albert.stone@canonical.com-20120209011720-tztl7ik3qayz80p4
first commit to bzr for qemu

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright 2011 Calxeda, Inc.
 
3
 * Based on xilinx_axienet.c Copyright (c) 2011 Edgar E. Iglesias.
 
4
 *
 
5
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 
6
 * of this software and associated documentation files (the "Software"), to deal
 
7
 * in the Software without restriction, including without limitation the rights
 
8
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 
9
 * copies of the Software, and to permit persons to whom the Software is
 
10
 * furnished to do so, subject to the following conditions:
 
11
 *
 
12
 * The above copyright notice and this permission notice shall be included in
 
13
 * all copies or substantial portions of the Software.
 
14
 *
 
15
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 
16
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 
17
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
 
18
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 
19
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 
20
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 
21
 * THE SOFTWARE.
 
22
 */
 
23
 
 
24
#include "sysbus.h"
 
25
#include "qemu-char.h"
 
26
#include "qemu-log.h"
 
27
#include "net.h"
 
28
#include "net/checksum.h"
 
29
 
 
30
#define XGMAC_CONTROL           0x00000000      /* MAC Configuration */
 
31
#define XGMAC_FRAME_FILTER      0x00000001      /* MAC Frame Filter */
 
32
#define XGMAC_FLOW_CTRL         0x00000006      /* MAC Flow Control */
 
33
#define XGMAC_VLAN_TAG          0x00000007      /* VLAN Tags */
 
34
#define XGMAC_VERSION           0x00000008      /* Version */
 
35
#define XGMAC_VLAN_INCL         0x00000009      /* VLAN tag for insertion or replacement into tx frames */
 
36
#define XGMAC_LPI_CTRL          0x0000000a      /* LPI Control and Status */
 
37
#define XGMAC_LPI_TIMER         0x0000000b      /* LPI Timers Control */
 
38
#define XGMAC_TX_PACE           0x0000000c      /* Transmit Pace and Stretch */
 
39
#define XGMAC_VLAN_HASH         0x0000000d      /* VLAN Hash Table */
 
40
#define XGMAC_DEBUG             0x0000000e      /* Debug */
 
41
#define XGMAC_INT_STATUS        0x0000000f      /* Interrupt and Control */
 
42
#define XGMAC_HASH(n)           (0x00000300/4 + (n))    /* HASH table registers */
 
43
#define XGMAC_NUM_HASH          16
 
44
#define XGMAC_OPMODE            0x00000400/4    /* Operation Mode */
 
45
#define XGMAC_REMOTE_WAKE       0x00000700/4    /* Remote Wake-Up Frame Filter */
 
46
#define XGMAC_PMT               0x00000704/4    /* PMT Control and Status */
 
47
 
 
48
#define XGMAC_ADDR_HIGH(reg)            (0x00000010+(reg * 2))
 
49
#define XGMAC_ADDR_LOW(reg)             (0x00000011+(reg * 2))
 
50
 
 
51
#define DMA_BUS_MODE            0x000003c0      /* Bus Mode */
 
52
#define DMA_XMT_POLL_DEMAND     0x000003c1      /* Transmit Poll Demand */
 
53
#define DMA_RCV_POLL_DEMAND     0x000003c2      /* Received Poll Demand */
 
54
#define DMA_RCV_BASE_ADDR       0x000003c3      /* Receive List Base */
 
55
#define DMA_TX_BASE_ADDR        0x000003c4      /* Transmit List Base */
 
56
#define DMA_STATUS              0x000003c5      /* Status Register */
 
57
#define DMA_CONTROL             0x000003c6      /* Ctrl (Operational Mode) */
 
58
#define DMA_INTR_ENA            0x000003c7      /* Interrupt Enable */
 
59
#define DMA_MISSED_FRAME_CTR    0x000003c8      /* Missed Frame Counter */
 
60
#define DMA_RI_WATCHDOG_TIMER   0x000003c9      /* Receive Interrupt Watchdog Timer */
 
61
#define DMA_AXI_BUS             0x000003ca      /* AXI Bus Mode */
 
62
#define DMA_AXI_STATUS          0x000003cb      /* AXI Status */
 
63
#define DMA_CUR_TX_DESC_ADDR    0x000003d2      /* Current Host Tx Descriptor */
 
64
#define DMA_CUR_RX_DESC_ADDR    0x000003d3      /* Current Host Rx Descriptor */
 
65
#define DMA_CUR_TX_BUF_ADDR     0x000003d4      /* Current Host Tx Buffer */
 
66
#define DMA_CUR_RX_BUF_ADDR     0x000003d5      /* Current Host Rx Buffer */
 
67
#define DMA_HW_FEATURE          0x000003d6      /* Enabled Hardware Features */
 
68
 
 
69
/* DMA Status register defines */
 
70
#define DMA_STATUS_GMI          0x08000000      /* MMC interrupt */
 
71
#define DMA_STATUS_GLI          0x04000000      /* GMAC Line interface int */
 
72
#define DMA_STATUS_EB_MASK      0x00380000      /* Error Bits Mask */
 
73
#define DMA_STATUS_EB_TX_ABORT  0x00080000      /* Error Bits - TX Abort */
 
74
#define DMA_STATUS_EB_RX_ABORT  0x00100000      /* Error Bits - RX Abort */
 
75
#define DMA_STATUS_TS_MASK      0x00700000      /* Transmit Process State */
 
76
#define DMA_STATUS_TS_SHIFT     20
 
77
#define DMA_STATUS_RS_MASK      0x000e0000      /* Receive Process State */
 
78
#define DMA_STATUS_RS_SHIFT     17
 
79
#define DMA_STATUS_NIS          0x00010000      /* Normal Interrupt Summary */
 
80
#define DMA_STATUS_AIS          0x00008000      /* Abnormal Interrupt Summary */
 
81
#define DMA_STATUS_ERI          0x00004000      /* Early Receive Interrupt */
 
82
#define DMA_STATUS_FBI          0x00002000      /* Fatal Bus Error Interrupt */
 
83
#define DMA_STATUS_ETI          0x00000400      /* Early Transmit Interrupt */
 
84
#define DMA_STATUS_RWT          0x00000200      /* Receive Watchdog Timeout */
 
85
#define DMA_STATUS_RPS          0x00000100      /* Receive Process Stopped */
 
86
#define DMA_STATUS_RU           0x00000080      /* Receive Buffer Unavailable */
 
87
#define DMA_STATUS_RI           0x00000040      /* Receive Interrupt */
 
88
#define DMA_STATUS_UNF          0x00000020      /* Transmit Underflow */
 
89
#define DMA_STATUS_OVF          0x00000010      /* Receive Overflow */
 
90
#define DMA_STATUS_TJT          0x00000008      /* Transmit Jabber Timeout */
 
91
#define DMA_STATUS_TU           0x00000004      /* Transmit Buffer Unavailable */
 
92
#define DMA_STATUS_TPS          0x00000002      /* Transmit Process Stopped */
 
93
#define DMA_STATUS_TI           0x00000001      /* Transmit Interrupt */
 
94
 
 
95
/* DMA Control register defines */
 
96
#define DMA_CONTROL_ST          0x00002000      /* Start/Stop Transmission */
 
97
#define DMA_CONTROL_SR          0x00000002      /* Start/Stop Receive */
 
98
#define DMA_CONTROL_DFF         0x01000000      /* Disable flush of rx frames */
 
99
 
 
100
struct desc {
 
101
    uint32_t ctl_stat;
 
102
    uint16_t buffer1_size;
 
103
    uint16_t buffer2_size;
 
104
    uint32_t buffer1_addr;
 
105
    uint32_t buffer2_addr;
 
106
    uint32_t ext_stat;
 
107
    uint32_t res[3];
 
108
};
 
109
 
 
110
#define R_MAX 0x400
 
111
 
 
112
struct XgmacEnet {
 
113
    SysBusDevice busdev;
 
114
    qemu_irq sbd_irq;
 
115
    qemu_irq pmt_irq;
 
116
    qemu_irq mci_irq;
 
117
    void *dmach;
 
118
    NICState *nic;
 
119
    NICConf conf;
 
120
 
 
121
 
 
122
    uint32_t c_rxmem;
 
123
    uint32_t c_txmem;
 
124
    uint32_t c_phyaddr;
 
125
 
 
126
    struct {
 
127
        uint64_t rx_bytes;
 
128
        uint64_t tx_bytes;
 
129
 
 
130
        uint64_t rx;
 
131
        uint64_t rx_bcast;
 
132
        uint64_t rx_mcast;
 
133
    } stats;
 
134
 
 
135
    /* Receive configuration words.  */
 
136
    uint32_t rcw[2];
 
137
    /* Transmit config.  */
 
138
    uint32_t tc;
 
139
    uint32_t emmc;
 
140
    uint32_t phyc;
 
141
 
 
142
    /* Unicast Address Word.  */
 
143
    uint32_t uaw[2];
 
144
    /* Unicast address filter used with extended mcast.  */
 
145
    uint32_t ext_uaw[2];
 
146
    uint32_t fmi;
 
147
 
 
148
    uint32_t regs[R_MAX];
 
149
 
 
150
    /* Multicast filter addrs.  */
 
151
    uint32_t maddr[4][2];
 
152
    /* 32K x 1 lookup filter.  */
 
153
    uint32_t ext_mtable[1024];
 
154
 
 
155
 
 
156
    uint8_t *rxmem;
 
157
};
 
158
 
 
159
static void xgmac_read_desc(struct XgmacEnet *s, struct desc *d, int rx)
 
160
{
 
161
    uint32_t addr = rx ? s->regs[DMA_CUR_RX_DESC_ADDR] : s->regs[DMA_CUR_TX_DESC_ADDR];
 
162
    cpu_physical_memory_read(addr, d, sizeof(*d));
 
163
}
 
164
 
 
165
static void xgmac_write_desc(struct XgmacEnet *s, struct desc *d, int rx)
 
166
{
 
167
    int reg = rx ? DMA_CUR_RX_DESC_ADDR : DMA_CUR_TX_DESC_ADDR;
 
168
    uint32_t addr = s->regs[reg];
 
169
    
 
170
    if (!rx && (d->ctl_stat & 0x00200000))
 
171
        s->regs[reg] = s->regs[DMA_TX_BASE_ADDR];
 
172
    else if (rx && (d->buffer1_size & 0x8000))
 
173
        s->regs[reg] = s->regs[DMA_RCV_BASE_ADDR];
 
174
    else
 
175
        s->regs[reg] += sizeof(*d);
 
176
    
 
177
    cpu_physical_memory_write(addr, d, sizeof(*d));
 
178
}
 
179
 
 
180
static void xgmac_enet_send(struct XgmacEnet *s)
 
181
{
 
182
    struct desc bd;
 
183
    int frame_size;
 
184
    int len;
 
185
    uint8_t frame[8192];
 
186
    uint8_t *ptr;
 
187
 
 
188
    ptr = frame;
 
189
    frame_size = 0;
 
190
    while (1) {
 
191
        xgmac_read_desc(s, &bd, 0);
 
192
        //printf("tx_bd flags %08x len %d data %08x\n",
 
193
        //        bd.ctl_stat, bd.buffer1_size & 0xfff, bd.buffer1_addr);
 
194
        if ((bd.ctl_stat & 0x80000000) == 0) {
 
195
            /* Run out of descriptors to transmit.  */
 
196
            break;
 
197
        }
 
198
        len = (bd.buffer1_size & 0xfff) + (bd.buffer2_size & 0xfff);
 
199
 
 
200
        if ((bd.buffer1_size & 0xfff) >2048) {
 
201
            fprintf(stdout,"qemu:%s:ERROR...ERROR...ERROR... -- "
 
202
                        "xgmac buffer 1 len on send > 2048 (0x%x)\n",
 
203
                         __FUNCTION__,bd.buffer1_size & 0xfff);
 
204
            fflush(stdout);
 
205
        }
 
206
        if ((bd.buffer2_size & 0xfff) != 0) {
 
207
            fprintf(stdout,"qemu:%s:ERROR...ERROR...ERROR... -- "
 
208
                        "xgmac buffer 2 len on send != 0 (0x%x)\n",
 
209
                        __FUNCTION__,bd.buffer2_size & 0xfff);
 
210
            fflush(stdout);
 
211
        }
 
212
        if (len >= sizeof(frame)) {
 
213
            fprintf(stdout,"qemu:%s: buffer overflow %d read into %zu "
 
214
                        "buffer\n",__FUNCTION__,len,sizeof(frame));
 
215
            fprintf(stdout,"qemu:%s: buffer1.size=%d; buffer2.size=%d\n",
 
216
                        __FUNCTION__,bd.buffer1_size,bd.buffer2_size);
 
217
            fflush(stdout);
 
218
        }
 
219
        
 
220
        cpu_physical_memory_read(bd.buffer1_addr, ptr, len);
 
221
        ptr += len;
 
222
        frame_size += len;
 
223
        if (bd.ctl_stat & 0x20000000) {
 
224
            /* Last buffer in frame.  */
 
225
            //printf("Sending packet\n");
 
226
            qemu_send_packet(&s->nic->nc, frame, len);
 
227
            ptr = frame;
 
228
            frame_size = 0;
 
229
            s->regs[DMA_STATUS] |= DMA_STATUS_TI | DMA_STATUS_NIS;
 
230
        }
 
231
        bd.ctl_stat &= ~0x80000000;
 
232
        /* Write back the modified descriptor.  */
 
233
        xgmac_write_desc(s, &bd, 0);
 
234
    }
 
235
}
 
236
 
 
237
static void enet_update_irq(struct XgmacEnet *s)
 
238
{
 
239
    int stat = s->regs[DMA_STATUS] & s->regs[DMA_INTR_ENA];
 
240
    qemu_set_irq(s->sbd_irq, !!stat);
 
241
}
 
242
 
 
243
static uint32_t enet_readl(void *opaque, target_phys_addr_t addr)
 
244
{
 
245
    struct XgmacEnet *s = opaque;
 
246
    uint32_t r = 0;
 
247
    addr >>= 2;
 
248
 
 
249
    switch (addr) {
 
250
        case XGMAC_VERSION:
 
251
            r = 0x1012;
 
252
            break;
 
253
        default:
 
254
            if (addr < ARRAY_SIZE(s->regs)) {
 
255
                r = s->regs[addr];
 
256
            }
 
257
            //printf("%s addr=" TARGET_FMT_plx " v=%x\n",
 
258
            //                __func__, addr * 4, r);
 
259
            break;
 
260
    }
 
261
    return r;
 
262
}
 
263
 
 
264
static void
 
265
enet_writel(void *opaque, target_phys_addr_t addr, uint32_t value)
 
266
{
 
267
    struct XgmacEnet *s = opaque;
 
268
 
 
269
    addr >>= 2;
 
270
    //printf("%s addr=" TARGET_FMT_plx " v=%x\n",
 
271
    //               __func__, addr * 4, value);
 
272
    switch (addr) {
 
273
        case DMA_BUS_MODE:
 
274
            s->regs[DMA_BUS_MODE] = value & ~0x1;
 
275
            break;
 
276
        case DMA_XMT_POLL_DEMAND:
 
277
            xgmac_enet_send(s);
 
278
            break;
 
279
        case DMA_STATUS:
 
280
            s->regs[DMA_STATUS] = s->regs[DMA_STATUS] & ~value;
 
281
            break;
 
282
        case DMA_RCV_BASE_ADDR:
 
283
            s->regs[DMA_RCV_BASE_ADDR] = s->regs[DMA_CUR_RX_DESC_ADDR] = value;
 
284
            break;
 
285
        case DMA_TX_BASE_ADDR:
 
286
            s->regs[DMA_TX_BASE_ADDR] = s->regs[DMA_CUR_TX_DESC_ADDR] = value;
 
287
            break;
 
288
        default:
 
289
            if (addr < ARRAY_SIZE(s->regs)) {
 
290
                s->regs[addr] = value;
 
291
            }
 
292
            break;
 
293
    }
 
294
    enet_update_irq(s);
 
295
}
 
296
 
 
297
static CPUReadMemoryFunc * const enet_read[] = {
 
298
    &enet_readl,
 
299
    &enet_readl,
 
300
    &enet_readl,
 
301
};
 
302
 
 
303
static CPUWriteMemoryFunc * const enet_write[] = {
 
304
    &enet_writel,
 
305
    &enet_writel,
 
306
    &enet_writel,
 
307
};
 
308
 
 
309
static int eth_can_rx(VLANClientState *nc)
 
310
{
 
311
    struct XgmacEnet *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
312
 
 
313
    /* RX enabled?  */
 
314
    return s->regs[DMA_CONTROL] & DMA_CONTROL_SR;
 
315
}
 
316
 
 
317
static ssize_t eth_rx(VLANClientState *nc, const uint8_t *buf, size_t size)
 
318
{
 
319
    struct XgmacEnet *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
320
    static const unsigned char sa_bcast[6] = {0xff, 0xff, 0xff,
 
321
                                              0xff, 0xff, 0xff};
 
322
    static const unsigned char sa_ipmcast[3] = {0x01, 0x00, 0x52};
 
323
//    int promisc = s->fmi & (1 << 31);
 
324
    int unicast, broadcast, multicast;
 
325
//    int i;
 
326
    struct desc bd;
 
327
    ssize_t ret;
 
328
 
 
329
    //printf("%s: %zd bytes\n", __func__, size);
 
330
 
 
331
    unicast = ~buf[0] & 0x1;
 
332
    broadcast = memcmp(buf, sa_bcast, 6) == 0;
 
333
    multicast = !unicast && !broadcast;
 
334
    if (multicast && (memcmp(sa_ipmcast, buf, sizeof sa_ipmcast) == 0)) {
 
335
//        ip_multicast = 1;
 
336
    }
 
337
#if 0
 
338
    /* Basic Address filters.  If you want to use the extended filters
 
339
       you'll generally have to place the ethernet mac into promiscuous mode
 
340
       to avoid the basic filtering from dropping most frames.  */
 
341
    if (!promisc) {
 
342
        if (unicast) {
 
343
            if (!enet_match_addr(buf, s->uaw[0], s->uaw[1])) {
 
344
                return size;
 
345
            }
 
346
        } else {
 
347
            if (broadcast) {
 
348
                /* Broadcast.  */
 
349
                if (s->regs[R_RAF] & RAF_BCAST_REJ) {
 
350
                    return size;
 
351
                }
 
352
            } else {
 
353
                int drop = 1;
 
354
 
 
355
                /* Multicast.  */
 
356
                if (s->regs[R_RAF] & RAF_MCAST_REJ) {
 
357
                    return size;
 
358
                }
 
359
 
 
360
                for (i = 0; i < 4; i++) {
 
361
                    if (enet_match_addr(buf, s->maddr[i][0], s->maddr[i][1])) {
 
362
                        drop = 0;
 
363
                        break;
 
364
                    }
 
365
                }
 
366
 
 
367
                if (drop) {
 
368
                    return size;
 
369
                }
 
370
            }
 
371
        }
 
372
    }
 
373
 
 
374
    /* Extended mcast filtering enabled?  */
 
375
    if (axienet_newfunc_enabled(s) && axienet_extmcf_enabled(s)) {
 
376
        if (unicast) {
 
377
            if (!enet_match_addr(buf, s->ext_uaw[0], s->ext_uaw[1])) {
 
378
                return size;
 
379
            }
 
380
        } else {
 
381
            if (broadcast) {
 
382
                /* Broadcast. ???  */
 
383
                if (s->regs[R_RAF] & RAF_BCAST_REJ) {
 
384
                    return size;
 
385
                }
 
386
            } else {
 
387
                int idx, bit;
 
388
 
 
389
                /* Multicast.  */
 
390
                if (!memcmp(buf, sa_ipmcast, 3)) {
 
391
                    return size;
 
392
                }
 
393
 
 
394
                idx  = (buf[4] & 0x7f) << 8;
 
395
                idx |= buf[5];
 
396
 
 
397
                bit = 1 << (idx & 0x1f);
 
398
                idx >>= 5;
 
399
 
 
400
                if (!(s->ext_mtable[idx] & bit)) {
 
401
                    return size;
 
402
                }
 
403
            }
 
404
        }
 
405
    }
 
406
#endif
 
407
    if (size < 12) {
 
408
        s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
 
409
        ret = -1;
 
410
        goto out;
 
411
    }
 
412
 
 
413
    xgmac_read_desc(s, &bd, 1);
 
414
    if ((bd.ctl_stat & 0x80000000) == 0) {
 
415
        s->regs[DMA_STATUS] |= DMA_STATUS_RU | DMA_STATUS_AIS;
 
416
        ret = size;
 
417
        goto out;
 
418
    }
 
419
 
 
420
    cpu_physical_memory_write(bd.buffer1_addr, buf, size);
 
421
 
 
422
    // Add in the 4 bytes for crc (the real hw returns length incl crc)
 
423
    size += 4;
 
424
    bd.ctl_stat = (size << 16) | 0x300;
 
425
    xgmac_write_desc(s, &bd, 1);
 
426
 
 
427
    s->stats.rx_bytes += size;
 
428
    s->stats.rx++;
 
429
    if (multicast) {
 
430
        s->stats.rx_mcast++;
 
431
    } else if (broadcast) {
 
432
        s->stats.rx_bcast++;
 
433
    }
 
434
 
 
435
    s->regs[DMA_STATUS] |= DMA_STATUS_RI | DMA_STATUS_NIS;
 
436
    ret = size;
 
437
 
 
438
out:
 
439
    enet_update_irq(s);
 
440
    return ret;
 
441
}
 
442
 
 
443
static void eth_cleanup(VLANClientState *nc)
 
444
{
 
445
    /* FIXME.  */
 
446
    struct XgmacEnet *s = DO_UPCAST(NICState, nc, nc)->opaque;
 
447
    g_free(s);
 
448
}
 
449
 
 
450
static NetClientInfo net_xgmac_enet_info = {
 
451
    .type = NET_CLIENT_TYPE_NIC,
 
452
    .size = sizeof(NICState),
 
453
    .can_receive = eth_can_rx,
 
454
    .receive = eth_rx,
 
455
    .cleanup = eth_cleanup,
 
456
};
 
457
 
 
458
static int xgmac_enet_init(SysBusDevice *dev)
 
459
{
 
460
    struct XgmacEnet *s = FROM_SYSBUS(typeof(*s), dev);
 
461
    int enet_regs;
 
462
 
 
463
    sysbus_init_irq(dev, &s->sbd_irq);
 
464
    sysbus_init_irq(dev, &s->pmt_irq);
 
465
    sysbus_init_irq(dev, &s->mci_irq);
 
466
 
 
467
    enet_regs = cpu_register_io_memory(enet_read, enet_write, s,
 
468
                                       DEVICE_LITTLE_ENDIAN);
 
469
    sysbus_init_mmio(dev, 0x1000, enet_regs);
 
470
 
 
471
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
 
472
    s->nic = qemu_new_nic(&net_xgmac_enet_info, &s->conf,
 
473
                          dev->qdev.info->name, dev->qdev.id, s);
 
474
    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
 
475
 
 
476
    s->regs[XGMAC_ADDR_HIGH(0)] = (s->conf.macaddr.a[5] << 8) | s->conf.macaddr.a[4];
 
477
    s->regs[XGMAC_ADDR_LOW(0)] = (s->conf.macaddr.a[3] << 24) | 
 
478
                                 (s->conf.macaddr.a[2] << 16) |
 
479
                                 (s->conf.macaddr.a[1] << 8) |
 
480
                                 s->conf.macaddr.a[0];
 
481
 
 
482
    return 0;
 
483
}
 
484
 
 
485
static SysBusDeviceInfo xgmac_enet_info = {
 
486
    .init = xgmac_enet_init,
 
487
    .qdev.name  = "xgmac",
 
488
    .qdev.size  = sizeof(struct XgmacEnet),
 
489
    .qdev.props = (Property[]) {
 
490
        DEFINE_PROP_UINT32("phyaddr", struct XgmacEnet, c_phyaddr, 7),
 
491
        DEFINE_NIC_PROPERTIES(struct XgmacEnet, conf),
 
492
        DEFINE_PROP_END_OF_LIST(),
 
493
    }
 
494
};
 
495
static void xgmac_enet_register(void)
 
496
{
 
497
    sysbus_register_withprop(&xgmac_enet_info);
 
498
}
 
499
 
 
500
device_init(xgmac_enet_register)