qemu/hw/net/dp8393x.c
<<
>>
Prefs
   1/*
   2 * QEMU NS SONIC DP8393x netcard
   3 *
   4 * Copyright (c) 2008-2009 Herve Poussineau
   5 *
   6 * This program is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU General Public License as
   8 * published by the Free Software Foundation; either version 2 of
   9 * the License, or (at your option) any later version.
  10 *
  11 * This program is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14 * GNU General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU General Public License along
  17 * with this program; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19
  20#include "qemu/osdep.h"
  21#include "hw/sysbus.h"
  22#include "net/net.h"
  23#include "qapi/error.h"
  24#include "qemu/timer.h"
  25#include <zlib.h>
  26
  27//#define DEBUG_SONIC
  28
  29#define SONIC_PROM_SIZE 0x1000
  30
  31#ifdef DEBUG_SONIC
  32#define DPRINTF(fmt, ...) \
  33do { printf("sonic: " fmt , ##  __VA_ARGS__); } while (0)
  34static const char* reg_names[] = {
  35    "CR", "DCR", "RCR", "TCR", "IMR", "ISR", "UTDA", "CTDA",
  36    "TPS", "TFC", "TSA0", "TSA1", "TFS", "URDA", "CRDA", "CRBA0",
  37    "CRBA1", "RBWC0", "RBWC1", "EOBC", "URRA", "RSA", "REA", "RRP",
  38    "RWP", "TRBA0", "TRBA1", "0x1b", "0x1c", "0x1d", "0x1e", "LLFA",
  39    "TTDA", "CEP", "CAP2", "CAP1", "CAP0", "CE", "CDP", "CDC",
  40    "SR", "WT0", "WT1", "RSC", "CRCT", "FAET", "MPT", "MDT",
  41    "0x30", "0x31", "0x32", "0x33", "0x34", "0x35", "0x36", "0x37",
  42    "0x38", "0x39", "0x3a", "0x3b", "0x3c", "0x3d", "0x3e", "DCR2" };
  43#else
  44#define DPRINTF(fmt, ...) do {} while (0)
  45#endif
  46
  47#define SONIC_ERROR(fmt, ...) \
  48do { printf("sonic ERROR: %s: " fmt, __func__ , ## __VA_ARGS__); } while (0)
  49
  50#define SONIC_CR     0x00
  51#define SONIC_DCR    0x01
  52#define SONIC_RCR    0x02
  53#define SONIC_TCR    0x03
  54#define SONIC_IMR    0x04
  55#define SONIC_ISR    0x05
  56#define SONIC_UTDA   0x06
  57#define SONIC_CTDA   0x07
  58#define SONIC_TPS    0x08
  59#define SONIC_TFC    0x09
  60#define SONIC_TSA0   0x0a
  61#define SONIC_TSA1   0x0b
  62#define SONIC_TFS    0x0c
  63#define SONIC_URDA   0x0d
  64#define SONIC_CRDA   0x0e
  65#define SONIC_CRBA0  0x0f
  66#define SONIC_CRBA1  0x10
  67#define SONIC_RBWC0  0x11
  68#define SONIC_RBWC1  0x12
  69#define SONIC_EOBC   0x13
  70#define SONIC_URRA   0x14
  71#define SONIC_RSA    0x15
  72#define SONIC_REA    0x16
  73#define SONIC_RRP    0x17
  74#define SONIC_RWP    0x18
  75#define SONIC_TRBA0  0x19
  76#define SONIC_TRBA1  0x1a
  77#define SONIC_LLFA   0x1f
  78#define SONIC_TTDA   0x20
  79#define SONIC_CEP    0x21
  80#define SONIC_CAP2   0x22
  81#define SONIC_CAP1   0x23
  82#define SONIC_CAP0   0x24
  83#define SONIC_CE     0x25
  84#define SONIC_CDP    0x26
  85#define SONIC_CDC    0x27
  86#define SONIC_SR     0x28
  87#define SONIC_WT0    0x29
  88#define SONIC_WT1    0x2a
  89#define SONIC_RSC    0x2b
  90#define SONIC_CRCT   0x2c
  91#define SONIC_FAET   0x2d
  92#define SONIC_MPT    0x2e
  93#define SONIC_MDT    0x2f
  94#define SONIC_DCR2   0x3f
  95
  96#define SONIC_CR_HTX     0x0001
  97#define SONIC_CR_TXP     0x0002
  98#define SONIC_CR_RXDIS   0x0004
  99#define SONIC_CR_RXEN    0x0008
 100#define SONIC_CR_STP     0x0010
 101#define SONIC_CR_ST      0x0020
 102#define SONIC_CR_RST     0x0080
 103#define SONIC_CR_RRRA    0x0100
 104#define SONIC_CR_LCAM    0x0200
 105#define SONIC_CR_MASK    0x03bf
 106
 107#define SONIC_DCR_DW     0x0020
 108#define SONIC_DCR_LBR    0x2000
 109#define SONIC_DCR_EXBUS  0x8000
 110
 111#define SONIC_RCR_PRX    0x0001
 112#define SONIC_RCR_LBK    0x0002
 113#define SONIC_RCR_FAER   0x0004
 114#define SONIC_RCR_CRCR   0x0008
 115#define SONIC_RCR_CRS    0x0020
 116#define SONIC_RCR_LPKT   0x0040
 117#define SONIC_RCR_BC     0x0080
 118#define SONIC_RCR_MC     0x0100
 119#define SONIC_RCR_LB0    0x0200
 120#define SONIC_RCR_LB1    0x0400
 121#define SONIC_RCR_AMC    0x0800
 122#define SONIC_RCR_PRO    0x1000
 123#define SONIC_RCR_BRD    0x2000
 124#define SONIC_RCR_RNT    0x4000
 125
 126#define SONIC_TCR_PTX    0x0001
 127#define SONIC_TCR_BCM    0x0002
 128#define SONIC_TCR_FU     0x0004
 129#define SONIC_TCR_EXC    0x0040
 130#define SONIC_TCR_CRSL   0x0080
 131#define SONIC_TCR_NCRS   0x0100
 132#define SONIC_TCR_EXD    0x0400
 133#define SONIC_TCR_CRCI   0x2000
 134#define SONIC_TCR_PINT   0x8000
 135
 136#define SONIC_ISR_RBE    0x0020
 137#define SONIC_ISR_RDE    0x0040
 138#define SONIC_ISR_TC     0x0080
 139#define SONIC_ISR_TXDN   0x0200
 140#define SONIC_ISR_PKTRX  0x0400
 141#define SONIC_ISR_PINT   0x0800
 142#define SONIC_ISR_LCD    0x1000
 143
 144#define TYPE_DP8393X "dp8393x"
 145#define DP8393X(obj) OBJECT_CHECK(dp8393xState, (obj), TYPE_DP8393X)
 146
 147typedef struct dp8393xState {
 148    SysBusDevice parent_obj;
 149
 150    /* Hardware */
 151    uint8_t it_shift;
 152    qemu_irq irq;
 153#ifdef DEBUG_SONIC
 154    int irq_level;
 155#endif
 156    QEMUTimer *watchdog;
 157    int64_t wt_last_update;
 158    NICConf conf;
 159    NICState *nic;
 160    MemoryRegion mmio;
 161    MemoryRegion prom;
 162
 163    /* Registers */
 164    uint8_t cam[16][6];
 165    uint16_t regs[0x40];
 166
 167    /* Temporaries */
 168    uint8_t tx_buffer[0x10000];
 169    int loopback_packet;
 170
 171    /* Memory access */
 172    void *dma_mr;
 173    AddressSpace as;
 174} dp8393xState;
 175
 176/* Accessor functions for values which are formed by
 177 * concatenating two 16 bit device registers. By putting these
 178 * in their own functions with a uint32_t return type we avoid the
 179 * pitfall of implicit sign extension where ((x << 16) | y) is a
 180 * signed 32 bit integer that might get sign-extended to a 64 bit integer.
 181 */
 182static uint32_t dp8393x_cdp(dp8393xState *s)
 183{
 184    return (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_CDP];
 185}
 186
 187static uint32_t dp8393x_crba(dp8393xState *s)
 188{
 189    return (s->regs[SONIC_CRBA1] << 16) | s->regs[SONIC_CRBA0];
 190}
 191
 192static uint32_t dp8393x_crda(dp8393xState *s)
 193{
 194    return (s->regs[SONIC_URDA] << 16) | s->regs[SONIC_CRDA];
 195}
 196
 197static uint32_t dp8393x_rbwc(dp8393xState *s)
 198{
 199    return (s->regs[SONIC_RBWC1] << 16) | s->regs[SONIC_RBWC0];
 200}
 201
 202static uint32_t dp8393x_rrp(dp8393xState *s)
 203{
 204    return (s->regs[SONIC_URRA] << 16) | s->regs[SONIC_RRP];
 205}
 206
 207static uint32_t dp8393x_tsa(dp8393xState *s)
 208{
 209    return (s->regs[SONIC_TSA1] << 16) | s->regs[SONIC_TSA0];
 210}
 211
 212static uint32_t dp8393x_ttda(dp8393xState *s)
 213{
 214    return (s->regs[SONIC_UTDA] << 16) | s->regs[SONIC_TTDA];
 215}
 216
 217static uint32_t dp8393x_wt(dp8393xState *s)
 218{
 219    return s->regs[SONIC_WT1] << 16 | s->regs[SONIC_WT0];
 220}
 221
 222static void dp8393x_update_irq(dp8393xState *s)
 223{
 224    int level = (s->regs[SONIC_IMR] & s->regs[SONIC_ISR]) ? 1 : 0;
 225
 226#ifdef DEBUG_SONIC
 227    if (level != s->irq_level) {
 228        s->irq_level = level;
 229        if (level) {
 230            DPRINTF("raise irq, isr is 0x%04x\n", s->regs[SONIC_ISR]);
 231        } else {
 232            DPRINTF("lower irq\n");
 233        }
 234    }
 235#endif
 236
 237    qemu_set_irq(s->irq, level);
 238}
 239
 240static void dp8393x_do_load_cam(dp8393xState *s)
 241{
 242    uint16_t data[8];
 243    int width, size;
 244    uint16_t index = 0;
 245
 246    width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
 247    size = sizeof(uint16_t) * 4 * width;
 248
 249    while (s->regs[SONIC_CDC] & 0x1f) {
 250        /* Fill current entry */
 251        address_space_rw(&s->as, dp8393x_cdp(s),
 252            MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
 253        s->cam[index][0] = data[1 * width] & 0xff;
 254        s->cam[index][1] = data[1 * width] >> 8;
 255        s->cam[index][2] = data[2 * width] & 0xff;
 256        s->cam[index][3] = data[2 * width] >> 8;
 257        s->cam[index][4] = data[3 * width] & 0xff;
 258        s->cam[index][5] = data[3 * width] >> 8;
 259        DPRINTF("load cam[%d] with %02x%02x%02x%02x%02x%02x\n", index,
 260            s->cam[index][0], s->cam[index][1], s->cam[index][2],
 261            s->cam[index][3], s->cam[index][4], s->cam[index][5]);
 262        /* Move to next entry */
 263        s->regs[SONIC_CDC]--;
 264        s->regs[SONIC_CDP] += size;
 265        index++;
 266    }
 267
 268    /* Read CAM enable */
 269    address_space_rw(&s->as, dp8393x_cdp(s),
 270        MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
 271    s->regs[SONIC_CE] = data[0 * width];
 272    DPRINTF("load cam done. cam enable mask 0x%04x\n", s->regs[SONIC_CE]);
 273
 274    /* Done */
 275    s->regs[SONIC_CR] &= ~SONIC_CR_LCAM;
 276    s->regs[SONIC_ISR] |= SONIC_ISR_LCD;
 277    dp8393x_update_irq(s);
 278}
 279
 280static void dp8393x_do_read_rra(dp8393xState *s)
 281{
 282    uint16_t data[8];
 283    int width, size;
 284
 285    /* Read memory */
 286    width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
 287    size = sizeof(uint16_t) * 4 * width;
 288    address_space_rw(&s->as, dp8393x_rrp(s),
 289        MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
 290
 291    /* Update SONIC registers */
 292    s->regs[SONIC_CRBA0] = data[0 * width];
 293    s->regs[SONIC_CRBA1] = data[1 * width];
 294    s->regs[SONIC_RBWC0] = data[2 * width];
 295    s->regs[SONIC_RBWC1] = data[3 * width];
 296    DPRINTF("CRBA0/1: 0x%04x/0x%04x, RBWC0/1: 0x%04x/0x%04x\n",
 297        s->regs[SONIC_CRBA0], s->regs[SONIC_CRBA1],
 298        s->regs[SONIC_RBWC0], s->regs[SONIC_RBWC1]);
 299
 300    /* Go to next entry */
 301    s->regs[SONIC_RRP] += size;
 302
 303    /* Handle wrap */
 304    if (s->regs[SONIC_RRP] == s->regs[SONIC_REA]) {
 305        s->regs[SONIC_RRP] = s->regs[SONIC_RSA];
 306    }
 307
 308    /* Check resource exhaustion */
 309    if (s->regs[SONIC_RRP] == s->regs[SONIC_RWP])
 310    {
 311        s->regs[SONIC_ISR] |= SONIC_ISR_RBE;
 312        dp8393x_update_irq(s);
 313    }
 314
 315    /* Done */
 316    s->regs[SONIC_CR] &= ~SONIC_CR_RRRA;
 317}
 318
 319static void dp8393x_do_software_reset(dp8393xState *s)
 320{
 321    timer_del(s->watchdog);
 322
 323    s->regs[SONIC_CR] &= ~(SONIC_CR_LCAM | SONIC_CR_RRRA | SONIC_CR_TXP | SONIC_CR_HTX);
 324    s->regs[SONIC_CR] |= SONIC_CR_RST | SONIC_CR_RXDIS;
 325}
 326
 327static void dp8393x_set_next_tick(dp8393xState *s)
 328{
 329    uint32_t ticks;
 330    int64_t delay;
 331
 332    if (s->regs[SONIC_CR] & SONIC_CR_STP) {
 333        timer_del(s->watchdog);
 334        return;
 335    }
 336
 337    ticks = dp8393x_wt(s);
 338    s->wt_last_update = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 339    delay = NANOSECONDS_PER_SECOND * ticks / 5000000;
 340    timer_mod(s->watchdog, s->wt_last_update + delay);
 341}
 342
 343static void dp8393x_update_wt_regs(dp8393xState *s)
 344{
 345    int64_t elapsed;
 346    uint32_t val;
 347
 348    if (s->regs[SONIC_CR] & SONIC_CR_STP) {
 349        timer_del(s->watchdog);
 350        return;
 351    }
 352
 353    elapsed = s->wt_last_update - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
 354    val = dp8393x_wt(s);
 355    val -= elapsed / 5000000;
 356    s->regs[SONIC_WT1] = (val >> 16) & 0xffff;
 357    s->regs[SONIC_WT0] = (val >> 0)  & 0xffff;
 358    dp8393x_set_next_tick(s);
 359
 360}
 361
 362static void dp8393x_do_start_timer(dp8393xState *s)
 363{
 364    s->regs[SONIC_CR] &= ~SONIC_CR_STP;
 365    dp8393x_set_next_tick(s);
 366}
 367
 368static void dp8393x_do_stop_timer(dp8393xState *s)
 369{
 370    s->regs[SONIC_CR] &= ~SONIC_CR_ST;
 371    dp8393x_update_wt_regs(s);
 372}
 373
 374static int dp8393x_can_receive(NetClientState *nc);
 375
 376static void dp8393x_do_receiver_enable(dp8393xState *s)
 377{
 378    s->regs[SONIC_CR] &= ~SONIC_CR_RXDIS;
 379    if (dp8393x_can_receive(s->nic->ncs)) {
 380        qemu_flush_queued_packets(qemu_get_queue(s->nic));
 381    }
 382}
 383
 384static void dp8393x_do_receiver_disable(dp8393xState *s)
 385{
 386    s->regs[SONIC_CR] &= ~SONIC_CR_RXEN;
 387}
 388
 389static void dp8393x_do_transmit_packets(dp8393xState *s)
 390{
 391    NetClientState *nc = qemu_get_queue(s->nic);
 392    uint16_t data[12];
 393    int width, size;
 394    int tx_len, len;
 395    uint16_t i;
 396
 397    width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
 398
 399    while (1) {
 400        /* Read memory */
 401        size = sizeof(uint16_t) * 6 * width;
 402        s->regs[SONIC_TTDA] = s->regs[SONIC_CTDA];
 403        DPRINTF("Transmit packet at %08x\n", dp8393x_ttda(s));
 404        address_space_rw(&s->as,
 405            dp8393x_ttda(s) + sizeof(uint16_t) * width,
 406            MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
 407        tx_len = 0;
 408
 409        /* Update registers */
 410        s->regs[SONIC_TCR] = data[0 * width] & 0xf000;
 411        s->regs[SONIC_TPS] = data[1 * width];
 412        s->regs[SONIC_TFC] = data[2 * width];
 413        s->regs[SONIC_TSA0] = data[3 * width];
 414        s->regs[SONIC_TSA1] = data[4 * width];
 415        s->regs[SONIC_TFS] = data[5 * width];
 416
 417        /* Handle programmable interrupt */
 418        if (s->regs[SONIC_TCR] & SONIC_TCR_PINT) {
 419            s->regs[SONIC_ISR] |= SONIC_ISR_PINT;
 420        } else {
 421            s->regs[SONIC_ISR] &= ~SONIC_ISR_PINT;
 422        }
 423
 424        for (i = 0; i < s->regs[SONIC_TFC]; ) {
 425            /* Append fragment */
 426            len = s->regs[SONIC_TFS];
 427            if (tx_len + len > sizeof(s->tx_buffer)) {
 428                len = sizeof(s->tx_buffer) - tx_len;
 429            }
 430            address_space_rw(&s->as, dp8393x_tsa(s),
 431                MEMTXATTRS_UNSPECIFIED, &s->tx_buffer[tx_len], len, 0);
 432            tx_len += len;
 433
 434            i++;
 435            if (i != s->regs[SONIC_TFC]) {
 436                /* Read next fragment details */
 437                size = sizeof(uint16_t) * 3 * width;
 438                address_space_rw(&s->as,
 439                    dp8393x_ttda(s) + sizeof(uint16_t) * (4 + 3 * i) * width,
 440                    MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
 441                s->regs[SONIC_TSA0] = data[0 * width];
 442                s->regs[SONIC_TSA1] = data[1 * width];
 443                s->regs[SONIC_TFS] = data[2 * width];
 444            }
 445        }
 446
 447        /* Handle Ethernet checksum */
 448        if (!(s->regs[SONIC_TCR] & SONIC_TCR_CRCI)) {
 449            /* Don't append FCS there, to look like slirp packets
 450             * which don't have one */
 451        } else {
 452            /* Remove existing FCS */
 453            tx_len -= 4;
 454        }
 455
 456        if (s->regs[SONIC_RCR] & (SONIC_RCR_LB1 | SONIC_RCR_LB0)) {
 457            /* Loopback */
 458            s->regs[SONIC_TCR] |= SONIC_TCR_CRSL;
 459            if (nc->info->can_receive(nc)) {
 460                s->loopback_packet = 1;
 461                nc->info->receive(nc, s->tx_buffer, tx_len);
 462            }
 463        } else {
 464            /* Transmit packet */
 465            qemu_send_packet(nc, s->tx_buffer, tx_len);
 466        }
 467        s->regs[SONIC_TCR] |= SONIC_TCR_PTX;
 468
 469        /* Write status */
 470        data[0 * width] = s->regs[SONIC_TCR] & 0x0fff; /* status */
 471        size = sizeof(uint16_t) * width;
 472        address_space_rw(&s->as,
 473            dp8393x_ttda(s),
 474            MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 1);
 475
 476        if (!(s->regs[SONIC_CR] & SONIC_CR_HTX)) {
 477            /* Read footer of packet */
 478            size = sizeof(uint16_t) * width;
 479            address_space_rw(&s->as,
 480                dp8393x_ttda(s) +
 481                             sizeof(uint16_t) *
 482                             (4 + 3 * s->regs[SONIC_TFC]) * width,
 483                MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
 484            s->regs[SONIC_CTDA] = data[0 * width] & ~0x1;
 485            if (data[0 * width] & 0x1) {
 486                /* EOL detected */
 487                break;
 488            }
 489        }
 490    }
 491
 492    /* Done */
 493    s->regs[SONIC_CR] &= ~SONIC_CR_TXP;
 494    s->regs[SONIC_ISR] |= SONIC_ISR_TXDN;
 495    dp8393x_update_irq(s);
 496}
 497
 498static void dp8393x_do_halt_transmission(dp8393xState *s)
 499{
 500    /* Nothing to do */
 501}
 502
 503static void dp8393x_do_command(dp8393xState *s, uint16_t command)
 504{
 505    if ((s->regs[SONIC_CR] & SONIC_CR_RST) && !(command & SONIC_CR_RST)) {
 506        s->regs[SONIC_CR] &= ~SONIC_CR_RST;
 507        return;
 508    }
 509
 510    s->regs[SONIC_CR] |= (command & SONIC_CR_MASK);
 511
 512    if (command & SONIC_CR_HTX)
 513        dp8393x_do_halt_transmission(s);
 514    if (command & SONIC_CR_TXP)
 515        dp8393x_do_transmit_packets(s);
 516    if (command & SONIC_CR_RXDIS)
 517        dp8393x_do_receiver_disable(s);
 518    if (command & SONIC_CR_RXEN)
 519        dp8393x_do_receiver_enable(s);
 520    if (command & SONIC_CR_STP)
 521        dp8393x_do_stop_timer(s);
 522    if (command & SONIC_CR_ST)
 523        dp8393x_do_start_timer(s);
 524    if (command & SONIC_CR_RST)
 525        dp8393x_do_software_reset(s);
 526    if (command & SONIC_CR_RRRA)
 527        dp8393x_do_read_rra(s);
 528    if (command & SONIC_CR_LCAM)
 529        dp8393x_do_load_cam(s);
 530}
 531
 532static uint64_t dp8393x_read(void *opaque, hwaddr addr, unsigned int size)
 533{
 534    dp8393xState *s = opaque;
 535    int reg = addr >> s->it_shift;
 536    uint16_t val = 0;
 537
 538    switch (reg) {
 539        /* Update data before reading it */
 540        case SONIC_WT0:
 541        case SONIC_WT1:
 542            dp8393x_update_wt_regs(s);
 543            val = s->regs[reg];
 544            break;
 545        /* Accept read to some registers only when in reset mode */
 546        case SONIC_CAP2:
 547        case SONIC_CAP1:
 548        case SONIC_CAP0:
 549            if (s->regs[SONIC_CR] & SONIC_CR_RST) {
 550                val = s->cam[s->regs[SONIC_CEP] & 0xf][2* (SONIC_CAP0 - reg) + 1] << 8;
 551                val |= s->cam[s->regs[SONIC_CEP] & 0xf][2* (SONIC_CAP0 - reg)];
 552            }
 553            break;
 554        /* All other registers have no special contrainst */
 555        default:
 556            val = s->regs[reg];
 557    }
 558
 559    DPRINTF("read 0x%04x from reg %s\n", val, reg_names[reg]);
 560
 561    return val;
 562}
 563
 564static void dp8393x_write(void *opaque, hwaddr addr, uint64_t data,
 565                          unsigned int size)
 566{
 567    dp8393xState *s = opaque;
 568    int reg = addr >> s->it_shift;
 569
 570    DPRINTF("write 0x%04x to reg %s\n", (uint16_t)data, reg_names[reg]);
 571
 572    switch (reg) {
 573        /* Command register */
 574        case SONIC_CR:
 575            dp8393x_do_command(s, data);
 576            break;
 577        /* Prevent write to read-only registers */
 578        case SONIC_CAP2:
 579        case SONIC_CAP1:
 580        case SONIC_CAP0:
 581        case SONIC_SR:
 582        case SONIC_MDT:
 583            DPRINTF("writing to reg %d invalid\n", reg);
 584            break;
 585        /* Accept write to some registers only when in reset mode */
 586        case SONIC_DCR:
 587            if (s->regs[SONIC_CR] & SONIC_CR_RST) {
 588                s->regs[reg] = data & 0xbfff;
 589            } else {
 590                DPRINTF("writing to DCR invalid\n");
 591            }
 592            break;
 593        case SONIC_DCR2:
 594            if (s->regs[SONIC_CR] & SONIC_CR_RST) {
 595                s->regs[reg] = data & 0xf017;
 596            } else {
 597                DPRINTF("writing to DCR2 invalid\n");
 598            }
 599            break;
 600        /* 12 lower bytes are Read Only */
 601        case SONIC_TCR:
 602            s->regs[reg] = data & 0xf000;
 603            break;
 604        /* 9 lower bytes are Read Only */
 605        case SONIC_RCR:
 606            s->regs[reg] = data & 0xffe0;
 607            break;
 608        /* Ignore most significant bit */
 609        case SONIC_IMR:
 610            s->regs[reg] = data & 0x7fff;
 611            dp8393x_update_irq(s);
 612            break;
 613        /* Clear bits by writing 1 to them */
 614        case SONIC_ISR:
 615            data &= s->regs[reg];
 616            s->regs[reg] &= ~data;
 617            if (data & SONIC_ISR_RBE) {
 618                dp8393x_do_read_rra(s);
 619            }
 620            dp8393x_update_irq(s);
 621            if (dp8393x_can_receive(s->nic->ncs)) {
 622                qemu_flush_queued_packets(qemu_get_queue(s->nic));
 623            }
 624            break;
 625        /* Ignore least significant bit */
 626        case SONIC_RSA:
 627        case SONIC_REA:
 628        case SONIC_RRP:
 629        case SONIC_RWP:
 630            s->regs[reg] = data & 0xfffe;
 631            break;
 632        /* Invert written value for some registers */
 633        case SONIC_CRCT:
 634        case SONIC_FAET:
 635        case SONIC_MPT:
 636            s->regs[reg] = data ^ 0xffff;
 637            break;
 638        /* All other registers have no special contrainst */
 639        default:
 640            s->regs[reg] = data;
 641    }
 642
 643    if (reg == SONIC_WT0 || reg == SONIC_WT1) {
 644        dp8393x_set_next_tick(s);
 645    }
 646}
 647
 648static const MemoryRegionOps dp8393x_ops = {
 649    .read = dp8393x_read,
 650    .write = dp8393x_write,
 651    .impl.min_access_size = 2,
 652    .impl.max_access_size = 2,
 653    .endianness = DEVICE_NATIVE_ENDIAN,
 654};
 655
 656static void dp8393x_watchdog(void *opaque)
 657{
 658    dp8393xState *s = opaque;
 659
 660    if (s->regs[SONIC_CR] & SONIC_CR_STP) {
 661        return;
 662    }
 663
 664    s->regs[SONIC_WT1] = 0xffff;
 665    s->regs[SONIC_WT0] = 0xffff;
 666    dp8393x_set_next_tick(s);
 667
 668    /* Signal underflow */
 669    s->regs[SONIC_ISR] |= SONIC_ISR_TC;
 670    dp8393x_update_irq(s);
 671}
 672
 673static int dp8393x_can_receive(NetClientState *nc)
 674{
 675    dp8393xState *s = qemu_get_nic_opaque(nc);
 676
 677    if (!(s->regs[SONIC_CR] & SONIC_CR_RXEN))
 678        return 0;
 679    if (s->regs[SONIC_ISR] & SONIC_ISR_RBE)
 680        return 0;
 681    return 1;
 682}
 683
 684static int dp8393x_receive_filter(dp8393xState *s, const uint8_t * buf,
 685                                  int size)
 686{
 687    static const uint8_t bcast[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
 688    int i;
 689
 690    /* Check promiscuous mode */
 691    if ((s->regs[SONIC_RCR] & SONIC_RCR_PRO) && (buf[0] & 1) == 0) {
 692        return 0;
 693    }
 694
 695    /* Check multicast packets */
 696    if ((s->regs[SONIC_RCR] & SONIC_RCR_AMC) && (buf[0] & 1) == 1) {
 697        return SONIC_RCR_MC;
 698    }
 699
 700    /* Check broadcast */
 701    if ((s->regs[SONIC_RCR] & SONIC_RCR_BRD) && !memcmp(buf, bcast, sizeof(bcast))) {
 702        return SONIC_RCR_BC;
 703    }
 704
 705    /* Check CAM */
 706    for (i = 0; i < 16; i++) {
 707        if (s->regs[SONIC_CE] & (1 << i)) {
 708             /* Entry enabled */
 709             if (!memcmp(buf, s->cam[i], sizeof(s->cam[i]))) {
 710                 return 0;
 711             }
 712        }
 713    }
 714
 715    return -1;
 716}
 717
 718static ssize_t dp8393x_receive(NetClientState *nc, const uint8_t * buf,
 719                               size_t size)
 720{
 721    dp8393xState *s = qemu_get_nic_opaque(nc);
 722    uint16_t data[10];
 723    int packet_type;
 724    uint32_t available, address;
 725    int width, rx_len = size;
 726    uint32_t checksum;
 727
 728    width = (s->regs[SONIC_DCR] & SONIC_DCR_DW) ? 2 : 1;
 729
 730    s->regs[SONIC_RCR] &= ~(SONIC_RCR_PRX | SONIC_RCR_LBK | SONIC_RCR_FAER |
 731        SONIC_RCR_CRCR | SONIC_RCR_LPKT | SONIC_RCR_BC | SONIC_RCR_MC);
 732
 733    packet_type = dp8393x_receive_filter(s, buf, size);
 734    if (packet_type < 0) {
 735        DPRINTF("packet not for netcard\n");
 736        return -1;
 737    }
 738
 739    /* XXX: Check byte ordering */
 740
 741    /* Check for EOL */
 742    if (s->regs[SONIC_LLFA] & 0x1) {
 743        /* Are we still in resource exhaustion? */
 744        size = sizeof(uint16_t) * 1 * width;
 745        address = dp8393x_crda(s) + sizeof(uint16_t) * 5 * width;
 746        address_space_rw(&s->as, address, MEMTXATTRS_UNSPECIFIED,
 747                         (uint8_t *)data, size, 0);
 748        if (data[0 * width] & 0x1) {
 749            /* Still EOL ; stop reception */
 750            return -1;
 751        } else {
 752            s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
 753        }
 754    }
 755
 756    /* Save current position */
 757    s->regs[SONIC_TRBA1] = s->regs[SONIC_CRBA1];
 758    s->regs[SONIC_TRBA0] = s->regs[SONIC_CRBA0];
 759
 760    /* Calculate the ethernet checksum */
 761    checksum = cpu_to_le32(crc32(0, buf, rx_len));
 762
 763    /* Put packet into RBA */
 764    DPRINTF("Receive packet at %08x\n", dp8393x_crba(s));
 765    address = dp8393x_crba(s);
 766    address_space_rw(&s->as, address,
 767        MEMTXATTRS_UNSPECIFIED, (uint8_t *)buf, rx_len, 1);
 768    address += rx_len;
 769    address_space_rw(&s->as, address,
 770        MEMTXATTRS_UNSPECIFIED, (uint8_t *)&checksum, 4, 1);
 771    rx_len += 4;
 772    s->regs[SONIC_CRBA1] = address >> 16;
 773    s->regs[SONIC_CRBA0] = address & 0xffff;
 774    available = dp8393x_rbwc(s);
 775    available -= rx_len / 2;
 776    s->regs[SONIC_RBWC1] = available >> 16;
 777    s->regs[SONIC_RBWC0] = available & 0xffff;
 778
 779    /* Update status */
 780    if (dp8393x_rbwc(s) < s->regs[SONIC_EOBC]) {
 781        s->regs[SONIC_RCR] |= SONIC_RCR_LPKT;
 782    }
 783    s->regs[SONIC_RCR] |= packet_type;
 784    s->regs[SONIC_RCR] |= SONIC_RCR_PRX;
 785    if (s->loopback_packet) {
 786        s->regs[SONIC_RCR] |= SONIC_RCR_LBK;
 787        s->loopback_packet = 0;
 788    }
 789
 790    /* Write status to memory */
 791    DPRINTF("Write status at %08x\n", dp8393x_crda(s));
 792    data[0 * width] = s->regs[SONIC_RCR]; /* status */
 793    data[1 * width] = rx_len; /* byte count */
 794    data[2 * width] = s->regs[SONIC_TRBA0]; /* pkt_ptr0 */
 795    data[3 * width] = s->regs[SONIC_TRBA1]; /* pkt_ptr1 */
 796    data[4 * width] = s->regs[SONIC_RSC]; /* seq_no */
 797    size = sizeof(uint16_t) * 5 * width;
 798    address_space_rw(&s->as, dp8393x_crda(s),
 799        MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 1);
 800
 801    /* Move to next descriptor */
 802    size = sizeof(uint16_t) * width;
 803    address_space_rw(&s->as, dp8393x_crda(s) + sizeof(uint16_t) * 5 * width,
 804        MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, size, 0);
 805    s->regs[SONIC_LLFA] = data[0 * width];
 806    if (s->regs[SONIC_LLFA] & 0x1) {
 807        /* EOL detected */
 808        s->regs[SONIC_ISR] |= SONIC_ISR_RDE;
 809    } else {
 810        data[0 * width] = 0; /* in_use */
 811        address_space_rw(&s->as, dp8393x_crda(s) + sizeof(uint16_t) * 6 * width,
 812            MEMTXATTRS_UNSPECIFIED, (uint8_t *)data, sizeof(uint16_t), 1);
 813        s->regs[SONIC_CRDA] = s->regs[SONIC_LLFA];
 814        s->regs[SONIC_ISR] |= SONIC_ISR_PKTRX;
 815        s->regs[SONIC_RSC] = (s->regs[SONIC_RSC] & 0xff00) | (((s->regs[SONIC_RSC] & 0x00ff) + 1) & 0x00ff);
 816
 817        if (s->regs[SONIC_RCR] & SONIC_RCR_LPKT) {
 818            /* Read next RRA */
 819            dp8393x_do_read_rra(s);
 820        }
 821    }
 822
 823    /* Done */
 824    dp8393x_update_irq(s);
 825
 826    return size;
 827}
 828
 829static void dp8393x_reset(DeviceState *dev)
 830{
 831    dp8393xState *s = DP8393X(dev);
 832    timer_del(s->watchdog);
 833
 834    memset(s->regs, 0, sizeof(s->regs));
 835    s->regs[SONIC_CR] = SONIC_CR_RST | SONIC_CR_STP | SONIC_CR_RXDIS;
 836    s->regs[SONIC_DCR] &= ~(SONIC_DCR_EXBUS | SONIC_DCR_LBR);
 837    s->regs[SONIC_RCR] &= ~(SONIC_RCR_LB0 | SONIC_RCR_LB1 | SONIC_RCR_BRD | SONIC_RCR_RNT);
 838    s->regs[SONIC_TCR] |= SONIC_TCR_NCRS | SONIC_TCR_PTX;
 839    s->regs[SONIC_TCR] &= ~SONIC_TCR_BCM;
 840    s->regs[SONIC_IMR] = 0;
 841    s->regs[SONIC_ISR] = 0;
 842    s->regs[SONIC_DCR2] = 0;
 843    s->regs[SONIC_EOBC] = 0x02F8;
 844    s->regs[SONIC_RSC] = 0;
 845    s->regs[SONIC_CE] = 0;
 846    s->regs[SONIC_RSC] = 0;
 847
 848    /* Network cable is connected */
 849    s->regs[SONIC_RCR] |= SONIC_RCR_CRS;
 850
 851    dp8393x_update_irq(s);
 852}
 853
 854static NetClientInfo net_dp83932_info = {
 855    .type = NET_CLIENT_DRIVER_NIC,
 856    .size = sizeof(NICState),
 857    .can_receive = dp8393x_can_receive,
 858    .receive = dp8393x_receive,
 859};
 860
 861static void dp8393x_instance_init(Object *obj)
 862{
 863    SysBusDevice *sbd = SYS_BUS_DEVICE(obj);
 864    dp8393xState *s = DP8393X(obj);
 865
 866    sysbus_init_mmio(sbd, &s->mmio);
 867    sysbus_init_mmio(sbd, &s->prom);
 868    sysbus_init_irq(sbd, &s->irq);
 869}
 870
 871static void dp8393x_realize(DeviceState *dev, Error **errp)
 872{
 873    dp8393xState *s = DP8393X(dev);
 874    int i, checksum;
 875    uint8_t *prom;
 876    Error *local_err = NULL;
 877
 878    address_space_init(&s->as, s->dma_mr, "dp8393x");
 879    memory_region_init_io(&s->mmio, OBJECT(dev), &dp8393x_ops, s,
 880                          "dp8393x-regs", 0x40 << s->it_shift);
 881
 882    s->nic = qemu_new_nic(&net_dp83932_info, &s->conf,
 883                          object_get_typename(OBJECT(dev)), dev->id, s);
 884    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
 885
 886    s->watchdog = timer_new_ns(QEMU_CLOCK_VIRTUAL, dp8393x_watchdog, s);
 887    s->regs[SONIC_SR] = 0x0004; /* only revision recognized by Linux */
 888
 889    memory_region_init_ram(&s->prom, OBJECT(dev),
 890                           "dp8393x-prom", SONIC_PROM_SIZE, &local_err);
 891    if (local_err) {
 892        error_propagate(errp, local_err);
 893        return;
 894    }
 895    memory_region_set_readonly(&s->prom, true);
 896    prom = memory_region_get_ram_ptr(&s->prom);
 897    checksum = 0;
 898    for (i = 0; i < 6; i++) {
 899        prom[i] = s->conf.macaddr.a[i];
 900        checksum += prom[i];
 901        if (checksum > 0xff) {
 902            checksum = (checksum + 1) & 0xff;
 903        }
 904    }
 905    prom[7] = 0xff - checksum;
 906}
 907
 908static const VMStateDescription vmstate_dp8393x = {
 909    .name = "dp8393x",
 910    .version_id = 0,
 911    .minimum_version_id = 0,
 912    .fields = (VMStateField []) {
 913        VMSTATE_BUFFER_UNSAFE(cam, dp8393xState, 0, 16 * 6),
 914        VMSTATE_UINT16_ARRAY(regs, dp8393xState, 0x40),
 915        VMSTATE_END_OF_LIST()
 916    }
 917};
 918
 919static Property dp8393x_properties[] = {
 920    DEFINE_NIC_PROPERTIES(dp8393xState, conf),
 921    DEFINE_PROP_PTR("dma_mr", dp8393xState, dma_mr),
 922    DEFINE_PROP_UINT8("it_shift", dp8393xState, it_shift, 0),
 923    DEFINE_PROP_END_OF_LIST(),
 924};
 925
 926static void dp8393x_class_init(ObjectClass *klass, void *data)
 927{
 928    DeviceClass *dc = DEVICE_CLASS(klass);
 929
 930    set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
 931    dc->realize = dp8393x_realize;
 932    dc->reset = dp8393x_reset;
 933    dc->vmsd = &vmstate_dp8393x;
 934    dc->props = dp8393x_properties;
 935    /* Reason: dma_mr property can't be set */
 936    dc->user_creatable = false;
 937}
 938
 939static const TypeInfo dp8393x_info = {
 940    .name          = TYPE_DP8393X,
 941    .parent        = TYPE_SYS_BUS_DEVICE,
 942    .instance_size = sizeof(dp8393xState),
 943    .instance_init = dp8393x_instance_init,
 944    .class_init    = dp8393x_class_init,
 945};
 946
 947static void dp8393x_register_types(void)
 948{
 949    type_register_static(&dp8393x_info);
 950}
 951
 952type_init(dp8393x_register_types)
 953