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