xref: /openbmc/qemu/hw/net/sungem.c (revision d6454270)
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