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