xref: /qemu/hw/net/tulip.c (revision 34ea023d4b959f35be8771470483c57dbbe2447d)
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