Revision 1248f8d4 hw/lan9118.c

b/hw/lan9118.c
235 235
    int32_t rxp_offset;
236 236
    int32_t rxp_size;
237 237
    int32_t rxp_pad;
238

  
239
    uint32_t write_word_prev_offset;
240
    uint32_t write_word_n;
241
    uint16_t write_word_l;
242
    uint16_t write_word_h;
243
    uint32_t read_word_prev_offset;
244
    uint32_t read_word_n;
245
    uint32_t read_long;
246

  
247
    uint32_t mode_16bit;
238 248
} lan9118_state;
239 249

  
240 250
static const VMStateDescription vmstate_lan9118 = {
241 251
    .name = "lan9118",
242
    .version_id = 1,
252
    .version_id = 2,
243 253
    .minimum_version_id = 1,
244 254
    .fields = (VMStateField[]) {
245 255
        VMSTATE_PTIMER(timer, lan9118_state),
......
294 304
        VMSTATE_INT32(rxp_offset, lan9118_state),
295 305
        VMSTATE_INT32(rxp_size, lan9118_state),
296 306
        VMSTATE_INT32(rxp_pad, lan9118_state),
307
        VMSTATE_UINT32_V(write_word_prev_offset, lan9118_state, 2),
308
        VMSTATE_UINT32_V(write_word_n, lan9118_state, 2),
309
        VMSTATE_UINT16_V(write_word_l, lan9118_state, 2),
310
        VMSTATE_UINT16_V(write_word_h, lan9118_state, 2),
311
        VMSTATE_UINT32_V(read_word_prev_offset, lan9118_state, 2),
312
        VMSTATE_UINT32_V(read_word_n, lan9118_state, 2),
313
        VMSTATE_UINT32_V(read_long, lan9118_state, 2),
314
        VMSTATE_UINT32_V(mode_16bit, lan9118_state, 2),
297 315
        VMSTATE_END_OF_LIST()
298 316
    }
299 317
};
......
390 408
    s->fifo_int = 0x48000000;
391 409
    s->rx_cfg = 0;
392 410
    s->tx_cfg = 0;
393
    s->hw_cfg = 0x00050000;
411
    s->hw_cfg = s->mode_16bit ? 0x00050000 : 0x00050004;
394 412
    s->pmt_ctrl &= 0x45;
395 413
    s->gpio_cfg = 0;
396 414
    s->txp->fifo_used = 0;
......
429 447
    s->mac_mii_data = 0;
430 448
    s->mac_flow = 0;
431 449

  
450
    s->read_word_n = 0;
451
    s->write_word_n = 0;
452

  
432 453
    phy_reset(s);
433 454

  
434 455
    s->eeprom_writable = 0;
......
984 1005
{
985 1006
    lan9118_state *s = (lan9118_state *)opaque;
986 1007
    offset &= 0xff;
987
    
1008

  
988 1009
    //DPRINTF("Write reg 0x%02x = 0x%08x\n", (int)offset, val);
989 1010
    if (offset >= 0x20 && offset < 0x40) {
990 1011
        /* TX FIFO */
......
1034 1055
            /* SRST */
1035 1056
            lan9118_reset(&s->busdev.qdev);
1036 1057
        } else {
1037
            s->hw_cfg = val & 0x003f300;
1058
            s->hw_cfg = (val & 0x003f300) | (s->hw_cfg & 0x4);
1038 1059
        }
1039 1060
        break;
1040 1061
    case CSR_RX_DP_CTRL:
......
1113 1134
    lan9118_update(s);
1114 1135
}
1115 1136

  
1137
static void lan9118_writew(void *opaque, target_phys_addr_t offset,
1138
                           uint32_t val)
1139
{
1140
    lan9118_state *s = (lan9118_state *)opaque;
1141
    offset &= 0xff;
1142

  
1143
    if (s->write_word_prev_offset != (offset & ~0x3)) {
1144
        /* New offset, reset word counter */
1145
        s->write_word_n = 0;
1146
        s->write_word_prev_offset = offset & ~0x3;
1147
    }
1148

  
1149
    if (offset & 0x2) {
1150
        s->write_word_h = val;
1151
    } else {
1152
        s->write_word_l = val;
1153
    }
1154

  
1155
    //DPRINTF("Writew reg 0x%02x = 0x%08x\n", (int)offset, val);
1156
    s->write_word_n++;
1157
    if (s->write_word_n == 2) {
1158
        s->write_word_n = 0;
1159
        lan9118_writel(s, offset & ~3, s->write_word_l +
1160
                (s->write_word_h << 16), 4);
1161
    }
1162
}
1163

  
1164
static void lan9118_16bit_mode_write(void *opaque, target_phys_addr_t offset,
1165
                                     uint64_t val, unsigned size)
1166
{
1167
    switch (size) {
1168
    case 2:
1169
        return lan9118_writew(opaque, offset, (uint32_t)val);
1170
    case 4:
1171
        return lan9118_writel(opaque, offset, val, size);
1172
    }
1173

  
1174
    hw_error("lan9118_write: Bad size 0x%x\n", size);
1175
}
1176

  
1116 1177
static uint64_t lan9118_readl(void *opaque, target_phys_addr_t offset,
1117 1178
                              unsigned size)
1118 1179
{
......
1149 1210
    case CSR_TX_CFG:
1150 1211
        return s->tx_cfg;
1151 1212
    case CSR_HW_CFG:
1152
        return s->hw_cfg | 0x4;
1213
        return s->hw_cfg;
1153 1214
    case CSR_RX_DP_CTRL:
1154 1215
        return 0;
1155 1216
    case CSR_RX_FIFO_INF:
......
1187 1248
    return 0;
1188 1249
}
1189 1250

  
1251
static uint32_t lan9118_readw(void *opaque, target_phys_addr_t offset)
1252
{
1253
    lan9118_state *s = (lan9118_state *)opaque;
1254
    uint32_t val;
1255

  
1256
    if (s->read_word_prev_offset != (offset & ~0x3)) {
1257
        /* New offset, reset word counter */
1258
        s->read_word_n = 0;
1259
        s->read_word_prev_offset = offset & ~0x3;
1260
    }
1261

  
1262
    s->read_word_n++;
1263
    if (s->read_word_n == 1) {
1264
        s->read_long = lan9118_readl(s, offset & ~3, 4);
1265
    } else {
1266
        s->read_word_n = 0;
1267
    }
1268

  
1269
    if (offset & 2) {
1270
        val = s->read_long >> 16;
1271
    } else {
1272
        val = s->read_long & 0xFFFF;
1273
    }
1274

  
1275
    //DPRINTF("Readw reg 0x%02x, val 0x%x\n", (int)offset, val);
1276
    return val;
1277
}
1278

  
1279
static uint64_t lan9118_16bit_mode_read(void *opaque, target_phys_addr_t offset,
1280
                                        unsigned size)
1281
{
1282
    switch (size) {
1283
    case 2:
1284
        return lan9118_readw(opaque, offset);
1285
    case 4:
1286
        return lan9118_readl(opaque, offset, size);
1287
    }
1288

  
1289
    hw_error("lan9118_read: Bad size 0x%x\n", size);
1290
    return 0;
1291
}
1292

  
1190 1293
static const MemoryRegionOps lan9118_mem_ops = {
1191 1294
    .read = lan9118_readl,
1192 1295
    .write = lan9118_writel,
1193 1296
    .endianness = DEVICE_NATIVE_ENDIAN,
1194 1297
};
1195 1298

  
1299
static const MemoryRegionOps lan9118_16bit_mem_ops = {
1300
    .read = lan9118_16bit_mode_read,
1301
    .write = lan9118_16bit_mode_write,
1302
    .endianness = DEVICE_NATIVE_ENDIAN,
1303
};
1304

  
1196 1305
static void lan9118_cleanup(VLANClientState *nc)
1197 1306
{
1198 1307
    lan9118_state *s = DO_UPCAST(NICState, nc, nc)->opaque;
......
1214 1323
    lan9118_state *s = FROM_SYSBUS(lan9118_state, dev);
1215 1324
    QEMUBH *bh;
1216 1325
    int i;
1326
    const MemoryRegionOps *mem_ops =
1327
            s->mode_16bit ? &lan9118_16bit_mem_ops : &lan9118_mem_ops;
1217 1328

  
1218
    memory_region_init_io(&s->mmio, &lan9118_mem_ops, s, "lan9118-mmio", 0x100);
1329
    memory_region_init_io(&s->mmio, mem_ops, s, "lan9118-mmio", 0x100);
1219 1330
    sysbus_init_mmio(dev, &s->mmio);
1220 1331
    sysbus_init_irq(dev, &s->irq);
1221 1332
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
......
1240 1351

  
1241 1352
static Property lan9118_properties[] = {
1242 1353
    DEFINE_NIC_PROPERTIES(lan9118_state, conf),
1354
    DEFINE_PROP_UINT32("mode_16bit", lan9118_state, mode_16bit, 0),
1243 1355
    DEFINE_PROP_END_OF_LIST(),
1244 1356
};
1245 1357

  

Also available in: Unified diff