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