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 --- |