qemu

FORK: QEMU emulator
git clone https://git.neptards.moe/neptards/qemu.git
Log | Files | Refs | Submodules | LICENSE

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 
     62 enum 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 
     89 static uint8_t get_byte(uint32_t addr)
     90 {
     91     return ldub_phys(&address_space_memory, addr);
     92 }
     93 
     94 static void set_byte(uint32_t addr, uint8_t c)
     95 {
     96     return stb_phys(&address_space_memory, addr, c);
     97 }
     98 
     99 static uint16_t get_uint16(uint32_t addr)
    100 {
    101     return lduw_be_phys(&address_space_memory, addr);
    102 }
    103 
    104 static void set_uint16(uint32_t addr, uint16_t w)
    105 {
    106     return stw_be_phys(&address_space_memory, addr, w);
    107 }
    108 
    109 static 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 
    116 static 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 
    123 struct 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 
    136 static 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 
    170 static 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 
    183 static 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 
    207 void 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 
    214 static 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 
    222 static 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 
    236 static 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 
    330 static 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 
    341 static 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 
    406 static 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 
    443 void 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 
    460 uint32_t i82596_ioport_readw(void *opaque, uint32_t addr)
    461 {
    462     return -1;
    463 }
    464 
    465 void i82596_h_reset(void *opaque)
    466 {
    467     I82596State *s = opaque;
    468 
    469     i82596_s_reset(s);
    470 }
    471 
    472 bool 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 
    493 ssize_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 
    729 const 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 
    740 void 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 }