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