Revision e5e23ab8

b/hw/eepro100.c
20 20
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 21
 *
22 22
 * Tested features (i82559):
23
 *      PXE boot (i386) ok
23
 *      PXE boot (i386 guest, i386 / mips / mipsel / ppc host) ok
24 24
 *      Linux networking (i386) ok
25 25
 *
26 26
 * Untested:
27
 *      non-i386 platforms
28 27
 *      Windows networking
29 28
 *
30 29
 * References:
......
139 138

  
140 139
/* Offsets to the various registers.
141 140
   All accesses need not be longword aligned. */
142
enum speedo_offsets {
141
typedef enum {
143 142
    SCBStatus = 0,              /* Status Word. */
144 143
    SCBAck = 1,
145 144
    SCBCmd = 2,                 /* Rx/Command Unit command and status. */
......
154 153
    SCBpmdr = 27,               /* Power Management Driver. */
155 154
    SCBgctrl = 28,              /* General Control. */
156 155
    SCBgstat = 29,              /* General Status. */
157
};
156
} E100RegisterOffset;
158 157

  
159 158
/* A speedo3 transmit buffer descriptor with two buffers... */
160 159
typedef struct {
......
258 257
    /* Statistical counters. Also used for wake-up packet (i82559). */
259 258
    eepro100_stats_t statistics;
260 259

  
260
    /* Data in mem is always in the byte order of the controller (le).
261
     * It must be dword aligned to allow direct access to 32 bit values. */
262
    uint8_t mem[PCI_MEM_SIZE] __attribute__((aligned(8)));;
263

  
261 264
    /* Configuration bytes. */
262 265
    uint8_t configuration[22];
263 266

  
264
    /* Data in mem is always in the byte order of the controller (le). */
265
    uint8_t mem[PCI_MEM_SIZE];
266 267
    /* vmstate for each particular nic */
267 268
    VMStateDescription *vmstate;
268 269

  
......
316 317
    0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
317 318
};
318 319

  
319
/* XXX: optimize */
320
static void stl_le_phys(target_phys_addr_t addr, uint32_t val)
320
/* Read a 16 bit little endian value from physical memory. */
321
static uint16_t e100_ldw_le_phys(target_phys_addr_t addr)
322
{
323
    /* Load 16 bit (little endian) word from emulated hardware. */
324
    uint16_t val;
325
    cpu_physical_memory_read(addr, &val, sizeof(val));
326
    return le16_to_cpu(val);
327
}
328

  
329
/* Read a 32 bit little endian value from physical memory. */
330
static uint32_t e100_ldl_le_phys(target_phys_addr_t addr)
331
{
332
    /* Load 32 bit (little endian) word from emulated hardware. */
333
    uint32_t val;
334
    cpu_physical_memory_read(addr, &val, sizeof(val));
335
    return le32_to_cpu(val);
336
}
337

  
338
/* Write a 16 bit little endian value to physical memory. */
339
static void e100_stw_le_phys(target_phys_addr_t addr, uint16_t val)
340
{
341
    val = cpu_to_le16(val);
342
    cpu_physical_memory_write(addr, &val, sizeof(val));
343
}
344

  
345
/* Write a 32 bit little endian value to physical memory. */
346
static void e100_stl_le_phys(target_phys_addr_t addr, uint32_t val)
321 347
{
322 348
    val = cpu_to_le32(val);
323 349
    cpu_physical_memory_write(addr, &val, sizeof(val));
......
348 374
    return (crc & BITS(7, 2)) >> 2;
349 375
}
350 376

  
377
/* Read a 16 bit control/status (CSR) register. */
378
static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
379
{
380
    assert(!((uintptr_t)&s->mem[addr] & 1));
381
    return le16_to_cpup((uint16_t *)&s->mem[addr]);
382
}
383

  
384
/* Read a 32 bit control/status (CSR) register. */
385
static uint32_t e100_read_reg4(EEPRO100State *s, E100RegisterOffset addr)
386
{
387
    assert(!((uintptr_t)&s->mem[addr] & 3));
388
    return le32_to_cpup((uint32_t *)&s->mem[addr]);
389
}
390

  
391
/* Write a 16 bit control/status (CSR) register. */
392
static void e100_write_reg2(EEPRO100State *s, E100RegisterOffset addr,
393
                            uint16_t val)
394
{
395
    assert(!((uintptr_t)&s->mem[addr] & 1));
396
    cpu_to_le16w((uint16_t *)&s->mem[addr], val);
397
}
398

  
399
/* Read a 32 bit control/status (CSR) register. */
400
static void e100_write_reg4(EEPRO100State *s, E100RegisterOffset addr,
401
                            uint32_t val)
402
{
403
    assert(!((uintptr_t)&s->mem[addr] & 3));
404
    cpu_to_le32w((uint32_t *)&s->mem[addr], val);
405
}
406

  
351 407
#if defined(DEBUG_EEPRO100)
352 408
static const char *nic_dump(const uint8_t * buf, unsigned size)
353 409
{
......
599 655
    TRACE(EEPROM, logout("checksum=0x%04x\n", eeprom_contents[EEPROM_SIZE - 1]));
600 656

  
601 657
    memset(s->mem, 0, sizeof(s->mem));
602
    uint32_t val = BIT(21);
603
    memcpy(&s->mem[SCBCtrlMDI], &val, sizeof(val));
658
    e100_write_reg4(s, SCBCtrlMDI, BIT(21));
604 659

  
605 660
    assert(sizeof(s->mdimem) == sizeof(eepro100_mdi_default));
606 661
    memcpy(&s->mdimem[0], &eepro100_mdi_default[0], sizeof(s->mdimem));
......
704 759
     * Number of data should check configuration!!!
705 760
     */
706 761
    cpu_physical_memory_write(s->statsaddr, &s->statistics, s->stats_size);
707
    stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
708
    stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
709
    stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
710
    stl_le_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);
762
    e100_stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
763
    e100_stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
764
    e100_stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
765
    e100_stl_le_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);
711 766
#if 0
712
    stw_le_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
713
    stw_le_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
767
    e100_stw_le_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
768
    e100_stw_le_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
714 769
    missing("CU dump statistical counters");
715 770
#endif
716 771
}
......
747 802
    }
748 803
    assert(tcb_bytes <= sizeof(buf));
749 804
    while (size < tcb_bytes) {
750
        uint32_t tx_buffer_address = ldl_phys(tbd_address);
751
        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
805
        uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
806
        uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
752 807
#if 0
753
        uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
808
        uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
754 809
#endif
755 810
        tbd_address += 8;
756 811
        TRACE(RXTX, logout
......
769 824
        if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
770 825
            /* Extended Flexible TCB. */
771 826
            for (; tbd_count < 2; tbd_count++) {
772
                uint32_t tx_buffer_address = ldl_phys(tbd_address);
773
                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
774
                uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
827
                uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
828
                uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
829
                uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
775 830
                tbd_address += 8;
776 831
                TRACE(RXTX, logout
777 832
                    ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
......
787 842
        }
788 843
        tbd_address = tbd_array;
789 844
        for (; tbd_count < s->tx.tbd_count; tbd_count++) {
790
            uint32_t tx_buffer_address = ldl_phys(tbd_address);
791
            uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
792
            uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
845
            uint32_t tx_buffer_address = e100_ldl_le_phys(tbd_address);
846
            uint16_t tx_buffer_size = e100_ldw_le_phys(tbd_address + 4);
847
            uint16_t tx_buffer_el = e100_ldw_le_phys(tbd_address + 6);
793 848
            tbd_address += 8;
794 849
            TRACE(RXTX, logout
795 850
                ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
......
897 952
            break;
898 953
        }
899 954
        /* Write new status. */
900
        stw_phys(s->cb_address, s->tx.status | ok_status | STATUS_C);
955
        e100_stw_le_phys(s->cb_address, s->tx.status | ok_status | STATUS_C);
901 956
        if (bit_i) {
902 957
            /* CU completed action. */
903 958
            eepro100_cx_interrupt(s);
......
964 1019
        /* Dump statistical counters. */
965 1020
        TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val));
966 1021
        dump_statistics(s);
967
        stl_le_phys(s->statsaddr + s->stats_size, 0xa005);
1022
        e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa005);
968 1023
        break;
969 1024
    case CU_CMD_BASE:
970 1025
        /* Load CU base. */
......
975 1030
        /* Dump and reset statistical counters. */
976 1031
        TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val));
977 1032
        dump_statistics(s);
978
        stl_le_phys(s->statsaddr + s->stats_size, 0xa007);
1033
        e100_stl_le_phys(s->statsaddr + s->stats_size, 0xa007);
979 1034
        memset(&s->statistics, 0, sizeof(s->statistics));
980 1035
        break;
981 1036
    case CU_SRESUME:
......
1058 1113

  
1059 1114
static uint16_t eepro100_read_eeprom(EEPRO100State * s)
1060 1115
{
1061
    uint16_t val;
1062
    memcpy(&val, &s->mem[SCBeeprom], sizeof(val));
1116
    uint16_t val = e100_read_reg2(s, SCBeeprom);
1063 1117
    if (eeprom93xx_read(s->eeprom)) {
1064 1118
        val |= EEPROM_DO;
1065 1119
    } else {
......
1129 1183

  
1130 1184
static uint32_t eepro100_read_mdi(EEPRO100State * s)
1131 1185
{
1132
    uint32_t val;
1133
    memcpy(&val, &s->mem[0x10], sizeof(val));
1186
    uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
1134 1187

  
1135 1188
#ifdef DEBUG_EEPRO100
1136 1189
    uint8_t raiseint = (val & BIT(29)) >> 29;
......
1239 1292
        }
1240 1293
    }
1241 1294
    val = (val & 0xffff0000) + data;
1242
    memcpy(&s->mem[0x10], &val, sizeof(val));
1295
    e100_write_reg4(s, SCBCtrlMDI, val);
1243 1296
}
1244 1297

  
1245 1298
/*****************************************************************************
......
1266 1319

  
1267 1320
static void eepro100_write_port(EEPRO100State * s, uint32_t val)
1268 1321
{
1269
    val = le32_to_cpu(val);
1270 1322
    uint32_t address = (val & ~PORT_SELECTION_MASK);
1271 1323
    uint8_t selection = (val & PORT_SELECTION_MASK);
1272 1324
    switch (selection) {
......
1301 1353
{
1302 1354
    uint8_t val = 0;
1303 1355
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1304
        memcpy(&val, &s->mem[addr], sizeof(val));
1356
        val = s->mem[addr];
1305 1357
    }
1306 1358

  
1307 1359
    switch (addr) {
......
1344 1396
{
1345 1397
    uint16_t val = 0;
1346 1398
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1347
        memcpy(&val, &s->mem[addr], sizeof(val));
1399
        val = e100_read_reg2(s, addr);
1348 1400
    }
1349 1401

  
1350 1402
    switch (addr) {
......
1367 1419
{
1368 1420
    uint32_t val = 0;
1369 1421
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1370
        memcpy(&val, &s->mem[addr], sizeof(val));
1422
        val = e100_read_reg4(s, addr);
1371 1423
    }
1372 1424

  
1373 1425
    switch (addr) {
......
1398 1450
{
1399 1451
    /* SCBStatus is readonly. */
1400 1452
    if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
1401
        memcpy(&s->mem[addr], &val, sizeof(val));
1453
        s->mem[addr] = val;
1402 1454
    }
1403 1455

  
1404 1456
    switch (addr) {
......
1441 1493
{
1442 1494
    /* SCBStatus is readonly. */
1443 1495
    if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
1444
        memcpy(&s->mem[addr], &val, sizeof(val));
1496
        e100_write_reg2(s, addr, val);
1445 1497
    }
1446 1498

  
1447 1499
    switch (addr) {
......
1468 1520
static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
1469 1521
{
1470 1522
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1471
        memcpy(&s->mem[addr], &val, sizeof(val));
1523
        e100_write_reg4(s, addr, val);
1472 1524
    }
1473 1525

  
1474 1526
    switch (addr) {
......
1760 1812
#endif
1761 1813
    TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n",
1762 1814
          rfd_command, rx.link, rx.rx_buf_addr, rfd_size));
1763
    stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status),
1764
             rfd_status);
1765
    stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size);
1815
    e100_stw_le_phys(s->ru_base + s->ru_offset +
1816
                     offsetof(eepro100_rx_t, status), rfd_status);
1817
    e100_stw_le_phys(s->ru_base + s->ru_offset +
1818
                     offsetof(eepro100_rx_t, count), size);
1766 1819
    /* Early receive interrupt not supported. */
1767 1820
#if 0
1768 1821
    eepro100_er_interrupt(s);
......
1891 1944
    /* Handler for memory-mapped I/O */
1892 1945
    s->mmio_index =
1893 1946
        cpu_register_io_memory(pci_mmio_read, pci_mmio_write, s,
1894
                               DEVICE_NATIVE_ENDIAN);
1947
                               DEVICE_LITTLE_ENDIAN);
1895 1948

  
1896 1949
    pci_register_bar_simple(&s->dev, 0, PCI_MEM_SIZE,
1897 1950
                            PCI_BASE_ADDRESS_MEM_PREFETCH, s->mmio_index);

Also available in: Unified diff