1 /* 2 * QEMU model of SUN GEM ethernet controller 3 * 4 * As found in Apple ASICs among others 5 * 6 * Copyright 2016 Ben Herrenschmidt 7 * Copyright 2017 Mark Cave-Ayland 8 */ 9 10 #include "qemu/osdep.h" 11 #include "hw/pci/pci.h" 12 #include "migration/vmstate.h" 13 #include "qemu/log.h" 14 #include "qemu/module.h" 15 #include "net/net.h" 16 #include "net/eth.h" 17 #include "net/checksum.h" 18 #include "hw/net/mii.h" 19 #include "sysemu/sysemu.h" 20 #include "trace.h" 21 22 #define TYPE_SUNGEM "sungem" 23 24 #define SUNGEM(obj) OBJECT_CHECK(SunGEMState, (obj), TYPE_SUNGEM) 25 26 #define MAX_PACKET_SIZE 9016 27 28 #define SUNGEM_MMIO_SIZE 0x200000 29 30 /* Global registers */ 31 #define SUNGEM_MMIO_GREG_SIZE 0x2000 32 33 #define GREG_SEBSTATE 0x0000UL /* SEB State Register */ 34 35 #define GREG_STAT 0x000CUL /* Status Register */ 36 #define GREG_STAT_TXINTME 0x00000001 /* TX INTME frame transferred */ 37 #define GREG_STAT_TXALL 0x00000002 /* All TX frames transferred */ 38 #define GREG_STAT_TXDONE 0x00000004 /* One TX frame transferred */ 39 #define GREG_STAT_RXDONE 0x00000010 /* One RX frame arrived */ 40 #define GREG_STAT_RXNOBUF 0x00000020 /* No free RX buffers available */ 41 #define GREG_STAT_RXTAGERR 0x00000040 /* RX tag framing is corrupt */ 42 #define GREG_STAT_TXMAC 0x00004000 /* TX MAC signalled interrupt */ 43 #define GREG_STAT_RXMAC 0x00008000 /* RX MAC signalled interrupt */ 44 #define GREG_STAT_MAC 0x00010000 /* MAC Control signalled irq */ 45 #define GREG_STAT_TXNR 0xfff80000 /* == TXDMA_TXDONE reg val */ 46 #define GREG_STAT_TXNR_SHIFT 19 47 48 /* These interrupts are edge latches in the status register, 49 * reading it (or writing the corresponding bit in IACK) will 50 * clear them 51 */ 52 #define GREG_STAT_LATCH (GREG_STAT_TXALL | GREG_STAT_TXINTME | \ 53 GREG_STAT_RXDONE | GREG_STAT_RXDONE | \ 54 GREG_STAT_RXNOBUF | GREG_STAT_RXTAGERR) 55 56 #define GREG_IMASK 0x0010UL /* Interrupt Mask Register */ 57 #define GREG_IACK 0x0014UL /* Interrupt ACK Register */ 58 #define GREG_STAT2 0x001CUL /* Alias of GREG_STAT */ 59 #define GREG_PCIESTAT 0x1000UL /* PCI Error Status Register */ 60 #define GREG_PCIEMASK 0x1004UL /* PCI Error Mask Register */ 61 62 #define GREG_SWRST 0x1010UL /* Software Reset Register */ 63 #define GREG_SWRST_TXRST 0x00000001 /* TX Software Reset */ 64 #define GREG_SWRST_RXRST 0x00000002 /* RX Software Reset */ 65 #define GREG_SWRST_RSTOUT 0x00000004 /* Force RST# pin active */ 66 67 /* TX DMA Registers */ 68 #define SUNGEM_MMIO_TXDMA_SIZE 0x1000 69 70 #define TXDMA_KICK 0x0000UL /* TX Kick Register */ 71 72 #define TXDMA_CFG 0x0004UL /* TX Configuration Register */ 73 #define TXDMA_CFG_ENABLE 0x00000001 /* Enable TX DMA channel */ 74 #define TXDMA_CFG_RINGSZ 0x0000001e /* TX descriptor ring size */ 75 76 #define TXDMA_DBLOW 0x0008UL /* TX Desc. Base Low */ 77 #define TXDMA_DBHI 0x000CUL /* TX Desc. Base High */ 78 #define TXDMA_PCNT 0x0024UL /* TX FIFO Packet Counter */ 79 #define TXDMA_SMACHINE 0x0028UL /* TX State Machine Register */ 80 #define TXDMA_DPLOW 0x0030UL /* TX Data Pointer Low */ 81 #define TXDMA_DPHI 0x0034UL /* TX Data Pointer High */ 82 #define TXDMA_TXDONE 0x0100UL /* TX Completion Register */ 83 #define TXDMA_FTAG 0x0108UL /* TX FIFO Tag */ 84 #define TXDMA_FSZ 0x0118UL /* TX FIFO Size */ 85 86 /* Receive DMA Registers */ 87 #define SUNGEM_MMIO_RXDMA_SIZE 0x2000 88 89 #define RXDMA_CFG 0x0000UL /* RX Configuration Register */ 90 #define RXDMA_CFG_ENABLE 0x00000001 /* Enable RX DMA channel */ 91 #define RXDMA_CFG_RINGSZ 0x0000001e /* RX descriptor ring size */ 92 #define RXDMA_CFG_FBOFF 0x00001c00 /* Offset of first data byte */ 93 #define RXDMA_CFG_CSUMOFF 0x000fe000 /* Skip bytes before csum calc */ 94 95 #define RXDMA_DBLOW 0x0004UL /* RX Descriptor Base Low */ 96 #define RXDMA_DBHI 0x0008UL /* RX Descriptor Base High */ 97 #define RXDMA_PCNT 0x0018UL /* RX FIFO Packet Counter */ 98 #define RXDMA_SMACHINE 0x001CUL /* RX State Machine Register */ 99 #define RXDMA_PTHRESH 0x0020UL /* Pause Thresholds */ 100 #define RXDMA_DPLOW 0x0024UL /* RX Data Pointer Low */ 101 #define RXDMA_DPHI 0x0028UL /* RX Data Pointer High */ 102 #define RXDMA_KICK 0x0100UL /* RX Kick Register */ 103 #define RXDMA_DONE 0x0104UL /* RX Completion Register */ 104 #define RXDMA_BLANK 0x0108UL /* RX Blanking Register */ 105 #define RXDMA_FTAG 0x0110UL /* RX FIFO Tag */ 106 #define RXDMA_FSZ 0x0120UL /* RX FIFO Size */ 107 108 /* MAC Registers */ 109 #define SUNGEM_MMIO_MAC_SIZE 0x200 110 111 #define MAC_TXRST 0x0000UL /* TX MAC Software Reset Command */ 112 #define MAC_RXRST 0x0004UL /* RX MAC Software Reset Command */ 113 #define MAC_TXSTAT 0x0010UL /* TX MAC Status Register */ 114 #define MAC_RXSTAT 0x0014UL /* RX MAC Status Register */ 115 116 #define MAC_CSTAT 0x0018UL /* MAC Control Status Register */ 117 #define MAC_CSTAT_PTR 0xffff0000 /* Pause Time Received */ 118 119 #define MAC_TXMASK 0x0020UL /* TX MAC Mask Register */ 120 #define MAC_RXMASK 0x0024UL /* RX MAC Mask Register */ 121 #define MAC_MCMASK 0x0028UL /* MAC Control Mask Register */ 122 123 #define MAC_TXCFG 0x0030UL /* TX MAC Configuration Register */ 124 #define MAC_TXCFG_ENAB 0x00000001 /* TX MAC Enable */ 125 126 #define MAC_RXCFG 0x0034UL /* RX MAC Configuration Register */ 127 #define MAC_RXCFG_ENAB 0x00000001 /* RX MAC Enable */ 128 #define MAC_RXCFG_SFCS 0x00000004 /* Strip FCS */ 129 #define MAC_RXCFG_PROM 0x00000008 /* Promiscuous Mode */ 130 #define MAC_RXCFG_PGRP 0x00000010 /* Promiscuous Group */ 131 #define MAC_RXCFG_HFE 0x00000020 /* Hash Filter Enable */ 132 133 #define MAC_XIFCFG 0x003CUL /* XIF Configuration Register */ 134 #define MAC_XIFCFG_LBCK 0x00000002 /* Loopback TX to RX */ 135 136 #define MAC_MINFSZ 0x0050UL /* MinFrameSize Register */ 137 #define MAC_MAXFSZ 0x0054UL /* MaxFrameSize Register */ 138 #define MAC_ADDR0 0x0080UL /* MAC Address 0 Register */ 139 #define MAC_ADDR1 0x0084UL /* MAC Address 1 Register */ 140 #define MAC_ADDR2 0x0088UL /* MAC Address 2 Register */ 141 #define MAC_ADDR3 0x008CUL /* MAC Address 3 Register */ 142 #define MAC_ADDR4 0x0090UL /* MAC Address 4 Register */ 143 #define MAC_ADDR5 0x0094UL /* MAC Address 5 Register */ 144 #define MAC_HASH0 0x00C0UL /* Hash Table 0 Register */ 145 #define MAC_PATMPS 0x0114UL /* Peak Attempts Register */ 146 #define MAC_SMACHINE 0x0134UL /* State Machine Register */ 147 148 /* MIF Registers */ 149 #define SUNGEM_MMIO_MIF_SIZE 0x20 150 151 #define MIF_FRAME 0x000CUL /* MIF Frame/Output Register */ 152 #define MIF_FRAME_OP 0x30000000 /* OPcode */ 153 #define MIF_FRAME_PHYAD 0x0f800000 /* PHY ADdress */ 154 #define MIF_FRAME_REGAD 0x007c0000 /* REGister ADdress */ 155 #define MIF_FRAME_TALSB 0x00010000 /* Turn Around LSB */ 156 #define MIF_FRAME_DATA 0x0000ffff /* Instruction Payload */ 157 158 #define MIF_CFG 0x0010UL /* MIF Configuration Register */ 159 #define MIF_CFG_MDI0 0x00000100 /* MDIO_0 present or read-bit */ 160 #define MIF_CFG_MDI1 0x00000200 /* MDIO_1 present or read-bit */ 161 162 #define MIF_STATUS 0x0018UL /* MIF Status Register */ 163 #define MIF_SMACHINE 0x001CUL /* MIF State Machine Register */ 164 165 /* PCS/Serialink Registers */ 166 #define SUNGEM_MMIO_PCS_SIZE 0x60 167 #define PCS_MIISTAT 0x0004UL /* PCS MII Status Register */ 168 #define PCS_ISTAT 0x0018UL /* PCS Interrupt Status Reg */ 169 #define PCS_SSTATE 0x005CUL /* Serialink State Register */ 170 171 /* Descriptors */ 172 struct gem_txd { 173 uint64_t control_word; 174 uint64_t buffer; 175 }; 176 177 #define TXDCTRL_BUFSZ 0x0000000000007fffULL /* Buffer Size */ 178 #define TXDCTRL_CSTART 0x00000000001f8000ULL /* CSUM Start Offset */ 179 #define TXDCTRL_COFF 0x000000001fe00000ULL /* CSUM Stuff Offset */ 180 #define TXDCTRL_CENAB 0x0000000020000000ULL /* CSUM Enable */ 181 #define TXDCTRL_EOF 0x0000000040000000ULL /* End of Frame */ 182 #define TXDCTRL_SOF 0x0000000080000000ULL /* Start of Frame */ 183 #define TXDCTRL_INTME 0x0000000100000000ULL /* "Interrupt Me" */ 184 185 struct gem_rxd { 186 uint64_t status_word; 187 uint64_t buffer; 188 }; 189 190 #define RXDCTRL_HPASS 0x1000000000000000ULL /* Passed Hash Filter */ 191 #define RXDCTRL_ALTMAC 0x2000000000000000ULL /* Matched ALT MAC */ 192 193 194 typedef struct { 195 PCIDevice pdev; 196 197 MemoryRegion sungem; 198 MemoryRegion greg; 199 MemoryRegion txdma; 200 MemoryRegion rxdma; 201 MemoryRegion mac; 202 MemoryRegion mif; 203 MemoryRegion pcs; 204 NICState *nic; 205 NICConf conf; 206 uint32_t phy_addr; 207 208 uint32_t gregs[SUNGEM_MMIO_GREG_SIZE >> 2]; 209 uint32_t txdmaregs[SUNGEM_MMIO_TXDMA_SIZE >> 2]; 210 uint32_t rxdmaregs[SUNGEM_MMIO_RXDMA_SIZE >> 2]; 211 uint32_t macregs[SUNGEM_MMIO_MAC_SIZE >> 2]; 212 uint32_t mifregs[SUNGEM_MMIO_MIF_SIZE >> 2]; 213 uint32_t pcsregs[SUNGEM_MMIO_PCS_SIZE >> 2]; 214 215 /* Cache some useful things */ 216 uint32_t rx_mask; 217 uint32_t tx_mask; 218 219 /* Current tx packet */ 220 uint8_t tx_data[MAX_PACKET_SIZE]; 221 uint32_t tx_size; 222 uint64_t tx_first_ctl; 223 } SunGEMState; 224 225 226 static void sungem_eval_irq(SunGEMState *s) 227 { 228 uint32_t stat, mask; 229 230 mask = s->gregs[GREG_IMASK >> 2]; 231 stat = s->gregs[GREG_STAT >> 2] & ~GREG_STAT_TXNR; 232 if (stat & ~mask) { 233 pci_set_irq(PCI_DEVICE(s), 1); 234 } else { 235 pci_set_irq(PCI_DEVICE(s), 0); 236 } 237 } 238 239 static void sungem_update_status(SunGEMState *s, uint32_t bits, bool val) 240 { 241 uint32_t stat; 242 243 stat = s->gregs[GREG_STAT >> 2]; 244 if (val) { 245 stat |= bits; 246 } else { 247 stat &= ~bits; 248 } 249 s->gregs[GREG_STAT >> 2] = stat; 250 sungem_eval_irq(s); 251 } 252 253 static void sungem_eval_cascade_irq(SunGEMState *s) 254 { 255 uint32_t stat, mask; 256 257 mask = s->macregs[MAC_TXSTAT >> 2]; 258 stat = s->macregs[MAC_TXMASK >> 2]; 259 if (stat & ~mask) { 260 sungem_update_status(s, GREG_STAT_TXMAC, true); 261 } else { 262 sungem_update_status(s, GREG_STAT_TXMAC, false); 263 } 264 265 mask = s->macregs[MAC_RXSTAT >> 2]; 266 stat = s->macregs[MAC_RXMASK >> 2]; 267 if (stat & ~mask) { 268 sungem_update_status(s, GREG_STAT_RXMAC, true); 269 } else { 270 sungem_update_status(s, GREG_STAT_RXMAC, false); 271 } 272 273 mask = s->macregs[MAC_CSTAT >> 2]; 274 stat = s->macregs[MAC_MCMASK >> 2] & ~MAC_CSTAT_PTR; 275 if (stat & ~mask) { 276 sungem_update_status(s, GREG_STAT_MAC, true); 277 } else { 278 sungem_update_status(s, GREG_STAT_MAC, false); 279 } 280 } 281 282 static void sungem_do_tx_csum(SunGEMState *s) 283 { 284 uint16_t start, off; 285 uint32_t csum; 286 287 start = (s->tx_first_ctl & TXDCTRL_CSTART) >> 15; 288 off = (s->tx_first_ctl & TXDCTRL_COFF) >> 21; 289 290 trace_sungem_tx_checksum(start, off); 291 292 if (start > (s->tx_size - 2) || off > (s->tx_size - 2)) { 293 trace_sungem_tx_checksum_oob(); 294 return; 295 } 296 297 csum = net_raw_checksum(s->tx_data + start, s->tx_size - start); 298 stw_be_p(s->tx_data + off, csum); 299 } 300 301 static void sungem_send_packet(SunGEMState *s, const uint8_t *buf, 302 int size) 303 { 304 NetClientState *nc = qemu_get_queue(s->nic); 305 306 if (s->macregs[MAC_XIFCFG >> 2] & MAC_XIFCFG_LBCK) { 307 nc->info->receive(nc, buf, size); 308 } else { 309 qemu_send_packet(nc, buf, size); 310 } 311 } 312 313 static void sungem_process_tx_desc(SunGEMState *s, struct gem_txd *desc) 314 { 315 PCIDevice *d = PCI_DEVICE(s); 316 uint32_t len; 317 318 /* If it's a start of frame, discard anything we had in the 319 * buffer and start again. This should be an error condition 320 * if we had something ... for now we ignore it 321 */ 322 if (desc->control_word & TXDCTRL_SOF) { 323 if (s->tx_first_ctl) { 324 trace_sungem_tx_unfinished(); 325 } 326 s->tx_size = 0; 327 s->tx_first_ctl = desc->control_word; 328 } 329 330 /* Grab data size */ 331 len = desc->control_word & TXDCTRL_BUFSZ; 332 333 /* Clamp it to our max size */ 334 if ((s->tx_size + len) > MAX_PACKET_SIZE) { 335 trace_sungem_tx_overflow(); 336 len = MAX_PACKET_SIZE - s->tx_size; 337 } 338 339 /* Read the data */ 340 pci_dma_read(d, desc->buffer, &s->tx_data[s->tx_size], len); 341 s->tx_size += len; 342 343 /* If end of frame, send packet */ 344 if (desc->control_word & TXDCTRL_EOF) { 345 trace_sungem_tx_finished(s->tx_size); 346 347 /* Handle csum */ 348 if (s->tx_first_ctl & TXDCTRL_CENAB) { 349 sungem_do_tx_csum(s); 350 } 351 352 /* Send it */ 353 sungem_send_packet(s, s->tx_data, s->tx_size); 354 355 /* No more pending packet */ 356 s->tx_size = 0; 357 s->tx_first_ctl = 0; 358 } 359 } 360 361 static void sungem_tx_kick(SunGEMState *s) 362 { 363 PCIDevice *d = PCI_DEVICE(s); 364 uint32_t comp, kick; 365 uint32_t txdma_cfg, txmac_cfg, ints; 366 uint64_t dbase; 367 368 trace_sungem_tx_kick(); 369 370 /* Check that both TX MAC and TX DMA are enabled. We don't 371 * handle DMA-less direct FIFO operations (we don't emulate 372 * the FIFO at all). 373 * 374 * A write to TXDMA_KICK while DMA isn't enabled can happen 375 * when the driver is resetting the pointer. 376 */ 377 txdma_cfg = s->txdmaregs[TXDMA_CFG >> 2]; 378 txmac_cfg = s->macregs[MAC_TXCFG >> 2]; 379 if (!(txdma_cfg & TXDMA_CFG_ENABLE) || 380 !(txmac_cfg & MAC_TXCFG_ENAB)) { 381 trace_sungem_tx_disabled(); 382 return; 383 } 384 385 /* XXX Test min frame size register ? */ 386 /* XXX Test max frame size register ? */ 387 388 dbase = s->txdmaregs[TXDMA_DBHI >> 2]; 389 dbase = (dbase << 32) | s->txdmaregs[TXDMA_DBLOW >> 2]; 390 391 comp = s->txdmaregs[TXDMA_TXDONE >> 2] & s->tx_mask; 392 kick = s->txdmaregs[TXDMA_KICK >> 2] & s->tx_mask; 393 394 trace_sungem_tx_process(comp, kick, s->tx_mask + 1); 395 396 /* This is rather primitive for now, we just send everything we 397 * can in one go, like e1000. Ideally we should do the sending 398 * from some kind of background task 399 */ 400 while (comp != kick) { 401 struct gem_txd desc; 402 403 /* Read the next descriptor */ 404 pci_dma_read(d, dbase + comp * sizeof(desc), &desc, sizeof(desc)); 405 406 /* Byteswap descriptor */ 407 desc.control_word = le64_to_cpu(desc.control_word); 408 desc.buffer = le64_to_cpu(desc.buffer); 409 trace_sungem_tx_desc(comp, desc.control_word, desc.buffer); 410 411 /* Send it for processing */ 412 sungem_process_tx_desc(s, &desc); 413 414 /* Interrupt */ 415 ints = GREG_STAT_TXDONE; 416 if (desc.control_word & TXDCTRL_INTME) { 417 ints |= GREG_STAT_TXINTME; 418 } 419 sungem_update_status(s, ints, true); 420 421 /* Next ! */ 422 comp = (comp + 1) & s->tx_mask; 423 s->txdmaregs[TXDMA_TXDONE >> 2] = comp; 424 } 425 426 /* We sent everything, set status/irq bit */ 427 sungem_update_status(s, GREG_STAT_TXALL, true); 428 } 429 430 static bool sungem_rx_full(SunGEMState *s, uint32_t kick, uint32_t done) 431 { 432 return kick == ((done + 1) & s->rx_mask); 433 } 434 435 static int sungem_can_receive(NetClientState *nc) 436 { 437 SunGEMState *s = qemu_get_nic_opaque(nc); 438 uint32_t kick, done, rxdma_cfg, rxmac_cfg; 439 bool full; 440 441 rxmac_cfg = s->macregs[MAC_RXCFG >> 2]; 442 rxdma_cfg = s->rxdmaregs[RXDMA_CFG >> 2]; 443 444 /* If MAC disabled, can't receive */ 445 if ((rxmac_cfg & MAC_RXCFG_ENAB) == 0) { 446 trace_sungem_rx_mac_disabled(); 447 return 0; 448 } 449 if ((rxdma_cfg & RXDMA_CFG_ENABLE) == 0) { 450 trace_sungem_rx_txdma_disabled(); 451 return 0; 452 } 453 454 /* Check RX availability */ 455 kick = s->rxdmaregs[RXDMA_KICK >> 2]; 456 done = s->rxdmaregs[RXDMA_DONE >> 2]; 457 full = sungem_rx_full(s, kick, done); 458 459 trace_sungem_rx_check(!full, kick, done); 460 461 return !full; 462 } 463 464 enum { 465 rx_no_match, 466 rx_match_promisc, 467 rx_match_bcast, 468 rx_match_allmcast, 469 rx_match_mcast, 470 rx_match_mac, 471 rx_match_altmac, 472 }; 473 474 static int sungem_check_rx_mac(SunGEMState *s, const uint8_t *mac, uint32_t crc) 475 { 476 uint32_t rxcfg = s->macregs[MAC_RXCFG >> 2]; 477 uint32_t mac0, mac1, mac2; 478 479 /* Promisc enabled ? */ 480 if (rxcfg & MAC_RXCFG_PROM) { 481 return rx_match_promisc; 482 } 483 484 /* Format MAC address into dwords */ 485 mac0 = (mac[4] << 8) | mac[5]; 486 mac1 = (mac[2] << 8) | mac[3]; 487 mac2 = (mac[0] << 8) | mac[1]; 488 489 trace_sungem_rx_mac_check(mac0, mac1, mac2); 490 491 /* Is this a broadcast frame ? */ 492 if (mac0 == 0xffff && mac1 == 0xffff && mac2 == 0xffff) { 493 return rx_match_bcast; 494 } 495 496 /* TODO: Implement address filter registers (or we don't care ?) */ 497 498 /* Is this a multicast frame ? */ 499 if (mac[0] & 1) { 500 trace_sungem_rx_mac_multicast(); 501 502 /* Promisc group enabled ? */ 503 if (rxcfg & MAC_RXCFG_PGRP) { 504 return rx_match_allmcast; 505 } 506 507 /* TODO: Check MAC control frames (or we don't care) ? */ 508 509 /* Check hash filter (somebody check that's correct ?) */ 510 if (rxcfg & MAC_RXCFG_HFE) { 511 uint32_t hash, idx; 512 513 crc >>= 24; 514 idx = (crc >> 2) & 0x3c; 515 hash = s->macregs[(MAC_HASH0 + idx) >> 2]; 516 if (hash & (1 << (15 - (crc & 0xf)))) { 517 return rx_match_mcast; 518 } 519 } 520 return rx_no_match; 521 } 522 523 /* Main MAC check */ 524 trace_sungem_rx_mac_compare(s->macregs[MAC_ADDR0 >> 2], 525 s->macregs[MAC_ADDR1 >> 2], 526 s->macregs[MAC_ADDR2 >> 2]); 527 528 if (mac0 == s->macregs[MAC_ADDR0 >> 2] && 529 mac1 == s->macregs[MAC_ADDR1 >> 2] && 530 mac2 == s->macregs[MAC_ADDR2 >> 2]) { 531 return rx_match_mac; 532 } 533 534 /* Alt MAC check */ 535 if (mac0 == s->macregs[MAC_ADDR3 >> 2] && 536 mac1 == s->macregs[MAC_ADDR4 >> 2] && 537 mac2 == s->macregs[MAC_ADDR5 >> 2]) { 538 return rx_match_altmac; 539 } 540 541 return rx_no_match; 542 } 543 544 static ssize_t sungem_receive(NetClientState *nc, const uint8_t *buf, 545 size_t size) 546 { 547 SunGEMState *s = qemu_get_nic_opaque(nc); 548 PCIDevice *d = PCI_DEVICE(s); 549 uint32_t mac_crc, done, kick, max_fsize; 550 uint32_t fcs_size, ints, rxdma_cfg, rxmac_cfg, csum, coff; 551 uint8_t smallbuf[60]; 552 struct gem_rxd desc; 553 uint64_t dbase, baddr; 554 unsigned int rx_cond; 555 556 trace_sungem_rx_packet(size); 557 558 rxmac_cfg = s->macregs[MAC_RXCFG >> 2]; 559 rxdma_cfg = s->rxdmaregs[RXDMA_CFG >> 2]; 560 max_fsize = s->macregs[MAC_MAXFSZ >> 2] & 0x7fff; 561 562 /* If MAC or DMA disabled, can't receive */ 563 if (!(rxdma_cfg & RXDMA_CFG_ENABLE) || 564 !(rxmac_cfg & MAC_RXCFG_ENAB)) { 565 trace_sungem_rx_disabled(); 566 return 0; 567 } 568 569 /* Size adjustment for FCS */ 570 if (rxmac_cfg & MAC_RXCFG_SFCS) { 571 fcs_size = 0; 572 } else { 573 fcs_size = 4; 574 } 575 576 /* Discard frame smaller than a MAC or larger than max frame size 577 * (when accounting for FCS) 578 */ 579 if (size < 6 || (size + 4) > max_fsize) { 580 trace_sungem_rx_bad_frame_size(size); 581 /* XXX Increment error statistics ? */ 582 return size; 583 } 584 585 /* We don't drop too small frames since we get them in qemu, we pad 586 * them instead. We should probably use the min frame size register 587 * but I don't want to use a variable size staging buffer and I 588 * know both MacOS and Linux use the default 64 anyway. We use 60 589 * here to account for the non-existent FCS. 590 */ 591 if (size < 60) { 592 memcpy(smallbuf, buf, size); 593 memset(&smallbuf[size], 0, 60 - size); 594 buf = smallbuf; 595 size = 60; 596 } 597 598 /* Get MAC crc */ 599 mac_crc = net_crc32_le(buf, ETH_ALEN); 600 601 /* Packet isn't for me ? */ 602 rx_cond = sungem_check_rx_mac(s, buf, mac_crc); 603 if (rx_cond == rx_no_match) { 604 /* Just drop it */ 605 trace_sungem_rx_unmatched(); 606 return size; 607 } 608 609 /* Get ring pointers */ 610 kick = s->rxdmaregs[RXDMA_KICK >> 2] & s->rx_mask; 611 done = s->rxdmaregs[RXDMA_DONE >> 2] & s->rx_mask; 612 613 trace_sungem_rx_process(done, kick, s->rx_mask + 1); 614 615 /* Ring full ? Can't receive */ 616 if (sungem_rx_full(s, kick, done)) { 617 trace_sungem_rx_ringfull(); 618 return 0; 619 } 620 621 /* Note: The real GEM will fetch descriptors in blocks of 4, 622 * for now we handle them one at a time, I think the driver will 623 * cope 624 */ 625 626 dbase = s->rxdmaregs[RXDMA_DBHI >> 2]; 627 dbase = (dbase << 32) | s->rxdmaregs[RXDMA_DBLOW >> 2]; 628 629 /* Read the next descriptor */ 630 pci_dma_read(d, dbase + done * sizeof(desc), &desc, sizeof(desc)); 631 632 trace_sungem_rx_desc(le64_to_cpu(desc.status_word), 633 le64_to_cpu(desc.buffer)); 634 635 /* Effective buffer address */ 636 baddr = le64_to_cpu(desc.buffer) & ~7ull; 637 baddr |= (rxdma_cfg & RXDMA_CFG_FBOFF) >> 10; 638 639 /* Write buffer out */ 640 pci_dma_write(d, baddr, buf, size); 641 642 if (fcs_size) { 643 /* Should we add an FCS ? Linux doesn't ask us to strip it, 644 * however I believe nothing checks it... For now we just 645 * do nothing. It's faster this way. 646 */ 647 } 648 649 /* Calculate the checksum */ 650 coff = (rxdma_cfg & RXDMA_CFG_CSUMOFF) >> 13; 651 csum = net_raw_checksum((uint8_t *)buf + coff, size - coff); 652 653 /* Build the updated descriptor */ 654 desc.status_word = (size + fcs_size) << 16; 655 desc.status_word |= ((uint64_t)(mac_crc >> 16)) << 44; 656 desc.status_word |= csum; 657 if (rx_cond == rx_match_mcast) { 658 desc.status_word |= RXDCTRL_HPASS; 659 } 660 if (rx_cond == rx_match_altmac) { 661 desc.status_word |= RXDCTRL_ALTMAC; 662 } 663 desc.status_word = cpu_to_le64(desc.status_word); 664 665 pci_dma_write(d, dbase + done * sizeof(desc), &desc, sizeof(desc)); 666 667 done = (done + 1) & s->rx_mask; 668 s->rxdmaregs[RXDMA_DONE >> 2] = done; 669 670 /* XXX Unconditionally set RX interrupt for now. The interrupt 671 * mitigation timer might well end up adding more overhead than 672 * helping here... 673 */ 674 ints = GREG_STAT_RXDONE; 675 if (sungem_rx_full(s, kick, done)) { 676 ints |= GREG_STAT_RXNOBUF; 677 } 678 sungem_update_status(s, ints, true); 679 680 return size; 681 } 682 683 static void sungem_set_link_status(NetClientState *nc) 684 { 685 /* We don't do anything for now as I believe none of the OSes 686 * drivers use the MIF autopoll feature nor the PHY interrupt 687 */ 688 } 689 690 static void sungem_update_masks(SunGEMState *s) 691 { 692 uint32_t sz; 693 694 sz = 1 << (((s->rxdmaregs[RXDMA_CFG >> 2] & RXDMA_CFG_RINGSZ) >> 1) + 5); 695 s->rx_mask = sz - 1; 696 697 sz = 1 << (((s->txdmaregs[TXDMA_CFG >> 2] & TXDMA_CFG_RINGSZ) >> 1) + 5); 698 s->tx_mask = sz - 1; 699 } 700 701 static void sungem_reset_rx(SunGEMState *s) 702 { 703 trace_sungem_rx_reset(); 704 705 /* XXX Do RXCFG */ 706 /* XXX Check value */ 707 s->rxdmaregs[RXDMA_FSZ >> 2] = 0x140; 708 s->rxdmaregs[RXDMA_DONE >> 2] = 0; 709 s->rxdmaregs[RXDMA_KICK >> 2] = 0; 710 s->rxdmaregs[RXDMA_CFG >> 2] = 0x1000010; 711 s->rxdmaregs[RXDMA_PTHRESH >> 2] = 0xf8; 712 s->rxdmaregs[RXDMA_BLANK >> 2] = 0; 713 714 sungem_update_masks(s); 715 } 716 717 static void sungem_reset_tx(SunGEMState *s) 718 { 719 trace_sungem_tx_reset(); 720 721 /* XXX Do TXCFG */ 722 /* XXX Check value */ 723 s->txdmaregs[TXDMA_FSZ >> 2] = 0x90; 724 s->txdmaregs[TXDMA_TXDONE >> 2] = 0; 725 s->txdmaregs[TXDMA_KICK >> 2] = 0; 726 s->txdmaregs[TXDMA_CFG >> 2] = 0x118010; 727 728 sungem_update_masks(s); 729 730 s->tx_size = 0; 731 s->tx_first_ctl = 0; 732 } 733 734 static void sungem_reset_all(SunGEMState *s, bool pci_reset) 735 { 736 trace_sungem_reset(pci_reset); 737 738 sungem_reset_rx(s); 739 sungem_reset_tx(s); 740 741 s->gregs[GREG_IMASK >> 2] = 0xFFFFFFF; 742 s->gregs[GREG_STAT >> 2] = 0; 743 if (pci_reset) { 744 uint8_t *ma = s->conf.macaddr.a; 745 746 s->gregs[GREG_SWRST >> 2] = 0; 747 s->macregs[MAC_ADDR0 >> 2] = (ma[4] << 8) | ma[5]; 748 s->macregs[MAC_ADDR1 >> 2] = (ma[2] << 8) | ma[3]; 749 s->macregs[MAC_ADDR2 >> 2] = (ma[0] << 8) | ma[1]; 750 } else { 751 s->gregs[GREG_SWRST >> 2] &= GREG_SWRST_RSTOUT; 752 } 753 s->mifregs[MIF_CFG >> 2] = MIF_CFG_MDI0; 754 } 755 756 static void sungem_mii_write(SunGEMState *s, uint8_t phy_addr, 757 uint8_t reg_addr, uint16_t val) 758 { 759 trace_sungem_mii_write(phy_addr, reg_addr, val); 760 761 /* XXX TODO */ 762 } 763 764 static uint16_t __sungem_mii_read(SunGEMState *s, uint8_t phy_addr, 765 uint8_t reg_addr) 766 { 767 if (phy_addr != s->phy_addr) { 768 return 0xffff; 769 } 770 /* Primitive emulation of a BCM5201 to please the driver, 771 * ID is 0x00406210. TODO: Do a gigabit PHY like BCM5400 772 */ 773 switch (reg_addr) { 774 case MII_BMCR: 775 return 0; 776 case MII_PHYID1: 777 return 0x0040; 778 case MII_PHYID2: 779 return 0x6210; 780 case MII_BMSR: 781 if (qemu_get_queue(s->nic)->link_down) { 782 return MII_BMSR_100TX_FD | MII_BMSR_AUTONEG; 783 } else { 784 return MII_BMSR_100TX_FD | MII_BMSR_AN_COMP | 785 MII_BMSR_AUTONEG | MII_BMSR_LINK_ST; 786 } 787 case MII_ANLPAR: 788 case MII_ANAR: 789 return MII_ANLPAR_TXFD; 790 case 0x18: /* 5201 AUX status */ 791 return 3; /* 100FD */ 792 default: 793 return 0; 794 }; 795 } 796 static uint16_t sungem_mii_read(SunGEMState *s, uint8_t phy_addr, 797 uint8_t reg_addr) 798 { 799 uint16_t val; 800 801 val = __sungem_mii_read(s, phy_addr, reg_addr); 802 803 trace_sungem_mii_read(phy_addr, reg_addr, val); 804 805 return val; 806 } 807 808 static uint32_t sungem_mii_op(SunGEMState *s, uint32_t val) 809 { 810 uint8_t phy_addr, reg_addr, op; 811 812 /* Ignore not start of frame */ 813 if ((val >> 30) != 1) { 814 trace_sungem_mii_invalid_sof(val >> 30); 815 return 0xffff; 816 } 817 phy_addr = (val & MIF_FRAME_PHYAD) >> 23; 818 reg_addr = (val & MIF_FRAME_REGAD) >> 18; 819 op = (val & MIF_FRAME_OP) >> 28; 820 switch (op) { 821 case 1: 822 sungem_mii_write(s, phy_addr, reg_addr, val & MIF_FRAME_DATA); 823 return val | MIF_FRAME_TALSB; 824 case 2: 825 return sungem_mii_read(s, phy_addr, reg_addr) | MIF_FRAME_TALSB; 826 default: 827 trace_sungem_mii_invalid_op(op); 828 } 829 return 0xffff | MIF_FRAME_TALSB; 830 } 831 832 static void sungem_mmio_greg_write(void *opaque, hwaddr addr, uint64_t val, 833 unsigned size) 834 { 835 SunGEMState *s = opaque; 836 837 if (!(addr < 0x20) && !(addr >= 0x1000 && addr <= 0x1010)) { 838 qemu_log_mask(LOG_GUEST_ERROR, 839 "Write to unknown GREG register 0x%"HWADDR_PRIx"\n", 840 addr); 841 return; 842 } 843 844 trace_sungem_mmio_greg_write(addr, val); 845 846 /* Pre-write filter */ 847 switch (addr) { 848 /* Read only registers */ 849 case GREG_SEBSTATE: 850 case GREG_STAT: 851 case GREG_STAT2: 852 case GREG_PCIESTAT: 853 return; /* No actual write */ 854 case GREG_IACK: 855 val &= GREG_STAT_LATCH; 856 s->gregs[GREG_STAT >> 2] &= ~val; 857 sungem_eval_irq(s); 858 return; /* No actual write */ 859 case GREG_PCIEMASK: 860 val &= 0x7; 861 break; 862 } 863 864 s->gregs[addr >> 2] = val; 865 866 /* Post write action */ 867 switch (addr) { 868 case GREG_IMASK: 869 /* Re-evaluate interrupt */ 870 sungem_eval_irq(s); 871 break; 872 case GREG_SWRST: 873 switch (val & (GREG_SWRST_TXRST | GREG_SWRST_RXRST)) { 874 case GREG_SWRST_RXRST: 875 sungem_reset_rx(s); 876 break; 877 case GREG_SWRST_TXRST: 878 sungem_reset_tx(s); 879 break; 880 case GREG_SWRST_RXRST | GREG_SWRST_TXRST: 881 sungem_reset_all(s, false); 882 } 883 break; 884 } 885 } 886 887 static uint64_t sungem_mmio_greg_read(void *opaque, hwaddr addr, unsigned size) 888 { 889 SunGEMState *s = opaque; 890 uint32_t val; 891 892 if (!(addr < 0x20) && !(addr >= 0x1000 && addr <= 0x1010)) { 893 qemu_log_mask(LOG_GUEST_ERROR, 894 "Read from unknown GREG register 0x%"HWADDR_PRIx"\n", 895 addr); 896 return 0; 897 } 898 899 val = s->gregs[addr >> 2]; 900 901 trace_sungem_mmio_greg_read(addr, val); 902 903 switch (addr) { 904 case GREG_STAT: 905 /* Side effect, clear bottom 7 bits */ 906 s->gregs[GREG_STAT >> 2] &= ~GREG_STAT_LATCH; 907 sungem_eval_irq(s); 908 909 /* Inject TX completion in returned value */ 910 val = (val & ~GREG_STAT_TXNR) | 911 (s->txdmaregs[TXDMA_TXDONE >> 2] << GREG_STAT_TXNR_SHIFT); 912 break; 913 case GREG_STAT2: 914 /* Return the status reg without side effect 915 * (and inject TX completion in returned value) 916 */ 917 val = (s->gregs[GREG_STAT >> 2] & ~GREG_STAT_TXNR) | 918 (s->txdmaregs[TXDMA_TXDONE >> 2] << GREG_STAT_TXNR_SHIFT); 919 break; 920 } 921 922 return val; 923 } 924 925 static const MemoryRegionOps sungem_mmio_greg_ops = { 926 .read = sungem_mmio_greg_read, 927 .write = sungem_mmio_greg_write, 928 .endianness = DEVICE_LITTLE_ENDIAN, 929 .impl = { 930 .min_access_size = 4, 931 .max_access_size = 4, 932 }, 933 }; 934 935 static void sungem_mmio_txdma_write(void *opaque, hwaddr addr, uint64_t val, 936 unsigned size) 937 { 938 SunGEMState *s = opaque; 939 940 if (!(addr < 0x38) && !(addr >= 0x100 && addr <= 0x118)) { 941 qemu_log_mask(LOG_GUEST_ERROR, 942 "Write to unknown TXDMA register 0x%"HWADDR_PRIx"\n", 943 addr); 944 return; 945 } 946 947 trace_sungem_mmio_txdma_write(addr, val); 948 949 /* Pre-write filter */ 950 switch (addr) { 951 /* Read only registers */ 952 case TXDMA_TXDONE: 953 case TXDMA_PCNT: 954 case TXDMA_SMACHINE: 955 case TXDMA_DPLOW: 956 case TXDMA_DPHI: 957 case TXDMA_FSZ: 958 case TXDMA_FTAG: 959 return; /* No actual write */ 960 } 961 962 s->txdmaregs[addr >> 2] = val; 963 964 /* Post write action */ 965 switch (addr) { 966 case TXDMA_KICK: 967 sungem_tx_kick(s); 968 break; 969 case TXDMA_CFG: 970 sungem_update_masks(s); 971 break; 972 } 973 } 974 975 static uint64_t sungem_mmio_txdma_read(void *opaque, hwaddr addr, unsigned size) 976 { 977 SunGEMState *s = opaque; 978 uint32_t val; 979 980 if (!(addr < 0x38) && !(addr >= 0x100 && addr <= 0x118)) { 981 qemu_log_mask(LOG_GUEST_ERROR, 982 "Read from unknown TXDMA register 0x%"HWADDR_PRIx"\n", 983 addr); 984 return 0; 985 } 986 987 val = s->txdmaregs[addr >> 2]; 988 989 trace_sungem_mmio_txdma_read(addr, val); 990 991 return val; 992 } 993 994 static const MemoryRegionOps sungem_mmio_txdma_ops = { 995 .read = sungem_mmio_txdma_read, 996 .write = sungem_mmio_txdma_write, 997 .endianness = DEVICE_LITTLE_ENDIAN, 998 .impl = { 999 .min_access_size = 4, 1000 .max_access_size = 4, 1001 }, 1002 }; 1003 1004 static void sungem_mmio_rxdma_write(void *opaque, hwaddr addr, uint64_t val, 1005 unsigned size) 1006 { 1007 SunGEMState *s = opaque; 1008 1009 if (!(addr <= 0x28) && !(addr >= 0x100 && addr <= 0x120)) { 1010 qemu_log_mask(LOG_GUEST_ERROR, 1011 "Write to unknown RXDMA register 0x%"HWADDR_PRIx"\n", 1012 addr); 1013 return; 1014 } 1015 1016 trace_sungem_mmio_rxdma_write(addr, val); 1017 1018 /* Pre-write filter */ 1019 switch (addr) { 1020 /* Read only registers */ 1021 case RXDMA_DONE: 1022 case RXDMA_PCNT: 1023 case RXDMA_SMACHINE: 1024 case RXDMA_DPLOW: 1025 case RXDMA_DPHI: 1026 case RXDMA_FSZ: 1027 case RXDMA_FTAG: 1028 return; /* No actual write */ 1029 } 1030 1031 s->rxdmaregs[addr >> 2] = val; 1032 1033 /* Post write action */ 1034 switch (addr) { 1035 case RXDMA_KICK: 1036 trace_sungem_rx_kick(val); 1037 break; 1038 case RXDMA_CFG: 1039 sungem_update_masks(s); 1040 if ((s->macregs[MAC_RXCFG >> 2] & MAC_RXCFG_ENAB) != 0 && 1041 (s->rxdmaregs[RXDMA_CFG >> 2] & RXDMA_CFG_ENABLE) != 0) { 1042 qemu_flush_queued_packets(qemu_get_queue(s->nic)); 1043 } 1044 break; 1045 } 1046 } 1047 1048 static uint64_t sungem_mmio_rxdma_read(void *opaque, hwaddr addr, unsigned size) 1049 { 1050 SunGEMState *s = opaque; 1051 uint32_t val; 1052 1053 if (!(addr <= 0x28) && !(addr >= 0x100 && addr <= 0x120)) { 1054 qemu_log_mask(LOG_GUEST_ERROR, 1055 "Read from unknown RXDMA register 0x%"HWADDR_PRIx"\n", 1056 addr); 1057 return 0; 1058 } 1059 1060 val = s->rxdmaregs[addr >> 2]; 1061 1062 trace_sungem_mmio_rxdma_read(addr, val); 1063 1064 return val; 1065 } 1066 1067 static const MemoryRegionOps sungem_mmio_rxdma_ops = { 1068 .read = sungem_mmio_rxdma_read, 1069 .write = sungem_mmio_rxdma_write, 1070 .endianness = DEVICE_LITTLE_ENDIAN, 1071 .impl = { 1072 .min_access_size = 4, 1073 .max_access_size = 4, 1074 }, 1075 }; 1076 1077 static void sungem_mmio_mac_write(void *opaque, hwaddr addr, uint64_t val, 1078 unsigned size) 1079 { 1080 SunGEMState *s = opaque; 1081 1082 if (!(addr <= 0x134)) { 1083 qemu_log_mask(LOG_GUEST_ERROR, 1084 "Write to unknown MAC register 0x%"HWADDR_PRIx"\n", 1085 addr); 1086 return; 1087 } 1088 1089 trace_sungem_mmio_mac_write(addr, val); 1090 1091 /* Pre-write filter */ 1092 switch (addr) { 1093 /* Read only registers */ 1094 case MAC_TXRST: /* Not technically read-only but will do for now */ 1095 case MAC_RXRST: /* Not technically read-only but will do for now */ 1096 case MAC_TXSTAT: 1097 case MAC_RXSTAT: 1098 case MAC_CSTAT: 1099 case MAC_PATMPS: 1100 case MAC_SMACHINE: 1101 return; /* No actual write */ 1102 case MAC_MINFSZ: 1103 /* 10-bits implemented */ 1104 val &= 0x3ff; 1105 break; 1106 } 1107 1108 s->macregs[addr >> 2] = val; 1109 1110 /* Post write action */ 1111 switch (addr) { 1112 case MAC_TXMASK: 1113 case MAC_RXMASK: 1114 case MAC_MCMASK: 1115 sungem_eval_cascade_irq(s); 1116 break; 1117 case MAC_RXCFG: 1118 sungem_update_masks(s); 1119 if ((s->macregs[MAC_RXCFG >> 2] & MAC_RXCFG_ENAB) != 0 && 1120 (s->rxdmaregs[RXDMA_CFG >> 2] & RXDMA_CFG_ENABLE) != 0) { 1121 qemu_flush_queued_packets(qemu_get_queue(s->nic)); 1122 } 1123 break; 1124 } 1125 } 1126 1127 static uint64_t sungem_mmio_mac_read(void *opaque, hwaddr addr, unsigned size) 1128 { 1129 SunGEMState *s = opaque; 1130 uint32_t val; 1131 1132 if (!(addr <= 0x134)) { 1133 qemu_log_mask(LOG_GUEST_ERROR, 1134 "Read from unknown MAC register 0x%"HWADDR_PRIx"\n", 1135 addr); 1136 return 0; 1137 } 1138 1139 val = s->macregs[addr >> 2]; 1140 1141 trace_sungem_mmio_mac_read(addr, val); 1142 1143 switch (addr) { 1144 case MAC_TXSTAT: 1145 /* Side effect, clear all */ 1146 s->macregs[addr >> 2] = 0; 1147 sungem_update_status(s, GREG_STAT_TXMAC, false); 1148 break; 1149 case MAC_RXSTAT: 1150 /* Side effect, clear all */ 1151 s->macregs[addr >> 2] = 0; 1152 sungem_update_status(s, GREG_STAT_RXMAC, false); 1153 break; 1154 case MAC_CSTAT: 1155 /* Side effect, interrupt bits */ 1156 s->macregs[addr >> 2] &= MAC_CSTAT_PTR; 1157 sungem_update_status(s, GREG_STAT_MAC, false); 1158 break; 1159 } 1160 1161 return val; 1162 } 1163 1164 static const MemoryRegionOps sungem_mmio_mac_ops = { 1165 .read = sungem_mmio_mac_read, 1166 .write = sungem_mmio_mac_write, 1167 .endianness = DEVICE_LITTLE_ENDIAN, 1168 .impl = { 1169 .min_access_size = 4, 1170 .max_access_size = 4, 1171 }, 1172 }; 1173 1174 static void sungem_mmio_mif_write(void *opaque, hwaddr addr, uint64_t val, 1175 unsigned size) 1176 { 1177 SunGEMState *s = opaque; 1178 1179 if (!(addr <= 0x1c)) { 1180 qemu_log_mask(LOG_GUEST_ERROR, 1181 "Write to unknown MIF register 0x%"HWADDR_PRIx"\n", 1182 addr); 1183 return; 1184 } 1185 1186 trace_sungem_mmio_mif_write(addr, val); 1187 1188 /* Pre-write filter */ 1189 switch (addr) { 1190 /* Read only registers */ 1191 case MIF_STATUS: 1192 case MIF_SMACHINE: 1193 return; /* No actual write */ 1194 case MIF_CFG: 1195 /* Maintain the RO MDI bits to advertize an MDIO PHY on MDI0 */ 1196 val &= ~MIF_CFG_MDI1; 1197 val |= MIF_CFG_MDI0; 1198 break; 1199 } 1200 1201 s->mifregs[addr >> 2] = val; 1202 1203 /* Post write action */ 1204 switch (addr) { 1205 case MIF_FRAME: 1206 s->mifregs[addr >> 2] = sungem_mii_op(s, val); 1207 break; 1208 } 1209 } 1210 1211 static uint64_t sungem_mmio_mif_read(void *opaque, hwaddr addr, unsigned size) 1212 { 1213 SunGEMState *s = opaque; 1214 uint32_t val; 1215 1216 if (!(addr <= 0x1c)) { 1217 qemu_log_mask(LOG_GUEST_ERROR, 1218 "Read from unknown MIF register 0x%"HWADDR_PRIx"\n", 1219 addr); 1220 return 0; 1221 } 1222 1223 val = s->mifregs[addr >> 2]; 1224 1225 trace_sungem_mmio_mif_read(addr, val); 1226 1227 return val; 1228 } 1229 1230 static const MemoryRegionOps sungem_mmio_mif_ops = { 1231 .read = sungem_mmio_mif_read, 1232 .write = sungem_mmio_mif_write, 1233 .endianness = DEVICE_LITTLE_ENDIAN, 1234 .impl = { 1235 .min_access_size = 4, 1236 .max_access_size = 4, 1237 }, 1238 }; 1239 1240 static void sungem_mmio_pcs_write(void *opaque, hwaddr addr, uint64_t val, 1241 unsigned size) 1242 { 1243 SunGEMState *s = opaque; 1244 1245 if (!(addr <= 0x18) && !(addr >= 0x50 && addr <= 0x5c)) { 1246 qemu_log_mask(LOG_GUEST_ERROR, 1247 "Write to unknown PCS register 0x%"HWADDR_PRIx"\n", 1248 addr); 1249 return; 1250 } 1251 1252 trace_sungem_mmio_pcs_write(addr, val); 1253 1254 /* Pre-write filter */ 1255 switch (addr) { 1256 /* Read only registers */ 1257 case PCS_MIISTAT: 1258 case PCS_ISTAT: 1259 case PCS_SSTATE: 1260 return; /* No actual write */ 1261 } 1262 1263 s->pcsregs[addr >> 2] = val; 1264 } 1265 1266 static uint64_t sungem_mmio_pcs_read(void *opaque, hwaddr addr, unsigned size) 1267 { 1268 SunGEMState *s = opaque; 1269 uint32_t val; 1270 1271 if (!(addr <= 0x18) && !(addr >= 0x50 && addr <= 0x5c)) { 1272 qemu_log_mask(LOG_GUEST_ERROR, 1273 "Read from unknown PCS register 0x%"HWADDR_PRIx"\n", 1274 addr); 1275 return 0; 1276 } 1277 1278 val = s->pcsregs[addr >> 2]; 1279 1280 trace_sungem_mmio_pcs_read(addr, val); 1281 1282 return val; 1283 } 1284 1285 static const MemoryRegionOps sungem_mmio_pcs_ops = { 1286 .read = sungem_mmio_pcs_read, 1287 .write = sungem_mmio_pcs_write, 1288 .endianness = DEVICE_LITTLE_ENDIAN, 1289 .impl = { 1290 .min_access_size = 4, 1291 .max_access_size = 4, 1292 }, 1293 }; 1294 1295 static void sungem_uninit(PCIDevice *dev) 1296 { 1297 SunGEMState *s = SUNGEM(dev); 1298 1299 qemu_del_nic(s->nic); 1300 } 1301 1302 static NetClientInfo net_sungem_info = { 1303 .type = NET_CLIENT_DRIVER_NIC, 1304 .size = sizeof(NICState), 1305 .can_receive = sungem_can_receive, 1306 .receive = sungem_receive, 1307 .link_status_changed = sungem_set_link_status, 1308 }; 1309 1310 static void sungem_realize(PCIDevice *pci_dev, Error **errp) 1311 { 1312 DeviceState *dev = DEVICE(pci_dev); 1313 SunGEMState *s = SUNGEM(pci_dev); 1314 uint8_t *pci_conf; 1315 1316 pci_conf = pci_dev->config; 1317 1318 pci_set_word(pci_conf + PCI_STATUS, 1319 PCI_STATUS_FAST_BACK | 1320 PCI_STATUS_DEVSEL_MEDIUM | 1321 PCI_STATUS_66MHZ); 1322 1323 pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, 0x0); 1324 pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, 0x0); 1325 1326 pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */ 1327 pci_conf[PCI_MIN_GNT] = 0x40; 1328 pci_conf[PCI_MAX_LAT] = 0x40; 1329 1330 sungem_reset_all(s, true); 1331 memory_region_init(&s->sungem, OBJECT(s), "sungem", SUNGEM_MMIO_SIZE); 1332 1333 memory_region_init_io(&s->greg, OBJECT(s), &sungem_mmio_greg_ops, s, 1334 "sungem.greg", SUNGEM_MMIO_GREG_SIZE); 1335 memory_region_add_subregion(&s->sungem, 0, &s->greg); 1336 1337 memory_region_init_io(&s->txdma, OBJECT(s), &sungem_mmio_txdma_ops, s, 1338 "sungem.txdma", SUNGEM_MMIO_TXDMA_SIZE); 1339 memory_region_add_subregion(&s->sungem, 0x2000, &s->txdma); 1340 1341 memory_region_init_io(&s->rxdma, OBJECT(s), &sungem_mmio_rxdma_ops, s, 1342 "sungem.rxdma", SUNGEM_MMIO_RXDMA_SIZE); 1343 memory_region_add_subregion(&s->sungem, 0x4000, &s->rxdma); 1344 1345 memory_region_init_io(&s->mac, OBJECT(s), &sungem_mmio_mac_ops, s, 1346 "sungem.mac", SUNGEM_MMIO_MAC_SIZE); 1347 memory_region_add_subregion(&s->sungem, 0x6000, &s->mac); 1348 1349 memory_region_init_io(&s->mif, OBJECT(s), &sungem_mmio_mif_ops, s, 1350 "sungem.mif", SUNGEM_MMIO_MIF_SIZE); 1351 memory_region_add_subregion(&s->sungem, 0x6200, &s->mif); 1352 1353 memory_region_init_io(&s->pcs, OBJECT(s), &sungem_mmio_pcs_ops, s, 1354 "sungem.pcs", SUNGEM_MMIO_PCS_SIZE); 1355 memory_region_add_subregion(&s->sungem, 0x9000, &s->pcs); 1356 1357 pci_register_bar(pci_dev, 0, PCI_BASE_ADDRESS_SPACE_MEMORY, &s->sungem); 1358 1359 qemu_macaddr_default_if_unset(&s->conf.macaddr); 1360 s->nic = qemu_new_nic(&net_sungem_info, &s->conf, 1361 object_get_typename(OBJECT(dev)), 1362 dev->id, s); 1363 qemu_format_nic_info_str(qemu_get_queue(s->nic), 1364 s->conf.macaddr.a); 1365 } 1366 1367 static void sungem_reset(DeviceState *dev) 1368 { 1369 SunGEMState *s = SUNGEM(dev); 1370 1371 sungem_reset_all(s, true); 1372 } 1373 1374 static void sungem_instance_init(Object *obj) 1375 { 1376 SunGEMState *s = SUNGEM(obj); 1377 1378 device_add_bootindex_property(obj, &s->conf.bootindex, 1379 "bootindex", "/ethernet-phy@0", 1380 DEVICE(obj), NULL); 1381 } 1382 1383 static Property sungem_properties[] = { 1384 DEFINE_NIC_PROPERTIES(SunGEMState, conf), 1385 /* Phy address should be 0 for most Apple machines except 1386 * for K2 in which case it's 1. Will be set by a machine 1387 * override. 1388 */ 1389 DEFINE_PROP_UINT32("phy_addr", SunGEMState, phy_addr, 0), 1390 DEFINE_PROP_END_OF_LIST(), 1391 }; 1392 1393 static const VMStateDescription vmstate_sungem = { 1394 .name = "sungem", 1395 .version_id = 0, 1396 .minimum_version_id = 0, 1397 .fields = (VMStateField[]) { 1398 VMSTATE_PCI_DEVICE(pdev, SunGEMState), 1399 VMSTATE_MACADDR(conf.macaddr, SunGEMState), 1400 VMSTATE_UINT32(phy_addr, SunGEMState), 1401 VMSTATE_UINT32_ARRAY(gregs, SunGEMState, (SUNGEM_MMIO_GREG_SIZE >> 2)), 1402 VMSTATE_UINT32_ARRAY(txdmaregs, SunGEMState, 1403 (SUNGEM_MMIO_TXDMA_SIZE >> 2)), 1404 VMSTATE_UINT32_ARRAY(rxdmaregs, SunGEMState, 1405 (SUNGEM_MMIO_RXDMA_SIZE >> 2)), 1406 VMSTATE_UINT32_ARRAY(macregs, SunGEMState, (SUNGEM_MMIO_MAC_SIZE >> 2)), 1407 VMSTATE_UINT32_ARRAY(mifregs, SunGEMState, (SUNGEM_MMIO_MIF_SIZE >> 2)), 1408 VMSTATE_UINT32_ARRAY(pcsregs, SunGEMState, (SUNGEM_MMIO_PCS_SIZE >> 2)), 1409 VMSTATE_UINT32(rx_mask, SunGEMState), 1410 VMSTATE_UINT32(tx_mask, SunGEMState), 1411 VMSTATE_UINT8_ARRAY(tx_data, SunGEMState, MAX_PACKET_SIZE), 1412 VMSTATE_UINT32(tx_size, SunGEMState), 1413 VMSTATE_UINT64(tx_first_ctl, SunGEMState), 1414 VMSTATE_END_OF_LIST() 1415 } 1416 }; 1417 1418 static void sungem_class_init(ObjectClass *klass, void *data) 1419 { 1420 DeviceClass *dc = DEVICE_CLASS(klass); 1421 PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); 1422 1423 k->realize = sungem_realize; 1424 k->exit = sungem_uninit; 1425 k->vendor_id = PCI_VENDOR_ID_APPLE; 1426 k->device_id = PCI_DEVICE_ID_APPLE_UNI_N_GMAC; 1427 k->revision = 0x01; 1428 k->class_id = PCI_CLASS_NETWORK_ETHERNET; 1429 dc->vmsd = &vmstate_sungem; 1430 dc->reset = sungem_reset; 1431 dc->props = sungem_properties; 1432 set_bit(DEVICE_CATEGORY_NETWORK, dc->categories); 1433 } 1434 1435 static const TypeInfo sungem_info = { 1436 .name = TYPE_SUNGEM, 1437 .parent = TYPE_PCI_DEVICE, 1438 .instance_size = sizeof(SunGEMState), 1439 .class_init = sungem_class_init, 1440 .instance_init = sungem_instance_init, 1441 .interfaces = (InterfaceInfo[]) { 1442 { INTERFACE_CONVENTIONAL_PCI_DEVICE }, 1443 { } 1444 } 1445 }; 1446 1447 static void sungem_register_types(void) 1448 { 1449 type_register_static(&sungem_info); 1450 } 1451 1452 type_init(sungem_register_types) 1453