Commit 91cc029598b7cd37c726175e05df7e45e9df6ffb
1 parent
c03b0f0f
initial sparc32 lance and pcnet merge
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2142 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
2 changed files
with
327 additions
and
588 deletions
hw/lance.c deleted
100644 → 0
1 | -/* | |
2 | - * QEMU Lance emulation | |
3 | - * | |
4 | - * Copyright (c) 2003-2005 Fabrice Bellard | |
5 | - * | |
6 | - * Permission is hereby granted, free of charge, to any person obtaining a copy | |
7 | - * of this software and associated documentation files (the "Software"), to deal | |
8 | - * in the Software without restriction, including without limitation the rights | |
9 | - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | |
10 | - * copies of the Software, and to permit persons to whom the Software is | |
11 | - * furnished to do so, subject to the following conditions: | |
12 | - * | |
13 | - * The above copyright notice and this permission notice shall be included in | |
14 | - * all copies or substantial portions of the Software. | |
15 | - * | |
16 | - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
17 | - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
18 | - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
19 | - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | |
20 | - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | |
21 | - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | |
22 | - * THE SOFTWARE. | |
23 | - */ | |
24 | -#include "vl.h" | |
25 | - | |
26 | -/* debug LANCE card */ | |
27 | -//#define DEBUG_LANCE | |
28 | - | |
29 | -#ifdef DEBUG_LANCE | |
30 | -#define DPRINTF(fmt, args...) \ | |
31 | -do { printf("LANCE: " fmt , ##args); } while (0) | |
32 | -#else | |
33 | -#define DPRINTF(fmt, args...) | |
34 | -#endif | |
35 | - | |
36 | -#ifndef LANCE_LOG_TX_BUFFERS | |
37 | -#define LANCE_LOG_TX_BUFFERS 4 | |
38 | -#define LANCE_LOG_RX_BUFFERS 4 | |
39 | -#endif | |
40 | - | |
41 | -#define LE_CSR0 0 | |
42 | -#define LE_CSR1 1 | |
43 | -#define LE_CSR2 2 | |
44 | -#define LE_CSR3 3 | |
45 | -#define LE_NREGS (LE_CSR3 + 1) | |
46 | -#define LE_MAXREG LE_CSR3 | |
47 | - | |
48 | -#define LE_RDP 0 | |
49 | -#define LE_RAP 1 | |
50 | - | |
51 | -#define LE_MO_PROM 0x8000 /* Enable promiscuous mode */ | |
52 | - | |
53 | -#define LE_C0_ERR 0x8000 /* Error: set if BAB, SQE, MISS or ME is set */ | |
54 | -#define LE_C0_BABL 0x4000 /* BAB: Babble: tx timeout. */ | |
55 | -#define LE_C0_CERR 0x2000 /* SQE: Signal quality error */ | |
56 | -#define LE_C0_MISS 0x1000 /* MISS: Missed a packet */ | |
57 | -#define LE_C0_MERR 0x0800 /* ME: Memory error */ | |
58 | -#define LE_C0_RINT 0x0400 /* Received interrupt */ | |
59 | -#define LE_C0_TINT 0x0200 /* Transmitter Interrupt */ | |
60 | -#define LE_C0_IDON 0x0100 /* IFIN: Init finished. */ | |
61 | -#define LE_C0_INTR 0x0080 /* Interrupt or error */ | |
62 | -#define LE_C0_INEA 0x0040 /* Interrupt enable */ | |
63 | -#define LE_C0_RXON 0x0020 /* Receiver on */ | |
64 | -#define LE_C0_TXON 0x0010 /* Transmitter on */ | |
65 | -#define LE_C0_TDMD 0x0008 /* Transmitter demand */ | |
66 | -#define LE_C0_STOP 0x0004 /* Stop the card */ | |
67 | -#define LE_C0_STRT 0x0002 /* Start the card */ | |
68 | -#define LE_C0_INIT 0x0001 /* Init the card */ | |
69 | - | |
70 | -#define LE_C3_BSWP 0x4 /* SWAP */ | |
71 | -#define LE_C3_ACON 0x2 /* ALE Control */ | |
72 | -#define LE_C3_BCON 0x1 /* Byte control */ | |
73 | - | |
74 | -/* Receive message descriptor 1 */ | |
75 | -#define LE_R1_OWN 0x80 /* Who owns the entry */ | |
76 | -#define LE_R1_ERR 0x40 /* Error: if FRA, OFL, CRC or BUF is set */ | |
77 | -#define LE_R1_FRA 0x20 /* FRA: Frame error */ | |
78 | -#define LE_R1_OFL 0x10 /* OFL: Frame overflow */ | |
79 | -#define LE_R1_CRC 0x08 /* CRC error */ | |
80 | -#define LE_R1_BUF 0x04 /* BUF: Buffer error */ | |
81 | -#define LE_R1_SOP 0x02 /* Start of packet */ | |
82 | -#define LE_R1_EOP 0x01 /* End of packet */ | |
83 | -#define LE_R1_POK 0x03 /* Packet is complete: SOP + EOP */ | |
84 | - | |
85 | -#define LE_T1_OWN 0x80 /* Lance owns the packet */ | |
86 | -#define LE_T1_ERR 0x40 /* Error summary */ | |
87 | -#define LE_T1_EMORE 0x10 /* Error: more than one retry needed */ | |
88 | -#define LE_T1_EONE 0x08 /* Error: one retry needed */ | |
89 | -#define LE_T1_EDEF 0x04 /* Error: deferred */ | |
90 | -#define LE_T1_SOP 0x02 /* Start of packet */ | |
91 | -#define LE_T1_EOP 0x01 /* End of packet */ | |
92 | -#define LE_T1_POK 0x03 /* Packet is complete: SOP + EOP */ | |
93 | - | |
94 | -#define LE_T3_BUF 0x8000 /* Buffer error */ | |
95 | -#define LE_T3_UFL 0x4000 /* Error underflow */ | |
96 | -#define LE_T3_LCOL 0x1000 /* Error late collision */ | |
97 | -#define LE_T3_CLOS 0x0800 /* Error carrier loss */ | |
98 | -#define LE_T3_RTY 0x0400 /* Error retry */ | |
99 | -#define LE_T3_TDR 0x03ff /* Time Domain Reflectometry counter */ | |
100 | - | |
101 | -#define TX_RING_SIZE (1 << (LANCE_LOG_TX_BUFFERS)) | |
102 | -#define TX_RING_MOD_MASK (TX_RING_SIZE - 1) | |
103 | -#define TX_RING_LEN_BITS ((LANCE_LOG_TX_BUFFERS) << 29) | |
104 | - | |
105 | -#define RX_RING_SIZE (1 << (LANCE_LOG_RX_BUFFERS)) | |
106 | -#define RX_RING_MOD_MASK (RX_RING_SIZE - 1) | |
107 | -#define RX_RING_LEN_BITS ((LANCE_LOG_RX_BUFFERS) << 29) | |
108 | - | |
109 | -#define PKT_BUF_SZ 1544 | |
110 | -#define RX_BUFF_SIZE PKT_BUF_SZ | |
111 | -#define TX_BUFF_SIZE PKT_BUF_SZ | |
112 | - | |
113 | -struct lance_rx_desc { | |
114 | - unsigned short rmd0; /* low address of packet */ | |
115 | - unsigned char rmd1_bits; /* descriptor bits */ | |
116 | - unsigned char rmd1_hadr; /* high address of packet */ | |
117 | - short length; /* This length is 2s complement (negative)! | |
118 | - * Buffer length | |
119 | - */ | |
120 | - unsigned short mblength; /* This is the actual number of bytes received */ | |
121 | -}; | |
122 | - | |
123 | -struct lance_tx_desc { | |
124 | - unsigned short tmd0; /* low address of packet */ | |
125 | - unsigned char tmd1_bits; /* descriptor bits */ | |
126 | - unsigned char tmd1_hadr; /* high address of packet */ | |
127 | - short length; /* Length is 2s complement (negative)! */ | |
128 | - unsigned short misc; | |
129 | -}; | |
130 | - | |
131 | -/* The LANCE initialization block, described in databook. */ | |
132 | -/* On the Sparc, this block should be on a DMA region */ | |
133 | -struct lance_init_block { | |
134 | - unsigned short mode; /* Pre-set mode (reg. 15) */ | |
135 | - unsigned char phys_addr[6]; /* Physical ethernet address */ | |
136 | - unsigned filter[2]; /* Multicast filter. */ | |
137 | - | |
138 | - /* Receive and transmit ring base, along with extra bits. */ | |
139 | - unsigned short rx_ptr; /* receive descriptor addr */ | |
140 | - unsigned short rx_len; /* receive len and high addr */ | |
141 | - unsigned short tx_ptr; /* transmit descriptor addr */ | |
142 | - unsigned short tx_len; /* transmit len and high addr */ | |
143 | - | |
144 | - /* The Tx and Rx ring entries must aligned on 8-byte boundaries. */ | |
145 | - struct lance_rx_desc brx_ring[RX_RING_SIZE]; | |
146 | - struct lance_tx_desc btx_ring[TX_RING_SIZE]; | |
147 | - | |
148 | - char tx_buf[TX_RING_SIZE][TX_BUFF_SIZE]; | |
149 | - char pad[2]; /* align rx_buf for copy_and_sum(). */ | |
150 | - char rx_buf[RX_RING_SIZE][RX_BUFF_SIZE]; | |
151 | -}; | |
152 | - | |
153 | -#define LEDMA_REGS 4 | |
154 | -#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1) | |
155 | - | |
156 | -typedef struct LANCEState { | |
157 | - VLANClientState *vc; | |
158 | - uint8_t macaddr[6]; /* init mac address */ | |
159 | - uint32_t leptr; | |
160 | - uint16_t addr; | |
161 | - uint16_t regs[LE_NREGS]; | |
162 | - uint8_t phys[6]; /* mac address */ | |
163 | - int irq; | |
164 | - unsigned int rxptr, txptr; | |
165 | - uint32_t ledmaregs[LEDMA_REGS]; | |
166 | -} LANCEState; | |
167 | - | |
168 | -static void lance_send(void *opaque); | |
169 | - | |
170 | -static void lance_reset(void *opaque) | |
171 | -{ | |
172 | - LANCEState *s = opaque; | |
173 | - memcpy(s->phys, s->macaddr, 6); | |
174 | - s->rxptr = 0; | |
175 | - s->txptr = 0; | |
176 | - memset(s->regs, 0, LE_NREGS * 2); | |
177 | - s->regs[LE_CSR0] = LE_C0_STOP; | |
178 | - memset(s->ledmaregs, 0, LEDMA_REGS * 4); | |
179 | -} | |
180 | - | |
181 | -static uint32_t lance_mem_readw(void *opaque, target_phys_addr_t addr) | |
182 | -{ | |
183 | - LANCEState *s = opaque; | |
184 | - uint32_t saddr; | |
185 | - | |
186 | - saddr = addr & LE_MAXREG; | |
187 | - switch (saddr >> 1) { | |
188 | - case LE_RDP: | |
189 | - DPRINTF("read dreg[%d] = %4.4x\n", s->addr, s->regs[s->addr]); | |
190 | - return s->regs[s->addr]; | |
191 | - case LE_RAP: | |
192 | - DPRINTF("read areg = %4.4x\n", s->addr); | |
193 | - return s->addr; | |
194 | - default: | |
195 | - DPRINTF("read unknown(%d)\n", saddr >> 1); | |
196 | - break; | |
197 | - } | |
198 | - return 0; | |
199 | -} | |
200 | - | |
201 | -static void lance_mem_writew(void *opaque, target_phys_addr_t addr, | |
202 | - uint32_t val) | |
203 | -{ | |
204 | - LANCEState *s = opaque; | |
205 | - uint32_t saddr; | |
206 | - uint16_t reg; | |
207 | - | |
208 | - saddr = addr & LE_MAXREG; | |
209 | - switch (saddr >> 1) { | |
210 | - case LE_RDP: | |
211 | - DPRINTF("write dreg[%d] = %4.4x\n", s->addr, val); | |
212 | - switch (s->addr) { | |
213 | - case LE_CSR0: | |
214 | - if (val & LE_C0_STOP) { | |
215 | - s->regs[LE_CSR0] = LE_C0_STOP; | |
216 | - break; | |
217 | - } | |
218 | - | |
219 | - reg = s->regs[LE_CSR0]; | |
220 | - | |
221 | - // 1 = clear for some bits | |
222 | - reg &= ~(val & 0x7f00); | |
223 | - | |
224 | - // generated bits | |
225 | - reg &= ~(LE_C0_ERR | LE_C0_INTR); | |
226 | - if (reg & 0x7100) | |
227 | - reg |= LE_C0_ERR; | |
228 | - if (reg & 0x7f00) | |
229 | - reg |= LE_C0_INTR; | |
230 | - | |
231 | - // direct bit | |
232 | - reg &= ~LE_C0_INEA; | |
233 | - reg |= val & LE_C0_INEA; | |
234 | - | |
235 | - // exclusive bits | |
236 | - if (val & LE_C0_INIT) { | |
237 | - reg |= LE_C0_IDON | LE_C0_INIT; | |
238 | - reg &= ~LE_C0_STOP; | |
239 | - } else if (val & LE_C0_STRT) { | |
240 | - reg |= LE_C0_STRT | LE_C0_RXON | LE_C0_TXON; | |
241 | - reg &= ~LE_C0_STOP; | |
242 | - } | |
243 | - | |
244 | - s->regs[LE_CSR0] = reg; | |
245 | - break; | |
246 | - case LE_CSR1: | |
247 | - s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff); | |
248 | - s->regs[s->addr] = val; | |
249 | - break; | |
250 | - case LE_CSR2: | |
251 | - s->leptr = (s->leptr & 0xffff) | ((val & 0xffff) << 16); | |
252 | - s->regs[s->addr] = val; | |
253 | - break; | |
254 | - case LE_CSR3: | |
255 | - s->regs[s->addr] = val; | |
256 | - break; | |
257 | - } | |
258 | - break; | |
259 | - case LE_RAP: | |
260 | - DPRINTF("write areg = %4.4x\n", val); | |
261 | - if (val < LE_NREGS) | |
262 | - s->addr = val; | |
263 | - break; | |
264 | - default: | |
265 | - DPRINTF("write unknown(%d) = %4.4x\n", saddr >> 1, val); | |
266 | - break; | |
267 | - } | |
268 | - lance_send(s); | |
269 | -} | |
270 | - | |
271 | -static CPUReadMemoryFunc *lance_mem_read[3] = { | |
272 | - lance_mem_readw, | |
273 | - lance_mem_readw, | |
274 | - lance_mem_readw, | |
275 | -}; | |
276 | - | |
277 | -static CPUWriteMemoryFunc *lance_mem_write[3] = { | |
278 | - lance_mem_writew, | |
279 | - lance_mem_writew, | |
280 | - lance_mem_writew, | |
281 | -}; | |
282 | - | |
283 | - | |
284 | -#define MIN_BUF_SIZE 60 | |
285 | - | |
286 | -static int lance_can_receive(void *opaque) | |
287 | -{ | |
288 | - return 1; | |
289 | -} | |
290 | - | |
291 | -static void lance_receive(void *opaque, const uint8_t * buf, int size) | |
292 | -{ | |
293 | - LANCEState *s = opaque; | |
294 | - uint32_t dmaptr = s->leptr + s->ledmaregs[3]; | |
295 | - struct lance_init_block *ib; | |
296 | - unsigned int i, old_rxptr; | |
297 | - uint16_t temp16; | |
298 | - uint8_t temp8; | |
299 | - | |
300 | - DPRINTF("receive size %d\n", size); | |
301 | - if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) | |
302 | - return; | |
303 | - | |
304 | - ib = (void *) iommu_translate(dmaptr); | |
305 | - | |
306 | - old_rxptr = s->rxptr; | |
307 | - for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); | |
308 | - i = (i + 1) & RX_RING_MOD_MASK) { | |
309 | - cpu_physical_memory_read((uint32_t) & ib->brx_ring[i].rmd1_bits, | |
310 | - (void *) &temp8, 1); | |
311 | - if (temp8 == (LE_R1_OWN)) { | |
312 | - s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK; | |
313 | - temp16 = size + 4; | |
314 | - bswap16s(&temp16); | |
315 | - cpu_physical_memory_write((uint32_t) & ib->brx_ring[i]. | |
316 | - mblength, (void *) &temp16, 2); | |
317 | - cpu_physical_memory_write((uint32_t) & ib->rx_buf[i], buf, | |
318 | - size); | |
319 | - temp8 = LE_R1_POK; | |
320 | - cpu_physical_memory_write((uint32_t) & ib->brx_ring[i]. | |
321 | - rmd1_bits, (void *) &temp8, 1); | |
322 | - s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR; | |
323 | - if (s->regs[LE_CSR0] & LE_C0_INEA) | |
324 | - pic_set_irq(s->irq, 1); | |
325 | - DPRINTF("got packet, len %d\n", size); | |
326 | - return; | |
327 | - } | |
328 | - } | |
329 | -} | |
330 | - | |
331 | -static void lance_send(void *opaque) | |
332 | -{ | |
333 | - LANCEState *s = opaque; | |
334 | - uint32_t dmaptr = s->leptr + s->ledmaregs[3]; | |
335 | - struct lance_init_block *ib; | |
336 | - unsigned int i, old_txptr; | |
337 | - uint16_t temp16; | |
338 | - uint8_t temp8; | |
339 | - char pkt_buf[PKT_BUF_SZ]; | |
340 | - | |
341 | - DPRINTF("sending packet? (csr0 %4.4x)\n", s->regs[LE_CSR0]); | |
342 | - if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) | |
343 | - return; | |
344 | - | |
345 | - ib = (void *) iommu_translate(dmaptr); | |
346 | - | |
347 | - DPRINTF("sending packet? (dmaptr %8.8x) (ib %p) (btx_ring %p)\n", | |
348 | - dmaptr, ib, &ib->btx_ring); | |
349 | - old_txptr = s->txptr; | |
350 | - for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); | |
351 | - i = (i + 1) & TX_RING_MOD_MASK) { | |
352 | - cpu_physical_memory_read((uint32_t) & ib->btx_ring[i].tmd1_bits, | |
353 | - (void *) &temp8, 1); | |
354 | - if (temp8 == (LE_T1_POK | LE_T1_OWN)) { | |
355 | - cpu_physical_memory_read((uint32_t) & ib->btx_ring[i].length, | |
356 | - (void *) &temp16, 2); | |
357 | - bswap16s(&temp16); | |
358 | - temp16 = (~temp16) + 1; | |
359 | - cpu_physical_memory_read((uint32_t) & ib->tx_buf[i], pkt_buf, | |
360 | - temp16); | |
361 | - DPRINTF("sending packet, len %d\n", temp16); | |
362 | - qemu_send_packet(s->vc, pkt_buf, temp16); | |
363 | - temp8 = LE_T1_POK; | |
364 | - cpu_physical_memory_write((uint32_t) & ib->btx_ring[i]. | |
365 | - tmd1_bits, (void *) &temp8, 1); | |
366 | - s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK; | |
367 | - s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR; | |
368 | - } | |
369 | - } | |
370 | - if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA)) | |
371 | - pic_set_irq(s->irq, 1); | |
372 | -} | |
373 | - | |
374 | -static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr) | |
375 | -{ | |
376 | - LANCEState *s = opaque; | |
377 | - uint32_t saddr; | |
378 | - | |
379 | - saddr = (addr & LEDMA_MAXADDR) >> 2; | |
380 | - return s->ledmaregs[saddr]; | |
381 | -} | |
382 | - | |
383 | -static void ledma_mem_writel(void *opaque, target_phys_addr_t addr, | |
384 | - uint32_t val) | |
385 | -{ | |
386 | - LANCEState *s = opaque; | |
387 | - uint32_t saddr; | |
388 | - | |
389 | - saddr = (addr & LEDMA_MAXADDR) >> 2; | |
390 | - s->ledmaregs[saddr] = val; | |
391 | -} | |
392 | - | |
393 | -static CPUReadMemoryFunc *ledma_mem_read[3] = { | |
394 | - ledma_mem_readl, | |
395 | - ledma_mem_readl, | |
396 | - ledma_mem_readl, | |
397 | -}; | |
398 | - | |
399 | -static CPUWriteMemoryFunc *ledma_mem_write[3] = { | |
400 | - ledma_mem_writel, | |
401 | - ledma_mem_writel, | |
402 | - ledma_mem_writel, | |
403 | -}; | |
404 | - | |
405 | -static void lance_save(QEMUFile * f, void *opaque) | |
406 | -{ | |
407 | - LANCEState *s = opaque; | |
408 | - int i; | |
409 | - | |
410 | - qemu_put_be32s(f, &s->leptr); | |
411 | - qemu_put_be16s(f, &s->addr); | |
412 | - for (i = 0; i < LE_NREGS; i++) | |
413 | - qemu_put_be16s(f, &s->regs[i]); | |
414 | - qemu_put_buffer(f, s->phys, 6); | |
415 | - qemu_put_be32s(f, &s->irq); | |
416 | - for (i = 0; i < LEDMA_REGS; i++) | |
417 | - qemu_put_be32s(f, &s->ledmaregs[i]); | |
418 | -} | |
419 | - | |
420 | -static int lance_load(QEMUFile * f, void *opaque, int version_id) | |
421 | -{ | |
422 | - LANCEState *s = opaque; | |
423 | - int i; | |
424 | - | |
425 | - if (version_id != 1) | |
426 | - return -EINVAL; | |
427 | - | |
428 | - qemu_get_be32s(f, &s->leptr); | |
429 | - qemu_get_be16s(f, &s->addr); | |
430 | - for (i = 0; i < LE_NREGS; i++) | |
431 | - qemu_get_be16s(f, &s->regs[i]); | |
432 | - qemu_get_buffer(f, s->phys, 6); | |
433 | - qemu_get_be32s(f, &s->irq); | |
434 | - for (i = 0; i < LEDMA_REGS; i++) | |
435 | - qemu_get_be32s(f, &s->ledmaregs[i]); | |
436 | - return 0; | |
437 | -} | |
438 | - | |
439 | -void lance_init(NICInfo * nd, int irq, uint32_t leaddr, uint32_t ledaddr) | |
440 | -{ | |
441 | - LANCEState *s; | |
442 | - int lance_io_memory, ledma_io_memory; | |
443 | - | |
444 | - s = qemu_mallocz(sizeof(LANCEState)); | |
445 | - if (!s) | |
446 | - return; | |
447 | - | |
448 | - s->irq = irq; | |
449 | - | |
450 | - lance_io_memory = | |
451 | - cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s); | |
452 | - cpu_register_physical_memory(leaddr, 4, lance_io_memory); | |
453 | - | |
454 | - ledma_io_memory = | |
455 | - cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s); | |
456 | - cpu_register_physical_memory(ledaddr, 16, ledma_io_memory); | |
457 | - | |
458 | - memcpy(s->macaddr, nd->macaddr, 6); | |
459 | - | |
460 | - lance_reset(s); | |
461 | - | |
462 | - s->vc = | |
463 | - qemu_new_vlan_client(nd->vlan, lance_receive, lance_can_receive, | |
464 | - s); | |
465 | - | |
466 | - snprintf(s->vc->info_str, sizeof(s->vc->info_str), | |
467 | - "lance macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | |
468 | - s->macaddr[0], | |
469 | - s->macaddr[1], | |
470 | - s->macaddr[2], s->macaddr[3], s->macaddr[4], s->macaddr[5]); | |
471 | - | |
472 | - register_savevm("lance", leaddr, 1, lance_save, lance_load, s); | |
473 | - qemu_register_reset(lance_reset, s); | |
474 | -} |
hw/pcnet.c
... | ... | @@ -27,6 +27,16 @@ |
27 | 27 | * AMD Publication# 19436 Rev:E Amendment/0 Issue Date: June 2000 |
28 | 28 | */ |
29 | 29 | |
30 | +/* | |
31 | + * On Sparc32, this is the Lance (Am7990) part of chip STP2000 (Master I/O), also | |
32 | + * produced as NCR89C100. See | |
33 | + * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt | |
34 | + * and | |
35 | + * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt | |
36 | + */ | |
37 | + | |
38 | +/* TODO: remove little endian host assumptions */ | |
39 | + | |
30 | 40 | #include "vl.h" |
31 | 41 | |
32 | 42 | //#define PCNET_DEBUG |
... | ... | @@ -46,11 +56,12 @@ typedef struct PCNetState_st PCNetState; |
46 | 56 | |
47 | 57 | struct PCNetState_st { |
48 | 58 | PCIDevice dev; |
59 | + PCIDevice *pci_dev; | |
49 | 60 | VLANClientState *vc; |
50 | 61 | NICInfo *nd; |
51 | 62 | QEMUTimer *poll_timer; |
52 | - int mmio_io_addr, rap, isr, lnkst; | |
53 | - target_phys_addr_t rdra, tdra; | |
63 | + int mmio_index, rap, isr, lnkst; | |
64 | + uint32_t rdra, tdra; | |
54 | 65 | uint8_t prom[16]; |
55 | 66 | uint16_t csr[128]; |
56 | 67 | uint16_t bcr[32]; |
... | ... | @@ -58,6 +69,12 @@ struct PCNetState_st { |
58 | 69 | int xmit_pos, recv_pos; |
59 | 70 | uint8_t buffer[4096]; |
60 | 71 | int tx_busy; |
72 | + void (*set_irq_cb)(void *s, int isr); | |
73 | + void (*phys_mem_read)(void *dma_opaque, target_phys_addr_t addr, | |
74 | + uint8_t *buf, int len); | |
75 | + void (*phys_mem_write)(void *dma_opaque, target_phys_addr_t addr, | |
76 | + uint8_t *buf, int len); | |
77 | + void *dma_opaque; | |
61 | 78 | }; |
62 | 79 | |
63 | 80 | /* XXX: using bitfields for target memory structures is almost surely |
... | ... | @@ -99,6 +116,7 @@ struct qemu_ether_header { |
99 | 116 | #define CSR_TXON(S) !!(((S)->csr[0])&0x0010) |
100 | 117 | #define CSR_RXON(S) !!(((S)->csr[0])&0x0020) |
101 | 118 | #define CSR_INEA(S) !!(((S)->csr[0])&0x0040) |
119 | +#define CSR_BIGENDIAN(S) !!(((S)->csr[3])&0x0004) | |
102 | 120 | #define CSR_LAPPEN(S) !!(((S)->csr[3])&0x0020) |
103 | 121 | #define CSR_DXSUFLO(S) !!(((S)->csr[3])&0x0040) |
104 | 122 | #define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800) |
... | ... | @@ -147,35 +165,19 @@ struct qemu_ether_header { |
147 | 165 | |
148 | 166 | struct pcnet_initblk16 { |
149 | 167 | uint16_t mode; |
150 | - uint16_t padr1; | |
151 | - uint16_t padr2; | |
152 | - uint16_t padr3; | |
153 | - uint16_t ladrf1; | |
154 | - uint16_t ladrf2; | |
155 | - uint16_t ladrf3; | |
156 | - uint16_t ladrf4; | |
157 | - unsigned PACKED_FIELD(rdra:24); | |
158 | - unsigned PACKED_FIELD(res1:5); | |
159 | - unsigned PACKED_FIELD(rlen:3); | |
160 | - unsigned PACKED_FIELD(tdra:24); | |
161 | - unsigned PACKED_FIELD(res2:5); | |
162 | - unsigned PACKED_FIELD(tlen:3); | |
168 | + uint16_t padr[3]; | |
169 | + uint16_t ladrf[4]; | |
170 | + uint32_t rdra; | |
171 | + uint32_t tdra; | |
163 | 172 | }; |
164 | 173 | |
165 | 174 | struct pcnet_initblk32 { |
166 | 175 | uint16_t mode; |
167 | - unsigned PACKED_FIELD(res1:4); | |
168 | - unsigned PACKED_FIELD(rlen:4); | |
169 | - unsigned PACKED_FIELD(res2:4); | |
170 | - unsigned PACKED_FIELD(tlen:4); | |
171 | - uint16_t padr1; | |
172 | - uint16_t padr2; | |
173 | - uint16_t padr3; | |
176 | + uint8_t rlen; | |
177 | + uint8_t tlen; | |
178 | + uint16_t padr[3]; | |
174 | 179 | uint16_t _res; |
175 | - uint16_t ladrf1; | |
176 | - uint16_t ladrf2; | |
177 | - uint16_t ladrf3; | |
178 | - uint16_t ladrf4; | |
180 | + uint16_t ladrf[4]; | |
179 | 181 | uint32_t rdra; |
180 | 182 | uint32_t tdra; |
181 | 183 | }; |
... | ... | @@ -255,22 +257,32 @@ static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd, target_p |
255 | 257 | { |
256 | 258 | if (!BCR_SWSTYLE(s)) { |
257 | 259 | uint16_t xda[4]; |
258 | - cpu_physical_memory_read(addr, | |
260 | + s->phys_mem_read(s->dma_opaque, addr, | |
259 | 261 | (void *)&xda[0], sizeof(xda)); |
260 | - ((uint32_t *)tmd)[0] = (xda[0]&0xffff) | | |
262 | + if (CSR_BIGENDIAN(s)) { | |
263 | + ((uint32_t *)tmd)[0] = be16_to_cpu(xda[0]) | | |
264 | + ((be16_to_cpu(xda[1]) & 0x00ff) << 16); | |
265 | + ((uint32_t *)tmd)[1] = be16_to_cpu(xda[2]) | | |
266 | + ((be16_to_cpu(xda[1]) & 0xff00) << 16); | |
267 | + ((uint32_t *)tmd)[2] = | |
268 | + (be16_to_cpu(xda[3]) & 0xffff) << 16; | |
269 | + ((uint32_t *)tmd)[3] = 0; | |
270 | + } else { | |
271 | + ((uint32_t *)tmd)[0] = (xda[0]&0xffff) | | |
261 | 272 | ((xda[1]&0x00ff) << 16); |
262 | - ((uint32_t *)tmd)[1] = (xda[2]&0xffff)| | |
273 | + ((uint32_t *)tmd)[1] = (xda[2]&0xffff)| | |
263 | 274 | ((xda[1] & 0xff00) << 16); |
264 | - ((uint32_t *)tmd)[2] = | |
275 | + ((uint32_t *)tmd)[2] = | |
265 | 276 | (xda[3] & 0xffff) << 16; |
266 | - ((uint32_t *)tmd)[3] = 0; | |
277 | + ((uint32_t *)tmd)[3] = 0; | |
278 | + } | |
267 | 279 | } |
268 | 280 | else |
269 | 281 | if (BCR_SWSTYLE(s) != 3) |
270 | - cpu_physical_memory_read(addr, (void *)tmd, 16); | |
282 | + s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, 16); | |
271 | 283 | else { |
272 | 284 | uint32_t xda[4]; |
273 | - cpu_physical_memory_read(addr, | |
285 | + s->phys_mem_read(s->dma_opaque, addr, | |
274 | 286 | (void *)&xda[0], sizeof(xda)); |
275 | 287 | ((uint32_t *)tmd)[0] = xda[2]; |
276 | 288 | ((uint32_t *)tmd)[1] = xda[1]; |
... | ... | @@ -283,24 +295,32 @@ static inline void pcnet_tmd_store(PCNetState *s, struct pcnet_TMD *tmd, target_ |
283 | 295 | { |
284 | 296 | if (!BCR_SWSTYLE(s)) { |
285 | 297 | uint16_t xda[4]; |
286 | - xda[0] = ((uint32_t *)tmd)[0] & 0xffff; | |
287 | - xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) | | |
288 | - ((((uint32_t *)tmd)[1]>>16)&0xff00); | |
289 | - xda[2] = ((uint32_t *)tmd)[1] & 0xffff; | |
290 | - xda[3] = ((uint32_t *)tmd)[2] >> 16; | |
291 | - cpu_physical_memory_write(addr, | |
298 | + if (CSR_BIGENDIAN(s)) { | |
299 | + xda[0] = cpu_to_be16(((uint32_t *)tmd)[0] & 0xffff); | |
300 | + xda[1] = cpu_to_be16(((((uint32_t *)tmd)[0] >> 16) & 0x00ff) | | |
301 | + ((((uint32_t *)tmd)[1] >> 16) & 0xff00)); | |
302 | + xda[2] = cpu_to_be16(((uint32_t *)tmd)[1] & 0xffff); | |
303 | + xda[3] = cpu_to_be16(((uint32_t *)tmd)[2] >> 16); | |
304 | + } else { | |
305 | + xda[0] = ((uint32_t *)tmd)[0] & 0xffff; | |
306 | + xda[1] = ((((uint32_t *)tmd)[0]>>16)&0x00ff) | | |
307 | + ((((uint32_t *)tmd)[1]>>16)&0xff00); | |
308 | + xda[2] = ((uint32_t *)tmd)[1] & 0xffff; | |
309 | + xda[3] = ((uint32_t *)tmd)[2] >> 16; | |
310 | + } | |
311 | + s->phys_mem_write(s->dma_opaque, addr, | |
292 | 312 | (void *)&xda[0], sizeof(xda)); |
293 | 313 | } |
294 | 314 | else { |
295 | 315 | if (BCR_SWSTYLE(s) != 3) |
296 | - cpu_physical_memory_write(addr, (void *)tmd, 16); | |
316 | + s->phys_mem_write(s->dma_opaque, addr, (void *)tmd, 16); | |
297 | 317 | else { |
298 | 318 | uint32_t xda[4]; |
299 | 319 | xda[0] = ((uint32_t *)tmd)[2]; |
300 | 320 | xda[1] = ((uint32_t *)tmd)[1]; |
301 | 321 | xda[2] = ((uint32_t *)tmd)[0]; |
302 | 322 | xda[3] = ((uint32_t *)tmd)[3]; |
303 | - cpu_physical_memory_write(addr, | |
323 | + s->phys_mem_write(s->dma_opaque, addr, | |
304 | 324 | (void *)&xda[0], sizeof(xda)); |
305 | 325 | } |
306 | 326 | } |
... | ... | @@ -310,21 +330,30 @@ static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_p |
310 | 330 | { |
311 | 331 | if (!BCR_SWSTYLE(s)) { |
312 | 332 | uint16_t rda[4]; |
313 | - cpu_physical_memory_read(addr, | |
333 | + s->phys_mem_read(s->dma_opaque, addr, | |
314 | 334 | (void *)&rda[0], sizeof(rda)); |
315 | - ((uint32_t *)rmd)[0] = (rda[0]&0xffff)| | |
335 | + if (CSR_BIGENDIAN(s)) { | |
336 | + ((uint32_t *)rmd)[0] = (be16_to_cpu(rda[0]) & 0xffff) | | |
337 | + ((be16_to_cpu(rda[1]) & 0x00ff) << 16); | |
338 | + ((uint32_t *)rmd)[1] = (be16_to_cpu(rda[2]) & 0xffff) | | |
339 | + ((be16_to_cpu(rda[1]) & 0xff00) << 16); | |
340 | + ((uint32_t *)rmd)[2] = be16_to_cpu(rda[3]) & 0xffff; | |
341 | + ((uint32_t *)rmd)[3] = 0; | |
342 | + } else { | |
343 | + ((uint32_t *)rmd)[0] = (rda[0]&0xffff)| | |
316 | 344 | ((rda[1] & 0x00ff) << 16); |
317 | - ((uint32_t *)rmd)[1] = (rda[2]&0xffff)| | |
345 | + ((uint32_t *)rmd)[1] = (rda[2]&0xffff)| | |
318 | 346 | ((rda[1] & 0xff00) << 16); |
319 | - ((uint32_t *)rmd)[2] = rda[3] & 0xffff; | |
320 | - ((uint32_t *)rmd)[3] = 0; | |
347 | + ((uint32_t *)rmd)[2] = rda[3] & 0xffff; | |
348 | + ((uint32_t *)rmd)[3] = 0; | |
349 | + } | |
321 | 350 | } |
322 | 351 | else |
323 | 352 | if (BCR_SWSTYLE(s) != 3) |
324 | - cpu_physical_memory_read(addr, (void *)rmd, 16); | |
353 | + s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, 16); | |
325 | 354 | else { |
326 | 355 | uint32_t rda[4]; |
327 | - cpu_physical_memory_read(addr, | |
356 | + s->phys_mem_read(s->dma_opaque, addr, | |
328 | 357 | (void *)&rda[0], sizeof(rda)); |
329 | 358 | ((uint32_t *)rmd)[0] = rda[2]; |
330 | 359 | ((uint32_t *)rmd)[1] = rda[1]; |
... | ... | @@ -336,25 +365,33 @@ static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd, target_p |
336 | 365 | static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_phys_addr_t addr) |
337 | 366 | { |
338 | 367 | if (!BCR_SWSTYLE(s)) { |
339 | - uint16_t rda[4]; \ | |
340 | - rda[0] = ((uint32_t *)rmd)[0] & 0xffff; \ | |
341 | - rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)|\ | |
342 | - ((((uint32_t *)rmd)[1]>>16)&0xff00);\ | |
343 | - rda[2] = ((uint32_t *)rmd)[1] & 0xffff; \ | |
344 | - rda[3] = ((uint32_t *)rmd)[2] & 0xffff; \ | |
345 | - cpu_physical_memory_write(addr, \ | |
346 | - (void *)&rda[0], sizeof(rda)); \ | |
368 | + uint16_t rda[4]; | |
369 | + if (CSR_BIGENDIAN(s)) { | |
370 | + rda[0] = cpu_to_be16(((uint32_t *)rmd)[0] & 0xffff); | |
371 | + rda[1] = cpu_to_be16(((((uint32_t *)rmd)[0] >> 16) & 0xff) | | |
372 | + ((((uint32_t *)rmd)[1] >> 16) & 0xff00)); | |
373 | + rda[2] = cpu_to_be16(((uint32_t *)rmd)[1] & 0xffff); | |
374 | + rda[3] = cpu_to_be16(((uint32_t *)rmd)[2] & 0xffff); | |
375 | + } else { | |
376 | + rda[0] = ((uint32_t *)rmd)[0] & 0xffff; | |
377 | + rda[1] = ((((uint32_t *)rmd)[0]>>16)&0xff)| | |
378 | + ((((uint32_t *)rmd)[1]>>16)&0xff00); | |
379 | + rda[2] = ((uint32_t *)rmd)[1] & 0xffff; | |
380 | + rda[3] = ((uint32_t *)rmd)[2] & 0xffff; | |
381 | + } | |
382 | + s->phys_mem_write(s->dma_opaque, addr, | |
383 | + (void *)&rda[0], sizeof(rda)); | |
347 | 384 | } |
348 | 385 | else { |
349 | 386 | if (BCR_SWSTYLE(s) != 3) |
350 | - cpu_physical_memory_write(addr, (void *)rmd, 16); | |
387 | + s->phys_mem_write(s->dma_opaque, addr, (void *)rmd, 16); | |
351 | 388 | else { |
352 | 389 | uint32_t rda[4]; |
353 | 390 | rda[0] = ((uint32_t *)rmd)[2]; |
354 | 391 | rda[1] = ((uint32_t *)rmd)[1]; |
355 | 392 | rda[2] = ((uint32_t *)rmd)[0]; |
356 | 393 | rda[3] = ((uint32_t *)rmd)[3]; |
357 | - cpu_physical_memory_write(addr, | |
394 | + s->phys_mem_write(s->dma_opaque, addr, | |
358 | 395 | (void *)&rda[0], sizeof(rda)); |
359 | 396 | } |
360 | 397 | } |
... | ... | @@ -391,7 +428,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ |
391 | 428 | case 0x00: \ |
392 | 429 | do { \ |
393 | 430 | uint16_t rda[4]; \ |
394 | - cpu_physical_memory_read((ADDR), \ | |
431 | + s->phys_mem_read(s->dma_opaque, (ADDR), \ | |
395 | 432 | (void *)&rda[0], sizeof(rda)); \ |
396 | 433 | (RES) |= (rda[2] & 0xf000)!=0xf000; \ |
397 | 434 | (RES) |= (rda[3] & 0xf000)!=0x0000; \ |
... | ... | @@ -401,7 +438,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ |
401 | 438 | case 0x02: \ |
402 | 439 | do { \ |
403 | 440 | uint32_t rda[4]; \ |
404 | - cpu_physical_memory_read((ADDR), \ | |
441 | + s->phys_mem_read(s->dma_opaque, (ADDR), \ | |
405 | 442 | (void *)&rda[0], sizeof(rda)); \ |
406 | 443 | (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \ |
407 | 444 | (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \ |
... | ... | @@ -410,7 +447,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ |
410 | 447 | case 0x03: \ |
411 | 448 | do { \ |
412 | 449 | uint32_t rda[4]; \ |
413 | - cpu_physical_memory_read((ADDR), \ | |
450 | + s->phys_mem_read(s->dma_opaque, (ADDR), \ | |
414 | 451 | (void *)&rda[0], sizeof(rda)); \ |
415 | 452 | (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \ |
416 | 453 | (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \ |
... | ... | @@ -424,7 +461,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ |
424 | 461 | case 0x00: \ |
425 | 462 | do { \ |
426 | 463 | uint16_t xda[4]; \ |
427 | - cpu_physical_memory_read((ADDR), \ | |
464 | + s->phys_mem_read(s->dma_opaque, (ADDR), \ | |
428 | 465 | (void *)&xda[0], sizeof(xda)); \ |
429 | 466 | (RES) |= (xda[2] & 0xf000)!=0xf000;\ |
430 | 467 | } while (0); \ |
... | ... | @@ -434,7 +471,7 @@ static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd, target_ |
434 | 471 | case 0x03: \ |
435 | 472 | do { \ |
436 | 473 | uint32_t xda[4]; \ |
437 | - cpu_physical_memory_read((ADDR), \ | |
474 | + s->phys_mem_read(s->dma_opaque, (ADDR), \ | |
438 | 475 | (void *)&xda[0], sizeof(xda)); \ |
439 | 476 | (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \ |
440 | 477 | } while (0); \ |
... | ... | @@ -721,51 +758,86 @@ static void pcnet_update_irq(PCNetState *s) |
721 | 758 | printf("pcnet: INTA=%d\n", isr); |
722 | 759 | #endif |
723 | 760 | } |
724 | - pci_set_irq(&s->dev, 0, isr); | |
725 | - s->isr = isr; | |
761 | + s->set_irq_cb(s, isr); | |
762 | + s->isr = isr; | |
726 | 763 | } |
727 | 764 | |
728 | 765 | static void pcnet_init(PCNetState *s) |
729 | 766 | { |
767 | + int rlen, tlen; | |
768 | + uint16_t *padr, *ladrf, mode; | |
769 | + uint32_t rdra, tdra; | |
770 | + | |
730 | 771 | #ifdef PCNET_DEBUG |
731 | 772 | printf("pcnet_init init_addr=0x%08x\n", PHYSADDR(s,CSR_IADR(s))); |
732 | 773 | #endif |
733 | 774 | |
734 | -#define PCNET_INIT() do { \ | |
735 | - cpu_physical_memory_read(PHYSADDR(s,CSR_IADR(s)), \ | |
736 | - (uint8_t *)&initblk, sizeof(initblk)); \ | |
737 | - s->csr[15] = le16_to_cpu(initblk.mode); \ | |
738 | - CSR_RCVRL(s) = (initblk.rlen < 9) ? (1 << initblk.rlen) : 512; \ | |
739 | - CSR_XMTRL(s) = (initblk.tlen < 9) ? (1 << initblk.tlen) : 512; \ | |
740 | - s->csr[ 6] = (initblk.tlen << 12) | (initblk.rlen << 8); \ | |
741 | - s->csr[ 8] = le16_to_cpu(initblk.ladrf1); \ | |
742 | - s->csr[ 9] = le16_to_cpu(initblk.ladrf2); \ | |
743 | - s->csr[10] = le16_to_cpu(initblk.ladrf3); \ | |
744 | - s->csr[11] = le16_to_cpu(initblk.ladrf4); \ | |
745 | - s->csr[12] = le16_to_cpu(initblk.padr1); \ | |
746 | - s->csr[13] = le16_to_cpu(initblk.padr2); \ | |
747 | - s->csr[14] = le16_to_cpu(initblk.padr3); \ | |
748 | - s->rdra = PHYSADDR(s,initblk.rdra); \ | |
749 | - s->tdra = PHYSADDR(s,initblk.tdra); \ | |
750 | -} while (0) | |
751 | - | |
752 | 775 | if (BCR_SSIZE32(s)) { |
753 | 776 | struct pcnet_initblk32 initblk; |
754 | - PCNET_INIT(); | |
755 | -#ifdef PCNET_DEBUG | |
756 | - printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n", | |
757 | - initblk.rlen, initblk.tlen); | |
758 | -#endif | |
777 | + s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)), | |
778 | + (uint8_t *)&initblk, sizeof(initblk)); | |
779 | + mode = initblk.mode; | |
780 | + rlen = initblk.rlen >> 4; | |
781 | + tlen = initblk.tlen >> 4; | |
782 | + ladrf = initblk.ladrf; | |
783 | + padr = initblk.padr; | |
784 | + if (CSR_BIGENDIAN(s)) { | |
785 | + rdra = be32_to_cpu(initblk.rdra); | |
786 | + tdra = be32_to_cpu(initblk.tdra); | |
787 | + } else { | |
788 | + rdra = le32_to_cpu(initblk.rdra); | |
789 | + tdra = le32_to_cpu(initblk.tdra); | |
790 | + } | |
791 | + s->rdra = PHYSADDR(s,initblk.rdra); | |
792 | + s->tdra = PHYSADDR(s,initblk.tdra); | |
759 | 793 | } else { |
760 | 794 | struct pcnet_initblk16 initblk; |
761 | - PCNET_INIT(); | |
762 | -#ifdef PCNET_DEBUG | |
763 | - printf("initblk.rlen=0x%02x, initblk.tlen=0x%02x\n", | |
764 | - initblk.rlen, initblk.tlen); | |
795 | + s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)), | |
796 | + (uint8_t *)&initblk, sizeof(initblk)); | |
797 | + mode = initblk.mode; | |
798 | + ladrf = initblk.ladrf; | |
799 | + padr = initblk.padr; | |
800 | + if (CSR_BIGENDIAN(s)) { | |
801 | + rdra = be32_to_cpu(initblk.rdra); | |
802 | + tdra = be32_to_cpu(initblk.tdra); | |
803 | + } else { | |
804 | + rdra = le32_to_cpu(initblk.rdra); | |
805 | + tdra = le32_to_cpu(initblk.tdra); | |
806 | + } | |
807 | + rlen = rdra >> 29; | |
808 | + tlen = tdra >> 29; | |
809 | + rdra &= 0x00ffffff; | |
810 | + tdra &= 0x00ffffff; | |
811 | + } | |
812 | + | |
813 | +#if defined(PCNET_DEBUG) | |
814 | + printf("rlen=%d tlen=%d\n", | |
815 | + rlen, tlen); | |
765 | 816 | #endif |
817 | + CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512; | |
818 | + CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512; | |
819 | + s->csr[ 6] = (tlen << 12) | (rlen << 8); | |
820 | + if (CSR_BIGENDIAN(s)) { | |
821 | + s->csr[15] = be16_to_cpu(mode); | |
822 | + s->csr[ 8] = be16_to_cpu(ladrf[0]); | |
823 | + s->csr[ 9] = be16_to_cpu(ladrf[1]); | |
824 | + s->csr[10] = be16_to_cpu(ladrf[2]); | |
825 | + s->csr[11] = be16_to_cpu(ladrf[3]); | |
826 | + s->csr[12] = be16_to_cpu(padr[0]); | |
827 | + s->csr[13] = be16_to_cpu(padr[1]); | |
828 | + s->csr[14] = be16_to_cpu(padr[2]); | |
829 | + } else { | |
830 | + s->csr[15] = le16_to_cpu(mode); | |
831 | + s->csr[ 8] = le16_to_cpu(ladrf[0]); | |
832 | + s->csr[ 9] = le16_to_cpu(ladrf[1]); | |
833 | + s->csr[10] = le16_to_cpu(ladrf[2]); | |
834 | + s->csr[11] = le16_to_cpu(ladrf[3]); | |
835 | + s->csr[12] = le16_to_cpu(padr[0]); | |
836 | + s->csr[13] = le16_to_cpu(padr[1]); | |
837 | + s->csr[14] = le16_to_cpu(padr[2]); | |
766 | 838 | } |
767 | - | |
768 | -#undef PCNET_INIT | |
839 | + s->rdra = PHYSADDR(s, rdra); | |
840 | + s->tdra = PHYSADDR(s, tdra); | |
769 | 841 | |
770 | 842 | CSR_RCVRC(s) = CSR_RCVRL(s); |
771 | 843 | CSR_XMTRC(s) = CSR_XMTRL(s); |
... | ... | @@ -1035,7 +1107,7 @@ static void pcnet_receive(void *opaque, const uint8_t *buf, int size) |
1035 | 1107 | #define PCNET_RECV_STORE() do { \ |
1036 | 1108 | int count = MIN(4096 - rmd.rmd1.bcnt,size); \ |
1037 | 1109 | target_phys_addr_t rbadr = PHYSADDR(s, rmd.rmd0.rbadr); \ |
1038 | - cpu_physical_memory_write(rbadr, src, count); \ | |
1110 | + s->phys_mem_write(s->dma_opaque, rbadr, src, count); \ | |
1039 | 1111 | src += count; size -= count; \ |
1040 | 1112 | rmd.rmd2.mcnt = count; rmd.rmd1.own = 0; \ |
1041 | 1113 | RMDSTORE(&rmd, PHYSADDR(s,crda)); \ |
... | ... | @@ -1125,14 +1197,14 @@ static void pcnet_transmit(PCNetState *s) |
1125 | 1197 | if (tmd.tmd1.stp) { |
1126 | 1198 | s->xmit_pos = 0; |
1127 | 1199 | if (!tmd.tmd1.enp) { |
1128 | - cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr), | |
1200 | + s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr), | |
1129 | 1201 | s->buffer, 4096 - tmd.tmd1.bcnt); |
1130 | 1202 | s->xmit_pos += 4096 - tmd.tmd1.bcnt; |
1131 | 1203 | } |
1132 | 1204 | xmit_cxda = PHYSADDR(s,CSR_CXDA(s)); |
1133 | 1205 | } |
1134 | 1206 | if (tmd.tmd1.enp && (s->xmit_pos >= 0)) { |
1135 | - cpu_physical_memory_read(PHYSADDR(s, tmd.tmd0.tbadr), | |
1207 | + s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tmd0.tbadr), | |
1136 | 1208 | s->buffer + s->xmit_pos, 4096 - tmd.tmd1.bcnt); |
1137 | 1209 | s->xmit_pos += 4096 - tmd.tmd1.bcnt; |
1138 | 1210 | #ifdef PCNET_DEBUG |
... | ... | @@ -1426,8 +1498,9 @@ static uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap) |
1426 | 1498 | return val; |
1427 | 1499 | } |
1428 | 1500 | |
1429 | -static void pcnet_h_reset(PCNetState *s) | |
1501 | +void pcnet_h_reset(void *opaque) | |
1430 | 1502 | { |
1503 | + PCNetState *s = opaque; | |
1431 | 1504 | int i; |
1432 | 1505 | uint16_t checksum; |
1433 | 1506 | |
... | ... | @@ -1703,6 +1776,90 @@ static uint32_t pcnet_mmio_readl(void *opaque, target_phys_addr_t addr) |
1703 | 1776 | } |
1704 | 1777 | |
1705 | 1778 | |
1779 | +static void pcnet_save(QEMUFile *f, void *opaque) | |
1780 | +{ | |
1781 | + PCNetState *s = opaque; | |
1782 | + unsigned int i; | |
1783 | + | |
1784 | + if (s->pci_dev) | |
1785 | + pci_device_save(s->pci_dev, f); | |
1786 | + | |
1787 | + qemu_put_be32s(f, &s->rap); | |
1788 | + qemu_put_be32s(f, &s->isr); | |
1789 | + qemu_put_be32s(f, &s->lnkst); | |
1790 | + qemu_put_be32s(f, &s->rdra); | |
1791 | + qemu_put_be32s(f, &s->tdra); | |
1792 | + qemu_put_buffer(f, s->prom, 16); | |
1793 | + for (i = 0; i < 128; i++) | |
1794 | + qemu_put_be16s(f, &s->csr[i]); | |
1795 | + for (i = 0; i < 32; i++) | |
1796 | + qemu_put_be16s(f, &s->bcr[i]); | |
1797 | + qemu_put_be64s(f, &s->timer); | |
1798 | + qemu_put_be32s(f, &s->xmit_pos); | |
1799 | + qemu_put_be32s(f, &s->recv_pos); | |
1800 | + qemu_put_buffer(f, s->buffer, 4096); | |
1801 | + qemu_put_be32s(f, &s->tx_busy); | |
1802 | + qemu_put_timer(f, s->poll_timer); | |
1803 | +} | |
1804 | + | |
1805 | +static int pcnet_load(QEMUFile *f, void *opaque, int version_id) | |
1806 | +{ | |
1807 | + PCNetState *s = opaque; | |
1808 | + int i, ret; | |
1809 | + | |
1810 | + if (version_id != 2) | |
1811 | + return -EINVAL; | |
1812 | + | |
1813 | + if (s->pci_dev) { | |
1814 | + ret = pci_device_load(s->pci_dev, f); | |
1815 | + if (ret < 0) | |
1816 | + return ret; | |
1817 | + } | |
1818 | + | |
1819 | + qemu_get_be32s(f, &s->rap); | |
1820 | + qemu_get_be32s(f, &s->isr); | |
1821 | + qemu_get_be32s(f, &s->lnkst); | |
1822 | + qemu_get_be32s(f, &s->rdra); | |
1823 | + qemu_get_be32s(f, &s->tdra); | |
1824 | + qemu_get_buffer(f, s->prom, 16); | |
1825 | + for (i = 0; i < 128; i++) | |
1826 | + qemu_get_be16s(f, &s->csr[i]); | |
1827 | + for (i = 0; i < 32; i++) | |
1828 | + qemu_get_be16s(f, &s->bcr[i]); | |
1829 | + qemu_get_be64s(f, &s->timer); | |
1830 | + qemu_get_be32s(f, &s->xmit_pos); | |
1831 | + qemu_get_be32s(f, &s->recv_pos); | |
1832 | + qemu_get_buffer(f, s->buffer, 4096); | |
1833 | + qemu_get_be32s(f, &s->tx_busy); | |
1834 | + qemu_get_timer(f, s->poll_timer); | |
1835 | + | |
1836 | + return 0; | |
1837 | +} | |
1838 | + | |
1839 | +static void pcnet_common_init(PCNetState *d, NICInfo *nd, const char *info_str) | |
1840 | +{ | |
1841 | + d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d); | |
1842 | + | |
1843 | + d->nd = nd; | |
1844 | + | |
1845 | + d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, | |
1846 | + pcnet_can_receive, d); | |
1847 | + | |
1848 | + snprintf(d->vc->info_str, sizeof(d->vc->info_str), | |
1849 | + "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | |
1850 | + d->nd->macaddr[0], | |
1851 | + d->nd->macaddr[1], | |
1852 | + d->nd->macaddr[2], | |
1853 | + d->nd->macaddr[3], | |
1854 | + d->nd->macaddr[4], | |
1855 | + d->nd->macaddr[5]); | |
1856 | + | |
1857 | + pcnet_h_reset(d); | |
1858 | + register_savevm("pcnet", 0, 2, pcnet_save, pcnet_load, d); | |
1859 | +} | |
1860 | + | |
1861 | +/* PCI interface */ | |
1862 | + | |
1706 | 1863 | static CPUWriteMemoryFunc *pcnet_mmio_write[] = { |
1707 | 1864 | (CPUWriteMemoryFunc *)&pcnet_mmio_writeb, |
1708 | 1865 | (CPUWriteMemoryFunc *)&pcnet_mmio_writew, |
... | ... | @@ -1724,7 +1881,26 @@ static void pcnet_mmio_map(PCIDevice *pci_dev, int region_num, |
1724 | 1881 | printf("pcnet_ioport_map addr=0x%08x 0x%08x\n", addr, size); |
1725 | 1882 | #endif |
1726 | 1883 | |
1727 | - cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_io_addr); | |
1884 | + cpu_register_physical_memory(addr, PCNET_PNPMMIO_SIZE, d->mmio_index); | |
1885 | +} | |
1886 | + | |
1887 | +static void pcnet_pci_set_irq_cb(void *opaque, int isr) | |
1888 | +{ | |
1889 | + PCNetState *s = opaque; | |
1890 | + | |
1891 | + pci_set_irq(&s->dev, 0, isr); | |
1892 | +} | |
1893 | + | |
1894 | +static void pci_physical_memory_write(void *dma_opaque, target_phys_addr_t addr, | |
1895 | + uint8_t *buf, int len) | |
1896 | +{ | |
1897 | + cpu_physical_memory_write(addr, buf, len); | |
1898 | +} | |
1899 | + | |
1900 | +static void pci_physical_memory_read(void *dma_opaque, target_phys_addr_t addr, | |
1901 | + uint8_t *buf, int len) | |
1902 | +{ | |
1903 | + cpu_physical_memory_read(addr, buf, len); | |
1728 | 1904 | } |
1729 | 1905 | |
1730 | 1906 | void pci_pcnet_init(PCIBus *bus, NICInfo *nd) |
... | ... | @@ -1760,7 +1936,7 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd) |
1760 | 1936 | pci_conf[0x3f] = 0xff; |
1761 | 1937 | |
1762 | 1938 | /* Handler for memory-mapped I/O */ |
1763 | - d->mmio_io_addr = | |
1939 | + d->mmio_index = | |
1764 | 1940 | cpu_register_io_memory(0, pcnet_mmio_read, pcnet_mmio_write, d); |
1765 | 1941 | |
1766 | 1942 | pci_register_io_region((PCIDevice *)d, 0, PCNET_IOPORT_SIZE, |
... | ... | @@ -1769,21 +1945,58 @@ void pci_pcnet_init(PCIBus *bus, NICInfo *nd) |
1769 | 1945 | pci_register_io_region((PCIDevice *)d, 1, PCNET_PNPMMIO_SIZE, |
1770 | 1946 | PCI_ADDRESS_SPACE_MEM, pcnet_mmio_map); |
1771 | 1947 | |
1772 | - d->poll_timer = qemu_new_timer(vm_clock, pcnet_poll_timer, d); | |
1948 | + d->set_irq_cb = pcnet_pci_set_irq_cb; | |
1949 | + d->phys_mem_read = pci_physical_memory_read; | |
1950 | + d->phys_mem_write = pci_physical_memory_write; | |
1951 | + d->pci_dev = &d->dev; | |
1773 | 1952 | |
1774 | - d->nd = nd; | |
1953 | + pcnet_common_init(d, nd, "pcnet"); | |
1954 | +} | |
1775 | 1955 | |
1776 | - d->vc = qemu_new_vlan_client(nd->vlan, pcnet_receive, | |
1777 | - pcnet_can_receive, d); | |
1778 | - | |
1779 | - snprintf(d->vc->info_str, sizeof(d->vc->info_str), | |
1780 | - "pcnet macaddr=%02x:%02x:%02x:%02x:%02x:%02x", | |
1781 | - d->nd->macaddr[0], | |
1782 | - d->nd->macaddr[1], | |
1783 | - d->nd->macaddr[2], | |
1784 | - d->nd->macaddr[3], | |
1785 | - d->nd->macaddr[4], | |
1786 | - d->nd->macaddr[5]); | |
1956 | +/* SPARC32 interface */ | |
1787 | 1957 | |
1788 | - pcnet_h_reset(d); | |
1958 | +#if defined (TARGET_SPARC) && !defined(TARGET_SPARC64) // Avoid compile failure | |
1959 | + | |
1960 | +static CPUReadMemoryFunc *lance_mem_read[3] = { | |
1961 | + (CPUReadMemoryFunc *)&pcnet_ioport_readw, | |
1962 | + (CPUReadMemoryFunc *)&pcnet_ioport_readw, | |
1963 | + (CPUReadMemoryFunc *)&pcnet_ioport_readw, | |
1964 | +}; | |
1965 | + | |
1966 | +static CPUWriteMemoryFunc *lance_mem_write[3] = { | |
1967 | + (CPUWriteMemoryFunc *)&pcnet_ioport_writew, | |
1968 | + (CPUWriteMemoryFunc *)&pcnet_ioport_writew, | |
1969 | + (CPUWriteMemoryFunc *)&pcnet_ioport_writew, | |
1970 | +}; | |
1971 | + | |
1972 | +static void pcnet_sparc_set_irq_cb(void *opaque, int isr) | |
1973 | +{ | |
1974 | + PCNetState *s = opaque; | |
1975 | + | |
1976 | + ledma_set_irq(s->dma_opaque, isr); | |
1977 | +} | |
1978 | + | |
1979 | +void *lance_init(NICInfo *nd, uint32_t leaddr, void *dma_opaque) | |
1980 | +{ | |
1981 | + PCNetState *d; | |
1982 | + int lance_io_memory; | |
1983 | + | |
1984 | + d = qemu_mallocz(sizeof(PCNetState)); | |
1985 | + if (!d) | |
1986 | + return NULL; | |
1987 | + | |
1988 | + lance_io_memory = | |
1989 | + cpu_register_io_memory(0, lance_mem_read, lance_mem_write, d); | |
1990 | + | |
1991 | + d->dma_opaque = dma_opaque; | |
1992 | + cpu_register_physical_memory(leaddr, 4, lance_io_memory); | |
1993 | + | |
1994 | + d->set_irq_cb = pcnet_sparc_set_irq_cb; | |
1995 | + d->phys_mem_read = ledma_memory_read; | |
1996 | + d->phys_mem_write = ledma_memory_write; | |
1997 | + | |
1998 | + pcnet_common_init(d, nd, "lance"); | |
1999 | + | |
2000 | + return d; | |
1789 | 2001 | } |
2002 | +#endif /* TARGET_SPARC */ | ... | ... |