dp8393x.c (1ccda935d4fcc82a4371dc23d660197b0a6b6951) dp8393x.c (19f703477314a5db09ffc3c0f6be9c45645f8302)
1/*
2 * QEMU NS SONIC DP8393x netcard
3 *
4 * Copyright (c) 2008-2009 Herve Poussineau
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of

--- 261 unchanged lines hidden (view full) ---

270 int width, size;
271 uint16_t index = 0;
272
273 width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
274 size = sizeof(uint16_t) * 4 * width;
275
276 while (s->regs[SONIC_CDC] & 0x1f) {
277 /* Fill current entry */
1/*
2 * QEMU NS SONIC DP8393x netcard
3 *
4 * Copyright (c) 2008-2009 Herve Poussineau
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of

--- 261 unchanged lines hidden (view full) ---

270 int width, size;
271 uint16_t index = 0;
272
273 width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
274 size = sizeof(uint16_t) * 4 * width;
275
276 while (s->regs[SONIC_CDC] & 0x1f) {
277 /* Fill current entry */
278 address_space_rw(&s->as, dp8393x_cdp(s),
279 MEMTXATTRS_UNSPECIFIED, s->data, size, false);
278 address_space_read(&s->as, dp8393x_cdp(s),
279 MEMTXATTRS_UNSPECIFIED, s->data, size);
280 s->cam[index][0] = dp8393x_get(s, width, 1) & 0xff;
281 s->cam[index][1] = dp8393x_get(s, width, 1) >> 8;
282 s->cam[index][2] = dp8393x_get(s, width, 2) & 0xff;
283 s->cam[index][3] = dp8393x_get(s, width, 2) >> 8;
284 s->cam[index][4] = dp8393x_get(s, width, 3) & 0xff;
285 s->cam[index][5] = dp8393x_get(s, width, 3) >> 8;
286 DPRINTF("load cam[%d] with %02x%02x%02x%02x%02x%02x\n", index,
287 s->cam[index][0], s->cam[index][1], s->cam[index][2],
288 s->cam[index][3], s->cam[index][4], s->cam[index][5]);
289 /* Move to next entry */
290 s->regs[SONIC_CDC]--;
291 s->regs[SONIC_CDP] += size;
292 index++;
293 }
294
295 /* Read CAM enable */
280 s->cam[index][0] = dp8393x_get(s, width, 1) & 0xff;
281 s->cam[index][1] = dp8393x_get(s, width, 1) >> 8;
282 s->cam[index][2] = dp8393x_get(s, width, 2) & 0xff;
283 s->cam[index][3] = dp8393x_get(s, width, 2) >> 8;
284 s->cam[index][4] = dp8393x_get(s, width, 3) & 0xff;
285 s->cam[index][5] = dp8393x_get(s, width, 3) >> 8;
286 DPRINTF("load cam[%d] with %02x%02x%02x%02x%02x%02x\n", index,
287 s->cam[index][0], s->cam[index][1], s->cam[index][2],
288 s->cam[index][3], s->cam[index][4], s->cam[index][5]);
289 /* Move to next entry */
290 s->regs[SONIC_CDC]--;
291 s->regs[SONIC_CDP] += size;
292 index++;
293 }
294
295 /* Read CAM enable */
296 address_space_rw(&s->as, dp8393x_cdp(s),
297 MEMTXATTRS_UNSPECIFIED, s->data, size, false);
296 address_space_read(&s->as, dp8393x_cdp(s),
297 MEMTXATTRS_UNSPECIFIED, s->data, size);
298 s->regs[SONIC_CE] = dp8393x_get(s, width, 0);
299 DPRINTF("load cam done. cam enable mask 0x%04x\n", s->regs[SONIC_CE]);
300
301 /* Done */
302 s->regs[SONIC_CR] &= ~SONIC_CR_LCAM;
303 s->regs[SONIC_ISR] |= SONIC_ISR_LCD;
304 dp8393x_update_irq(s);
305}
306
307static void dp8393x_do_read_rra(dp8393xState *s)
308{
309 int width, size;
310
311 /* Read memory */
312 width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
313 size = sizeof(uint16_t) * 4 * width;
298 s->regs[SONIC_CE] = dp8393x_get(s, width, 0);
299 DPRINTF("load cam done. cam enable mask 0x%04x\n", s->regs[SONIC_CE]);
300
301 /* Done */
302 s->regs[SONIC_CR] &= ~SONIC_CR_LCAM;
303 s->regs[SONIC_ISR] |= SONIC_ISR_LCD;
304 dp8393x_update_irq(s);
305}
306
307static void dp8393x_do_read_rra(dp8393xState *s)
308{
309 int width, size;
310
311 /* Read memory */
312 width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
313 size = sizeof(uint16_t) * 4 * width;
314 address_space_rw(&s->as, dp8393x_rrp(s),
315 MEMTXATTRS_UNSPECIFIED, s->data, size, false);
314 address_space_read(&s->as, dp8393x_rrp(s),
315 MEMTXATTRS_UNSPECIFIED, s->data, size);
316
317 /* Update SONIC registers */
318 s->regs[SONIC_CRBA0] = dp8393x_get(s, width, 0);
319 s->regs[SONIC_CRBA1] = dp8393x_get(s, width, 1);
320 s->regs[SONIC_RBWC0] = dp8393x_get(s, width, 2);
321 s->regs[SONIC_RBWC1] = dp8393x_get(s, width, 3);
322 DPRINTF("CRBA0/1: 0x%04x/0x%04x, RBWC0/1: 0x%04x/0x%04x\n",
323 s->regs[SONIC_CRBA0], s->regs[SONIC_CRBA1],

--- 97 unchanged lines hidden (view full) ---

421
422 width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
423
424 while (1) {
425 /* Read memory */
426 size = sizeof(uint16_t) * 6 * width;
427 s->regs[SONIC_TTDA] = s->regs[SONIC_CTDA];
428 DPRINTF("Transmit packet at %08x\n", dp8393x_ttda(s));
316
317 /* Update SONIC registers */
318 s->regs[SONIC_CRBA0] = dp8393x_get(s, width, 0);
319 s->regs[SONIC_CRBA1] = dp8393x_get(s, width, 1);
320 s->regs[SONIC_RBWC0] = dp8393x_get(s, width, 2);
321 s->regs[SONIC_RBWC1] = dp8393x_get(s, width, 3);
322 DPRINTF("CRBA0/1: 0x%04x/0x%04x, RBWC0/1: 0x%04x/0x%04x\n",
323 s->regs[SONIC_CRBA0], s->regs[SONIC_CRBA1],

--- 97 unchanged lines hidden (view full) ---

421
422 width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
423
424 while (1) {
425 /* Read memory */
426 size = sizeof(uint16_t) * 6 * width;
427 s->regs[SONIC_TTDA] = s->regs[SONIC_CTDA];
428 DPRINTF("Transmit packet at %08x\n", dp8393x_ttda(s));
429 address_space_rw(&s->as, dp8393x_ttda(s) + sizeof(uint16_t) * width,
430 MEMTXATTRS_UNSPECIFIED, s->data, size, false);
429 address_space_read(&s->as, dp8393x_ttda(s) + sizeof(uint16_t) * width,
430 MEMTXATTRS_UNSPECIFIED, s->data, size);
431 tx_len = 0;
432
433 /* Update registers */
434 s->regs[SONIC_TCR] = dp8393x_get(s, width, 0) & 0xf000;
435 s->regs[SONIC_TPS] = dp8393x_get(s, width, 1);
436 s->regs[SONIC_TFC] = dp8393x_get(s, width, 2);
437 s->regs[SONIC_TSA0] = dp8393x_get(s, width, 3);
438 s->regs[SONIC_TSA1] = dp8393x_get(s, width, 4);

--- 7 unchanged lines hidden (view full) ---

446 }
447
448 for (i = 0; i < s->regs[SONIC_TFC]; ) {
449 /* Append fragment */
450 len = s->regs[SONIC_TFS];
451 if (tx_len + len > sizeof(s->tx_buffer)) {
452 len = sizeof(s->tx_buffer) - tx_len;
453 }
431 tx_len = 0;
432
433 /* Update registers */
434 s->regs[SONIC_TCR] = dp8393x_get(s, width, 0) & 0xf000;
435 s->regs[SONIC_TPS] = dp8393x_get(s, width, 1);
436 s->regs[SONIC_TFC] = dp8393x_get(s, width, 2);
437 s->regs[SONIC_TSA0] = dp8393x_get(s, width, 3);
438 s->regs[SONIC_TSA1] = dp8393x_get(s, width, 4);

--- 7 unchanged lines hidden (view full) ---

446 }
447
448 for (i = 0; i < s->regs[SONIC_TFC]; ) {
449 /* Append fragment */
450 len = s->regs[SONIC_TFS];
451 if (tx_len + len > sizeof(s->tx_buffer)) {
452 len = sizeof(s->tx_buffer) - tx_len;
453 }
454 address_space_rw(&s->as, dp8393x_tsa(s),
455 MEMTXATTRS_UNSPECIFIED,
456 &s->tx_buffer[tx_len], len, false);
454 address_space_read(&s->as, dp8393x_tsa(s), MEMTXATTRS_UNSPECIFIED,
455 &s->tx_buffer[tx_len], len);
457 tx_len += len;
458
459 i++;
460 if (i != s->regs[SONIC_TFC]) {
461 /* Read next fragment details */
462 size = sizeof(uint16_t) * 3 * width;
456 tx_len += len;
457
458 i++;
459 if (i != s->regs[SONIC_TFC]) {
460 /* Read next fragment details */
461 size = sizeof(uint16_t) * 3 * width;
463 address_space_rw(&s->as,
464 dp8393x_ttda(s) + sizeof(uint16_t) * (4 + 3 * i) * width,
465 MEMTXATTRS_UNSPECIFIED, s->data, size, false);
462 address_space_read(&s->as,
463 dp8393x_ttda(s)
464 + sizeof(uint16_t) * width * (4 + 3 * i),
465 MEMTXATTRS_UNSPECIFIED, s->data,
466 size);
466 s->regs[SONIC_TSA0] = dp8393x_get(s, width, 0);
467 s->regs[SONIC_TSA1] = dp8393x_get(s, width, 1);
468 s->regs[SONIC_TFS] = dp8393x_get(s, width, 2);
469 }
470 }
471
472 /* Handle Ethernet checksum */
473 if (!(s->regs[SONIC_TCR] & SONIC_TCR_CRCI)) {

--- 16 unchanged lines hidden (view full) ---

490 qemu_send_packet(nc, s->tx_buffer, tx_len);
491 }
492 s->regs[SONIC_TCR] |= SONIC_TCR_PTX;
493
494 /* Write status */
495 dp8393x_put(s, width, 0,
496 s->regs[SONIC_TCR] & 0x0fff); /* status */
497 size = sizeof(uint16_t) * width;
467 s->regs[SONIC_TSA0] = dp8393x_get(s, width, 0);
468 s->regs[SONIC_TSA1] = dp8393x_get(s, width, 1);
469 s->regs[SONIC_TFS] = dp8393x_get(s, width, 2);
470 }
471 }
472
473 /* Handle Ethernet checksum */
474 if (!(s->regs[SONIC_TCR] & SONIC_TCR_CRCI)) {

--- 16 unchanged lines hidden (view full) ---

491 qemu_send_packet(nc, s->tx_buffer, tx_len);
492 }
493 s->regs[SONIC_TCR] |= SONIC_TCR_PTX;
494
495 /* Write status */
496 dp8393x_put(s, width, 0,
497 s->regs[SONIC_TCR] & 0x0fff); /* status */
498 size = sizeof(uint16_t) * width;
498 address_space_rw(&s->as,
499 dp8393x_ttda(s),
500 MEMTXATTRS_UNSPECIFIED, s->data, size, true);
499 address_space_write(&s->as, dp8393x_ttda(s),
500 MEMTXATTRS_UNSPECIFIED, s->data, size);
501
502 if (!(s->regs[SONIC_CR] & SONIC_CR_HTX)) {
503 /* Read footer of packet */
504 size = sizeof(uint16_t) * width;
501
502 if (!(s->regs[SONIC_CR] & SONIC_CR_HTX)) {
503 /* Read footer of packet */
504 size = sizeof(uint16_t) * width;
505 address_space_rw(&s->as,
506 dp8393x_ttda(s) +
507 sizeof(uint16_t) *
508 (4 + 3 * s->regs[SONIC_TFC]) * width,
509 MEMTXATTRS_UNSPECIFIED, s->data, size, false);
505 address_space_read(&s->as,
506 dp8393x_ttda(s)
507 + sizeof(uint16_t) * width
508 * (4 + 3 * s->regs[SONIC_TFC]),
509 MEMTXATTRS_UNSPECIFIED, s->data,
510 size);
510 s->regs[SONIC_CTDA] = dp8393x_get(s, width, 0) & ~0x1;
511 if (dp8393x_get(s, width, 0) & 0x1) {
512 /* EOL detected */
513 break;
514 }
515 }
516 }
517

--- 245 unchanged lines hidden (view full) ---

763
764 /* XXX: Check byte ordering */
765
766 /* Check for EOL */
767 if (s->regs[SONIC_LLFA] & 0x1) {
768 /* Are we still in resource exhaustion? */
769 size = sizeof(uint16_t) * 1 * width;
770 address = dp8393x_crda(s) + sizeof(uint16_t) * 5 * width;
511 s->regs[SONIC_CTDA] = dp8393x_get(s, width, 0) & ~0x1;
512 if (dp8393x_get(s, width, 0) & 0x1) {
513 /* EOL detected */
514 break;
515 }
516 }
517 }
518

--- 245 unchanged lines hidden (view full) ---

764
765 /* XXX: Check byte ordering */
766
767 /* Check for EOL */
768 if (s->regs[SONIC_LLFA] & 0x1) {
769 /* Are we still in resource exhaustion? */
770 size = sizeof(uint16_t) * 1 * width;
771 address = dp8393x_crda(s) + sizeof(uint16_t) * 5 * width;
771 address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
772 s->data, size, false);
772 address_space_read(&s->as, address, MEMTXATTRS_UNSPECIFIED,
773 s->data, size);
773 if (dp8393x_get(s, width, 0) & 0x1) {
774 /* Still EOL ; stop reception */
775 return -1;
776 } else {
777 s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
778 }
779 }
780
781 /* Save current position */
782 s->regs[SONIC_TRBA1] = s->regs[SONIC_CRBA1];
783 s->regs[SONIC_TRBA0] = s->regs[SONIC_CRBA0];
784
785 /* Calculate the ethernet checksum */
786 checksum = cpu_to_le32(crc32(0, buf, rx_len));
787
788 /* Put packet into RBA */
789 DPRINTF("Receive packet at %08x\n", dp8393x_crba(s));
790 address = dp8393x_crba(s);
774 if (dp8393x_get(s, width, 0) & 0x1) {
775 /* Still EOL ; stop reception */
776 return -1;
777 } else {
778 s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
779 }
780 }
781
782 /* Save current position */
783 s->regs[SONIC_TRBA1] = s->regs[SONIC_CRBA1];
784 s->regs[SONIC_TRBA0] = s->regs[SONIC_CRBA0];
785
786 /* Calculate the ethernet checksum */
787 checksum = cpu_to_le32(crc32(0, buf, rx_len));
788
789 /* Put packet into RBA */
790 DPRINTF("Receive packet at %08x\n", dp8393x_crba(s));
791 address = dp8393x_crba(s);
791 address_space_write(&s->as, address, MEMTXATTRS_UNSPECIFIED, buf, rx_len);
792 address_space_write(&s->as, address, MEMTXATTRS_UNSPECIFIED,
793 buf, rx_len);
792 address += rx_len;
794 address += rx_len;
793 address_space_rw(&s->as, address,
794 MEMTXATTRS_UNSPECIFIED, &checksum, 4, true);
795 address_space_write(&s->as, address, MEMTXATTRS_UNSPECIFIED,
796 &checksum, 4);
795 rx_len += 4;
796 s->regs[SONIC_CRBA1] = address >> 16;
797 s->regs[SONIC_CRBA0] = address & 0xffff;
798 available = dp8393x_rbwc(s);
799 available -= rx_len / 2;
800 s->regs[SONIC_RBWC1] = available >> 16;
801 s->regs[SONIC_RBWC0] = available & 0xffff;
802

--- 11 unchanged lines hidden (view full) ---

814 /* Write status to memory */
815 DPRINTF("Write status at %08x\n", dp8393x_crda(s));
816 dp8393x_put(s, width, 0, s->regs[SONIC_RCR]); /* status */
817 dp8393x_put(s, width, 1, rx_len); /* byte count */
818 dp8393x_put(s, width, 2, s->regs[SONIC_TRBA0]); /* pkt_ptr0 */
819 dp8393x_put(s, width, 3, s->regs[SONIC_TRBA1]); /* pkt_ptr1 */
820 dp8393x_put(s, width, 4, s->regs[SONIC_RSC]); /* seq_no */
821 size = sizeof(uint16_t) * 5 * width;
797 rx_len += 4;
798 s->regs[SONIC_CRBA1] = address >> 16;
799 s->regs[SONIC_CRBA0] = address & 0xffff;
800 available = dp8393x_rbwc(s);
801 available -= rx_len / 2;
802 s->regs[SONIC_RBWC1] = available >> 16;
803 s->regs[SONIC_RBWC0] = available & 0xffff;
804

--- 11 unchanged lines hidden (view full) ---

816 /* Write status to memory */
817 DPRINTF("Write status at %08x\n", dp8393x_crda(s));
818 dp8393x_put(s, width, 0, s->regs[SONIC_RCR]); /* status */
819 dp8393x_put(s, width, 1, rx_len); /* byte count */
820 dp8393x_put(s, width, 2, s->regs[SONIC_TRBA0]); /* pkt_ptr0 */
821 dp8393x_put(s, width, 3, s->regs[SONIC_TRBA1]); /* pkt_ptr1 */
822 dp8393x_put(s, width, 4, s->regs[SONIC_RSC]); /* seq_no */
823 size = sizeof(uint16_t) * 5 * width;
822 address_space_rw(&s->as, dp8393x_crda(s),
823 MEMTXATTRS_UNSPECIFIED, s->data, size, true);
824 address_space_write(&s->as, dp8393x_crda(s),
825 MEMTXATTRS_UNSPECIFIED,
826 s->data, size);
824
825 /* Move to next descriptor */
826 size = sizeof(uint16_t) * width;
827
828 /* Move to next descriptor */
829 size = sizeof(uint16_t) * width;
827 address_space_rw(&s->as, dp8393x_crda(s) + sizeof(uint16_t) * 5 * width,
828 MEMTXATTRS_UNSPECIFIED, s->data, size, false);
830 address_space_read(&s->as,
831 dp8393x_crda(s) + sizeof(uint16_t) * 5 * width,
832 MEMTXATTRS_UNSPECIFIED, s->data, size);
829 s->regs[SONIC_LLFA] = dp8393x_get(s, width, 0);
830 if (s->regs[SONIC_LLFA] & 0x1) {
831 /* EOL detected */
832 s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
833 } else {
834 /* Clear in_use, but it is always 16bit wide */
835 int offset = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
836 if (s->big_endian && width == 2) {
837 /* we need to adjust the offset of the 16bit field */
838 offset += sizeof(uint16_t);
839 }
840 s->data[0] = 0;
833 s->regs[SONIC_LLFA] = dp8393x_get(s, width, 0);
834 if (s->regs[SONIC_LLFA] & 0x1) {
835 /* EOL detected */
836 s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
837 } else {
838 /* Clear in_use, but it is always 16bit wide */
839 int offset = dp8393x_crda(s) + sizeof(uint16_t) * 6 * width;
840 if (s->big_endian && width == 2) {
841 /* we need to adjust the offset of the 16bit field */
842 offset += sizeof(uint16_t);
843 }
844 s->data[0] = 0;
841 address_space_rw(&s->as, offset, MEMTXATTRS_UNSPECIFIED,
842 s->data, sizeof(uint16_t), true);
845 address_space_write(&s->as, offset, MEMTXATTRS_UNSPECIFIED,
846 s->data, sizeof(uint16_t));
843 s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
844 s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
845 s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
846
847 if (s->regs[SONIC_RCR] & SONIC_RCR_LPKT) {
848 /* Read next RRA */
849 dp8393x_do_read_rra(s);
850 }

--- 132 unchanged lines hidden ---
847 s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
848 s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
849 s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
850
851 if (s->regs[SONIC_RCR] & SONIC_RCR_LPKT) {
852 /* Read next RRA */
853 dp8393x_do_read_rra(s);
854 }

--- 132 unchanged lines hidden ---