Revision 5fafdf24 hw/rtl8139.c
b/hw/rtl8139.c | ||
---|---|---|
1 | 1 |
/** |
2 | 2 |
* QEMU RTL8139 emulation |
3 |
*
|
|
3 |
* |
|
4 | 4 |
* Copyright (c) 2006 Igor Kovalenko |
5 |
*
|
|
5 |
* |
|
6 | 6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | 7 |
* of this software and associated documentation files (the "Software"), to deal |
8 | 8 |
* in the Software without restriction, including without limitation the rights |
... | ... | |
20 | 20 |
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
21 | 21 |
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN |
22 | 22 |
* THE SOFTWARE. |
23 |
|
|
23 |
|
|
24 | 24 |
* Modifications: |
25 | 25 |
* 2006-Jan-28 Mark Malakanov : TSAD and CSCR implementation (for Windows driver) |
26 |
*
|
|
26 |
* |
|
27 | 27 |
* 2006-Apr-28 Juergen Lock : EEPROM emulation changes for FreeBSD driver |
28 | 28 |
* HW revision ID changes for FreeBSD driver |
29 |
*
|
|
29 |
* |
|
30 | 30 |
* 2006-Jul-01 Igor Kovalenko : Implemented loopback mode for FreeBSD driver |
31 | 31 |
* Corrected packet transfer reassembly routine for 8139C+ mode |
32 | 32 |
* Rearranged debugging print statements |
... | ... | |
305 | 305 |
CSCR_LinkDownCmd = 0x0f3c0, |
306 | 306 |
*/ |
307 | 307 |
enum CSCRBits { |
308 |
CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */
|
|
308 |
CSCR_Testfun = 1<<15, /* 1 = Auto-neg speeds up internal timer, WO, def 0 */ |
|
309 | 309 |
CSCR_LD = 1<<9, /* Active low TPI link disable signal. When low, TPI still transmits link pulses and TPI stays in good link state. def 1*/ |
310 | 310 |
CSCR_HEART_BIT = 1<<8, /* 1 = HEART BEAT enable, 0 = HEART BEAT disable. HEART BEAT function is only valid in 10Mbps mode. def 1*/ |
311 | 311 |
CSCR_JBEN = 1<<7, /* 1 = enable jabber function. 0 = disable jabber function, def 1*/ |
312 |
CSCR_F_LINK_100 = 1<<6, /* Used to login force good link in 100Mbps for diagnostic purposes. 1 = DISABLE, 0 = ENABLE. def 1*/
|
|
312 |
CSCR_F_LINK_100 = 1<<6, /* Used to login force good link in 100Mbps for diagnostic purposes. 1 = DISABLE, 0 = ENABLE. def 1*/ |
|
313 | 313 |
CSCR_F_Connect = 1<<5, /* Assertion of this bit forces the disconnect function to be bypassed. def 0*/ |
314 | 314 |
CSCR_Con_status = 1<<3, /* This bit indicates the status of the connection. 1 = valid connected link detected; 0 = disconnected link detected. RO def 0*/ |
315 | 315 |
CSCR_Con_status_En = 1<<2, /* Assertion of this bit configures LED1 pin to indicate connection status. def 0*/ |
... | ... | |
813 | 813 |
uint32_t packet_header = 0; |
814 | 814 |
|
815 | 815 |
uint8_t buf1[60]; |
816 |
static const uint8_t broadcast_macaddr[6] =
|
|
816 |
static const uint8_t broadcast_macaddr[6] = |
|
817 | 817 |
{ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; |
818 | 818 |
|
819 | 819 |
DEBUG_PRINT((">>> RTL8139: received len=%d\n", size)); |
... | ... | |
890 | 890 |
++s->tally_counters.RxOkMul; |
891 | 891 |
|
892 | 892 |
} else if (s->phys[0] == buf[0] && |
893 |
s->phys[1] == buf[1] &&
|
|
894 |
s->phys[2] == buf[2] &&
|
|
895 |
s->phys[3] == buf[3] &&
|
|
896 |
s->phys[4] == buf[4] &&
|
|
893 |
s->phys[1] == buf[1] && |
|
894 |
s->phys[2] == buf[2] && |
|
895 |
s->phys[3] == buf[3] && |
|
896 |
s->phys[4] == buf[4] && |
|
897 | 897 |
s->phys[5] == buf[5]) { |
898 | 898 |
/* match */ |
899 | 899 |
if (!(s->RxConfig & AcceptMyPhys)) |
... | ... | |
1225 | 1225 |
s->Config3 = 0x1; /* fast back-to-back compatible */ |
1226 | 1226 |
s->Config5 = 0x0; |
1227 | 1227 |
|
1228 |
s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD;
|
|
1228 |
s->CSCR = CSCR_F_LINK_100 | CSCR_HEART_BIT | CSCR_LD; |
|
1229 | 1229 |
|
1230 | 1230 |
s->CpCmd = 0x0; /* reset C+ mode */ |
1231 | 1231 |
|
... | ... | |
2420 | 2420 |
|((s->TxStatus[2] & TxUnderrun)?TSAD_TUN2:0) |
2421 | 2421 |
|((s->TxStatus[1] & TxUnderrun)?TSAD_TUN1:0) |
2422 | 2422 |
|((s->TxStatus[0] & TxUnderrun)?TSAD_TUN0:0) |
2423 |
|
|
2423 |
|
|
2424 | 2424 |
|((s->TxStatus[3] & TxAborted )?TSAD_TABT3:0) |
2425 | 2425 |
|((s->TxStatus[2] & TxAborted )?TSAD_TABT2:0) |
2426 | 2426 |
|((s->TxStatus[1] & TxAborted )?TSAD_TABT1:0) |
2427 | 2427 |
|((s->TxStatus[0] & TxAborted )?TSAD_TABT0:0) |
2428 |
|
|
2428 |
|
|
2429 | 2429 |
|((s->TxStatus[3] & TxHostOwns )?TSAD_OWN3:0) |
2430 | 2430 |
|((s->TxStatus[2] & TxHostOwns )?TSAD_OWN2:0) |
2431 | 2431 |
|((s->TxStatus[1] & TxHostOwns )?TSAD_OWN1:0) |
2432 | 2432 |
|((s->TxStatus[0] & TxHostOwns )?TSAD_OWN0:0) ; |
2433 |
|
|
2433 |
|
|
2434 | 2434 |
|
2435 | 2435 |
DEBUG_PRINT(("RTL8139: TSAD read val=0x%04x\n", ret)); |
2436 | 2436 |
|
... | ... | |
3315 | 3315 |
RTL8139State rtl8139; |
3316 | 3316 |
} PCIRTL8139State; |
3317 | 3317 |
|
3318 |
static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num,
|
|
3318 |
static void rtl8139_mmio_map(PCIDevice *pci_dev, int region_num, |
|
3319 | 3319 |
uint32_t addr, uint32_t size, int type) |
3320 | 3320 |
{ |
3321 | 3321 |
PCIRTL8139State *d = (PCIRTL8139State *)pci_dev; |
... | ... | |
3324 | 3324 |
cpu_register_physical_memory(addr + 0, 0x100, s->rtl8139_mmio_io_addr); |
3325 | 3325 |
} |
3326 | 3326 |
|
3327 |
static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num,
|
|
3327 |
static void rtl8139_ioport_map(PCIDevice *pci_dev, int region_num, |
|
3328 | 3328 |
uint32_t addr, uint32_t size, int type) |
3329 | 3329 |
{ |
3330 | 3330 |
PCIRTL8139State *d = (PCIRTL8139State *)pci_dev; |
... | ... | |
3354 | 3354 |
|
3355 | 3355 |
static inline int64_t rtl8139_get_next_tctr_time(RTL8139State *s, int64_t current_time) |
3356 | 3356 |
{ |
3357 |
int64_t next_time = current_time +
|
|
3357 |
int64_t next_time = current_time + |
|
3358 | 3358 |
muldiv64(1, ticks_per_sec, PCI_FREQUENCY); |
3359 | 3359 |
if (next_time <= current_time) |
3360 | 3360 |
next_time = current_time + 1; |
... | ... | |
3400 | 3400 |
rtl8139_update_irq(s); |
3401 | 3401 |
} |
3402 | 3402 |
|
3403 |
qemu_mod_timer(s->timer,
|
|
3403 |
qemu_mod_timer(s->timer, |
|
3404 | 3404 |
rtl8139_get_next_tctr_time(s,curr_time)); |
3405 | 3405 |
} |
3406 | 3406 |
#endif /* RTL8139_ONBOARD_TIMER */ |
... | ... | |
3410 | 3410 |
PCIRTL8139State *d; |
3411 | 3411 |
RTL8139State *s; |
3412 | 3412 |
uint8_t *pci_conf; |
3413 |
|
|
3413 |
|
|
3414 | 3414 |
d = (PCIRTL8139State *)pci_register_device(bus, |
3415 | 3415 |
"RTL8139", sizeof(PCIRTL8139State), |
3416 |
devfn,
|
|
3416 |
devfn, |
|
3417 | 3417 |
NULL, NULL); |
3418 | 3418 |
pci_conf = d->dev.config; |
3419 | 3419 |
pci_conf[0x00] = 0xec; /* Realtek 8139 */ |
... | ... | |
3434 | 3434 |
s->rtl8139_mmio_io_addr = |
3435 | 3435 |
cpu_register_io_memory(0, rtl8139_mmio_read, rtl8139_mmio_write, s); |
3436 | 3436 |
|
3437 |
pci_register_io_region(&d->dev, 0, 0x100,
|
|
3437 |
pci_register_io_region(&d->dev, 0, 0x100, |
|
3438 | 3438 |
PCI_ADDRESS_SPACE_IO, rtl8139_ioport_map); |
3439 | 3439 |
|
3440 |
pci_register_io_region(&d->dev, 1, 0x100,
|
|
3440 |
pci_register_io_region(&d->dev, 1, 0x100, |
|
3441 | 3441 |
PCI_ADDRESS_SPACE_MEM, rtl8139_mmio_map); |
3442 | 3442 |
|
3443 | 3443 |
s->pci_dev = (PCIDevice *)d; |
... | ... | |
3458 | 3458 |
s->cplus_txbuffer = NULL; |
3459 | 3459 |
s->cplus_txbuffer_len = 0; |
3460 | 3460 |
s->cplus_txbuffer_offset = 0; |
3461 |
|
|
3461 |
|
|
3462 | 3462 |
/* XXX: instance number ? */ |
3463 | 3463 |
register_savevm("rtl8139", 0, 3, rtl8139_save, rtl8139_load, s); |
3464 | 3464 |
|
3465 | 3465 |
#if RTL8139_ONBOARD_TIMER |
3466 | 3466 |
s->timer = qemu_new_timer(vm_clock, rtl8139_timer, s); |
3467 | 3467 |
|
3468 |
qemu_mod_timer(s->timer,
|
|
3468 |
qemu_mod_timer(s->timer, |
|
3469 | 3469 |
rtl8139_get_next_tctr_time(s,qemu_get_clock(vm_clock))); |
3470 | 3470 |
#endif /* RTL8139_ONBOARD_TIMER */ |
3471 | 3471 |
} |
Also available in: Unified diff