qemu/hw/net/smc91c111.c
<<
>>
Prefs
   1/*
   2 * SMSC 91C111 Ethernet interface emulation
   3 *
   4 * Copyright (c) 2005 CodeSourcery, LLC.
   5 * Written by Paul Brook
   6 *
   7 * This code is licensed under the GPL
   8 */
   9
  10#include "qemu/osdep.h"
  11#include "hw/sysbus.h"
  12#include "net/net.h"
  13#include "hw/devices.h"
  14#include "qemu/log.h"
  15/* For crc32 */
  16#include <zlib.h>
  17
  18/* Number of 2k memory pages available.  */
  19#define NUM_PACKETS 4
  20
  21#define TYPE_SMC91C111 "smc91c111"
  22#define SMC91C111(obj) OBJECT_CHECK(smc91c111_state, (obj), TYPE_SMC91C111)
  23
  24typedef struct {
  25    SysBusDevice parent_obj;
  26
  27    NICState *nic;
  28    NICConf conf;
  29    uint16_t tcr;
  30    uint16_t rcr;
  31    uint16_t cr;
  32    uint16_t ctr;
  33    uint16_t gpr;
  34    uint16_t ptr;
  35    uint16_t ercv;
  36    qemu_irq irq;
  37    int bank;
  38    int packet_num;
  39    int tx_alloc;
  40    /* Bitmask of allocated packets.  */
  41    int allocated;
  42    int tx_fifo_len;
  43    int tx_fifo[NUM_PACKETS];
  44    int rx_fifo_len;
  45    int rx_fifo[NUM_PACKETS];
  46    int tx_fifo_done_len;
  47    int tx_fifo_done[NUM_PACKETS];
  48    /* Packet buffer memory.  */
  49    uint8_t data[NUM_PACKETS][2048];
  50    uint8_t int_level;
  51    uint8_t int_mask;
  52    MemoryRegion mmio;
  53} smc91c111_state;
  54
  55static const VMStateDescription vmstate_smc91c111 = {
  56    .name = "smc91c111",
  57    .version_id = 1,
  58    .minimum_version_id = 1,
  59    .fields = (VMStateField[]) {
  60        VMSTATE_UINT16(tcr, smc91c111_state),
  61        VMSTATE_UINT16(rcr, smc91c111_state),
  62        VMSTATE_UINT16(cr, smc91c111_state),
  63        VMSTATE_UINT16(ctr, smc91c111_state),
  64        VMSTATE_UINT16(gpr, smc91c111_state),
  65        VMSTATE_UINT16(ptr, smc91c111_state),
  66        VMSTATE_UINT16(ercv, smc91c111_state),
  67        VMSTATE_INT32(bank, smc91c111_state),
  68        VMSTATE_INT32(packet_num, smc91c111_state),
  69        VMSTATE_INT32(tx_alloc, smc91c111_state),
  70        VMSTATE_INT32(allocated, smc91c111_state),
  71        VMSTATE_INT32(tx_fifo_len, smc91c111_state),
  72        VMSTATE_INT32_ARRAY(tx_fifo, smc91c111_state, NUM_PACKETS),
  73        VMSTATE_INT32(rx_fifo_len, smc91c111_state),
  74        VMSTATE_INT32_ARRAY(rx_fifo, smc91c111_state, NUM_PACKETS),
  75        VMSTATE_INT32(tx_fifo_done_len, smc91c111_state),
  76        VMSTATE_INT32_ARRAY(tx_fifo_done, smc91c111_state, NUM_PACKETS),
  77        VMSTATE_BUFFER_UNSAFE(data, smc91c111_state, 0, NUM_PACKETS * 2048),
  78        VMSTATE_UINT8(int_level, smc91c111_state),
  79        VMSTATE_UINT8(int_mask, smc91c111_state),
  80        VMSTATE_END_OF_LIST()
  81    }
  82};
  83
  84#define RCR_SOFT_RST  0x8000
  85#define RCR_STRIP_CRC 0x0200
  86#define RCR_RXEN      0x0100
  87
  88#define TCR_EPH_LOOP  0x2000
  89#define TCR_NOCRC     0x0100
  90#define TCR_PAD_EN    0x0080
  91#define TCR_FORCOL    0x0004
  92#define TCR_LOOP      0x0002
  93#define TCR_TXEN      0x0001
  94
  95#define INT_MD        0x80
  96#define INT_ERCV      0x40
  97#define INT_EPH       0x20
  98#define INT_RX_OVRN   0x10
  99#define INT_ALLOC     0x08
 100#define INT_TX_EMPTY  0x04
 101#define INT_TX        0x02
 102#define INT_RCV       0x01
 103
 104#define CTR_AUTO_RELEASE  0x0800
 105#define CTR_RELOAD        0x0002
 106#define CTR_STORE         0x0001
 107
 108#define RS_ALGNERR      0x8000
 109#define RS_BRODCAST     0x4000
 110#define RS_BADCRC       0x2000
 111#define RS_ODDFRAME     0x1000
 112#define RS_TOOLONG      0x0800
 113#define RS_TOOSHORT     0x0400
 114#define RS_MULTICAST    0x0001
 115
 116/* Update interrupt status.  */
 117static void smc91c111_update(smc91c111_state *s)
 118{
 119    int level;
 120
 121    if (s->tx_fifo_len == 0)
 122        s->int_level |= INT_TX_EMPTY;
 123    if (s->tx_fifo_done_len != 0)
 124        s->int_level |= INT_TX;
 125    level = (s->int_level & s->int_mask) != 0;
 126    qemu_set_irq(s->irq, level);
 127}
 128
 129static int smc91c111_can_receive(smc91c111_state *s)
 130{
 131    if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST)) {
 132        return 1;
 133    }
 134    if (s->allocated == (1 << NUM_PACKETS) - 1 ||
 135        s->rx_fifo_len == NUM_PACKETS) {
 136        return 0;
 137    }
 138    return 1;
 139}
 140
 141static inline void smc91c111_flush_queued_packets(smc91c111_state *s)
 142{
 143    if (smc91c111_can_receive(s)) {
 144        qemu_flush_queued_packets(qemu_get_queue(s->nic));
 145    }
 146}
 147
 148/* Try to allocate a packet.  Returns 0x80 on failure.  */
 149static int smc91c111_allocate_packet(smc91c111_state *s)
 150{
 151    int i;
 152    if (s->allocated == (1 << NUM_PACKETS) - 1) {
 153        return 0x80;
 154    }
 155
 156    for (i = 0; i < NUM_PACKETS; i++) {
 157        if ((s->allocated & (1 << i)) == 0)
 158            break;
 159    }
 160    s->allocated |= 1 << i;
 161    return i;
 162}
 163
 164
 165/* Process a pending TX allocate.  */
 166static void smc91c111_tx_alloc(smc91c111_state *s)
 167{
 168    s->tx_alloc = smc91c111_allocate_packet(s);
 169    if (s->tx_alloc == 0x80)
 170        return;
 171    s->int_level |= INT_ALLOC;
 172    smc91c111_update(s);
 173}
 174
 175/* Remove and item from the RX FIFO.  */
 176static void smc91c111_pop_rx_fifo(smc91c111_state *s)
 177{
 178    int i;
 179
 180    s->rx_fifo_len--;
 181    if (s->rx_fifo_len) {
 182        for (i = 0; i < s->rx_fifo_len; i++)
 183            s->rx_fifo[i] = s->rx_fifo[i + 1];
 184        s->int_level |= INT_RCV;
 185    } else {
 186        s->int_level &= ~INT_RCV;
 187    }
 188    smc91c111_flush_queued_packets(s);
 189    smc91c111_update(s);
 190}
 191
 192/* Remove an item from the TX completion FIFO.  */
 193static void smc91c111_pop_tx_fifo_done(smc91c111_state *s)
 194{
 195    int i;
 196
 197    if (s->tx_fifo_done_len == 0)
 198        return;
 199    s->tx_fifo_done_len--;
 200    for (i = 0; i < s->tx_fifo_done_len; i++)
 201        s->tx_fifo_done[i] = s->tx_fifo_done[i + 1];
 202}
 203
 204/* Release the memory allocated to a packet.  */
 205static void smc91c111_release_packet(smc91c111_state *s, int packet)
 206{
 207    s->allocated &= ~(1 << packet);
 208    if (s->tx_alloc == 0x80)
 209        smc91c111_tx_alloc(s);
 210    smc91c111_flush_queued_packets(s);
 211}
 212
 213/* Flush the TX FIFO.  */
 214static void smc91c111_do_tx(smc91c111_state *s)
 215{
 216    int i;
 217    int len;
 218    int control;
 219    int packetnum;
 220    uint8_t *p;
 221
 222    if ((s->tcr & TCR_TXEN) == 0)
 223        return;
 224    if (s->tx_fifo_len == 0)
 225        return;
 226    for (i = 0; i < s->tx_fifo_len; i++) {
 227        packetnum = s->tx_fifo[i];
 228        p = &s->data[packetnum][0];
 229        /* Set status word.  */
 230        *(p++) = 0x01;
 231        *(p++) = 0x40;
 232        len = *(p++);
 233        len |= ((int)*(p++)) << 8;
 234        len -= 6;
 235        control = p[len + 1];
 236        if (control & 0x20)
 237            len++;
 238        /* ??? This overwrites the data following the buffer.
 239           Don't know what real hardware does.  */
 240        if (len < 64 && (s->tcr & TCR_PAD_EN)) {
 241            memset(p + len, 0, 64 - len);
 242            len = 64;
 243        }
 244#if 0
 245        {
 246            int add_crc;
 247
 248            /* The card is supposed to append the CRC to the frame.
 249               However none of the other network traffic has the CRC
 250               appended.  Suspect this is low level ethernet detail we
 251               don't need to worry about.  */
 252            add_crc = (control & 0x10) || (s->tcr & TCR_NOCRC) == 0;
 253            if (add_crc) {
 254                uint32_t crc;
 255
 256                crc = crc32(~0, p, len);
 257                memcpy(p + len, &crc, 4);
 258                len += 4;
 259            }
 260        }
 261#endif
 262        if (s->ctr & CTR_AUTO_RELEASE)
 263            /* Race?  */
 264            smc91c111_release_packet(s, packetnum);
 265        else if (s->tx_fifo_done_len < NUM_PACKETS)
 266            s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
 267        qemu_send_packet(qemu_get_queue(s->nic), p, len);
 268    }
 269    s->tx_fifo_len = 0;
 270    smc91c111_update(s);
 271}
 272
 273/* Add a packet to the TX FIFO.  */
 274static void smc91c111_queue_tx(smc91c111_state *s, int packet)
 275{
 276    if (s->tx_fifo_len == NUM_PACKETS)
 277        return;
 278    s->tx_fifo[s->tx_fifo_len++] = packet;
 279    smc91c111_do_tx(s);
 280}
 281
 282static void smc91c111_reset(DeviceState *dev)
 283{
 284    smc91c111_state *s = SMC91C111(dev);
 285
 286    s->bank = 0;
 287    s->tx_fifo_len = 0;
 288    s->tx_fifo_done_len = 0;
 289    s->rx_fifo_len = 0;
 290    s->allocated = 0;
 291    s->packet_num = 0;
 292    s->tx_alloc = 0;
 293    s->tcr = 0;
 294    s->rcr = 0;
 295    s->cr = 0xa0b1;
 296    s->ctr = 0x1210;
 297    s->ptr = 0;
 298    s->ercv = 0x1f;
 299    s->int_level = INT_TX_EMPTY;
 300    s->int_mask = 0;
 301    smc91c111_update(s);
 302}
 303
 304#define SET_LOW(name, val) s->name = (s->name & 0xff00) | val
 305#define SET_HIGH(name, val) s->name = (s->name & 0xff) | (val << 8)
 306
 307static void smc91c111_writeb(void *opaque, hwaddr offset,
 308                             uint32_t value)
 309{
 310    smc91c111_state *s = (smc91c111_state *)opaque;
 311
 312    offset = offset & 0xf;
 313    if (offset == 14) {
 314        s->bank = value;
 315        return;
 316    }
 317    if (offset == 15)
 318        return;
 319    switch (s->bank) {
 320    case 0:
 321        switch (offset) {
 322        case 0: /* TCR */
 323            SET_LOW(tcr, value);
 324            return;
 325        case 1:
 326            SET_HIGH(tcr, value);
 327            return;
 328        case 4: /* RCR */
 329            SET_LOW(rcr, value);
 330            return;
 331        case 5:
 332            SET_HIGH(rcr, value);
 333            if (s->rcr & RCR_SOFT_RST) {
 334                smc91c111_reset(DEVICE(s));
 335            }
 336            smc91c111_flush_queued_packets(s);
 337            return;
 338        case 10: case 11: /* RPCR */
 339            /* Ignored */
 340            return;
 341        case 12: case 13: /* Reserved */
 342            return;
 343        }
 344        break;
 345
 346    case 1:
 347        switch (offset) {
 348        case 0: /* CONFIG */
 349            SET_LOW(cr, value);
 350            return;
 351        case 1:
 352            SET_HIGH(cr,value);
 353            return;
 354        case 2: case 3: /* BASE */
 355        case 4: case 5: case 6: case 7: case 8: case 9: /* IA */
 356            /* Not implemented.  */
 357            return;
 358        case 10: /* Genral Purpose */
 359            SET_LOW(gpr, value);
 360            return;
 361        case 11:
 362            SET_HIGH(gpr, value);
 363            return;
 364        case 12: /* Control */
 365            if (value & 1) {
 366                qemu_log_mask(LOG_UNIMP,
 367                              "smc91c111: EEPROM store not implemented\n");
 368            }
 369            if (value & 2) {
 370                qemu_log_mask(LOG_UNIMP,
 371                              "smc91c111: EEPROM reload not implemented\n");
 372            }
 373            value &= ~3;
 374            SET_LOW(ctr, value);
 375            return;
 376        case 13:
 377            SET_HIGH(ctr, value);
 378            return;
 379        }
 380        break;
 381
 382    case 2:
 383        switch (offset) {
 384        case 0: /* MMU Command */
 385            switch (value >> 5) {
 386            case 0: /* no-op */
 387                break;
 388            case 1: /* Allocate for TX.  */
 389                s->tx_alloc = 0x80;
 390                s->int_level &= ~INT_ALLOC;
 391                smc91c111_update(s);
 392                smc91c111_tx_alloc(s);
 393                break;
 394            case 2: /* Reset MMU.  */
 395                s->allocated = 0;
 396                s->tx_fifo_len = 0;
 397                s->tx_fifo_done_len = 0;
 398                s->rx_fifo_len = 0;
 399                s->tx_alloc = 0;
 400                break;
 401            case 3: /* Remove from RX FIFO.  */
 402                smc91c111_pop_rx_fifo(s);
 403                break;
 404            case 4: /* Remove from RX FIFO and release.  */
 405                if (s->rx_fifo_len > 0) {
 406                    smc91c111_release_packet(s, s->rx_fifo[0]);
 407                }
 408                smc91c111_pop_rx_fifo(s);
 409                break;
 410            case 5: /* Release.  */
 411                smc91c111_release_packet(s, s->packet_num);
 412                break;
 413            case 6: /* Add to TX FIFO.  */
 414                smc91c111_queue_tx(s, s->packet_num);
 415                break;
 416            case 7: /* Reset TX FIFO.  */
 417                s->tx_fifo_len = 0;
 418                s->tx_fifo_done_len = 0;
 419                break;
 420            }
 421            return;
 422        case 1:
 423            /* Ignore.  */
 424            return;
 425        case 2: /* Packet Number Register */
 426            s->packet_num = value;
 427            return;
 428        case 3: case 4: case 5:
 429            /* Should be readonly, but linux writes to them anyway. Ignore.  */
 430            return;
 431        case 6: /* Pointer */
 432            SET_LOW(ptr, value);
 433            return;
 434        case 7:
 435            SET_HIGH(ptr, value);
 436            return;
 437        case 8: case 9: case 10: case 11: /* Data */
 438            {
 439                int p;
 440                int n;
 441
 442                if (s->ptr & 0x8000)
 443                    n = s->rx_fifo[0];
 444                else
 445                    n = s->packet_num;
 446                p = s->ptr & 0x07ff;
 447                if (s->ptr & 0x4000) {
 448                    s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff);
 449                } else {
 450                    p += (offset & 3);
 451                }
 452                s->data[n][p] = value;
 453            }
 454            return;
 455        case 12: /* Interrupt ACK.  */
 456            s->int_level &= ~(value & 0xd6);
 457            if (value & INT_TX)
 458                smc91c111_pop_tx_fifo_done(s);
 459            smc91c111_update(s);
 460            return;
 461        case 13: /* Interrupt mask.  */
 462            s->int_mask = value;
 463            smc91c111_update(s);
 464            return;
 465        }
 466        break;
 467
 468    case 3:
 469        switch (offset) {
 470        case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
 471            /* Multicast table.  */
 472            /* Not implemented.  */
 473            return;
 474        case 8: case 9: /* Management Interface.  */
 475            /* Not implemented.  */
 476            return;
 477        case 12: /* Early receive.  */
 478            s->ercv = value & 0x1f;
 479            return;
 480        case 13:
 481            /* Ignore.  */
 482            return;
 483        }
 484        break;
 485    }
 486    qemu_log_mask(LOG_GUEST_ERROR, "smc91c111_write(bank:%d) Illegal register"
 487                                   " 0x%" HWADDR_PRIx " = 0x%x\n",
 488                  s->bank, offset, value);
 489}
 490
 491static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
 492{
 493    smc91c111_state *s = (smc91c111_state *)opaque;
 494
 495    offset = offset & 0xf;
 496    if (offset == 14) {
 497        return s->bank;
 498    }
 499    if (offset == 15)
 500        return 0x33;
 501    switch (s->bank) {
 502    case 0:
 503        switch (offset) {
 504        case 0: /* TCR */
 505            return s->tcr & 0xff;
 506        case 1:
 507            return s->tcr >> 8;
 508        case 2: /* EPH Status */
 509            return 0;
 510        case 3:
 511            return 0x40;
 512        case 4: /* RCR */
 513            return s->rcr & 0xff;
 514        case 5:
 515            return s->rcr >> 8;
 516        case 6: /* Counter */
 517        case 7:
 518            /* Not implemented.  */
 519            return 0;
 520        case 8: /* Memory size.  */
 521            return NUM_PACKETS;
 522        case 9: /* Free memory available.  */
 523            {
 524                int i;
 525                int n;
 526                n = 0;
 527                for (i = 0; i < NUM_PACKETS; i++) {
 528                    if (s->allocated & (1 << i))
 529                        n++;
 530                }
 531                return n;
 532            }
 533        case 10: case 11: /* RPCR */
 534            /* Not implemented.  */
 535            return 0;
 536        case 12: case 13: /* Reserved */
 537            return 0;
 538        }
 539        break;
 540
 541    case 1:
 542        switch (offset) {
 543        case 0: /* CONFIG */
 544            return s->cr & 0xff;
 545        case 1:
 546            return s->cr >> 8;
 547        case 2: case 3: /* BASE */
 548            /* Not implemented.  */
 549            return 0;
 550        case 4: case 5: case 6: case 7: case 8: case 9: /* IA */
 551            return s->conf.macaddr.a[offset - 4];
 552        case 10: /* General Purpose */
 553            return s->gpr & 0xff;
 554        case 11:
 555            return s->gpr >> 8;
 556        case 12: /* Control */
 557            return s->ctr & 0xff;
 558        case 13:
 559            return s->ctr >> 8;
 560        }
 561        break;
 562
 563    case 2:
 564        switch (offset) {
 565        case 0: case 1: /* MMUCR Busy bit.  */
 566            return 0;
 567        case 2: /* Packet Number.  */
 568            return s->packet_num;
 569        case 3: /* Allocation Result.  */
 570            return s->tx_alloc;
 571        case 4: /* TX FIFO */
 572            if (s->tx_fifo_done_len == 0)
 573                return 0x80;
 574            else
 575                return s->tx_fifo_done[0];
 576        case 5: /* RX FIFO */
 577            if (s->rx_fifo_len == 0)
 578                return 0x80;
 579            else
 580                return s->rx_fifo[0];
 581        case 6: /* Pointer */
 582            return s->ptr & 0xff;
 583        case 7:
 584            return (s->ptr >> 8) & 0xf7;
 585        case 8: case 9: case 10: case 11: /* Data */
 586            {
 587                int p;
 588                int n;
 589
 590                if (s->ptr & 0x8000)
 591                    n = s->rx_fifo[0];
 592                else
 593                    n = s->packet_num;
 594                p = s->ptr & 0x07ff;
 595                if (s->ptr & 0x4000) {
 596                    s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x07ff);
 597                } else {
 598                    p += (offset & 3);
 599                }
 600                return s->data[n][p];
 601            }
 602        case 12: /* Interrupt status.  */
 603            return s->int_level;
 604        case 13: /* Interrupt mask.  */
 605            return s->int_mask;
 606        }
 607        break;
 608
 609    case 3:
 610        switch (offset) {
 611        case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
 612            /* Multicast table.  */
 613            /* Not implemented.  */
 614            return 0;
 615        case 8: /* Management Interface.  */
 616            /* Not implemented.  */
 617            return 0x30;
 618        case 9:
 619            return 0x33;
 620        case 10: /* Revision.  */
 621            return 0x91;
 622        case 11:
 623            return 0x33;
 624        case 12:
 625            return s->ercv;
 626        case 13:
 627            return 0;
 628        }
 629        break;
 630    }
 631    qemu_log_mask(LOG_GUEST_ERROR, "smc91c111_read(bank:%d) Illegal register"
 632                                   " 0x%" HWADDR_PRIx "\n",
 633                  s->bank, offset);
 634    return 0;
 635}
 636
 637static uint64_t smc91c111_readfn(void *opaque, hwaddr addr, unsigned size)
 638{
 639    int i;
 640    uint32_t val = 0;
 641
 642    for (i = 0; i < size; i++) {
 643        val |= smc91c111_readb(opaque, addr + i) << (i * 8);
 644    }
 645    return val;
 646}
 647
 648static void smc91c111_writefn(void *opaque, hwaddr addr,
 649                               uint64_t value, unsigned size)
 650{
 651    int i = 0;
 652
 653    /* 32-bit writes to offset 0xc only actually write to the bank select
 654     * register (offset 0xe), so skip the first two bytes we would write.
 655     */
 656    if (addr == 0xc && size == 4) {
 657        i += 2;
 658    }
 659
 660    for (; i < size; i++) {
 661        smc91c111_writeb(opaque, addr + i,
 662                         extract32(value, i * 8, 8));
 663    }
 664}
 665
 666static int smc91c111_can_receive_nc(NetClientState *nc)
 667{
 668    smc91c111_state *s = qemu_get_nic_opaque(nc);
 669
 670    return smc91c111_can_receive(s);
 671}
 672
 673static ssize_t smc91c111_receive(NetClientState *nc, const uint8_t *buf, size_t size)
 674{
 675    smc91c111_state *s = qemu_get_nic_opaque(nc);
 676    int status;
 677    int packetsize;
 678    uint32_t crc;
 679    int packetnum;
 680    uint8_t *p;
 681
 682    if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST))
 683        return -1;
 684    /* Short packets are padded with zeros.  Receiving a packet
 685       < 64 bytes long is considered an error condition.  */
 686    if (size < 64)
 687        packetsize = 64;
 688    else
 689        packetsize = (size & ~1);
 690    packetsize += 6;
 691    crc = (s->rcr & RCR_STRIP_CRC) == 0;
 692    if (crc)
 693        packetsize += 4;
 694    /* TODO: Flag overrun and receive errors.  */
 695    if (packetsize > 2048)
 696        return -1;
 697    packetnum = smc91c111_allocate_packet(s);
 698    if (packetnum == 0x80)
 699        return -1;
 700    s->rx_fifo[s->rx_fifo_len++] = packetnum;
 701
 702    p = &s->data[packetnum][0];
 703    /* ??? Multicast packets?  */
 704    status = 0;
 705    if (size > 1518)
 706        status |= RS_TOOLONG;
 707    if (size & 1)
 708        status |= RS_ODDFRAME;
 709    *(p++) = status & 0xff;
 710    *(p++) = status >> 8;
 711    *(p++) = packetsize & 0xff;
 712    *(p++) = packetsize >> 8;
 713    memcpy(p, buf, size & ~1);
 714    p += (size & ~1);
 715    /* Pad short packets.  */
 716    if (size < 64) {
 717        int pad;
 718
 719        if (size & 1)
 720            *(p++) = buf[size - 1];
 721        pad = 64 - size;
 722        memset(p, 0, pad);
 723        p += pad;
 724        size = 64;
 725    }
 726    /* It's not clear if the CRC should go before or after the last byte in
 727       odd sized packets.  Linux disables the CRC, so that's no help.
 728       The pictures in the documentation show the CRC aligned on a 16-bit
 729       boundary before the last odd byte, so that's what we do.  */
 730    if (crc) {
 731        crc = crc32(~0, buf, size);
 732        *(p++) = crc & 0xff; crc >>= 8;
 733        *(p++) = crc & 0xff; crc >>= 8;
 734        *(p++) = crc & 0xff; crc >>= 8;
 735        *(p++) = crc & 0xff;
 736    }
 737    if (size & 1) {
 738        *(p++) = buf[size - 1];
 739        *p = 0x60;
 740    } else {
 741        *(p++) = 0;
 742        *p = 0x40;
 743    }
 744    /* TODO: Raise early RX interrupt?  */
 745    s->int_level |= INT_RCV;
 746    smc91c111_update(s);
 747
 748    return size;
 749}
 750
 751static const MemoryRegionOps smc91c111_mem_ops = {
 752    /* The special case for 32 bit writes to 0xc means we can't just
 753     * set .impl.min/max_access_size to 1, unfortunately
 754     */
 755    .read = smc91c111_readfn,
 756    .write = smc91c111_writefn,
 757    .valid.min_access_size = 1,
 758    .valid.max_access_size = 4,
 759    .endianness = DEVICE_NATIVE_ENDIAN,
 760};
 761
 762static NetClientInfo net_smc91c111_info = {
 763    .type = NET_CLIENT_DRIVER_NIC,
 764    .size = sizeof(NICState),
 765    .can_receive = smc91c111_can_receive_nc,
 766    .receive = smc91c111_receive,
 767};
 768
 769static void smc91c111_realize(DeviceState *dev, Error **errp)
 770{
 771    SysBusDevice *sbd = SYS_BUS_DEVICE(dev);
 772    smc91c111_state *s = SMC91C111(dev);
 773
 774    memory_region_init_io(&s->mmio, OBJECT(s), &smc91c111_mem_ops, s,
 775                          "smc91c111-mmio", 16);
 776    sysbus_init_mmio(sbd, &s->mmio);
 777    sysbus_init_irq(sbd, &s->irq);
 778    qemu_macaddr_default_if_unset(&s->conf.macaddr);
 779    s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf,
 780                          object_get_typename(OBJECT(dev)), dev->id, s);
 781    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
 782    /* ??? Save/restore.  */
 783}
 784
 785static Property smc91c111_properties[] = {
 786    DEFINE_NIC_PROPERTIES(smc91c111_state, conf),
 787    DEFINE_PROP_END_OF_LIST(),
 788};
 789
 790static void smc91c111_class_init(ObjectClass *klass, void *data)
 791{
 792    DeviceClass *dc = DEVICE_CLASS(klass);
 793
 794    dc->realize = smc91c111_realize;
 795    dc->reset = smc91c111_reset;
 796    dc->vmsd = &vmstate_smc91c111;
 797    dc->props = smc91c111_properties;
 798}
 799
 800static const TypeInfo smc91c111_info = {
 801    .name          = TYPE_SMC91C111,
 802    .parent        = TYPE_SYS_BUS_DEVICE,
 803    .instance_size = sizeof(smc91c111_state),
 804    .class_init    = smc91c111_class_init,
 805};
 806
 807static void smc91c111_register_types(void)
 808{
 809    type_register_static(&smc91c111_info);
 810}
 811
 812/* Legacy helper function.  Should go away when machine config files are
 813   implemented.  */
 814void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
 815{
 816    DeviceState *dev;
 817    SysBusDevice *s;
 818
 819    qemu_check_nic_model(nd, "smc91c111");
 820    dev = qdev_create(NULL, TYPE_SMC91C111);
 821    qdev_set_nic_properties(dev, nd);
 822    qdev_init_nofail(dev);
 823    s = SYS_BUS_DEVICE(dev);
 824    sysbus_mmio_map(s, 0, base);
 825    sysbus_connect_irq(s, 0, irq);
 826}
 827
 828type_init(smc91c111_register_types)
 829