1*34ea023dSSven Schnelle /* 2*34ea023dSSven Schnelle * QEMU TULIP Emulation 3*34ea023dSSven Schnelle * 4*34ea023dSSven Schnelle * Copyright (c) 2019 Sven Schnelle <svens@stackframe.org> 5*34ea023dSSven Schnelle * 6*34ea023dSSven Schnelle * This work is licensed under the GNU GPL license version 2 or later. 7*34ea023dSSven Schnelle */ 8*34ea023dSSven Schnelle 9*34ea023dSSven Schnelle #include "qemu/osdep.h" 10*34ea023dSSven Schnelle #include "qemu/log.h" 11*34ea023dSSven Schnelle #include "hw/irq.h" 12*34ea023dSSven Schnelle #include "hw/pci/pci.h" 13*34ea023dSSven Schnelle #include "hw/qdev-properties.h" 14*34ea023dSSven Schnelle #include "hw/nvram/eeprom93xx.h" 15*34ea023dSSven Schnelle #include "migration/vmstate.h" 16*34ea023dSSven Schnelle #include "sysemu/sysemu.h" 17*34ea023dSSven Schnelle #include "tulip.h" 18*34ea023dSSven Schnelle #include "trace.h" 19*34ea023dSSven Schnelle #include "net/eth.h" 20*34ea023dSSven Schnelle 21*34ea023dSSven Schnelle typedef struct TULIPState { 22*34ea023dSSven Schnelle PCIDevice dev; 23*34ea023dSSven Schnelle MemoryRegion io; 24*34ea023dSSven Schnelle MemoryRegion memory; 25*34ea023dSSven Schnelle NICConf c; 26*34ea023dSSven Schnelle qemu_irq irq; 27*34ea023dSSven Schnelle NICState *nic; 28*34ea023dSSven Schnelle eeprom_t *eeprom; 29*34ea023dSSven Schnelle uint32_t csr[16]; 30*34ea023dSSven Schnelle 31*34ea023dSSven Schnelle /* state for MII */ 32*34ea023dSSven Schnelle uint32_t old_csr9; 33*34ea023dSSven Schnelle uint32_t mii_word; 34*34ea023dSSven Schnelle uint32_t mii_bitcnt; 35*34ea023dSSven Schnelle 36*34ea023dSSven Schnelle hwaddr current_rx_desc; 37*34ea023dSSven Schnelle hwaddr current_tx_desc; 38*34ea023dSSven Schnelle 39*34ea023dSSven Schnelle uint8_t rx_frame[2048]; 40*34ea023dSSven Schnelle uint8_t tx_frame[2048]; 41*34ea023dSSven Schnelle uint16_t tx_frame_len; 42*34ea023dSSven Schnelle uint16_t rx_frame_len; 43*34ea023dSSven Schnelle uint16_t rx_frame_size; 44*34ea023dSSven Schnelle 45*34ea023dSSven Schnelle uint32_t rx_status; 46*34ea023dSSven Schnelle uint8_t filter[16][6]; 47*34ea023dSSven Schnelle } TULIPState; 48*34ea023dSSven Schnelle 49*34ea023dSSven Schnelle static const VMStateDescription vmstate_pci_tulip = { 50*34ea023dSSven Schnelle .name = "tulip", 51*34ea023dSSven Schnelle .fields = (VMStateField[]) { 52*34ea023dSSven Schnelle VMSTATE_PCI_DEVICE(dev, TULIPState), 53*34ea023dSSven Schnelle VMSTATE_UINT32_ARRAY(csr, TULIPState, 16), 54*34ea023dSSven Schnelle VMSTATE_UINT32(old_csr9, TULIPState), 55*34ea023dSSven Schnelle VMSTATE_UINT32(mii_word, TULIPState), 56*34ea023dSSven Schnelle VMSTATE_UINT32(mii_bitcnt, TULIPState), 57*34ea023dSSven Schnelle VMSTATE_UINT64(current_rx_desc, TULIPState), 58*34ea023dSSven Schnelle VMSTATE_UINT64(current_tx_desc, TULIPState), 59*34ea023dSSven Schnelle VMSTATE_BUFFER(rx_frame, TULIPState), 60*34ea023dSSven Schnelle VMSTATE_BUFFER(tx_frame, TULIPState), 61*34ea023dSSven Schnelle VMSTATE_UINT16(rx_frame_len, TULIPState), 62*34ea023dSSven Schnelle VMSTATE_UINT16(tx_frame_len, TULIPState), 63*34ea023dSSven Schnelle VMSTATE_UINT16(rx_frame_size, TULIPState), 64*34ea023dSSven Schnelle VMSTATE_UINT32(rx_status, TULIPState), 65*34ea023dSSven Schnelle VMSTATE_UINT8_2DARRAY(filter, TULIPState, 16, 6), 66*34ea023dSSven Schnelle VMSTATE_END_OF_LIST() 67*34ea023dSSven Schnelle } 68*34ea023dSSven Schnelle }; 69*34ea023dSSven Schnelle 70*34ea023dSSven Schnelle static void tulip_desc_read(TULIPState *s, hwaddr p, 71*34ea023dSSven Schnelle struct tulip_descriptor *desc) 72*34ea023dSSven Schnelle { 73*34ea023dSSven Schnelle if (s->csr[0] & CSR0_DBO) { 74*34ea023dSSven Schnelle desc->status = ldl_be_pci_dma(&s->dev, p); 75*34ea023dSSven Schnelle desc->control = ldl_be_pci_dma(&s->dev, p + 4); 76*34ea023dSSven Schnelle desc->buf_addr1 = ldl_be_pci_dma(&s->dev, p + 8); 77*34ea023dSSven Schnelle desc->buf_addr2 = ldl_be_pci_dma(&s->dev, p + 12); 78*34ea023dSSven Schnelle } else { 79*34ea023dSSven Schnelle desc->status = ldl_le_pci_dma(&s->dev, p); 80*34ea023dSSven Schnelle desc->control = ldl_le_pci_dma(&s->dev, p + 4); 81*34ea023dSSven Schnelle desc->buf_addr1 = ldl_le_pci_dma(&s->dev, p + 8); 82*34ea023dSSven Schnelle desc->buf_addr2 = ldl_le_pci_dma(&s->dev, p + 12); 83*34ea023dSSven Schnelle } 84*34ea023dSSven Schnelle } 85*34ea023dSSven Schnelle 86*34ea023dSSven Schnelle static void tulip_desc_write(TULIPState *s, hwaddr p, 87*34ea023dSSven Schnelle struct tulip_descriptor *desc) 88*34ea023dSSven Schnelle { 89*34ea023dSSven Schnelle if (s->csr[0] & CSR0_DBO) { 90*34ea023dSSven Schnelle stl_be_pci_dma(&s->dev, p, desc->status); 91*34ea023dSSven Schnelle stl_be_pci_dma(&s->dev, p + 4, desc->control); 92*34ea023dSSven Schnelle stl_be_pci_dma(&s->dev, p + 8, desc->buf_addr1); 93*34ea023dSSven Schnelle stl_be_pci_dma(&s->dev, p + 12, desc->buf_addr2); 94*34ea023dSSven Schnelle } else { 95*34ea023dSSven Schnelle stl_le_pci_dma(&s->dev, p, desc->status); 96*34ea023dSSven Schnelle stl_le_pci_dma(&s->dev, p + 4, desc->control); 97*34ea023dSSven Schnelle stl_le_pci_dma(&s->dev, p + 8, desc->buf_addr1); 98*34ea023dSSven Schnelle stl_le_pci_dma(&s->dev, p + 12, desc->buf_addr2); 99*34ea023dSSven Schnelle } 100*34ea023dSSven Schnelle } 101*34ea023dSSven Schnelle 102*34ea023dSSven Schnelle static void tulip_update_int(TULIPState *s) 103*34ea023dSSven Schnelle { 104*34ea023dSSven Schnelle uint32_t ie = s->csr[5] & s->csr[7]; 105*34ea023dSSven Schnelle bool assert = false; 106*34ea023dSSven Schnelle 107*34ea023dSSven Schnelle s->csr[5] &= ~(CSR5_AIS | CSR5_NIS); 108*34ea023dSSven Schnelle 109*34ea023dSSven Schnelle if (ie & (CSR5_TI | CSR5_TU | CSR5_RI | CSR5_GTE | CSR5_ERI)) { 110*34ea023dSSven Schnelle s->csr[5] |= CSR5_NIS; 111*34ea023dSSven Schnelle } 112*34ea023dSSven Schnelle 113*34ea023dSSven Schnelle if (ie & (CSR5_LC | CSR5_GPI | CSR5_FBE | CSR5_LNF | CSR5_ETI | CSR5_RWT | 114*34ea023dSSven Schnelle CSR5_RPS | CSR5_RU | CSR5_UNF | CSR5_LNP_ANC | CSR5_TJT | 115*34ea023dSSven Schnelle CSR5_TPS)) { 116*34ea023dSSven Schnelle s->csr[5] |= CSR5_AIS; 117*34ea023dSSven Schnelle } 118*34ea023dSSven Schnelle 119*34ea023dSSven Schnelle assert = s->csr[5] & s->csr[7] & (CSR5_AIS | CSR5_NIS); 120*34ea023dSSven Schnelle trace_tulip_irq(s->csr[5], s->csr[7], assert ? "assert" : "deassert"); 121*34ea023dSSven Schnelle qemu_set_irq(s->irq, assert); 122*34ea023dSSven Schnelle } 123*34ea023dSSven Schnelle 124*34ea023dSSven Schnelle static bool tulip_rx_stopped(TULIPState *s) 125*34ea023dSSven Schnelle { 126*34ea023dSSven Schnelle return ((s->csr[5] >> CSR5_RS_SHIFT) & CSR5_RS_MASK) == CSR5_RS_STOPPED; 127*34ea023dSSven Schnelle } 128*34ea023dSSven Schnelle 129*34ea023dSSven Schnelle static void tulip_dump_tx_descriptor(TULIPState *s, 130*34ea023dSSven Schnelle struct tulip_descriptor *desc) 131*34ea023dSSven Schnelle { 132*34ea023dSSven Schnelle trace_tulip_descriptor("TX ", s->current_tx_desc, 133*34ea023dSSven Schnelle desc->status, desc->control >> 22, 134*34ea023dSSven Schnelle desc->control & 0x7ff, (desc->control >> 11) & 0x7ff, 135*34ea023dSSven Schnelle desc->buf_addr1, desc->buf_addr2); 136*34ea023dSSven Schnelle } 137*34ea023dSSven Schnelle 138*34ea023dSSven Schnelle static void tulip_dump_rx_descriptor(TULIPState *s, 139*34ea023dSSven Schnelle struct tulip_descriptor *desc) 140*34ea023dSSven Schnelle { 141*34ea023dSSven Schnelle trace_tulip_descriptor("RX ", s->current_rx_desc, 142*34ea023dSSven Schnelle desc->status, desc->control >> 22, 143*34ea023dSSven Schnelle desc->control & 0x7ff, (desc->control >> 11) & 0x7ff, 144*34ea023dSSven Schnelle desc->buf_addr1, desc->buf_addr2); 145*34ea023dSSven Schnelle } 146*34ea023dSSven Schnelle 147*34ea023dSSven Schnelle static void tulip_next_rx_descriptor(TULIPState *s, 148*34ea023dSSven Schnelle struct tulip_descriptor *desc) 149*34ea023dSSven Schnelle { 150*34ea023dSSven Schnelle if (desc->control & RDES1_RER) { 151*34ea023dSSven Schnelle s->current_rx_desc = s->csr[3]; 152*34ea023dSSven Schnelle } else if (desc->control & RDES1_RCH) { 153*34ea023dSSven Schnelle s->current_rx_desc = desc->buf_addr2; 154*34ea023dSSven Schnelle } else { 155*34ea023dSSven Schnelle s->current_rx_desc += sizeof(struct tulip_descriptor) + 156*34ea023dSSven Schnelle (((s->csr[0] >> CSR0_DSL_SHIFT) & CSR0_DSL_MASK) << 2); 157*34ea023dSSven Schnelle } 158*34ea023dSSven Schnelle s->current_rx_desc &= ~3ULL; 159*34ea023dSSven Schnelle } 160*34ea023dSSven Schnelle 161*34ea023dSSven Schnelle static void tulip_copy_rx_bytes(TULIPState *s, struct tulip_descriptor *desc) 162*34ea023dSSven Schnelle { 163*34ea023dSSven Schnelle int len1 = (desc->control >> RDES1_BUF1_SIZE_SHIFT) & RDES1_BUF1_SIZE_MASK; 164*34ea023dSSven Schnelle int len2 = (desc->control >> RDES1_BUF2_SIZE_SHIFT) & RDES1_BUF2_SIZE_MASK; 165*34ea023dSSven Schnelle int len; 166*34ea023dSSven Schnelle 167*34ea023dSSven Schnelle if (s->rx_frame_len && len1) { 168*34ea023dSSven Schnelle if (s->rx_frame_len > len1) { 169*34ea023dSSven Schnelle len = len1; 170*34ea023dSSven Schnelle } else { 171*34ea023dSSven Schnelle len = s->rx_frame_len; 172*34ea023dSSven Schnelle } 173*34ea023dSSven Schnelle pci_dma_write(&s->dev, desc->buf_addr1, s->rx_frame + 174*34ea023dSSven Schnelle (s->rx_frame_size - s->rx_frame_len), len); 175*34ea023dSSven Schnelle s->rx_frame_len -= len; 176*34ea023dSSven Schnelle } 177*34ea023dSSven Schnelle 178*34ea023dSSven Schnelle if (s->rx_frame_len && len2) { 179*34ea023dSSven Schnelle if (s->rx_frame_len > len2) { 180*34ea023dSSven Schnelle len = len2; 181*34ea023dSSven Schnelle } else { 182*34ea023dSSven Schnelle len = s->rx_frame_len; 183*34ea023dSSven Schnelle } 184*34ea023dSSven Schnelle pci_dma_write(&s->dev, desc->buf_addr2, s->rx_frame + 185*34ea023dSSven Schnelle (s->rx_frame_size - s->rx_frame_len), len); 186*34ea023dSSven Schnelle s->rx_frame_len -= len; 187*34ea023dSSven Schnelle } 188*34ea023dSSven Schnelle } 189*34ea023dSSven Schnelle 190*34ea023dSSven Schnelle static bool tulip_filter_address(TULIPState *s, const uint8_t *addr) 191*34ea023dSSven Schnelle { 192*34ea023dSSven Schnelle static const char broadcast[] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 193*34ea023dSSven Schnelle bool ret = false; 194*34ea023dSSven Schnelle int i; 195*34ea023dSSven Schnelle 196*34ea023dSSven Schnelle for (i = 0; i < 16 && ret == false; i++) { 197*34ea023dSSven Schnelle if (!memcmp(&s->filter[i], addr, ETH_ALEN)) { 198*34ea023dSSven Schnelle ret = true; 199*34ea023dSSven Schnelle } 200*34ea023dSSven Schnelle } 201*34ea023dSSven Schnelle 202*34ea023dSSven Schnelle if (!memcmp(addr, broadcast, ETH_ALEN)) { 203*34ea023dSSven Schnelle return true; 204*34ea023dSSven Schnelle } 205*34ea023dSSven Schnelle 206*34ea023dSSven Schnelle if (s->csr[6] & (CSR6_PR | CSR6_RA)) { 207*34ea023dSSven Schnelle /* Promiscuous mode enabled */ 208*34ea023dSSven Schnelle s->rx_status |= RDES0_FF; 209*34ea023dSSven Schnelle return true; 210*34ea023dSSven Schnelle } 211*34ea023dSSven Schnelle 212*34ea023dSSven Schnelle if ((s->csr[6] & CSR6_PM) && (addr[0] & 1)) { 213*34ea023dSSven Schnelle /* Pass all Multicast enabled */ 214*34ea023dSSven Schnelle s->rx_status |= RDES0_MF; 215*34ea023dSSven Schnelle return true; 216*34ea023dSSven Schnelle } 217*34ea023dSSven Schnelle 218*34ea023dSSven Schnelle if (s->csr[6] & CSR6_IF) { 219*34ea023dSSven Schnelle ret ^= true; 220*34ea023dSSven Schnelle } 221*34ea023dSSven Schnelle return ret; 222*34ea023dSSven Schnelle } 223*34ea023dSSven Schnelle 224*34ea023dSSven Schnelle static ssize_t tulip_receive(TULIPState *s, const uint8_t *buf, size_t size) 225*34ea023dSSven Schnelle { 226*34ea023dSSven Schnelle struct tulip_descriptor desc; 227*34ea023dSSven Schnelle 228*34ea023dSSven Schnelle trace_tulip_receive(buf, size); 229*34ea023dSSven Schnelle 230*34ea023dSSven Schnelle if (size < 14 || size > 2048 || s->rx_frame_len || tulip_rx_stopped(s)) { 231*34ea023dSSven Schnelle return 0; 232*34ea023dSSven Schnelle } 233*34ea023dSSven Schnelle 234*34ea023dSSven Schnelle if (!tulip_filter_address(s, buf)) { 235*34ea023dSSven Schnelle return size; 236*34ea023dSSven Schnelle } 237*34ea023dSSven Schnelle 238*34ea023dSSven Schnelle do { 239*34ea023dSSven Schnelle tulip_desc_read(s, s->current_rx_desc, &desc); 240*34ea023dSSven Schnelle tulip_dump_rx_descriptor(s, &desc); 241*34ea023dSSven Schnelle 242*34ea023dSSven Schnelle if (!(desc.status & RDES0_OWN)) { 243*34ea023dSSven Schnelle s->csr[5] |= CSR5_RU; 244*34ea023dSSven Schnelle tulip_update_int(s); 245*34ea023dSSven Schnelle return s->rx_frame_size - s->rx_frame_len; 246*34ea023dSSven Schnelle } 247*34ea023dSSven Schnelle desc.status = 0; 248*34ea023dSSven Schnelle 249*34ea023dSSven Schnelle if (!s->rx_frame_len) { 250*34ea023dSSven Schnelle s->rx_frame_size = size + 4; 251*34ea023dSSven Schnelle s->rx_status = RDES0_LS | 252*34ea023dSSven Schnelle ((s->rx_frame_size & RDES0_FL_MASK) << RDES0_FL_SHIFT); 253*34ea023dSSven Schnelle desc.status |= RDES0_FS; 254*34ea023dSSven Schnelle memcpy(s->rx_frame, buf, size); 255*34ea023dSSven Schnelle s->rx_frame_len = s->rx_frame_size; 256*34ea023dSSven Schnelle } 257*34ea023dSSven Schnelle 258*34ea023dSSven Schnelle tulip_copy_rx_bytes(s, &desc); 259*34ea023dSSven Schnelle 260*34ea023dSSven Schnelle if (!s->rx_frame_len) { 261*34ea023dSSven Schnelle desc.status |= s->rx_status; 262*34ea023dSSven Schnelle s->csr[5] |= CSR5_RI; 263*34ea023dSSven Schnelle tulip_update_int(s); 264*34ea023dSSven Schnelle } 265*34ea023dSSven Schnelle tulip_dump_rx_descriptor(s, &desc); 266*34ea023dSSven Schnelle tulip_desc_write(s, s->current_rx_desc, &desc); 267*34ea023dSSven Schnelle tulip_next_rx_descriptor(s, &desc); 268*34ea023dSSven Schnelle } while (s->rx_frame_len); 269*34ea023dSSven Schnelle return size; 270*34ea023dSSven Schnelle } 271*34ea023dSSven Schnelle 272*34ea023dSSven Schnelle static ssize_t tulip_receive_nc(NetClientState *nc, 273*34ea023dSSven Schnelle const uint8_t *buf, size_t size) 274*34ea023dSSven Schnelle { 275*34ea023dSSven Schnelle return tulip_receive(qemu_get_nic_opaque(nc), buf, size); 276*34ea023dSSven Schnelle } 277*34ea023dSSven Schnelle 278*34ea023dSSven Schnelle 279*34ea023dSSven Schnelle static NetClientInfo net_tulip_info = { 280*34ea023dSSven Schnelle .type = NET_CLIENT_DRIVER_NIC, 281*34ea023dSSven Schnelle .size = sizeof(NICState), 282*34ea023dSSven Schnelle .receive = tulip_receive_nc, 283*34ea023dSSven Schnelle }; 284*34ea023dSSven Schnelle 285*34ea023dSSven Schnelle static const char *tulip_reg_name(const hwaddr addr) 286*34ea023dSSven Schnelle { 287*34ea023dSSven Schnelle switch (addr) { 288*34ea023dSSven Schnelle case CSR(0): 289*34ea023dSSven Schnelle return "CSR0"; 290*34ea023dSSven Schnelle 291*34ea023dSSven Schnelle case CSR(1): 292*34ea023dSSven Schnelle return "CSR1"; 293*34ea023dSSven Schnelle 294*34ea023dSSven Schnelle case CSR(2): 295*34ea023dSSven Schnelle return "CSR2"; 296*34ea023dSSven Schnelle 297*34ea023dSSven Schnelle case CSR(3): 298*34ea023dSSven Schnelle return "CSR3"; 299*34ea023dSSven Schnelle 300*34ea023dSSven Schnelle case CSR(4): 301*34ea023dSSven Schnelle return "CSR4"; 302*34ea023dSSven Schnelle 303*34ea023dSSven Schnelle case CSR(5): 304*34ea023dSSven Schnelle return "CSR5"; 305*34ea023dSSven Schnelle 306*34ea023dSSven Schnelle case CSR(6): 307*34ea023dSSven Schnelle return "CSR6"; 308*34ea023dSSven Schnelle 309*34ea023dSSven Schnelle case CSR(7): 310*34ea023dSSven Schnelle return "CSR7"; 311*34ea023dSSven Schnelle 312*34ea023dSSven Schnelle case CSR(8): 313*34ea023dSSven Schnelle return "CSR8"; 314*34ea023dSSven Schnelle 315*34ea023dSSven Schnelle case CSR(9): 316*34ea023dSSven Schnelle return "CSR9"; 317*34ea023dSSven Schnelle 318*34ea023dSSven Schnelle case CSR(10): 319*34ea023dSSven Schnelle return "CSR10"; 320*34ea023dSSven Schnelle 321*34ea023dSSven Schnelle case CSR(11): 322*34ea023dSSven Schnelle return "CSR11"; 323*34ea023dSSven Schnelle 324*34ea023dSSven Schnelle case CSR(12): 325*34ea023dSSven Schnelle return "CSR12"; 326*34ea023dSSven Schnelle 327*34ea023dSSven Schnelle case CSR(13): 328*34ea023dSSven Schnelle return "CSR13"; 329*34ea023dSSven Schnelle 330*34ea023dSSven Schnelle case CSR(14): 331*34ea023dSSven Schnelle return "CSR14"; 332*34ea023dSSven Schnelle 333*34ea023dSSven Schnelle case CSR(15): 334*34ea023dSSven Schnelle return "CSR15"; 335*34ea023dSSven Schnelle 336*34ea023dSSven Schnelle default: 337*34ea023dSSven Schnelle break; 338*34ea023dSSven Schnelle } 339*34ea023dSSven Schnelle return ""; 340*34ea023dSSven Schnelle } 341*34ea023dSSven Schnelle 342*34ea023dSSven Schnelle static const char *tulip_rx_state_name(int state) 343*34ea023dSSven Schnelle { 344*34ea023dSSven Schnelle switch (state) { 345*34ea023dSSven Schnelle case CSR5_RS_STOPPED: 346*34ea023dSSven Schnelle return "STOPPED"; 347*34ea023dSSven Schnelle 348*34ea023dSSven Schnelle case CSR5_RS_RUNNING_FETCH: 349*34ea023dSSven Schnelle return "RUNNING/FETCH"; 350*34ea023dSSven Schnelle 351*34ea023dSSven Schnelle case CSR5_RS_RUNNING_CHECK_EOR: 352*34ea023dSSven Schnelle return "RUNNING/CHECK EOR"; 353*34ea023dSSven Schnelle 354*34ea023dSSven Schnelle case CSR5_RS_RUNNING_WAIT_RECEIVE: 355*34ea023dSSven Schnelle return "WAIT RECEIVE"; 356*34ea023dSSven Schnelle 357*34ea023dSSven Schnelle case CSR5_RS_SUSPENDED: 358*34ea023dSSven Schnelle return "SUSPENDED"; 359*34ea023dSSven Schnelle 360*34ea023dSSven Schnelle case CSR5_RS_RUNNING_CLOSE: 361*34ea023dSSven Schnelle return "RUNNING/CLOSE"; 362*34ea023dSSven Schnelle 363*34ea023dSSven Schnelle case CSR5_RS_RUNNING_FLUSH: 364*34ea023dSSven Schnelle return "RUNNING/FLUSH"; 365*34ea023dSSven Schnelle 366*34ea023dSSven Schnelle case CSR5_RS_RUNNING_QUEUE: 367*34ea023dSSven Schnelle return "RUNNING/QUEUE"; 368*34ea023dSSven Schnelle 369*34ea023dSSven Schnelle default: 370*34ea023dSSven Schnelle break; 371*34ea023dSSven Schnelle } 372*34ea023dSSven Schnelle return ""; 373*34ea023dSSven Schnelle } 374*34ea023dSSven Schnelle 375*34ea023dSSven Schnelle static const char *tulip_tx_state_name(int state) 376*34ea023dSSven Schnelle { 377*34ea023dSSven Schnelle switch (state) { 378*34ea023dSSven Schnelle case CSR5_TS_STOPPED: 379*34ea023dSSven Schnelle return "STOPPED"; 380*34ea023dSSven Schnelle 381*34ea023dSSven Schnelle case CSR5_TS_RUNNING_FETCH: 382*34ea023dSSven Schnelle return "RUNNING/FETCH"; 383*34ea023dSSven Schnelle 384*34ea023dSSven Schnelle case CSR5_TS_RUNNING_WAIT_EOT: 385*34ea023dSSven Schnelle return "RUNNING/WAIT EOT"; 386*34ea023dSSven Schnelle 387*34ea023dSSven Schnelle case CSR5_TS_RUNNING_READ_BUF: 388*34ea023dSSven Schnelle return "RUNNING/READ BUF"; 389*34ea023dSSven Schnelle 390*34ea023dSSven Schnelle case CSR5_TS_RUNNING_SETUP: 391*34ea023dSSven Schnelle return "RUNNING/SETUP"; 392*34ea023dSSven Schnelle 393*34ea023dSSven Schnelle case CSR5_TS_SUSPENDED: 394*34ea023dSSven Schnelle return "SUSPENDED"; 395*34ea023dSSven Schnelle 396*34ea023dSSven Schnelle case CSR5_TS_RUNNING_CLOSE: 397*34ea023dSSven Schnelle return "RUNNING/CLOSE"; 398*34ea023dSSven Schnelle 399*34ea023dSSven Schnelle default: 400*34ea023dSSven Schnelle break; 401*34ea023dSSven Schnelle } 402*34ea023dSSven Schnelle return ""; 403*34ea023dSSven Schnelle } 404*34ea023dSSven Schnelle 405*34ea023dSSven Schnelle static void tulip_update_rs(TULIPState *s, int state) 406*34ea023dSSven Schnelle { 407*34ea023dSSven Schnelle s->csr[5] &= ~(CSR5_RS_MASK << CSR5_RS_SHIFT); 408*34ea023dSSven Schnelle s->csr[5] |= (state & CSR5_RS_MASK) << CSR5_RS_SHIFT; 409*34ea023dSSven Schnelle trace_tulip_rx_state(tulip_rx_state_name(state)); 410*34ea023dSSven Schnelle } 411*34ea023dSSven Schnelle 412*34ea023dSSven Schnelle static uint16_t tulip_mdi_default[] = { 413*34ea023dSSven Schnelle /* MDI Registers 0 - 6, 7 */ 414*34ea023dSSven Schnelle 0x3100, 0xf02c, 0x7810, 0x0000, 0x0501, 0x4181, 0x0000, 0x0000, 415*34ea023dSSven Schnelle /* MDI Registers 8 - 15 */ 416*34ea023dSSven Schnelle 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 417*34ea023dSSven Schnelle /* MDI Registers 16 - 31 */ 418*34ea023dSSven Schnelle 0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 419*34ea023dSSven Schnelle 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 420*34ea023dSSven Schnelle }; 421*34ea023dSSven Schnelle 422*34ea023dSSven Schnelle /* Readonly mask for MDI (PHY) registers */ 423*34ea023dSSven Schnelle static const uint16_t tulip_mdi_mask[] = { 424*34ea023dSSven Schnelle 0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000, 425*34ea023dSSven Schnelle 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 426*34ea023dSSven Schnelle 0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 427*34ea023dSSven Schnelle 0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 428*34ea023dSSven Schnelle }; 429*34ea023dSSven Schnelle 430*34ea023dSSven Schnelle static uint16_t tulip_mii_read(TULIPState *s, int phy, int reg) 431*34ea023dSSven Schnelle { 432*34ea023dSSven Schnelle uint16_t ret = 0; 433*34ea023dSSven Schnelle if (phy == 1) { 434*34ea023dSSven Schnelle ret = tulip_mdi_default[reg]; 435*34ea023dSSven Schnelle } 436*34ea023dSSven Schnelle trace_tulip_mii_read(phy, reg, ret); 437*34ea023dSSven Schnelle return ret; 438*34ea023dSSven Schnelle } 439*34ea023dSSven Schnelle 440*34ea023dSSven Schnelle static void tulip_mii_write(TULIPState *s, int phy, int reg, uint16_t data) 441*34ea023dSSven Schnelle { 442*34ea023dSSven Schnelle trace_tulip_mii_write(phy, reg, data); 443*34ea023dSSven Schnelle 444*34ea023dSSven Schnelle if (phy != 1) { 445*34ea023dSSven Schnelle return; 446*34ea023dSSven Schnelle } 447*34ea023dSSven Schnelle 448*34ea023dSSven Schnelle tulip_mdi_default[reg] &= ~tulip_mdi_mask[reg]; 449*34ea023dSSven Schnelle tulip_mdi_default[reg] |= (data & tulip_mdi_mask[reg]); 450*34ea023dSSven Schnelle } 451*34ea023dSSven Schnelle 452*34ea023dSSven Schnelle static void tulip_mii(TULIPState *s) 453*34ea023dSSven Schnelle { 454*34ea023dSSven Schnelle uint32_t changed = s->old_csr9 ^ s->csr[9]; 455*34ea023dSSven Schnelle uint16_t data; 456*34ea023dSSven Schnelle int op, phy, reg; 457*34ea023dSSven Schnelle 458*34ea023dSSven Schnelle if (!(changed & CSR9_MDC)) { 459*34ea023dSSven Schnelle return; 460*34ea023dSSven Schnelle } 461*34ea023dSSven Schnelle 462*34ea023dSSven Schnelle if (!(s->csr[9] & CSR9_MDC)) { 463*34ea023dSSven Schnelle return; 464*34ea023dSSven Schnelle } 465*34ea023dSSven Schnelle 466*34ea023dSSven Schnelle s->mii_bitcnt++; 467*34ea023dSSven Schnelle s->mii_word <<= 1; 468*34ea023dSSven Schnelle 469*34ea023dSSven Schnelle if (s->csr[9] & CSR9_MDO && (s->mii_bitcnt < 16 || 470*34ea023dSSven Schnelle !(s->csr[9] & CSR9_MII))) { 471*34ea023dSSven Schnelle /* write op or address bits */ 472*34ea023dSSven Schnelle s->mii_word |= 1; 473*34ea023dSSven Schnelle } 474*34ea023dSSven Schnelle 475*34ea023dSSven Schnelle if (s->mii_bitcnt >= 16 && (s->csr[9] & CSR9_MII)) { 476*34ea023dSSven Schnelle if (s->mii_word & 0x8000) { 477*34ea023dSSven Schnelle s->csr[9] |= CSR9_MDI; 478*34ea023dSSven Schnelle } else { 479*34ea023dSSven Schnelle s->csr[9] &= ~CSR9_MDI; 480*34ea023dSSven Schnelle } 481*34ea023dSSven Schnelle } 482*34ea023dSSven Schnelle 483*34ea023dSSven Schnelle if (s->mii_word == 0xffffffff) { 484*34ea023dSSven Schnelle s->mii_bitcnt = 0; 485*34ea023dSSven Schnelle } else if (s->mii_bitcnt == 16) { 486*34ea023dSSven Schnelle op = (s->mii_word >> 12) & 0x0f; 487*34ea023dSSven Schnelle phy = (s->mii_word >> 7) & 0x1f; 488*34ea023dSSven Schnelle reg = (s->mii_word >> 2) & 0x1f; 489*34ea023dSSven Schnelle 490*34ea023dSSven Schnelle if (op == 6) { 491*34ea023dSSven Schnelle s->mii_word = tulip_mii_read(s, phy, reg); 492*34ea023dSSven Schnelle } 493*34ea023dSSven Schnelle } else if (s->mii_bitcnt == 32) { 494*34ea023dSSven Schnelle op = (s->mii_word >> 28) & 0x0f; 495*34ea023dSSven Schnelle phy = (s->mii_word >> 23) & 0x1f; 496*34ea023dSSven Schnelle reg = (s->mii_word >> 18) & 0x1f; 497*34ea023dSSven Schnelle data = s->mii_word & 0xffff; 498*34ea023dSSven Schnelle 499*34ea023dSSven Schnelle if (op == 5) { 500*34ea023dSSven Schnelle tulip_mii_write(s, phy, reg, data); 501*34ea023dSSven Schnelle } 502*34ea023dSSven Schnelle } 503*34ea023dSSven Schnelle } 504*34ea023dSSven Schnelle 505*34ea023dSSven Schnelle static uint32_t tulip_csr9_read(TULIPState *s) 506*34ea023dSSven Schnelle { 507*34ea023dSSven Schnelle if (s->csr[9] & CSR9_SR) { 508*34ea023dSSven Schnelle if (eeprom93xx_read(s->eeprom)) { 509*34ea023dSSven Schnelle s->csr[9] |= CSR9_SR_DO; 510*34ea023dSSven Schnelle } else { 511*34ea023dSSven Schnelle s->csr[9] &= ~CSR9_SR_DO; 512*34ea023dSSven Schnelle } 513*34ea023dSSven Schnelle } 514*34ea023dSSven Schnelle 515*34ea023dSSven Schnelle tulip_mii(s); 516*34ea023dSSven Schnelle return s->csr[9]; 517*34ea023dSSven Schnelle } 518*34ea023dSSven Schnelle 519*34ea023dSSven Schnelle static void tulip_update_ts(TULIPState *s, int state) 520*34ea023dSSven Schnelle { 521*34ea023dSSven Schnelle s->csr[5] &= ~(CSR5_TS_MASK << CSR5_TS_SHIFT); 522*34ea023dSSven Schnelle s->csr[5] |= (state & CSR5_TS_MASK) << CSR5_TS_SHIFT; 523*34ea023dSSven Schnelle trace_tulip_tx_state(tulip_tx_state_name(state)); 524*34ea023dSSven Schnelle } 525*34ea023dSSven Schnelle 526*34ea023dSSven Schnelle static uint64_t tulip_read(void *opaque, hwaddr addr, 527*34ea023dSSven Schnelle unsigned size) 528*34ea023dSSven Schnelle { 529*34ea023dSSven Schnelle TULIPState *s = opaque; 530*34ea023dSSven Schnelle uint64_t data = 0; 531*34ea023dSSven Schnelle 532*34ea023dSSven Schnelle switch (addr) { 533*34ea023dSSven Schnelle case CSR(9): 534*34ea023dSSven Schnelle data = tulip_csr9_read(s); 535*34ea023dSSven Schnelle break; 536*34ea023dSSven Schnelle 537*34ea023dSSven Schnelle case CSR(12): 538*34ea023dSSven Schnelle /* Fake autocompletion complete until we have PHY emulation */ 539*34ea023dSSven Schnelle data = 5 << CSR12_ANS_SHIFT; 540*34ea023dSSven Schnelle break; 541*34ea023dSSven Schnelle 542*34ea023dSSven Schnelle default: 543*34ea023dSSven Schnelle if (addr & 7) { 544*34ea023dSSven Schnelle qemu_log_mask(LOG_GUEST_ERROR, "%s: read access at unknown address" 545*34ea023dSSven Schnelle " 0x%"PRIx64"\n", __func__, addr); 546*34ea023dSSven Schnelle } else { 547*34ea023dSSven Schnelle data = s->csr[addr >> 3]; 548*34ea023dSSven Schnelle } 549*34ea023dSSven Schnelle break; 550*34ea023dSSven Schnelle } 551*34ea023dSSven Schnelle trace_tulip_reg_read(addr, tulip_reg_name(addr), size, data); 552*34ea023dSSven Schnelle return data; 553*34ea023dSSven Schnelle } 554*34ea023dSSven Schnelle 555*34ea023dSSven Schnelle static void tulip_tx(TULIPState *s, struct tulip_descriptor *desc) 556*34ea023dSSven Schnelle { 557*34ea023dSSven Schnelle if (s->tx_frame_len) { 558*34ea023dSSven Schnelle if ((s->csr[6] >> CSR6_OM_SHIFT) & CSR6_OM_MASK) { 559*34ea023dSSven Schnelle /* Internal or external Loopback */ 560*34ea023dSSven Schnelle tulip_receive(s, s->tx_frame, s->tx_frame_len); 561*34ea023dSSven Schnelle } else { 562*34ea023dSSven Schnelle qemu_send_packet(qemu_get_queue(s->nic), 563*34ea023dSSven Schnelle s->tx_frame, s->tx_frame_len); 564*34ea023dSSven Schnelle } 565*34ea023dSSven Schnelle } 566*34ea023dSSven Schnelle 567*34ea023dSSven Schnelle if (desc->control & TDES1_IC) { 568*34ea023dSSven Schnelle s->csr[5] |= CSR5_TI; 569*34ea023dSSven Schnelle tulip_update_int(s); 570*34ea023dSSven Schnelle } 571*34ea023dSSven Schnelle } 572*34ea023dSSven Schnelle 573*34ea023dSSven Schnelle static void tulip_copy_tx_buffers(TULIPState *s, struct tulip_descriptor *desc) 574*34ea023dSSven Schnelle { 575*34ea023dSSven Schnelle int len1 = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK; 576*34ea023dSSven Schnelle int len2 = (desc->control >> TDES1_BUF2_SIZE_SHIFT) & TDES1_BUF2_SIZE_MASK; 577*34ea023dSSven Schnelle 578*34ea023dSSven Schnelle if (len1) { 579*34ea023dSSven Schnelle pci_dma_read(&s->dev, desc->buf_addr1, 580*34ea023dSSven Schnelle s->tx_frame + s->tx_frame_len, len1); 581*34ea023dSSven Schnelle s->tx_frame_len += len1; 582*34ea023dSSven Schnelle } 583*34ea023dSSven Schnelle 584*34ea023dSSven Schnelle if (len2) { 585*34ea023dSSven Schnelle pci_dma_read(&s->dev, desc->buf_addr2, 586*34ea023dSSven Schnelle s->tx_frame + s->tx_frame_len, len2); 587*34ea023dSSven Schnelle s->tx_frame_len += len2; 588*34ea023dSSven Schnelle } 589*34ea023dSSven Schnelle desc->status = (len1 + len2) ? 0 : 0x7fffffff; 590*34ea023dSSven Schnelle } 591*34ea023dSSven Schnelle 592*34ea023dSSven Schnelle static void tulip_setup_filter_addr(TULIPState *s, uint8_t *buf, int n) 593*34ea023dSSven Schnelle { 594*34ea023dSSven Schnelle int offset = n * 12; 595*34ea023dSSven Schnelle 596*34ea023dSSven Schnelle s->filter[n][0] = buf[offset]; 597*34ea023dSSven Schnelle s->filter[n][1] = buf[offset + 1]; 598*34ea023dSSven Schnelle 599*34ea023dSSven Schnelle s->filter[n][2] = buf[offset + 4]; 600*34ea023dSSven Schnelle s->filter[n][3] = buf[offset + 5]; 601*34ea023dSSven Schnelle 602*34ea023dSSven Schnelle s->filter[n][4] = buf[offset + 8]; 603*34ea023dSSven Schnelle s->filter[n][5] = buf[offset + 9]; 604*34ea023dSSven Schnelle 605*34ea023dSSven Schnelle trace_tulip_setup_filter(n, s->filter[n][5], s->filter[n][4], 606*34ea023dSSven Schnelle s->filter[n][3], s->filter[n][2], s->filter[n][1], s->filter[n][0]); 607*34ea023dSSven Schnelle } 608*34ea023dSSven Schnelle 609*34ea023dSSven Schnelle static void tulip_setup_frame(TULIPState *s, 610*34ea023dSSven Schnelle struct tulip_descriptor *desc) 611*34ea023dSSven Schnelle { 612*34ea023dSSven Schnelle uint8_t buf[4096]; 613*34ea023dSSven Schnelle int len = (desc->control >> TDES1_BUF1_SIZE_SHIFT) & TDES1_BUF1_SIZE_MASK; 614*34ea023dSSven Schnelle int i; 615*34ea023dSSven Schnelle 616*34ea023dSSven Schnelle trace_tulip_setup_frame(); 617*34ea023dSSven Schnelle 618*34ea023dSSven Schnelle if (len == 192) { 619*34ea023dSSven Schnelle pci_dma_read(&s->dev, desc->buf_addr1, buf, len); 620*34ea023dSSven Schnelle for (i = 0; i < 16; i++) { 621*34ea023dSSven Schnelle tulip_setup_filter_addr(s, buf, i); 622*34ea023dSSven Schnelle } 623*34ea023dSSven Schnelle } 624*34ea023dSSven Schnelle 625*34ea023dSSven Schnelle desc->status = 0x7fffffff; 626*34ea023dSSven Schnelle 627*34ea023dSSven Schnelle if (desc->control & TDES1_IC) { 628*34ea023dSSven Schnelle s->csr[5] |= CSR5_TI; 629*34ea023dSSven Schnelle tulip_update_int(s); 630*34ea023dSSven Schnelle } 631*34ea023dSSven Schnelle } 632*34ea023dSSven Schnelle 633*34ea023dSSven Schnelle static void tulip_next_tx_descriptor(TULIPState *s, 634*34ea023dSSven Schnelle struct tulip_descriptor *desc) 635*34ea023dSSven Schnelle { 636*34ea023dSSven Schnelle if (desc->control & TDES1_TER) { 637*34ea023dSSven Schnelle s->current_tx_desc = s->csr[4]; 638*34ea023dSSven Schnelle } else if (desc->control & TDES1_TCH) { 639*34ea023dSSven Schnelle s->current_tx_desc = desc->buf_addr2; 640*34ea023dSSven Schnelle } else { 641*34ea023dSSven Schnelle s->current_tx_desc += sizeof(struct tulip_descriptor) + 642*34ea023dSSven Schnelle (((s->csr[0] >> CSR0_DSL_SHIFT) & CSR0_DSL_MASK) << 2); 643*34ea023dSSven Schnelle } 644*34ea023dSSven Schnelle s->current_tx_desc &= ~3ULL; 645*34ea023dSSven Schnelle } 646*34ea023dSSven Schnelle 647*34ea023dSSven Schnelle static uint32_t tulip_ts(TULIPState *s) 648*34ea023dSSven Schnelle { 649*34ea023dSSven Schnelle return (s->csr[5] >> CSR5_TS_SHIFT) & CSR5_TS_MASK; 650*34ea023dSSven Schnelle } 651*34ea023dSSven Schnelle 652*34ea023dSSven Schnelle static void tulip_xmit_list_update(TULIPState *s) 653*34ea023dSSven Schnelle { 654*34ea023dSSven Schnelle struct tulip_descriptor desc; 655*34ea023dSSven Schnelle 656*34ea023dSSven Schnelle if (tulip_ts(s) != CSR5_TS_SUSPENDED) { 657*34ea023dSSven Schnelle return; 658*34ea023dSSven Schnelle } 659*34ea023dSSven Schnelle 660*34ea023dSSven Schnelle for (;;) { 661*34ea023dSSven Schnelle tulip_desc_read(s, s->current_tx_desc, &desc); 662*34ea023dSSven Schnelle tulip_dump_tx_descriptor(s, &desc); 663*34ea023dSSven Schnelle 664*34ea023dSSven Schnelle if (!(desc.status & TDES0_OWN)) { 665*34ea023dSSven Schnelle tulip_update_ts(s, CSR5_TS_SUSPENDED); 666*34ea023dSSven Schnelle s->csr[5] |= CSR5_TU; 667*34ea023dSSven Schnelle tulip_update_int(s); 668*34ea023dSSven Schnelle return; 669*34ea023dSSven Schnelle } 670*34ea023dSSven Schnelle 671*34ea023dSSven Schnelle if (desc.control & TDES1_SET) { 672*34ea023dSSven Schnelle tulip_setup_frame(s, &desc); 673*34ea023dSSven Schnelle } else { 674*34ea023dSSven Schnelle if (desc.control & TDES1_FS) { 675*34ea023dSSven Schnelle s->tx_frame_len = 0; 676*34ea023dSSven Schnelle } 677*34ea023dSSven Schnelle 678*34ea023dSSven Schnelle tulip_copy_tx_buffers(s, &desc); 679*34ea023dSSven Schnelle 680*34ea023dSSven Schnelle if (desc.control & TDES1_LS) { 681*34ea023dSSven Schnelle tulip_tx(s, &desc); 682*34ea023dSSven Schnelle } 683*34ea023dSSven Schnelle } 684*34ea023dSSven Schnelle tulip_desc_write(s, s->current_tx_desc, &desc); 685*34ea023dSSven Schnelle tulip_next_tx_descriptor(s, &desc); 686*34ea023dSSven Schnelle } 687*34ea023dSSven Schnelle } 688*34ea023dSSven Schnelle 689*34ea023dSSven Schnelle static void tulip_csr9_write(TULIPState *s, uint32_t old_val, 690*34ea023dSSven Schnelle uint32_t new_val) 691*34ea023dSSven Schnelle { 692*34ea023dSSven Schnelle if (new_val & CSR9_SR) { 693*34ea023dSSven Schnelle eeprom93xx_write(s->eeprom, 694*34ea023dSSven Schnelle !!(new_val & CSR9_SR_CS), 695*34ea023dSSven Schnelle !!(new_val & CSR9_SR_SK), 696*34ea023dSSven Schnelle !!(new_val & CSR9_SR_DI)); 697*34ea023dSSven Schnelle } 698*34ea023dSSven Schnelle } 699*34ea023dSSven Schnelle 700*34ea023dSSven Schnelle static void tulip_reset(TULIPState *s) 701*34ea023dSSven Schnelle { 702*34ea023dSSven Schnelle trace_tulip_reset(); 703*34ea023dSSven Schnelle 704*34ea023dSSven Schnelle s->csr[0] = 0xfe000000; 705*34ea023dSSven Schnelle s->csr[1] = 0xffffffff; 706*34ea023dSSven Schnelle s->csr[2] = 0xffffffff; 707*34ea023dSSven Schnelle s->csr[5] = 0xf0000000; 708*34ea023dSSven Schnelle s->csr[6] = 0x32000040; 709*34ea023dSSven Schnelle s->csr[7] = 0xf3fe0000; 710*34ea023dSSven Schnelle s->csr[8] = 0xe0000000; 711*34ea023dSSven Schnelle s->csr[9] = 0xfff483ff; 712*34ea023dSSven Schnelle s->csr[11] = 0xfffe0000; 713*34ea023dSSven Schnelle s->csr[12] = 0x000000c6; 714*34ea023dSSven Schnelle s->csr[13] = 0xffff0000; 715*34ea023dSSven Schnelle s->csr[14] = 0xffffffff; 716*34ea023dSSven Schnelle s->csr[15] = 0x8ff00000; 717*34ea023dSSven Schnelle } 718*34ea023dSSven Schnelle 719*34ea023dSSven Schnelle static void tulip_qdev_reset(DeviceState *dev) 720*34ea023dSSven Schnelle { 721*34ea023dSSven Schnelle PCIDevice *d = PCI_DEVICE(dev); 722*34ea023dSSven Schnelle TULIPState *s = TULIP(d); 723*34ea023dSSven Schnelle 724*34ea023dSSven Schnelle tulip_reset(s); 725*34ea023dSSven Schnelle } 726*34ea023dSSven Schnelle 727*34ea023dSSven Schnelle static void tulip_write(void *opaque, hwaddr addr, 728*34ea023dSSven Schnelle uint64_t data, unsigned size) 729*34ea023dSSven Schnelle { 730*34ea023dSSven Schnelle TULIPState *s = opaque; 731*34ea023dSSven Schnelle trace_tulip_reg_write(addr, tulip_reg_name(addr), size, data); 732*34ea023dSSven Schnelle 733*34ea023dSSven Schnelle switch (addr) { 734*34ea023dSSven Schnelle case CSR(0): 735*34ea023dSSven Schnelle s->csr[0] = data; 736*34ea023dSSven Schnelle if (data & CSR0_SWR) { 737*34ea023dSSven Schnelle tulip_reset(s); 738*34ea023dSSven Schnelle tulip_update_int(s); 739*34ea023dSSven Schnelle } 740*34ea023dSSven Schnelle break; 741*34ea023dSSven Schnelle 742*34ea023dSSven Schnelle case CSR(1): 743*34ea023dSSven Schnelle tulip_xmit_list_update(s); 744*34ea023dSSven Schnelle break; 745*34ea023dSSven Schnelle 746*34ea023dSSven Schnelle case CSR(2): 747*34ea023dSSven Schnelle qemu_flush_queued_packets(qemu_get_queue(s->nic)); 748*34ea023dSSven Schnelle break; 749*34ea023dSSven Schnelle 750*34ea023dSSven Schnelle case CSR(3): 751*34ea023dSSven Schnelle s->csr[3] = data & ~3ULL; 752*34ea023dSSven Schnelle s->current_rx_desc = s->csr[3]; 753*34ea023dSSven Schnelle qemu_flush_queued_packets(qemu_get_queue(s->nic)); 754*34ea023dSSven Schnelle break; 755*34ea023dSSven Schnelle 756*34ea023dSSven Schnelle case CSR(4): 757*34ea023dSSven Schnelle s->csr[4] = data & ~3ULL; 758*34ea023dSSven Schnelle s->current_tx_desc = s->csr[4]; 759*34ea023dSSven Schnelle tulip_xmit_list_update(s); 760*34ea023dSSven Schnelle break; 761*34ea023dSSven Schnelle 762*34ea023dSSven Schnelle case CSR(5): 763*34ea023dSSven Schnelle /* Status register, write clears bit */ 764*34ea023dSSven Schnelle s->csr[5] &= ~(data & (CSR5_TI | CSR5_TPS | CSR5_TU | CSR5_TJT | 765*34ea023dSSven Schnelle CSR5_LNP_ANC | CSR5_UNF | CSR5_RI | CSR5_RU | 766*34ea023dSSven Schnelle CSR5_RPS | CSR5_RWT | CSR5_ETI | CSR5_GTE | 767*34ea023dSSven Schnelle CSR5_LNF | CSR5_FBE | CSR5_ERI | CSR5_AIS | 768*34ea023dSSven Schnelle CSR5_NIS | CSR5_GPI | CSR5_LC)); 769*34ea023dSSven Schnelle tulip_update_int(s); 770*34ea023dSSven Schnelle break; 771*34ea023dSSven Schnelle 772*34ea023dSSven Schnelle case CSR(6): 773*34ea023dSSven Schnelle s->csr[6] = data; 774*34ea023dSSven Schnelle if (s->csr[6] & CSR6_SR) { 775*34ea023dSSven Schnelle tulip_update_rs(s, CSR5_RS_RUNNING_WAIT_RECEIVE); 776*34ea023dSSven Schnelle qemu_flush_queued_packets(qemu_get_queue(s->nic)); 777*34ea023dSSven Schnelle } else { 778*34ea023dSSven Schnelle tulip_update_rs(s, CSR5_RS_STOPPED); 779*34ea023dSSven Schnelle } 780*34ea023dSSven Schnelle 781*34ea023dSSven Schnelle if (s->csr[6] & CSR6_ST) { 782*34ea023dSSven Schnelle tulip_update_ts(s, CSR5_TS_SUSPENDED); 783*34ea023dSSven Schnelle tulip_xmit_list_update(s); 784*34ea023dSSven Schnelle } else { 785*34ea023dSSven Schnelle tulip_update_ts(s, CSR5_TS_STOPPED); 786*34ea023dSSven Schnelle } 787*34ea023dSSven Schnelle break; 788*34ea023dSSven Schnelle 789*34ea023dSSven Schnelle case CSR(7): 790*34ea023dSSven Schnelle s->csr[7] = data; 791*34ea023dSSven Schnelle tulip_update_int(s); 792*34ea023dSSven Schnelle break; 793*34ea023dSSven Schnelle 794*34ea023dSSven Schnelle case CSR(8): 795*34ea023dSSven Schnelle s->csr[9] = data; 796*34ea023dSSven Schnelle break; 797*34ea023dSSven Schnelle 798*34ea023dSSven Schnelle case CSR(9): 799*34ea023dSSven Schnelle tulip_csr9_write(s, s->csr[9], data); 800*34ea023dSSven Schnelle /* don't clear MII read data */ 801*34ea023dSSven Schnelle s->csr[9] &= CSR9_MDI; 802*34ea023dSSven Schnelle s->csr[9] |= (data & ~CSR9_MDI); 803*34ea023dSSven Schnelle tulip_mii(s); 804*34ea023dSSven Schnelle s->old_csr9 = s->csr[9]; 805*34ea023dSSven Schnelle break; 806*34ea023dSSven Schnelle 807*34ea023dSSven Schnelle case CSR(10): 808*34ea023dSSven Schnelle s->csr[10] = data; 809*34ea023dSSven Schnelle break; 810*34ea023dSSven Schnelle 811*34ea023dSSven Schnelle case CSR(11): 812*34ea023dSSven Schnelle s->csr[11] = data; 813*34ea023dSSven Schnelle break; 814*34ea023dSSven Schnelle 815*34ea023dSSven Schnelle case CSR(12): 816*34ea023dSSven Schnelle /* SIA Status register, some bits are cleared by writing 1 */ 817*34ea023dSSven Schnelle s->csr[12] &= ~(data & (CSR12_MRA | CSR12_TRA | CSR12_ARA)); 818*34ea023dSSven Schnelle break; 819*34ea023dSSven Schnelle 820*34ea023dSSven Schnelle case CSR(13): 821*34ea023dSSven Schnelle s->csr[13] = data; 822*34ea023dSSven Schnelle break; 823*34ea023dSSven Schnelle 824*34ea023dSSven Schnelle case CSR(14): 825*34ea023dSSven Schnelle s->csr[14] = data; 826*34ea023dSSven Schnelle break; 827*34ea023dSSven Schnelle 828*34ea023dSSven Schnelle case CSR(15): 829*34ea023dSSven Schnelle s->csr[15] = data; 830*34ea023dSSven Schnelle break; 831*34ea023dSSven Schnelle 832*34ea023dSSven Schnelle default: 833*34ea023dSSven Schnelle qemu_log_mask(LOG_GUEST_ERROR, "%s: write to CSR at unknown address " 834*34ea023dSSven Schnelle "0x%"PRIx64"\n", __func__, addr); 835*34ea023dSSven Schnelle break; 836*34ea023dSSven Schnelle } 837*34ea023dSSven Schnelle } 838*34ea023dSSven Schnelle 839*34ea023dSSven Schnelle static const MemoryRegionOps tulip_ops = { 840*34ea023dSSven Schnelle .read = tulip_read, 841*34ea023dSSven Schnelle .write = tulip_write, 842*34ea023dSSven Schnelle .endianness = DEVICE_LITTLE_ENDIAN, 843*34ea023dSSven Schnelle .impl = { 844*34ea023dSSven Schnelle .min_access_size = 4, 845*34ea023dSSven Schnelle .max_access_size = 4, 846*34ea023dSSven Schnelle }, 847*34ea023dSSven Schnelle }; 848*34ea023dSSven Schnelle 849*34ea023dSSven Schnelle static void tulip_idblock_crc(TULIPState *s, uint16_t *srom) 850*34ea023dSSven Schnelle { 851*34ea023dSSven Schnelle int word, n; 852*34ea023dSSven Schnelle int bit; 853*34ea023dSSven Schnelle unsigned char bitval, crc; 854*34ea023dSSven Schnelle const int len = 9; 855*34ea023dSSven Schnelle n = 0; 856*34ea023dSSven Schnelle crc = -1; 857*34ea023dSSven Schnelle 858*34ea023dSSven Schnelle for (word = 0; word < len; word++) { 859*34ea023dSSven Schnelle for (bit = 15; bit >= 0; bit--) { 860*34ea023dSSven Schnelle if ((word == (len - 1)) && (bit == 7)) { 861*34ea023dSSven Schnelle /* 862*34ea023dSSven Schnelle * Insert the correct CRC result into input data stream 863*34ea023dSSven Schnelle * in place. 864*34ea023dSSven Schnelle */ 865*34ea023dSSven Schnelle srom[len - 1] = (srom[len - 1] & 0xff00) | (unsigned short)crc; 866*34ea023dSSven Schnelle break; 867*34ea023dSSven Schnelle } 868*34ea023dSSven Schnelle n++; 869*34ea023dSSven Schnelle bitval = ((srom[word] >> bit) & 1) ^ ((crc >> 7) & 1); 870*34ea023dSSven Schnelle crc = crc << 1; 871*34ea023dSSven Schnelle if (bitval == 1) { 872*34ea023dSSven Schnelle crc ^= 6; 873*34ea023dSSven Schnelle crc |= 0x01; 874*34ea023dSSven Schnelle } 875*34ea023dSSven Schnelle } 876*34ea023dSSven Schnelle } 877*34ea023dSSven Schnelle } 878*34ea023dSSven Schnelle 879*34ea023dSSven Schnelle static uint16_t tulip_srom_crc(TULIPState *s, uint8_t *eeprom, size_t len) 880*34ea023dSSven Schnelle { 881*34ea023dSSven Schnelle unsigned long crc = 0xffffffff; 882*34ea023dSSven Schnelle unsigned long flippedcrc = 0; 883*34ea023dSSven Schnelle unsigned char currentbyte; 884*34ea023dSSven Schnelle unsigned int msb, bit, i; 885*34ea023dSSven Schnelle 886*34ea023dSSven Schnelle for (i = 0; i < len; i++) { 887*34ea023dSSven Schnelle currentbyte = eeprom[i]; 888*34ea023dSSven Schnelle for (bit = 0; bit < 8; bit++) { 889*34ea023dSSven Schnelle msb = (crc >> 31) & 1; 890*34ea023dSSven Schnelle crc <<= 1; 891*34ea023dSSven Schnelle if (msb ^ (currentbyte & 1)) { 892*34ea023dSSven Schnelle crc ^= 0x04c11db6; 893*34ea023dSSven Schnelle crc |= 0x00000001; 894*34ea023dSSven Schnelle } 895*34ea023dSSven Schnelle currentbyte >>= 1; 896*34ea023dSSven Schnelle } 897*34ea023dSSven Schnelle } 898*34ea023dSSven Schnelle 899*34ea023dSSven Schnelle for (i = 0; i < 32; i++) { 900*34ea023dSSven Schnelle flippedcrc <<= 1; 901*34ea023dSSven Schnelle bit = crc & 1; 902*34ea023dSSven Schnelle crc >>= 1; 903*34ea023dSSven Schnelle flippedcrc += bit; 904*34ea023dSSven Schnelle } 905*34ea023dSSven Schnelle return (flippedcrc ^ 0xffffffff) & 0xffff; 906*34ea023dSSven Schnelle } 907*34ea023dSSven Schnelle 908*34ea023dSSven Schnelle static const uint8_t eeprom_default[128] = { 909*34ea023dSSven Schnelle 0x3c, 0x10, 0x4f, 0x10, 0x00, 0x00, 0x00, 0x00, 910*34ea023dSSven Schnelle 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 911*34ea023dSSven Schnelle 0x56, 0x08, 0x04, 0x01, 0x00, 0x80, 0x48, 0xb3, 912*34ea023dSSven Schnelle 0x0e, 0xa7, 0x00, 0x1e, 0x00, 0x00, 0x00, 0x08, 913*34ea023dSSven Schnelle 0x01, 0x8d, 0x03, 0x00, 0x00, 0x00, 0x00, 0x78, 914*34ea023dSSven Schnelle 0xe0, 0x01, 0x00, 0x50, 0x00, 0x18, 0x00, 0x00, 915*34ea023dSSven Schnelle 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 916*34ea023dSSven Schnelle 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 917*34ea023dSSven Schnelle 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 918*34ea023dSSven Schnelle 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 919*34ea023dSSven Schnelle 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 920*34ea023dSSven Schnelle 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xe8, 0x6b, 921*34ea023dSSven Schnelle 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 922*34ea023dSSven Schnelle 0x48, 0xb3, 0x0e, 0xa7, 0x40, 0x00, 0x00, 0x00, 923*34ea023dSSven Schnelle 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 924*34ea023dSSven Schnelle 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 925*34ea023dSSven Schnelle }; 926*34ea023dSSven Schnelle 927*34ea023dSSven Schnelle static void tulip_fill_eeprom(TULIPState *s) 928*34ea023dSSven Schnelle { 929*34ea023dSSven Schnelle uint16_t *eeprom = eeprom93xx_data(s->eeprom); 930*34ea023dSSven Schnelle memcpy(eeprom, eeprom_default, 128); 931*34ea023dSSven Schnelle 932*34ea023dSSven Schnelle /* patch in our mac address */ 933*34ea023dSSven Schnelle eeprom[10] = cpu_to_le16(s->c.macaddr.a[0] | (s->c.macaddr.a[1] << 8)); 934*34ea023dSSven Schnelle eeprom[11] = cpu_to_le16(s->c.macaddr.a[2] | (s->c.macaddr.a[3] << 8)); 935*34ea023dSSven Schnelle eeprom[12] = cpu_to_le16(s->c.macaddr.a[4] | (s->c.macaddr.a[5] << 8)); 936*34ea023dSSven Schnelle tulip_idblock_crc(s, eeprom); 937*34ea023dSSven Schnelle eeprom[63] = cpu_to_le16(tulip_srom_crc(s, (uint8_t *)eeprom, 126)); 938*34ea023dSSven Schnelle } 939*34ea023dSSven Schnelle 940*34ea023dSSven Schnelle static void pci_tulip_realize(PCIDevice *pci_dev, Error **errp) 941*34ea023dSSven Schnelle { 942*34ea023dSSven Schnelle TULIPState *s = DO_UPCAST(TULIPState, dev, pci_dev); 943*34ea023dSSven Schnelle uint8_t *pci_conf; 944*34ea023dSSven Schnelle 945*34ea023dSSven Schnelle pci_conf = s->dev.config; 946*34ea023dSSven Schnelle pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */ 947*34ea023dSSven Schnelle 948*34ea023dSSven Schnelle s->eeprom = eeprom93xx_new(&pci_dev->qdev, 64); 949*34ea023dSSven Schnelle tulip_fill_eeprom(s); 950*34ea023dSSven Schnelle 951*34ea023dSSven Schnelle memory_region_init_io(&s->io, OBJECT(&s->dev), &tulip_ops, s, 952*34ea023dSSven Schnelle "tulip-io", 128); 953*34ea023dSSven Schnelle 954*34ea023dSSven Schnelle memory_region_init_io(&s->memory, OBJECT(&s->dev), &tulip_ops, s, 955*34ea023dSSven Schnelle "tulip-mem", 128); 956*34ea023dSSven Schnelle 957*34ea023dSSven Schnelle pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io); 958*34ea023dSSven Schnelle pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->memory); 959*34ea023dSSven Schnelle 960*34ea023dSSven Schnelle s->irq = pci_allocate_irq(&s->dev); 961*34ea023dSSven Schnelle 962*34ea023dSSven Schnelle qemu_macaddr_default_if_unset(&s->c.macaddr); 963*34ea023dSSven Schnelle 964*34ea023dSSven Schnelle s->nic = qemu_new_nic(&net_tulip_info, &s->c, 965*34ea023dSSven Schnelle object_get_typename(OBJECT(pci_dev)), 966*34ea023dSSven Schnelle pci_dev->qdev.id, s); 967*34ea023dSSven Schnelle qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a); 968*34ea023dSSven Schnelle } 969*34ea023dSSven Schnelle 970*34ea023dSSven Schnelle static void pci_tulip_exit(PCIDevice *pci_dev) 971*34ea023dSSven Schnelle { 972*34ea023dSSven Schnelle TULIPState *s = DO_UPCAST(TULIPState, dev, pci_dev); 973*34ea023dSSven Schnelle 974*34ea023dSSven Schnelle qemu_del_nic(s->nic); 975*34ea023dSSven Schnelle qemu_free_irq(s->irq); 976*34ea023dSSven Schnelle eeprom93xx_free(&pci_dev->qdev, s->eeprom); 977*34ea023dSSven Schnelle } 978*34ea023dSSven Schnelle 979*34ea023dSSven Schnelle static void tulip_instance_init(Object *obj) 980*34ea023dSSven Schnelle { 981*34ea023dSSven Schnelle PCIDevice *pci_dev = PCI_DEVICE(obj); 982*34ea023dSSven Schnelle TULIPState *d = DO_UPCAST(TULIPState, dev, pci_dev); 983*34ea023dSSven Schnelle 984*34ea023dSSven Schnelle device_add_bootindex_property(obj, &d->c.bootindex, 985*34ea023dSSven Schnelle "bootindex", "/ethernet-phy@0", 986*34ea023dSSven Schnelle &pci_dev->qdev, NULL); 987*34ea023dSSven Schnelle } 988*34ea023dSSven Schnelle 989*34ea023dSSven Schnelle static Property tulip_properties[] = { 990*34ea023dSSven Schnelle DEFINE_NIC_PROPERTIES(TULIPState, c), 991*34ea023dSSven Schnelle DEFINE_PROP_END_OF_LIST(), 992*34ea023dSSven Schnelle }; 993*34ea023dSSven Schnelle 994*34ea023dSSven Schnelle static void tulip_class_init(ObjectClass *klass, void *data) 995*34ea023dSSven Schnelle { 996*34ea023dSSven Schnelle DeviceClass *dc = DEVICE_CLASS(klass); 997*34ea023dSSven Schnelle PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 998*34ea023dSSven Schnelle 999*34ea023dSSven Schnelle k->realize = pci_tulip_realize; 1000*34ea023dSSven Schnelle k->exit = pci_tulip_exit; 1001*34ea023dSSven Schnelle k->vendor_id = PCI_VENDOR_ID_DEC; 1002*34ea023dSSven Schnelle k->device_id = PCI_DEVICE_ID_DEC_21143; 1003*34ea023dSSven Schnelle k->subsystem_vendor_id = 0x103c; 1004*34ea023dSSven Schnelle k->subsystem_id = 0x104f; 1005*34ea023dSSven Schnelle k->class_id = PCI_CLASS_NETWORK_ETHERNET; 1006*34ea023dSSven Schnelle dc->vmsd = &vmstate_pci_tulip; 1007*34ea023dSSven Schnelle dc->props = tulip_properties; 1008*34ea023dSSven Schnelle dc->reset = tulip_qdev_reset; 1009*34ea023dSSven Schnelle set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 1010*34ea023dSSven Schnelle } 1011*34ea023dSSven Schnelle 1012*34ea023dSSven Schnelle static const TypeInfo tulip_info = { 1013*34ea023dSSven Schnelle .name = TYPE_TULIP, 1014*34ea023dSSven Schnelle .parent = TYPE_PCI_DEVICE, 1015*34ea023dSSven Schnelle .instance_size = sizeof(TULIPState), 1016*34ea023dSSven Schnelle .class_init = tulip_class_init, 1017*34ea023dSSven Schnelle .instance_init = tulip_instance_init, 1018*34ea023dSSven Schnelle .interfaces = (InterfaceInfo[]) { 1019*34ea023dSSven Schnelle { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 1020*34ea023dSSven Schnelle { }, 1021*34ea023dSSven Schnelle }, 1022*34ea023dSSven Schnelle }; 1023*34ea023dSSven Schnelle 1024*34ea023dSSven Schnelle static void tulip_register_types(void) 1025*34ea023dSSven Schnelle { 1026*34ea023dSSven Schnelle type_register_static(&tulip_info); 1027*34ea023dSSven Schnelle } 1028*34ea023dSSven Schnelle 1029*34ea023dSSven Schnelle type_init(tulip_register_types) 1030