Revision 66321a11 hw/lance.c
b/hw/lance.c | ||
---|---|---|
1 | 1 |
/* |
2 | 2 |
* QEMU Lance emulation |
3 | 3 |
* |
4 |
* Copyright (c) 2003-2004 Fabrice Bellard
|
|
4 |
* Copyright (c) 2003-2005 Fabrice Bellard
|
|
5 | 5 |
* |
6 | 6 |
* Permission is hereby granted, free of charge, to any person obtaining a copy |
7 | 7 |
* of this software and associated documentation files (the "Software"), to deal |
... | ... | |
26 | 26 |
/* debug LANCE card */ |
27 | 27 |
//#define DEBUG_LANCE |
28 | 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 |
|
|
29 | 36 |
#ifndef LANCE_LOG_TX_BUFFERS |
30 | 37 |
#define LANCE_LOG_TX_BUFFERS 4 |
31 | 38 |
#define LANCE_LOG_RX_BUFFERS 4 |
32 | 39 |
#endif |
33 | 40 |
|
34 |
#define CRC_POLYNOMIAL_BE 0x04c11db7UL /* Ethernet CRC, big endian */ |
|
35 |
#define CRC_POLYNOMIAL_LE 0xedb88320UL /* Ethernet CRC, little endian */ |
|
36 |
|
|
37 |
|
|
38 | 41 |
#define LE_CSR0 0 |
39 | 42 |
#define LE_CSR1 1 |
40 | 43 |
#define LE_CSR2 2 |
41 | 44 |
#define LE_CSR3 3 |
42 |
#define LE_MAXREG (LE_CSR3 + 1) |
|
45 |
#define LE_NREGS (LE_CSR3 + 1) |
|
46 |
#define LE_MAXREG LE_CSR3 |
|
43 | 47 |
|
44 | 48 |
#define LE_RDP 0 |
45 | 49 |
#define LE_RAP 1 |
... | ... | |
148 | 152 |
|
149 | 153 |
#define LEDMA_REGS 4 |
150 | 154 |
#define LEDMA_MAXADDR (LEDMA_REGS * 4 - 1) |
151 |
#if 0 |
|
152 |
/* Structure to describe the current status of DMA registers on the Sparc */ |
|
153 |
struct sparc_dma_registers { |
|
154 |
uint32_t cond_reg; /* DMA condition register */ |
|
155 |
uint32_t st_addr; /* Start address of this transfer */ |
|
156 |
uint32_t cnt; /* How many bytes to transfer */ |
|
157 |
uint32_t dma_test; /* DMA test register */ |
|
158 |
}; |
|
159 |
#endif |
|
160 | 155 |
|
161 | 156 |
typedef struct LANCEState { |
162 | 157 |
NetDriverState *nd; |
163 | 158 |
uint32_t leptr; |
164 | 159 |
uint16_t addr; |
165 |
uint16_t regs[LE_MAXREG];
|
|
160 |
uint16_t regs[LE_NREGS];
|
|
166 | 161 |
uint8_t phys[6]; /* mac address */ |
167 | 162 |
int irq; |
168 | 163 |
unsigned int rxptr, txptr; |
... | ... | |
177 | 172 |
memcpy(s->phys, s->nd->macaddr, 6); |
178 | 173 |
s->rxptr = 0; |
179 | 174 |
s->txptr = 0; |
180 |
memset(s->regs, 0, LE_MAXREG * 2);
|
|
175 |
memset(s->regs, 0, LE_NREGS * 2);
|
|
181 | 176 |
s->regs[LE_CSR0] = LE_C0_STOP; |
182 | 177 |
memset(s->ledmaregs, 0, LEDMA_REGS * 4); |
183 | 178 |
} |
... | ... | |
190 | 185 |
saddr = addr & LE_MAXREG; |
191 | 186 |
switch (saddr >> 1) { |
192 | 187 |
case LE_RDP: |
188 |
DPRINTF("read dreg[%d] = %4.4x\n", s->addr, s->regs[s->addr]); |
|
193 | 189 |
return s->regs[s->addr]; |
194 | 190 |
case LE_RAP: |
191 |
DPRINTF("read areg = %4.4x\n", s->addr); |
|
195 | 192 |
return s->addr; |
196 | 193 |
default: |
194 |
DPRINTF("read unknown(%d)\n", saddr>>1); |
|
197 | 195 |
break; |
198 | 196 |
} |
199 | 197 |
return 0; |
... | ... | |
208 | 206 |
saddr = addr & LE_MAXREG; |
209 | 207 |
switch (saddr >> 1) { |
210 | 208 |
case LE_RDP: |
209 |
DPRINTF("write dreg[%d] = %4.4x\n", s->addr, val); |
|
211 | 210 |
switch(s->addr) { |
212 | 211 |
case LE_CSR0: |
213 | 212 |
if (val & LE_C0_STOP) { |
... | ... | |
242 | 241 |
} |
243 | 242 |
|
244 | 243 |
s->regs[LE_CSR0] = reg; |
245 |
|
|
246 |
// trigger bits |
|
247 |
//if (val & LE_C0_TDMD) |
|
248 |
|
|
249 |
if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA)) |
|
250 |
pic_set_irq(s->irq, 1); |
|
251 | 244 |
break; |
252 | 245 |
case LE_CSR1: |
253 | 246 |
s->leptr = (s->leptr & 0xffff0000) | (val & 0xffff); |
... | ... | |
263 | 256 |
} |
264 | 257 |
break; |
265 | 258 |
case LE_RAP: |
266 |
if (val < LE_MAXREG) |
|
259 |
DPRINTF("write areg = %4.4x\n", val); |
|
260 |
if (val < LE_NREGS) |
|
267 | 261 |
s->addr = val; |
268 | 262 |
break; |
269 | 263 |
default: |
264 |
DPRINTF("write unknown(%d) = %4.4x\n", saddr>>1, val); |
|
270 | 265 |
break; |
271 | 266 |
} |
272 | 267 |
lance_send(s); |
... | ... | |
292 | 287 |
uint32_t dmaptr = s->leptr + s->ledmaregs[3]; |
293 | 288 |
struct lance_init_block *ib; |
294 | 289 |
int i; |
295 |
uint16_t temp;
|
|
290 |
uint8_t temp8;
|
|
296 | 291 |
|
297 | 292 |
if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) |
298 | 293 |
return 0; |
... | ... | |
300 | 295 |
ib = (void *) iommu_translate(dmaptr); |
301 | 296 |
|
302 | 297 |
for (i = 0; i < RX_RING_SIZE; i++) { |
303 |
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); |
|
304 |
temp &= 0xff; |
|
305 |
if (temp == (LE_R1_OWN)) { |
|
306 |
#ifdef DEBUG_LANCE |
|
307 |
fprintf(stderr, "lance: can receive %d\n", RX_BUFF_SIZE); |
|
308 |
#endif |
|
298 |
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1); |
|
299 |
if (temp8 == (LE_R1_OWN)) { |
|
300 |
DPRINTF("can receive %d\n", RX_BUFF_SIZE); |
|
309 | 301 |
return RX_BUFF_SIZE; |
310 | 302 |
} |
311 | 303 |
} |
312 |
#ifdef DEBUG_LANCE |
|
313 |
fprintf(stderr, "lance: cannot receive\n"); |
|
314 |
#endif |
|
304 |
DPRINTF("cannot receive\n"); |
|
315 | 305 |
return 0; |
316 | 306 |
} |
317 | 307 |
|
... | ... | |
322 | 312 |
LANCEState *s = opaque; |
323 | 313 |
uint32_t dmaptr = s->leptr + s->ledmaregs[3]; |
324 | 314 |
struct lance_init_block *ib; |
325 |
unsigned int i, old_rxptr, j; |
|
326 |
uint16_t temp; |
|
315 |
unsigned int i, old_rxptr; |
|
316 |
uint16_t temp16; |
|
317 |
uint8_t temp8; |
|
327 | 318 |
|
319 |
DPRINTF("receive size %d\n", size); |
|
328 | 320 |
if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) |
329 | 321 |
return; |
330 | 322 |
|
... | ... | |
332 | 324 |
|
333 | 325 |
old_rxptr = s->rxptr; |
334 | 326 |
for (i = s->rxptr; i != ((old_rxptr - 1) & RX_RING_MOD_MASK); i = (i + 1) & RX_RING_MOD_MASK) { |
335 |
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); |
|
336 |
if (temp == (LE_R1_OWN)) { |
|
327 |
cpu_physical_memory_read((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1);
|
|
328 |
if (temp8 == (LE_R1_OWN)) {
|
|
337 | 329 |
s->rxptr = (s->rxptr + 1) & RX_RING_MOD_MASK; |
338 |
temp = size; |
|
339 |
bswap16s(&temp); |
|
340 |
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp, 2); |
|
341 |
#if 0 |
|
330 |
temp16 = size + 4; |
|
331 |
bswap16s(&temp16); |
|
332 |
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].mblength, (void *) &temp16, 2); |
|
342 | 333 |
cpu_physical_memory_write((uint32_t)&ib->rx_buf[i], buf, size); |
343 |
#else |
|
344 |
for (j = 0; j < size; j++) { |
|
345 |
cpu_physical_memory_write(((uint32_t)&ib->rx_buf[i]) + j, &buf[j], 1); |
|
346 |
} |
|
347 |
#endif |
|
348 |
temp = LE_R1_POK; |
|
349 |
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp, 1); |
|
334 |
temp8 = LE_R1_POK; |
|
335 |
cpu_physical_memory_write((uint32_t)&ib->brx_ring[i].rmd1_bits, (void *) &temp8, 1); |
|
350 | 336 |
s->regs[LE_CSR0] |= LE_C0_RINT | LE_C0_INTR; |
351 |
if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA))
|
|
337 |
if (s->regs[LE_CSR0] & LE_C0_INEA)
|
|
352 | 338 |
pic_set_irq(s->irq, 1); |
353 |
#ifdef DEBUG_LANCE |
|
354 |
fprintf(stderr, "lance: got packet, len %d\n", size); |
|
355 |
#endif |
|
339 |
DPRINTF("got packet, len %d\n", size); |
|
356 | 340 |
return; |
357 | 341 |
} |
358 | 342 |
} |
... | ... | |
363 | 347 |
LANCEState *s = opaque; |
364 | 348 |
uint32_t dmaptr = s->leptr + s->ledmaregs[3]; |
365 | 349 |
struct lance_init_block *ib; |
366 |
unsigned int i, old_txptr, j; |
|
367 |
uint16_t temp; |
|
350 |
unsigned int i, old_txptr; |
|
351 |
uint16_t temp16; |
|
352 |
uint8_t temp8; |
|
368 | 353 |
char pkt_buf[PKT_BUF_SZ]; |
369 | 354 |
|
355 |
DPRINTF("sending packet? (csr0 %4.4x)\n", s->regs[LE_CSR0]); |
|
370 | 356 |
if ((s->regs[LE_CSR0] & LE_C0_STOP) == LE_C0_STOP) |
371 | 357 |
return; |
372 | 358 |
|
373 | 359 |
ib = (void *) iommu_translate(dmaptr); |
374 | 360 |
|
361 |
DPRINTF("sending packet? (dmaptr %8.8x) (ib %p) (btx_ring %p)\n", dmaptr, ib, &ib->btx_ring); |
|
375 | 362 |
old_txptr = s->txptr; |
376 | 363 |
for (i = s->txptr; i != ((old_txptr - 1) & TX_RING_MOD_MASK); i = (i + 1) & TX_RING_MOD_MASK) { |
377 |
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1); |
|
378 |
if (temp == (LE_T1_POK|LE_T1_OWN)) { |
|
379 |
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp, 2); |
|
380 |
bswap16s(&temp); |
|
381 |
temp = (~temp) + 1; |
|
382 |
#if 0 |
|
383 |
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp); |
|
384 |
#else |
|
385 |
for (j = 0; j < temp; j++) { |
|
386 |
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i] + j, &pkt_buf[j], 1); |
|
387 |
} |
|
388 |
#endif |
|
389 |
|
|
390 |
#ifdef DEBUG_LANCE |
|
391 |
fprintf(stderr, "lance: sending packet, len %d\n", temp); |
|
392 |
#endif |
|
393 |
qemu_send_packet(s->nd, pkt_buf, temp); |
|
394 |
temp = LE_T1_POK; |
|
395 |
cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp, 1); |
|
364 |
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1); |
|
365 |
if (temp8 == (LE_T1_POK|LE_T1_OWN)) { |
|
366 |
cpu_physical_memory_read((uint32_t)&ib->btx_ring[i].length, (void *) &temp16, 2); |
|
367 |
bswap16s(&temp16); |
|
368 |
temp16 = (~temp16) + 1; |
|
369 |
cpu_physical_memory_read((uint32_t)&ib->tx_buf[i], pkt_buf, temp16); |
|
370 |
DPRINTF("sending packet, len %d\n", temp16); |
|
371 |
qemu_send_packet(s->nd, pkt_buf, temp16); |
|
372 |
temp8 = LE_T1_POK; |
|
373 |
cpu_physical_memory_write((uint32_t)&ib->btx_ring[i].tmd1_bits, (void *) &temp8, 1); |
|
396 | 374 |
s->txptr = (s->txptr + 1) & TX_RING_MOD_MASK; |
397 | 375 |
s->regs[LE_CSR0] |= LE_C0_TINT | LE_C0_INTR; |
398 | 376 |
} |
399 | 377 |
} |
378 |
if ((s->regs[LE_CSR0] & LE_C0_INTR) && (s->regs[LE_CSR0] & LE_C0_INEA)) |
|
379 |
pic_set_irq(s->irq, 1); |
|
400 | 380 |
} |
401 | 381 |
|
402 | 382 |
static uint32_t ledma_mem_readl(void *opaque, target_phys_addr_t addr) |
... | ... | |
436 | 416 |
|
437 | 417 |
qemu_put_be32s(f, &s->leptr); |
438 | 418 |
qemu_put_be16s(f, &s->addr); |
439 |
for (i = 0; i < LE_MAXREG; i ++)
|
|
419 |
for (i = 0; i < LE_NREGS; i ++)
|
|
440 | 420 |
qemu_put_be16s(f, &s->regs[i]); |
441 | 421 |
qemu_put_buffer(f, s->phys, 6); |
442 | 422 |
qemu_put_be32s(f, &s->irq); |
... | ... | |
454 | 434 |
|
455 | 435 |
qemu_get_be32s(f, &s->leptr); |
456 | 436 |
qemu_get_be16s(f, &s->addr); |
457 |
for (i = 0; i < LE_MAXREG; i ++)
|
|
437 |
for (i = 0; i < LE_NREGS; i ++)
|
|
458 | 438 |
qemu_get_be16s(f, &s->regs[i]); |
459 | 439 |
qemu_get_buffer(f, s->phys, 6); |
460 | 440 |
qemu_get_be32s(f, &s->irq); |
... | ... | |
476 | 456 |
s->irq = irq; |
477 | 457 |
|
478 | 458 |
lance_io_memory = cpu_register_io_memory(0, lance_mem_read, lance_mem_write, s); |
479 |
cpu_register_physical_memory(leaddr, 8, lance_io_memory);
|
|
459 |
cpu_register_physical_memory(leaddr, 4, lance_io_memory);
|
|
480 | 460 |
|
481 | 461 |
ledma_io_memory = cpu_register_io_memory(0, ledma_mem_read, ledma_mem_write, s); |
482 | 462 |
cpu_register_physical_memory(ledaddr, 16, ledma_io_memory); |
Also available in: Unified diff