i82596.c (21770B)
1/* 2 * QEMU Intel i82596 (Apricot) emulation 3 * 4 * Copyright (c) 2019 Helge Deller <deller@gmx.de> 5 * This work is licensed under the GNU GPL license version 2 or later. 6 * 7 * This software was written to be compatible with the specification: 8 * https://www.intel.com/assets/pdf/general/82596ca.pdf 9 */ 10 11#include "qemu/osdep.h" 12#include "qemu/timer.h" 13#include "net/net.h" 14#include "net/eth.h" 15#include "hw/irq.h" 16#include "hw/qdev-properties.h" 17#include "migration/vmstate.h" 18#include "qemu/module.h" 19#include "trace.h" 20#include "i82596.h" 21#include <zlib.h> /* For crc32 */ 22 23#if defined(ENABLE_DEBUG) 24#define DBG(x) x 25#else 26#define DBG(x) do { } while (0) 27#endif 28 29#define USE_TIMER 0 30 31#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m) 32 33#define PKT_BUF_SZ 1536 34#define MAX_MC_CNT 64 35 36#define ISCP_BUSY 0x0001 37 38#define I596_NULL ((uint32_t)0xffffffff) 39 40#define SCB_STATUS_CX 0x8000 /* CU finished command with I bit */ 41#define SCB_STATUS_FR 0x4000 /* RU finished receiving a frame */ 42#define SCB_STATUS_CNA 0x2000 /* CU left active state */ 43#define SCB_STATUS_RNR 0x1000 /* RU left active state */ 44 45#define SCB_COMMAND_ACK_MASK \ 46 (SCB_STATUS_CX | SCB_STATUS_FR | SCB_STATUS_CNA | SCB_STATUS_RNR) 47 48#define CU_IDLE 0 49#define CU_SUSPENDED 1 50#define CU_ACTIVE 2 51 52#define RX_IDLE 0 53#define RX_SUSPENDED 1 54#define RX_READY 4 55 56#define CMD_EOL 0x8000 /* The last command of the list, stop. */ 57#define CMD_SUSP 0x4000 /* Suspend after doing cmd. */ 58#define CMD_INTR 0x2000 /* Interrupt after doing cmd. */ 59 60#define CMD_FLEX 0x0008 /* Enable flexible memory model */ 61 62enum commands { 63 CmdNOp = 0, CmdSASetup = 1, CmdConfigure = 2, CmdMulticastList = 3, 64 CmdTx = 4, CmdTDR = 5, CmdDump = 6, CmdDiagnose = 7 65}; 66 67#define STAT_C 0x8000 /* Set to 0 after execution */ 68#define STAT_B 0x4000 /* Command being executed */ 69#define STAT_OK 0x2000 /* Command executed ok */ 70#define STAT_A 0x1000 /* Command aborted */ 71 72#define I596_EOF 0x8000 73#define SIZE_MASK 0x3fff 74 75#define ETHER_TYPE_LEN 2 76#define VLAN_TCI_LEN 2 77#define VLAN_HLEN (ETHER_TYPE_LEN + VLAN_TCI_LEN) 78 79/* various flags in the chip config registers */ 80#define I596_PREFETCH (s->config[0] & 0x80) 81#define I596_PROMISC (s->config[8] & 0x01) 82#define I596_BC_DISABLE (s->config[8] & 0x02) /* broadcast disable */ 83#define I596_NOCRC_INS (s->config[8] & 0x08) 84#define I596_CRCINM (s->config[11] & 0x04) /* CRC appended */ 85#define I596_MC_ALL (s->config[11] & 0x20) 86#define I596_MULTIIA (s->config[13] & 0x40) 87 88 89static uint8_t get_byte(uint32_t addr) 90{ 91 return ldub_phys(&address_space_memory, addr); 92} 93 94static void set_byte(uint32_t addr, uint8_t c) 95{ 96 return stb_phys(&address_space_memory, addr, c); 97} 98 99static uint16_t get_uint16(uint32_t addr) 100{ 101 return lduw_be_phys(&address_space_memory, addr); 102} 103 104static void set_uint16(uint32_t addr, uint16_t w) 105{ 106 return stw_be_phys(&address_space_memory, addr, w); 107} 108 109static uint32_t get_uint32(uint32_t addr) 110{ 111 uint32_t lo = lduw_be_phys(&address_space_memory, addr); 112 uint32_t hi = lduw_be_phys(&address_space_memory, addr + 2); 113 return (hi << 16) | lo; 114} 115 116static void set_uint32(uint32_t addr, uint32_t val) 117{ 118 set_uint16(addr, (uint16_t) val); 119 set_uint16(addr + 2, val >> 16); 120} 121 122 123struct qemu_ether_header { 124 uint8_t ether_dhost[6]; 125 uint8_t ether_shost[6]; 126 uint16_t ether_type; 127}; 128 129#define PRINT_PKTHDR(txt, BUF) do { \ 130 struct qemu_ether_header *hdr = (void *)(BUF); \ 131 printf(txt ": packet dhost=" MAC_FMT ", shost=" MAC_FMT ", type=0x%04x\n",\ 132 MAC_ARG(hdr->ether_dhost), MAC_ARG(hdr->ether_shost), \ 133 be16_to_cpu(hdr->ether_type)); \ 134} while (0) 135 136static void i82596_transmit(I82596State *s, uint32_t addr) 137{ 138 uint32_t tdb_p; /* Transmit Buffer Descriptor */ 139 140 /* TODO: Check flexible mode */ 141 tdb_p = get_uint32(addr + 8); 142 while (tdb_p != I596_NULL) { 143 uint16_t size, len; 144 uint32_t tba; 145 146 size = get_uint16(tdb_p); 147 len = size & SIZE_MASK; 148 tba = get_uint32(tdb_p + 8); 149 trace_i82596_transmit(len, tba); 150 151 if (s->nic && len) { 152 assert(len <= sizeof(s->tx_buffer)); 153 address_space_read(&address_space_memory, tba, 154 MEMTXATTRS_UNSPECIFIED, s->tx_buffer, len); 155 DBG(PRINT_PKTHDR("Send", &s->tx_buffer)); 156 DBG(printf("Sending %d bytes\n", len)); 157 qemu_send_packet(qemu_get_queue(s->nic), s->tx_buffer, len); 158 } 159 160 /* was this the last package? */ 161 if (size & I596_EOF) { 162 break; 163 } 164 165 /* get next buffer pointer */ 166 tdb_p = get_uint32(tdb_p + 4); 167 } 168} 169 170static void set_individual_address(I82596State *s, uint32_t addr) 171{ 172 NetClientState *nc; 173 uint8_t *m; 174 175 nc = qemu_get_queue(s->nic); 176 m = s->conf.macaddr.a; 177 address_space_read(&address_space_memory, addr + 8, 178 MEMTXATTRS_UNSPECIFIED, m, ETH_ALEN); 179 qemu_format_nic_info_str(nc, m); 180 trace_i82596_new_mac(nc->info_str); 181} 182 183static void set_multicast_list(I82596State *s, uint32_t addr) 184{ 185 uint16_t mc_count, i; 186 187 memset(&s->mult[0], 0, sizeof(s->mult)); 188 mc_count = get_uint16(addr + 8) / ETH_ALEN; 189 addr += 10; 190 if (mc_count > MAX_MC_CNT) { 191 mc_count = MAX_MC_CNT; 192 } 193 for (i = 0; i < mc_count; i++) { 194 uint8_t multicast_addr[ETH_ALEN]; 195 address_space_read(&address_space_memory, addr + i * ETH_ALEN, 196 MEMTXATTRS_UNSPECIFIED, multicast_addr, ETH_ALEN); 197 DBG(printf("Add multicast entry " MAC_FMT "\n", 198 MAC_ARG(multicast_addr))); 199 unsigned mcast_idx = (net_crc32(multicast_addr, ETH_ALEN) & 200 BITS(7, 2)) >> 2; 201 assert(mcast_idx < 8 * sizeof(s->mult)); 202 s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7)); 203 } 204 trace_i82596_set_multicast(mc_count); 205} 206 207void i82596_set_link_status(NetClientState *nc) 208{ 209 I82596State *d = qemu_get_nic_opaque(nc); 210 211 d->lnkst = nc->link_down ? 0 : 0x8000; 212} 213 214static void update_scb_status(I82596State *s) 215{ 216 s->scb_status = (s->scb_status & 0xf000) 217 | (s->cu_status << 8) | (s->rx_status << 4); 218 set_uint16(s->scb, s->scb_status); 219} 220 221 222static void i82596_s_reset(I82596State *s) 223{ 224 trace_i82596_s_reset(s); 225 s->scp = 0; 226 s->scb_status = 0; 227 s->cu_status = CU_IDLE; 228 s->rx_status = RX_SUSPENDED; 229 s->cmd_p = I596_NULL; 230 s->lnkst = 0x8000; /* initial link state: up */ 231 s->ca = s->ca_active = 0; 232 s->send_irq = 0; 233} 234 235 236static void command_loop(I82596State *s) 237{ 238 uint16_t cmd; 239 uint16_t status; 240 uint8_t byte_cnt; 241 242 DBG(printf("STARTING COMMAND LOOP cmd_p=%08x\n", s->cmd_p)); 243 244 while (s->cmd_p != I596_NULL) { 245 /* set status */ 246 status = STAT_B; 247 set_uint16(s->cmd_p, status); 248 status = STAT_C | STAT_OK; /* update, but write later */ 249 250 cmd = get_uint16(s->cmd_p + 2); 251 DBG(printf("Running command %04x at %08x\n", cmd, s->cmd_p)); 252 253 switch (cmd & 0x07) { 254 case CmdNOp: 255 break; 256 case CmdSASetup: 257 set_individual_address(s, s->cmd_p); 258 break; 259 case CmdConfigure: 260 byte_cnt = get_byte(s->cmd_p + 8) & 0x0f; 261 byte_cnt = MAX(byte_cnt, 4); 262 byte_cnt = MIN(byte_cnt, sizeof(s->config)); 263 /* copy byte_cnt max. */ 264 address_space_read(&address_space_memory, s->cmd_p + 8, 265 MEMTXATTRS_UNSPECIFIED, s->config, byte_cnt); 266 /* config byte according to page 35ff */ 267 s->config[2] &= 0x82; /* mask valid bits */ 268 s->config[2] |= 0x40; 269 s->config[7] &= 0xf7; /* clear zero bit */ 270 assert(I596_NOCRC_INS == 0); /* do CRC insertion */ 271 s->config[10] = MAX(s->config[10], 5); /* min frame length */ 272 s->config[12] &= 0x40; /* only full duplex field valid */ 273 s->config[13] |= 0x3f; /* set ones in byte 13 */ 274 break; 275 case CmdTDR: 276 /* get signal LINK */ 277 set_uint32(s->cmd_p + 8, s->lnkst); 278 break; 279 case CmdTx: 280 i82596_transmit(s, s->cmd_p); 281 break; 282 case CmdMulticastList: 283 set_multicast_list(s, s->cmd_p); 284 break; 285 case CmdDump: 286 case CmdDiagnose: 287 printf("FIXME Command %d !!\n", cmd & 7); 288 assert(0); 289 } 290 291 /* update status */ 292 set_uint16(s->cmd_p, status); 293 294 s->cmd_p = get_uint32(s->cmd_p + 4); /* get link address */ 295 DBG(printf("NEXT addr would be %08x\n", s->cmd_p)); 296 if (s->cmd_p == 0) { 297 s->cmd_p = I596_NULL; 298 } 299 300 /* Stop when last command of the list. */ 301 if (cmd & CMD_EOL) { 302 s->cmd_p = I596_NULL; 303 } 304 /* Suspend after doing cmd? */ 305 if (cmd & CMD_SUSP) { 306 s->cu_status = CU_SUSPENDED; 307 printf("FIXME SUSPEND !!\n"); 308 } 309 /* Interrupt after doing cmd? */ 310 if (cmd & CMD_INTR) { 311 s->scb_status |= SCB_STATUS_CX; 312 } else { 313 s->scb_status &= ~SCB_STATUS_CX; 314 } 315 update_scb_status(s); 316 317 /* Interrupt after doing cmd? */ 318 if (cmd & CMD_INTR) { 319 s->send_irq = 1; 320 } 321 322 if (s->cu_status != CU_ACTIVE) { 323 break; 324 } 325 } 326 DBG(printf("FINISHED COMMAND LOOP\n")); 327 qemu_flush_queued_packets(qemu_get_queue(s->nic)); 328} 329 330static void i82596_flush_queue_timer(void *opaque) 331{ 332 I82596State *s = opaque; 333 if (0) { 334 timer_del(s->flush_queue_timer); 335 qemu_flush_queued_packets(qemu_get_queue(s->nic)); 336 timer_mod(s->flush_queue_timer, 337 qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 1000); 338 } 339} 340 341static void examine_scb(I82596State *s) 342{ 343 uint16_t command, cuc, ruc; 344 345 /* get the scb command word */ 346 command = get_uint16(s->scb + 2); 347 cuc = (command >> 8) & 0x7; 348 ruc = (command >> 4) & 0x7; 349 DBG(printf("MAIN COMMAND %04x cuc %02x ruc %02x\n", command, cuc, ruc)); 350 /* and clear the scb command word */ 351 set_uint16(s->scb + 2, 0); 352 353 s->scb_status &= ~(command & SCB_COMMAND_ACK_MASK); 354 355 switch (cuc) { 356 case 0: /* no change */ 357 break; 358 case 1: /* CUC_START */ 359 s->cu_status = CU_ACTIVE; 360 break; 361 case 4: /* CUC_ABORT */ 362 s->cu_status = CU_SUSPENDED; 363 s->scb_status |= SCB_STATUS_CNA; /* CU left active state */ 364 break; 365 default: 366 printf("WARNING: Unknown CUC %d!\n", cuc); 367 } 368 369 switch (ruc) { 370 case 0: /* no change */ 371 break; 372 case 1: /* RX_START */ 373 case 2: /* RX_RESUME */ 374 s->rx_status = RX_IDLE; 375 if (USE_TIMER) { 376 timer_mod(s->flush_queue_timer, qemu_clock_get_ms( 377 QEMU_CLOCK_VIRTUAL) + 1000); 378 } 379 break; 380 case 3: /* RX_SUSPEND */ 381 case 4: /* RX_ABORT */ 382 s->rx_status = RX_SUSPENDED; 383 s->scb_status |= SCB_STATUS_RNR; /* RU left active state */ 384 break; 385 default: 386 printf("WARNING: Unknown RUC %d!\n", ruc); 387 } 388 389 if (command & 0x80) { /* reset bit set? */ 390 i82596_s_reset(s); 391 } 392 393 /* execute commands from SCBL */ 394 if (s->cu_status != CU_SUSPENDED) { 395 if (s->cmd_p == I596_NULL) { 396 s->cmd_p = get_uint32(s->scb + 4); 397 } 398 } 399 400 /* update scb status */ 401 update_scb_status(s); 402 403 command_loop(s); 404} 405 406static void signal_ca(I82596State *s) 407{ 408 uint32_t iscp = 0; 409 410 /* trace_i82596_channel_attention(s); */ 411 if (s->scp) { 412 /* CA after reset -> do init with new scp. */ 413 s->sysbus = get_byte(s->scp + 3); /* big endian */ 414 DBG(printf("SYSBUS = %08x\n", s->sysbus)); 415 if (((s->sysbus >> 1) & 0x03) != 2) { 416 printf("WARNING: NO LINEAR MODE !!\n"); 417 } 418 if ((s->sysbus >> 7)) { 419 printf("WARNING: 32BIT LINMODE IN B-STEPPING NOT SUPPORTED !!\n"); 420 } 421 iscp = get_uint32(s->scp + 8); 422 s->scb = get_uint32(iscp + 4); 423 set_byte(iscp + 1, 0); /* clear BUSY flag in iscp */ 424 s->scp = 0; 425 } 426 427 s->ca++; /* count ca() */ 428 if (!s->ca_active) { 429 s->ca_active = 1; 430 while (s->ca) { 431 examine_scb(s); 432 s->ca--; 433 } 434 s->ca_active = 0; 435 } 436 437 if (s->send_irq) { 438 s->send_irq = 0; 439 qemu_set_irq(s->irq, 1); 440 } 441} 442 443void i82596_ioport_writew(void *opaque, uint32_t addr, uint32_t val) 444{ 445 I82596State *s = opaque; 446 /* printf("i82596_ioport_writew addr=0x%08x val=0x%04x\n", addr, val); */ 447 switch (addr) { 448 case PORT_RESET: /* Reset */ 449 i82596_s_reset(s); 450 break; 451 case PORT_ALTSCP: 452 s->scp = val; 453 break; 454 case PORT_CA: 455 signal_ca(s); 456 break; 457 } 458} 459 460uint32_t i82596_ioport_readw(void *opaque, uint32_t addr) 461{ 462 return -1; 463} 464 465void i82596_h_reset(void *opaque) 466{ 467 I82596State *s = opaque; 468 469 i82596_s_reset(s); 470} 471 472bool i82596_can_receive(NetClientState *nc) 473{ 474 I82596State *s = qemu_get_nic_opaque(nc); 475 476 if (s->rx_status == RX_SUSPENDED) { 477 return false; 478 } 479 480 if (!s->lnkst) { 481 return false; 482 } 483 484 if (USE_TIMER && !timer_pending(s->flush_queue_timer)) { 485 return true; 486 } 487 488 return true; 489} 490 491#define MIN_BUF_SIZE 60 492 493ssize_t i82596_receive(NetClientState *nc, const uint8_t *buf, size_t sz) 494{ 495 I82596State *s = qemu_get_nic_opaque(nc); 496 uint32_t rfd_p; 497 uint32_t rbd; 498 uint16_t is_broadcast = 0; 499 size_t len = sz; /* length of data for guest (including CRC) */ 500 size_t bufsz = sz; /* length of data in buf */ 501 uint32_t crc; 502 uint8_t *crc_ptr; 503 uint8_t buf1[MIN_BUF_SIZE + VLAN_HLEN]; 504 static const uint8_t broadcast_macaddr[6] = { 505 0xff, 0xff, 0xff, 0xff, 0xff, 0xff }; 506 507 DBG(printf("i82596_receive() start\n")); 508 509 if (USE_TIMER && timer_pending(s->flush_queue_timer)) { 510 return 0; 511 } 512 513 /* first check if receiver is enabled */ 514 if (s->rx_status == RX_SUSPENDED) { 515 trace_i82596_receive_analysis(">>> Receiving suspended"); 516 return -1; 517 } 518 519 if (!s->lnkst) { 520 trace_i82596_receive_analysis(">>> Link down"); 521 return -1; 522 } 523 524 /* Received frame smaller than configured "min frame len"? */ 525 if (sz < s->config[10]) { 526 printf("Received frame too small, %zu vs. %u bytes\n", 527 sz, s->config[10]); 528 return -1; 529 } 530 531 DBG(printf("Received %lu bytes\n", sz)); 532 533 if (I596_PROMISC) { 534 535 /* promiscuous: receive all */ 536 trace_i82596_receive_analysis( 537 ">>> packet received in promiscuous mode"); 538 539 } else { 540 541 if (!memcmp(buf, broadcast_macaddr, 6)) { 542 /* broadcast address */ 543 if (I596_BC_DISABLE) { 544 trace_i82596_receive_analysis(">>> broadcast packet rejected"); 545 546 return len; 547 } 548 549 trace_i82596_receive_analysis(">>> broadcast packet received"); 550 is_broadcast = 1; 551 552 } else if (buf[0] & 0x01) { 553 /* multicast */ 554 if (!I596_MC_ALL) { 555 trace_i82596_receive_analysis(">>> multicast packet rejected"); 556 557 return len; 558 } 559 560 int mcast_idx = (net_crc32(buf, ETH_ALEN) & BITS(7, 2)) >> 2; 561 assert(mcast_idx < 8 * sizeof(s->mult)); 562 563 if (!(s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7)))) { 564 trace_i82596_receive_analysis(">>> multicast address mismatch"); 565 566 return len; 567 } 568 569 trace_i82596_receive_analysis(">>> multicast packet received"); 570 is_broadcast = 1; 571 572 } else if (!memcmp(s->conf.macaddr.a, buf, 6)) { 573 574 /* match */ 575 trace_i82596_receive_analysis( 576 ">>> physical address matching packet received"); 577 578 } else { 579 580 trace_i82596_receive_analysis(">>> unknown packet"); 581 582 return len; 583 } 584 } 585 586 /* if too small buffer, then expand it */ 587 if (len < MIN_BUF_SIZE + VLAN_HLEN) { 588 memcpy(buf1, buf, len); 589 memset(buf1 + len, 0, MIN_BUF_SIZE + VLAN_HLEN - len); 590 buf = buf1; 591 if (len < MIN_BUF_SIZE) { 592 len = MIN_BUF_SIZE; 593 } 594 bufsz = len; 595 } 596 597 /* Calculate the ethernet checksum (4 bytes) */ 598 len += 4; 599 crc = cpu_to_be32(crc32(~0, buf, sz)); 600 crc_ptr = (uint8_t *) &crc; 601 602 rfd_p = get_uint32(s->scb + 8); /* get Receive Frame Descriptor */ 603 assert(rfd_p && rfd_p != I596_NULL); 604 605 /* get first Receive Buffer Descriptor Address */ 606 rbd = get_uint32(rfd_p + 8); 607 assert(rbd && rbd != I596_NULL); 608 609 trace_i82596_receive_packet(len); 610 /* PRINT_PKTHDR("Receive", buf); */ 611 612 while (len) { 613 uint16_t command, status; 614 uint32_t next_rfd; 615 616 command = get_uint16(rfd_p + 2); 617 assert(command & CMD_FLEX); /* assert Flex Mode */ 618 /* get first Receive Buffer Descriptor Address */ 619 rbd = get_uint32(rfd_p + 8); 620 assert(get_uint16(rfd_p + 14) == 0); 621 622 /* printf("Receive: rfd is %08x\n", rfd_p); */ 623 624 while (len) { 625 uint16_t buffer_size, num; 626 uint32_t rba; 627 size_t bufcount, crccount; 628 629 /* printf("Receive: rbd is %08x\n", rbd); */ 630 buffer_size = get_uint16(rbd + 12); 631 /* printf("buffer_size is 0x%x\n", buffer_size); */ 632 assert(buffer_size != 0); 633 634 num = buffer_size & SIZE_MASK; 635 if (num > len) { 636 num = len; 637 } 638 rba = get_uint32(rbd + 8); 639 /* printf("rba is 0x%x\n", rba); */ 640 /* 641 * Calculate how many bytes we want from buf[] and how many 642 * from the CRC. 643 */ 644 if ((len - num) >= 4) { 645 /* The whole guest buffer, we haven't hit the CRC yet */ 646 bufcount = num; 647 } else { 648 /* All that's left of buf[] */ 649 bufcount = len - 4; 650 } 651 crccount = num - bufcount; 652 653 if (bufcount > 0) { 654 /* Still some of the actual data buffer to transfer */ 655 assert(bufsz >= bufcount); 656 bufsz -= bufcount; 657 address_space_write(&address_space_memory, rba, 658 MEMTXATTRS_UNSPECIFIED, buf, bufcount); 659 rba += bufcount; 660 buf += bufcount; 661 len -= bufcount; 662 } 663 664 /* Write as much of the CRC as fits */ 665 if (crccount > 0) { 666 address_space_write(&address_space_memory, rba, 667 MEMTXATTRS_UNSPECIFIED, crc_ptr, crccount); 668 rba += crccount; 669 crc_ptr += crccount; 670 len -= crccount; 671 } 672 673 num |= 0x4000; /* set F BIT */ 674 if (len == 0) { 675 num |= I596_EOF; /* set EOF BIT */ 676 } 677 set_uint16(rbd + 0, num); /* write actual count with flags */ 678 679 /* get next rbd */ 680 rbd = get_uint32(rbd + 4); 681 /* printf("Next Receive: rbd is %08x\n", rbd); */ 682 683 if (buffer_size & I596_EOF) /* last entry */ 684 break; 685 } 686 687 /* Housekeeping, see pg. 18 */ 688 next_rfd = get_uint32(rfd_p + 4); 689 set_uint32(next_rfd + 8, rbd); 690 691 status = STAT_C | STAT_OK | is_broadcast; 692 set_uint16(rfd_p, status); 693 694 if (command & CMD_SUSP) { /* suspend after command? */ 695 s->rx_status = RX_SUSPENDED; 696 s->scb_status |= SCB_STATUS_RNR; /* RU left active state */ 697 break; 698 } 699 if (command & CMD_EOL) /* was it last Frame Descriptor? */ 700 break; 701 702 assert(len == 0); 703 } 704 705 assert(len == 0); 706 707 s->scb_status |= SCB_STATUS_FR; /* set "RU finished receiving frame" bit. */ 708 update_scb_status(s); 709 710 /* send IRQ that we received data */ 711 qemu_set_irq(s->irq, 1); 712 /* s->send_irq = 1; */ 713 714 if (0) { 715 DBG(printf("Checking:\n")); 716 rfd_p = get_uint32(s->scb + 8); /* get Receive Frame Descriptor */ 717 DBG(printf("Next Receive: rfd is %08x\n", rfd_p)); 718 rfd_p = get_uint32(rfd_p + 4); /* get Next Receive Frame Descriptor */ 719 DBG(printf("Next Receive: rfd is %08x\n", rfd_p)); 720 /* get first Receive Buffer Descriptor Address */ 721 rbd = get_uint32(rfd_p + 8); 722 DBG(printf("Next Receive: rbd is %08x\n", rbd)); 723 } 724 725 return sz; 726} 727 728 729const VMStateDescription vmstate_i82596 = { 730 .name = "i82596", 731 .version_id = 1, 732 .minimum_version_id = 1, 733 .fields = (VMStateField[]) { 734 VMSTATE_UINT16(lnkst, I82596State), 735 VMSTATE_TIMER_PTR(flush_queue_timer, I82596State), 736 VMSTATE_END_OF_LIST() 737 } 738}; 739 740void i82596_common_init(DeviceState *dev, I82596State *s, NetClientInfo *info) 741{ 742 if (s->conf.macaddr.a[0] == 0) { 743 qemu_macaddr_default_if_unset(&s->conf.macaddr); 744 } 745 s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), 746 dev->id, s); 747 qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a); 748 749 if (USE_TIMER) { 750 s->flush_queue_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, 751 i82596_flush_queue_timer, s); 752 } 753 s->lnkst = 0x8000; /* initial link state: up */ 754}