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