qemu/hw/net/pcnet.c
<<
>>
Prefs
   1/*
   2 * QEMU AMD PC-Net II (Am79C970A) emulation
   3 *
   4 * Copyright (c) 2004 Antony T Curtis
   5 *
   6 * Permission is hereby granted, free of charge, to any person obtaining a copy
   7 * of this software and associated documentation files (the "Software"), to deal
   8 * in the Software without restriction, including without limitation the rights
   9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  10 * copies of the Software, and to permit persons to whom the Software is
  11 * furnished to do so, subject to the following conditions:
  12 *
  13 * The above copyright notice and this permission notice shall be included in
  14 * all copies or substantial portions of the Software.
  15 *
  16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  19 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  22 * THE SOFTWARE.
  23 */
  24
  25/* This software was written to be compatible with the specification:
  26 * AMD Am79C970A PCnet-PCI II Ethernet Controller Data-Sheet
  27 * AMD Publication# 19436  Rev:E  Amendment/0  Issue Date: June 2000
  28 */
  29
  30/*
  31 * On Sparc32, this is the Lance (Am7990) part of chip STP2000 (Master I/O), also
  32 * produced as NCR89C100. See
  33 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR89C100.txt
  34 * and
  35 * http://www.ibiblio.org/pub/historic-linux/early-ports/Sparc/NCR/NCR92C990.txt
  36 */
  37
  38#include "qemu/osdep.h"
  39#include "qemu/log.h"
  40#include "hw/irq.h"
  41#include "hw/qdev-properties.h"
  42#include "migration/vmstate.h"
  43#include "net/net.h"
  44#include "net/eth.h"
  45#include "qemu/timer.h"
  46#include "trace.h"
  47
  48#include "pcnet.h"
  49
  50//#define PCNET_DEBUG
  51//#define PCNET_DEBUG_IO
  52//#define PCNET_DEBUG_BCR
  53//#define PCNET_DEBUG_CSR
  54//#define PCNET_DEBUG_RMD
  55//#define PCNET_DEBUG_TMD
  56//#define PCNET_DEBUG_MATCH
  57
  58
  59struct qemu_ether_header {
  60    uint8_t ether_dhost[6];
  61    uint8_t ether_shost[6];
  62    uint16_t ether_type;
  63};
  64
  65#define CSR_INIT(S)      !!(((S)->csr[0])&0x0001)
  66#define CSR_STRT(S)      !!(((S)->csr[0])&0x0002)
  67#define CSR_STOP(S)      !!(((S)->csr[0])&0x0004)
  68#define CSR_TDMD(S)      !!(((S)->csr[0])&0x0008)
  69#define CSR_TXON(S)      !!(((S)->csr[0])&0x0010)
  70#define CSR_RXON(S)      !!(((S)->csr[0])&0x0020)
  71#define CSR_INEA(S)      !!(((S)->csr[0])&0x0040)
  72#define CSR_BSWP(S)      !!(((S)->csr[3])&0x0004)
  73#define CSR_LAPPEN(S)    !!(((S)->csr[3])&0x0020)
  74#define CSR_DXSUFLO(S)   !!(((S)->csr[3])&0x0040)
  75#define CSR_ASTRP_RCV(S) !!(((S)->csr[4])&0x0800)
  76#define CSR_DPOLL(S)     !!(((S)->csr[4])&0x1000)
  77#define CSR_SPND(S)      !!(((S)->csr[5])&0x0001)
  78#define CSR_LTINTEN(S)   !!(((S)->csr[5])&0x4000)
  79#define CSR_TOKINTD(S)   !!(((S)->csr[5])&0x8000)
  80#define CSR_DRX(S)       !!(((S)->csr[15])&0x0001)
  81#define CSR_DTX(S)       !!(((S)->csr[15])&0x0002)
  82#define CSR_LOOP(S)      !!(((S)->csr[15])&0x0004)
  83#define CSR_DXMTFCS(S)   !!(((S)->csr[15])&0x0008)
  84#define CSR_INTL(S)      !!(((S)->csr[15])&0x0040)
  85#define CSR_DRCVPA(S)    !!(((S)->csr[15])&0x2000)
  86#define CSR_DRCVBC(S)    !!(((S)->csr[15])&0x4000)
  87#define CSR_PROM(S)      !!(((S)->csr[15])&0x8000)
  88
  89#define CSR_CRBC(S)      ((S)->csr[40])
  90#define CSR_CRST(S)      ((S)->csr[41])
  91#define CSR_CXBC(S)      ((S)->csr[42])
  92#define CSR_CXST(S)      ((S)->csr[43])
  93#define CSR_NRBC(S)      ((S)->csr[44])
  94#define CSR_NRST(S)      ((S)->csr[45])
  95#define CSR_POLL(S)      ((S)->csr[46])
  96#define CSR_PINT(S)      ((S)->csr[47])
  97#define CSR_RCVRC(S)     ((S)->csr[72])
  98#define CSR_XMTRC(S)     ((S)->csr[74])
  99#define CSR_RCVRL(S)     ((S)->csr[76])
 100#define CSR_XMTRL(S)     ((S)->csr[78])
 101#define CSR_MISSC(S)     ((S)->csr[112])
 102
 103#define CSR_IADR(S)      ((S)->csr[ 1] | ((uint32_t)(S)->csr[ 2] << 16))
 104#define CSR_CRBA(S)      ((S)->csr[18] | ((uint32_t)(S)->csr[19] << 16))
 105#define CSR_CXBA(S)      ((S)->csr[20] | ((uint32_t)(S)->csr[21] << 16))
 106#define CSR_NRBA(S)      ((S)->csr[22] | ((uint32_t)(S)->csr[23] << 16))
 107#define CSR_BADR(S)      ((S)->csr[24] | ((uint32_t)(S)->csr[25] << 16))
 108#define CSR_NRDA(S)      ((S)->csr[26] | ((uint32_t)(S)->csr[27] << 16))
 109#define CSR_CRDA(S)      ((S)->csr[28] | ((uint32_t)(S)->csr[29] << 16))
 110#define CSR_BADX(S)      ((S)->csr[30] | ((uint32_t)(S)->csr[31] << 16))
 111#define CSR_NXDA(S)      ((S)->csr[32] | ((uint32_t)(S)->csr[33] << 16))
 112#define CSR_CXDA(S)      ((S)->csr[34] | ((uint32_t)(S)->csr[35] << 16))
 113#define CSR_NNRD(S)      ((S)->csr[36] | ((uint32_t)(S)->csr[37] << 16))
 114#define CSR_NNXD(S)      ((S)->csr[38] | ((uint32_t)(S)->csr[39] << 16))
 115#define CSR_PXDA(S)      ((S)->csr[60] | ((uint32_t)(S)->csr[61] << 16))
 116#define CSR_NXBA(S)      ((S)->csr[64] | ((uint32_t)(S)->csr[65] << 16))
 117
 118#define PHYSADDR(S,A) \
 119  (BCR_SSIZE32(S) ? (A) : (A) | ((0xff00 & (uint32_t)(S)->csr[2])<<16))
 120
 121struct pcnet_initblk16 {
 122    uint16_t mode;
 123    uint16_t padr[3];
 124    uint16_t ladrf[4];
 125    uint32_t rdra;
 126    uint32_t tdra;
 127};
 128
 129struct pcnet_initblk32 {
 130    uint16_t mode;
 131    uint8_t rlen;
 132    uint8_t tlen;
 133    uint16_t padr[3];
 134    uint16_t _res;
 135    uint16_t ladrf[4];
 136    uint32_t rdra;
 137    uint32_t tdra;
 138};
 139
 140struct pcnet_TMD {
 141    uint32_t tbadr;
 142    int16_t length;
 143    int16_t status;
 144    uint32_t misc;
 145    uint32_t res;
 146};
 147
 148#define TMDL_BCNT_MASK  0x0fff
 149#define TMDL_BCNT_SH    0
 150#define TMDL_ONES_MASK  0xf000
 151#define TMDL_ONES_SH    12
 152
 153#define TMDS_BPE_MASK   0x0080
 154#define TMDS_BPE_SH     7
 155#define TMDS_ENP_MASK   0x0100
 156#define TMDS_ENP_SH     8
 157#define TMDS_STP_MASK   0x0200
 158#define TMDS_STP_SH     9
 159#define TMDS_DEF_MASK   0x0400
 160#define TMDS_DEF_SH     10
 161#define TMDS_ONE_MASK   0x0800
 162#define TMDS_ONE_SH     11
 163#define TMDS_LTINT_MASK 0x1000
 164#define TMDS_LTINT_SH   12
 165#define TMDS_NOFCS_MASK 0x2000
 166#define TMDS_NOFCS_SH   13
 167#define TMDS_ADDFCS_MASK TMDS_NOFCS_MASK
 168#define TMDS_ADDFCS_SH  TMDS_NOFCS_SH
 169#define TMDS_ERR_MASK   0x4000
 170#define TMDS_ERR_SH     14
 171#define TMDS_OWN_MASK   0x8000
 172#define TMDS_OWN_SH     15
 173
 174#define TMDM_TRC_MASK   0x0000000f
 175#define TMDM_TRC_SH     0
 176#define TMDM_TDR_MASK   0x03ff0000
 177#define TMDM_TDR_SH     16
 178#define TMDM_RTRY_MASK  0x04000000
 179#define TMDM_RTRY_SH    26
 180#define TMDM_LCAR_MASK  0x08000000
 181#define TMDM_LCAR_SH    27
 182#define TMDM_LCOL_MASK  0x10000000
 183#define TMDM_LCOL_SH    28
 184#define TMDM_EXDEF_MASK 0x20000000
 185#define TMDM_EXDEF_SH   29
 186#define TMDM_UFLO_MASK  0x40000000
 187#define TMDM_UFLO_SH    30
 188#define TMDM_BUFF_MASK  0x80000000
 189#define TMDM_BUFF_SH    31
 190
 191struct pcnet_RMD {
 192    uint32_t rbadr;
 193    int16_t buf_length;
 194    int16_t status;
 195    uint32_t msg_length;
 196    uint32_t res;
 197};
 198
 199#define RMDL_BCNT_MASK  0x0fff
 200#define RMDL_BCNT_SH    0
 201#define RMDL_ONES_MASK  0xf000
 202#define RMDL_ONES_SH    12
 203
 204#define RMDS_BAM_MASK   0x0010
 205#define RMDS_BAM_SH     4
 206#define RMDS_LFAM_MASK  0x0020
 207#define RMDS_LFAM_SH    5
 208#define RMDS_PAM_MASK   0x0040
 209#define RMDS_PAM_SH     6
 210#define RMDS_BPE_MASK   0x0080
 211#define RMDS_BPE_SH     7
 212#define RMDS_ENP_MASK   0x0100
 213#define RMDS_ENP_SH     8
 214#define RMDS_STP_MASK   0x0200
 215#define RMDS_STP_SH     9
 216#define RMDS_BUFF_MASK  0x0400
 217#define RMDS_BUFF_SH    10
 218#define RMDS_CRC_MASK   0x0800
 219#define RMDS_CRC_SH     11
 220#define RMDS_OFLO_MASK  0x1000
 221#define RMDS_OFLO_SH    12
 222#define RMDS_FRAM_MASK  0x2000
 223#define RMDS_FRAM_SH    13
 224#define RMDS_ERR_MASK   0x4000
 225#define RMDS_ERR_SH     14
 226#define RMDS_OWN_MASK   0x8000
 227#define RMDS_OWN_SH     15
 228
 229#define RMDM_MCNT_MASK  0x00000fff
 230#define RMDM_MCNT_SH    0
 231#define RMDM_ZEROS_MASK 0x0000f000
 232#define RMDM_ZEROS_SH   12
 233#define RMDM_RPC_MASK   0x00ff0000
 234#define RMDM_RPC_SH     16
 235#define RMDM_RCC_MASK   0xff000000
 236#define RMDM_RCC_SH     24
 237
 238#define SET_FIELD(regp, name, field, value)             \
 239  (*(regp) = (*(regp) & ~(name ## _ ## field ## _MASK)) \
 240             | ((value) << name ## _ ## field ## _SH))
 241
 242#define GET_FIELD(reg, name, field)                     \
 243  (((reg) & name ## _ ## field ## _MASK) >> name ## _ ## field ## _SH)
 244
 245#define PRINT_TMD(T) printf(                            \
 246        "TMD0 : TBADR=0x%08x\n"                         \
 247        "TMD1 : OWN=%d, ERR=%d, FCS=%d, LTI=%d, "       \
 248        "ONE=%d, DEF=%d, STP=%d, ENP=%d,\n"             \
 249        "       BPE=%d, BCNT=%d\n"                      \
 250        "TMD2 : BUF=%d, UFL=%d, EXD=%d, LCO=%d, "       \
 251        "LCA=%d, RTR=%d,\n"                             \
 252        "       TDR=%d, TRC=%d\n",                      \
 253        (T)->tbadr,                                     \
 254        GET_FIELD((T)->status, TMDS, OWN),              \
 255        GET_FIELD((T)->status, TMDS, ERR),              \
 256        GET_FIELD((T)->status, TMDS, NOFCS),            \
 257        GET_FIELD((T)->status, TMDS, LTINT),            \
 258        GET_FIELD((T)->status, TMDS, ONE),              \
 259        GET_FIELD((T)->status, TMDS, DEF),              \
 260        GET_FIELD((T)->status, TMDS, STP),              \
 261        GET_FIELD((T)->status, TMDS, ENP),              \
 262        GET_FIELD((T)->status, TMDS, BPE),              \
 263        4096-GET_FIELD((T)->length, TMDL, BCNT),        \
 264        GET_FIELD((T)->misc, TMDM, BUFF),               \
 265        GET_FIELD((T)->misc, TMDM, UFLO),               \
 266        GET_FIELD((T)->misc, TMDM, EXDEF),              \
 267        GET_FIELD((T)->misc, TMDM, LCOL),               \
 268        GET_FIELD((T)->misc, TMDM, LCAR),               \
 269        GET_FIELD((T)->misc, TMDM, RTRY),               \
 270        GET_FIELD((T)->misc, TMDM, TDR),                \
 271        GET_FIELD((T)->misc, TMDM, TRC))
 272
 273#define PRINT_RMD(R) printf(                            \
 274        "RMD0 : RBADR=0x%08x\n"                         \
 275        "RMD1 : OWN=%d, ERR=%d, FRAM=%d, OFLO=%d, "     \
 276        "CRC=%d, BUFF=%d, STP=%d, ENP=%d,\n       "     \
 277        "BPE=%d, PAM=%d, LAFM=%d, BAM=%d, ONES=%d, BCNT=%d\n" \
 278        "RMD2 : RCC=%d, RPC=%d, MCNT=%d, ZEROS=%d\n",   \
 279        (R)->rbadr,                                     \
 280        GET_FIELD((R)->status, RMDS, OWN),              \
 281        GET_FIELD((R)->status, RMDS, ERR),              \
 282        GET_FIELD((R)->status, RMDS, FRAM),             \
 283        GET_FIELD((R)->status, RMDS, OFLO),             \
 284        GET_FIELD((R)->status, RMDS, CRC),              \
 285        GET_FIELD((R)->status, RMDS, BUFF),             \
 286        GET_FIELD((R)->status, RMDS, STP),              \
 287        GET_FIELD((R)->status, RMDS, ENP),              \
 288        GET_FIELD((R)->status, RMDS, BPE),              \
 289        GET_FIELD((R)->status, RMDS, PAM),              \
 290        GET_FIELD((R)->status, RMDS, LFAM),             \
 291        GET_FIELD((R)->status, RMDS, BAM),              \
 292        GET_FIELD((R)->buf_length, RMDL, ONES),         \
 293        4096-GET_FIELD((R)->buf_length, RMDL, BCNT),    \
 294        GET_FIELD((R)->msg_length, RMDM, RCC),          \
 295        GET_FIELD((R)->msg_length, RMDM, RPC),          \
 296        GET_FIELD((R)->msg_length, RMDM, MCNT),         \
 297        GET_FIELD((R)->msg_length, RMDM, ZEROS))
 298
 299static inline void pcnet_tmd_load(PCNetState *s, struct pcnet_TMD *tmd,
 300                                  hwaddr addr)
 301{
 302    if (!BCR_SSIZE32(s)) {
 303        struct {
 304            uint32_t tbadr;
 305            int16_t length;
 306            int16_t status;
 307        } xda;
 308        s->phys_mem_read(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
 309        tmd->tbadr = le32_to_cpu(xda.tbadr) & 0xffffff;
 310        tmd->length = le16_to_cpu(xda.length);
 311        tmd->status = (le32_to_cpu(xda.tbadr) >> 16) & 0xff00;
 312        tmd->misc = le16_to_cpu(xda.status) << 16;
 313        tmd->res = 0;
 314    } else {
 315        s->phys_mem_read(s->dma_opaque, addr, (void *)tmd, sizeof(*tmd), 0);
 316        le32_to_cpus(&tmd->tbadr);
 317        le16_to_cpus((uint16_t *)&tmd->length);
 318        le16_to_cpus((uint16_t *)&tmd->status);
 319        le32_to_cpus(&tmd->misc);
 320        le32_to_cpus(&tmd->res);
 321        if (BCR_SWSTYLE(s) == 3) {
 322            uint32_t tmp = tmd->tbadr;
 323            tmd->tbadr = tmd->misc;
 324            tmd->misc = tmp;
 325        }
 326    }
 327}
 328
 329static inline void pcnet_tmd_store(PCNetState *s, const struct pcnet_TMD *tmd,
 330                                   hwaddr addr)
 331{
 332    if (!BCR_SSIZE32(s)) {
 333        struct {
 334            uint32_t tbadr;
 335            int16_t length;
 336            int16_t status;
 337        } xda;
 338        xda.tbadr = cpu_to_le32((tmd->tbadr & 0xffffff) |
 339                                ((tmd->status & 0xff00) << 16));
 340        xda.length = cpu_to_le16(tmd->length);
 341        xda.status = cpu_to_le16(tmd->misc >> 16);
 342        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
 343    } else {
 344        struct {
 345            uint32_t tbadr;
 346            int16_t length;
 347            int16_t status;
 348            uint32_t misc;
 349            uint32_t res;
 350        } xda;
 351        xda.tbadr = cpu_to_le32(tmd->tbadr);
 352        xda.length = cpu_to_le16(tmd->length);
 353        xda.status = cpu_to_le16(tmd->status);
 354        xda.misc = cpu_to_le32(tmd->misc);
 355        xda.res = cpu_to_le32(tmd->res);
 356        if (BCR_SWSTYLE(s) == 3) {
 357            uint32_t tmp = xda.tbadr;
 358            xda.tbadr = xda.misc;
 359            xda.misc = tmp;
 360        }
 361        s->phys_mem_write(s->dma_opaque, addr, (void *)&xda, sizeof(xda), 0);
 362    }
 363}
 364
 365static inline void pcnet_rmd_load(PCNetState *s, struct pcnet_RMD *rmd,
 366                                  hwaddr addr)
 367{
 368    if (!BCR_SSIZE32(s)) {
 369        struct {
 370            uint32_t rbadr;
 371            int16_t buf_length;
 372            int16_t msg_length;
 373        } rda;
 374        s->phys_mem_read(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
 375        rmd->rbadr = le32_to_cpu(rda.rbadr) & 0xffffff;
 376        rmd->buf_length = le16_to_cpu(rda.buf_length);
 377        rmd->status = (le32_to_cpu(rda.rbadr) >> 16) & 0xff00;
 378        rmd->msg_length = le16_to_cpu(rda.msg_length);
 379        rmd->res = 0;
 380    } else {
 381        s->phys_mem_read(s->dma_opaque, addr, (void *)rmd, sizeof(*rmd), 0);
 382        le32_to_cpus(&rmd->rbadr);
 383        le16_to_cpus((uint16_t *)&rmd->buf_length);
 384        le16_to_cpus((uint16_t *)&rmd->status);
 385        le32_to_cpus(&rmd->msg_length);
 386        le32_to_cpus(&rmd->res);
 387        if (BCR_SWSTYLE(s) == 3) {
 388            uint32_t tmp = rmd->rbadr;
 389            rmd->rbadr = rmd->msg_length;
 390            rmd->msg_length = tmp;
 391        }
 392    }
 393}
 394
 395static inline void pcnet_rmd_store(PCNetState *s, struct pcnet_RMD *rmd,
 396                                   hwaddr addr)
 397{
 398    if (!BCR_SSIZE32(s)) {
 399        struct {
 400            uint32_t rbadr;
 401            int16_t buf_length;
 402            int16_t msg_length;
 403        } rda;
 404        rda.rbadr = cpu_to_le32((rmd->rbadr & 0xffffff) |
 405                                ((rmd->status & 0xff00) << 16));
 406        rda.buf_length = cpu_to_le16(rmd->buf_length);
 407        rda.msg_length = cpu_to_le16(rmd->msg_length);
 408        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
 409    } else {
 410        struct {
 411            uint32_t rbadr;
 412            int16_t buf_length;
 413            int16_t status;
 414            uint32_t msg_length;
 415            uint32_t res;
 416        } rda;
 417        rda.rbadr = cpu_to_le32(rmd->rbadr);
 418        rda.buf_length = cpu_to_le16(rmd->buf_length);
 419        rda.status = cpu_to_le16(rmd->status);
 420        rda.msg_length = cpu_to_le32(rmd->msg_length);
 421        rda.res = cpu_to_le32(rmd->res);
 422        if (BCR_SWSTYLE(s) == 3) {
 423            uint32_t tmp = rda.rbadr;
 424            rda.rbadr = rda.msg_length;
 425            rda.msg_length = tmp;
 426        }
 427        s->phys_mem_write(s->dma_opaque, addr, (void *)&rda, sizeof(rda), 0);
 428    }
 429}
 430
 431
 432#define TMDLOAD(TMD,ADDR) pcnet_tmd_load(s,TMD,ADDR)
 433
 434#define TMDSTORE(TMD,ADDR) pcnet_tmd_store(s,TMD,ADDR)
 435
 436#define RMDLOAD(RMD,ADDR) pcnet_rmd_load(s,RMD,ADDR)
 437
 438#define RMDSTORE(RMD,ADDR) pcnet_rmd_store(s,RMD,ADDR)
 439
 440#if 1
 441
 442#define CHECK_RMD(ADDR,RES) do {                \
 443    struct pcnet_RMD rmd;                       \
 444    RMDLOAD(&rmd,(ADDR));                       \
 445    (RES) |= (GET_FIELD(rmd.buf_length, RMDL, ONES) != 15) \
 446          || (GET_FIELD(rmd.msg_length, RMDM, ZEROS) != 0); \
 447} while (0)
 448
 449#define CHECK_TMD(ADDR,RES) do {                \
 450    struct pcnet_TMD tmd;                       \
 451    TMDLOAD(&tmd,(ADDR));                       \
 452    (RES) |= (GET_FIELD(tmd.length, TMDL, ONES) != 15); \
 453} while (0)
 454
 455#else
 456
 457#define CHECK_RMD(ADDR,RES) do {                \
 458    switch (BCR_SWSTYLE(s)) {                   \
 459    case 0x00:                                  \
 460        {                                       \
 461            uint16_t rda[4];                    \
 462            s->phys_mem_read(s->dma_opaque, (ADDR), \
 463                (void *)&rda[0], sizeof(rda), 0); \
 464            (RES) |= (rda[2] & 0xf000)!=0xf000; \
 465            (RES) |= (rda[3] & 0xf000)!=0x0000; \
 466        }                                       \
 467        break;                                  \
 468    case 0x01:                                  \
 469    case 0x02:                                  \
 470        {                                       \
 471            uint32_t rda[4];                    \
 472            s->phys_mem_read(s->dma_opaque, (ADDR), \
 473                (void *)&rda[0], sizeof(rda), 0); \
 474            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
 475            (RES) |= (rda[2] & 0x0000f000L)!=0x00000000L; \
 476        }                                       \
 477        break;                                  \
 478    case 0x03:                                  \
 479        {                                       \
 480            uint32_t rda[4];                    \
 481            s->phys_mem_read(s->dma_opaque, (ADDR), \
 482                (void *)&rda[0], sizeof(rda), 0); \
 483            (RES) |= (rda[0] & 0x0000f000L)!=0x00000000L; \
 484            (RES) |= (rda[1] & 0x0000f000L)!=0x0000f000L; \
 485        }                                       \
 486        break;                                  \
 487    }                                           \
 488} while (0)
 489
 490#define CHECK_TMD(ADDR,RES) do {                \
 491    switch (BCR_SWSTYLE(s)) {                   \
 492    case 0x00:                                  \
 493        {                                       \
 494            uint16_t xda[4];                    \
 495            s->phys_mem_read(s->dma_opaque, (ADDR), \
 496                (void *)&xda[0], sizeof(xda), 0); \
 497            (RES) |= (xda[2] & 0xf000)!=0xf000; \
 498        }                                       \
 499        break;                                  \
 500    case 0x01:                                  \
 501    case 0x02:                                  \
 502    case 0x03:                                  \
 503        {                                       \
 504            uint32_t xda[4];                    \
 505            s->phys_mem_read(s->dma_opaque, (ADDR), \
 506                (void *)&xda[0], sizeof(xda), 0); \
 507            (RES) |= (xda[1] & 0x0000f000L)!=0x0000f000L; \
 508        }                                       \
 509        break;                                  \
 510    }                                           \
 511} while (0)
 512
 513#endif
 514
 515#define PRINT_PKTHDR(BUF) do {                  \
 516    struct qemu_ether_header *hdr = (void *)(BUF); \
 517    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, " \
 518           "shost=%02x:%02x:%02x:%02x:%02x:%02x, " \
 519           "type=0x%04x\n",                     \
 520           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2], \
 521           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5], \
 522           hdr->ether_shost[0],hdr->ether_shost[1],hdr->ether_shost[2], \
 523           hdr->ether_shost[3],hdr->ether_shost[4],hdr->ether_shost[5], \
 524           be16_to_cpu(hdr->ether_type));       \
 525} while (0)
 526
 527#define CRC(crc, ch)     (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
 528
 529/* generated using the AUTODIN II polynomial
 530 *    x^32 + x^26 + x^23 + x^22 + x^16 +
 531 *    x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
 532 */
 533static const uint32_t crctab[256] = {
 534    0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
 535    0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
 536    0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
 537    0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
 538    0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
 539    0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
 540    0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
 541    0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
 542    0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
 543    0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
 544    0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
 545    0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
 546    0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
 547    0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
 548    0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
 549    0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
 550    0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
 551    0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
 552    0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
 553    0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
 554    0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
 555    0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
 556    0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
 557    0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
 558    0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
 559    0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
 560    0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
 561    0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
 562    0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
 563    0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
 564    0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
 565    0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
 566    0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
 567    0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
 568    0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
 569    0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
 570    0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
 571    0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
 572    0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
 573    0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
 574    0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
 575    0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
 576    0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
 577    0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
 578    0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
 579    0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
 580    0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
 581    0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
 582    0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
 583    0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
 584    0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
 585    0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
 586    0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
 587    0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
 588    0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
 589    0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
 590    0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
 591    0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
 592    0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
 593    0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
 594    0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
 595    0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
 596    0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
 597    0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
 598};
 599
 600static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
 601{
 602    struct qemu_ether_header *hdr = (void *)buf;
 603    uint8_t padr[6] = {
 604        s->csr[12] & 0xff, s->csr[12] >> 8,
 605        s->csr[13] & 0xff, s->csr[13] >> 8,
 606        s->csr[14] & 0xff, s->csr[14] >> 8
 607    };
 608    int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, padr, 6);
 609#ifdef PCNET_DEBUG_MATCH
 610    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
 611           "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
 612           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
 613           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
 614           padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
 615    printf("padr_match result=%d\n", result);
 616#endif
 617    return result;
 618}
 619
 620static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
 621{
 622    static const uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 623    struct qemu_ether_header *hdr = (void *)buf;
 624    int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
 625#ifdef PCNET_DEBUG_MATCH
 626    printf("padr_bcast result=%d\n", result);
 627#endif
 628    return result;
 629}
 630
 631static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
 632{
 633    struct qemu_ether_header *hdr = (void *)buf;
 634    if ((*(hdr->ether_dhost)&0x01) &&
 635        ((uint64_t *)&s->csr[8])[0] != 0LL) {
 636        uint8_t ladr[8] = {
 637            s->csr[8] & 0xff, s->csr[8] >> 8,
 638            s->csr[9] & 0xff, s->csr[9] >> 8,
 639            s->csr[10] & 0xff, s->csr[10] >> 8,
 640            s->csr[11] & 0xff, s->csr[11] >> 8
 641        };
 642        int index = net_crc32_le(hdr->ether_dhost, ETH_ALEN) >> 26;
 643        return !!(ladr[index >> 3] & (1 << (index & 7)));
 644    }
 645    return 0;
 646}
 647
 648static inline hwaddr pcnet_rdra_addr(PCNetState *s, int idx)
 649{
 650    while (idx < 1) {
 651        idx += CSR_RCVRL(s);
 652    }
 653    return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
 654}
 655
 656static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
 657{
 658    int64_t next_time = current_time +
 659                        (65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s))) * 30;
 660
 661    if (next_time <= current_time) {
 662        next_time = current_time + 1;
 663    }
 664    return next_time;
 665}
 666
 667static void pcnet_poll(PCNetState *s);
 668static void pcnet_poll_timer(void *opaque);
 669
 670static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
 671static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
 672static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
 673
 674static void pcnet_s_reset(PCNetState *s)
 675{
 676    trace_pcnet_s_reset(s);
 677
 678    s->rdra = 0;
 679    s->tdra = 0;
 680    s->rap = 0;
 681
 682    s->bcr[BCR_BSBC] &= ~0x0080;
 683
 684    s->csr[0]   = 0x0004;
 685    s->csr[3]   = 0x0000;
 686    s->csr[4]   = 0x0115;
 687    s->csr[5]   = 0x0000;
 688    s->csr[6]   = 0x0000;
 689    s->csr[8]   = 0;
 690    s->csr[9]   = 0;
 691    s->csr[10]  = 0;
 692    s->csr[11]  = 0;
 693    s->csr[12]  = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
 694    s->csr[13]  = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
 695    s->csr[14]  = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
 696    s->csr[15] &= 0x21c4;
 697    s->csr[72]  = 1;
 698    s->csr[74]  = 1;
 699    s->csr[76]  = 1;
 700    s->csr[78]  = 1;
 701    s->csr[80]  = 0x1410;
 702    s->csr[88]  = 0x1003;
 703    s->csr[89]  = 0x0262;
 704    s->csr[94]  = 0x0000;
 705    s->csr[100] = 0x0200;
 706    s->csr[103] = 0x0105;
 707    s->csr[112] = 0x0000;
 708    s->csr[114] = 0x0000;
 709    s->csr[122] = 0x0000;
 710    s->csr[124] = 0x0000;
 711
 712    s->tx_busy = 0;
 713}
 714
 715static void pcnet_update_irq(PCNetState *s)
 716{
 717    int isr = 0;
 718    s->csr[0] &= ~0x0080;
 719
 720#if 1
 721    if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
 722        (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
 723        (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
 724#else
 725    if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
 726        (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
 727        (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
 728        (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
 729        (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
 730        (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
 731        (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
 732        (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
 733        (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
 734        (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
 735        (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
 736        (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
 737#endif
 738    {
 739
 740        isr = CSR_INEA(s);
 741        s->csr[0] |= 0x0080;
 742    }
 743
 744    if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
 745        s->csr[4] &= ~0x0080;
 746        s->csr[4] |= 0x0040;
 747        s->csr[0] |= 0x0080;
 748        isr = 1;
 749        trace_pcnet_user_int(s);
 750    }
 751
 752#if 1
 753    if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
 754#else
 755    if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
 756        (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
 757#endif
 758    {
 759        isr = 1;
 760        s->csr[0] |= 0x0080;
 761    }
 762
 763    if (isr != s->isr) {
 764        trace_pcnet_isr_change(s, isr, s->isr);
 765    }
 766    qemu_set_irq(s->irq, isr);
 767    s->isr = isr;
 768}
 769
 770static void pcnet_init(PCNetState *s)
 771{
 772    int rlen, tlen;
 773    uint16_t padr[3], ladrf[4], mode;
 774    uint32_t rdra, tdra;
 775
 776    trace_pcnet_init(s, PHYSADDR(s, CSR_IADR(s)));
 777
 778    if (BCR_SSIZE32(s)) {
 779        struct pcnet_initblk32 initblk;
 780        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
 781                (uint8_t *)&initblk, sizeof(initblk), 0);
 782        mode = le16_to_cpu(initblk.mode);
 783        rlen = initblk.rlen >> 4;
 784        tlen = initblk.tlen >> 4;
 785        ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
 786        ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
 787        ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
 788        ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
 789        padr[0] = le16_to_cpu(initblk.padr[0]);
 790        padr[1] = le16_to_cpu(initblk.padr[1]);
 791        padr[2] = le16_to_cpu(initblk.padr[2]);
 792        rdra = le32_to_cpu(initblk.rdra);
 793        tdra = le32_to_cpu(initblk.tdra);
 794    } else {
 795        struct pcnet_initblk16 initblk;
 796        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
 797                (uint8_t *)&initblk, sizeof(initblk), 0);
 798        mode = le16_to_cpu(initblk.mode);
 799        ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
 800        ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
 801        ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
 802        ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
 803        padr[0] = le16_to_cpu(initblk.padr[0]);
 804        padr[1] = le16_to_cpu(initblk.padr[1]);
 805        padr[2] = le16_to_cpu(initblk.padr[2]);
 806        rdra = le32_to_cpu(initblk.rdra);
 807        tdra = le32_to_cpu(initblk.tdra);
 808        rlen = rdra >> 29;
 809        tlen = tdra >> 29;
 810        rdra &= 0x00ffffff;
 811        tdra &= 0x00ffffff;
 812    }
 813
 814    trace_pcnet_rlen_tlen(s, rlen, tlen);
 815
 816    CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
 817    CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
 818    s->csr[ 6] = (tlen << 12) | (rlen << 8);
 819    s->csr[15] = mode;
 820    s->csr[ 8] = ladrf[0];
 821    s->csr[ 9] = ladrf[1];
 822    s->csr[10] = ladrf[2];
 823    s->csr[11] = ladrf[3];
 824    s->csr[12] = padr[0];
 825    s->csr[13] = padr[1];
 826    s->csr[14] = padr[2];
 827    s->rdra = PHYSADDR(s, rdra);
 828    s->tdra = PHYSADDR(s, tdra);
 829
 830    CSR_RCVRC(s) = CSR_RCVRL(s);
 831    CSR_XMTRC(s) = CSR_XMTRL(s);
 832
 833    trace_pcnet_ss32_rdra_tdra(s, BCR_SSIZE32(s),
 834                               s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
 835
 836    s->csr[0] |= 0x0101;
 837    s->csr[0] &= ~0x0004;       /* clear STOP bit */
 838
 839    qemu_flush_queued_packets(qemu_get_queue(s->nic));
 840}
 841
 842static void pcnet_start(PCNetState *s)
 843{
 844#ifdef PCNET_DEBUG
 845    printf("pcnet_start\n");
 846#endif
 847
 848    if (!CSR_DTX(s)) {
 849        s->csr[0] |= 0x0010;    /* set TXON */
 850    }
 851    if (!CSR_DRX(s)) {
 852        s->csr[0] |= 0x0020;    /* set RXON */
 853    }
 854    s->csr[0] &= ~0x0004;       /* clear STOP bit */
 855    s->csr[0] |= 0x0002;
 856    pcnet_poll_timer(s);
 857
 858    qemu_flush_queued_packets(qemu_get_queue(s->nic));
 859}
 860
 861static void pcnet_stop(PCNetState *s)
 862{
 863#ifdef PCNET_DEBUG
 864    printf("pcnet_stop\n");
 865#endif
 866    s->csr[0] &= ~0xffeb;
 867    s->csr[0] |= 0x0014;
 868    s->csr[4] &= ~0x02c2;
 869    s->csr[5] &= ~0x0011;
 870    pcnet_poll_timer(s);
 871}
 872
 873static void pcnet_rdte_poll(PCNetState *s)
 874{
 875    s->csr[28] = s->csr[29] = 0;
 876    if (s->rdra) {
 877        int bad = 0;
 878#if 1
 879        hwaddr crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
 880        hwaddr nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
 881        hwaddr nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
 882#else
 883        hwaddr crda = s->rdra +
 884            (CSR_RCVRL(s) - CSR_RCVRC(s)) *
 885            (BCR_SWSTYLE(s) ? 16 : 8 );
 886        int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
 887        hwaddr nrda = s->rdra +
 888            (CSR_RCVRL(s) - nrdc) *
 889            (BCR_SWSTYLE(s) ? 16 : 8 );
 890        int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
 891        hwaddr nnrd = s->rdra +
 892            (CSR_RCVRL(s) - nnrc) *
 893            (BCR_SWSTYLE(s) ? 16 : 8 );
 894#endif
 895
 896        CHECK_RMD(crda, bad);
 897        if (!bad) {
 898            CHECK_RMD(nrda, bad);
 899            if (bad || (nrda == crda)) nrda = 0;
 900            CHECK_RMD(nnrd, bad);
 901            if (bad || (nnrd == crda)) nnrd = 0;
 902
 903            s->csr[28] = crda & 0xffff;
 904            s->csr[29] = crda >> 16;
 905            s->csr[26] = nrda & 0xffff;
 906            s->csr[27] = nrda >> 16;
 907            s->csr[36] = nnrd & 0xffff;
 908            s->csr[37] = nnrd >> 16;
 909#ifdef PCNET_DEBUG
 910            if (bad) {
 911                printf("pcnet: BAD RMD RECORDS AFTER 0x" HWADDR_FMT_plx "\n",
 912                       crda);
 913            }
 914        } else {
 915            printf("pcnet: BAD RMD RDA=0x" HWADDR_FMT_plx "\n", crda);
 916#endif
 917        }
 918    }
 919
 920    if (CSR_CRDA(s)) {
 921        struct pcnet_RMD rmd;
 922        RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
 923        CSR_CRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
 924        CSR_CRST(s) = rmd.status;
 925#ifdef PCNET_DEBUG_RMD_X
 926        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMDL=0x%04x RMDS=0x%04x RMDM=0x%08x\n",
 927                PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
 928                rmd.buf_length, rmd.status, rmd.msg_length);
 929        PRINT_RMD(&rmd);
 930#endif
 931    } else {
 932        CSR_CRBC(s) = CSR_CRST(s) = 0;
 933    }
 934
 935    if (CSR_NRDA(s)) {
 936        struct pcnet_RMD rmd;
 937        RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
 938        CSR_NRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
 939        CSR_NRST(s) = rmd.status;
 940    } else {
 941        CSR_NRBC(s) = CSR_NRST(s) = 0;
 942    }
 943
 944}
 945
 946static int pcnet_tdte_poll(PCNetState *s)
 947{
 948    s->csr[34] = s->csr[35] = 0;
 949    if (s->tdra) {
 950        hwaddr cxda = s->tdra +
 951            (CSR_XMTRL(s) - CSR_XMTRC(s)) *
 952            (BCR_SWSTYLE(s) ? 16 : 8);
 953        int bad = 0;
 954        CHECK_TMD(cxda, bad);
 955        if (!bad) {
 956            if (CSR_CXDA(s) != cxda) {
 957                s->csr[60] = s->csr[34];
 958                s->csr[61] = s->csr[35];
 959                s->csr[62] = CSR_CXBC(s);
 960                s->csr[63] = CSR_CXST(s);
 961            }
 962            s->csr[34] = cxda & 0xffff;
 963            s->csr[35] = cxda >> 16;
 964#ifdef PCNET_DEBUG_X
 965            printf("pcnet: BAD TMD XDA=0x%08x\n", cxda);
 966#endif
 967        }
 968    }
 969
 970    if (CSR_CXDA(s)) {
 971        struct pcnet_TMD tmd;
 972
 973        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
 974
 975        CSR_CXBC(s) = GET_FIELD(tmd.length, TMDL, BCNT);
 976        CSR_CXST(s) = tmd.status;
 977    } else {
 978        CSR_CXBC(s) = CSR_CXST(s) = 0;
 979    }
 980
 981    return !!(CSR_CXST(s) & 0x8000);
 982}
 983
 984#define MIN_BUF_SIZE 60
 985
 986ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
 987{
 988    PCNetState *s = qemu_get_nic_opaque(nc);
 989    int is_padr = 0, is_bcast = 0, is_ladr = 0;
 990    int remaining;
 991    int crc_err = 0;
 992    size_t size = size_;
 993
 994    if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size ||
 995        (CSR_LOOP(s) && !s->looptest)) {
 996        return -1;
 997    }
 998#ifdef PCNET_DEBUG
 999    printf("pcnet_receive size=%zu\n", size);
1000#endif
1001
1002    if (CSR_PROM(s)
1003        || (is_padr=padr_match(s, buf, size))
1004        || (is_bcast=padr_bcast(s, buf, size))
1005        || (is_ladr=ladr_match(s, buf, size))) {
1006
1007        pcnet_rdte_poll(s);
1008
1009        if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
1010            struct pcnet_RMD rmd;
1011            int rcvrc = CSR_RCVRC(s)-1,i;
1012            hwaddr nrda;
1013            for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
1014                if (rcvrc <= 1)
1015                    rcvrc = CSR_RCVRL(s);
1016                nrda = s->rdra +
1017                    (CSR_RCVRL(s) - rcvrc) *
1018                    (BCR_SWSTYLE(s) ? 16 : 8 );
1019                RMDLOAD(&rmd, nrda);
1020                if (GET_FIELD(rmd.status, RMDS, OWN)) {
1021#ifdef PCNET_DEBUG_RMD
1022                    printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
1023                                rcvrc, CSR_RCVRC(s));
1024#endif
1025                    CSR_RCVRC(s) = rcvrc;
1026                    pcnet_rdte_poll(s);
1027                    break;
1028                }
1029            }
1030        }
1031
1032        if (!(CSR_CRST(s) & 0x8000)) {
1033#ifdef PCNET_DEBUG_RMD
1034            printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
1035#endif
1036            s->csr[0] |= 0x1000; /* Set MISS flag */
1037            CSR_MISSC(s)++;
1038        } else {
1039            uint8_t *src = s->buffer;
1040            hwaddr crda = CSR_CRDA(s);
1041            struct pcnet_RMD rmd;
1042            int pktcount = 0;
1043
1044            if (!s->looptest) {
1045                if (size > 4092) {
1046#ifdef PCNET_DEBUG_RMD
1047                    fprintf(stderr, "pcnet: truncates rx packet.\n");
1048#endif
1049                    size = 4092;
1050                }
1051                memcpy(src, buf, size);
1052                /* no need to compute the CRC */
1053                src[size] = 0;
1054                src[size + 1] = 0;
1055                src[size + 2] = 0;
1056                src[size + 3] = 0;
1057                size += 4;
1058            } else if (s->looptest == PCNET_LOOPTEST_CRC ||
1059                       !CSR_DXMTFCS(s) || size < MIN_BUF_SIZE+4) {
1060                uint32_t fcs = ~0;
1061                uint8_t *p = src;
1062
1063                while (p != &src[size])
1064                    CRC(fcs, *p++);
1065                *(uint32_t *)p = htonl(fcs);
1066                size += 4;
1067            } else {
1068                uint32_t fcs = ~0;
1069                uint8_t *p = src;
1070
1071                while (p != &src[size])
1072                    CRC(fcs, *p++);
1073                crc_err = (*(uint32_t *)p != htonl(fcs));
1074            }
1075
1076#ifdef PCNET_DEBUG_MATCH
1077            PRINT_PKTHDR(buf);
1078#endif
1079
1080            RMDLOAD(&rmd, PHYSADDR(s,crda));
1081            /*if (!CSR_LAPPEN(s))*/
1082                SET_FIELD(&rmd.status, RMDS, STP, 1);
1083
1084#define PCNET_RECV_STORE() do {                                 \
1085    int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),remaining); \
1086    hwaddr rbadr = PHYSADDR(s, rmd.rbadr);          \
1087    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
1088    src += count; remaining -= count;                           \
1089    SET_FIELD(&rmd.status, RMDS, OWN, 0);                       \
1090    RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
1091    pktcount++;                                                 \
1092} while (0)
1093
1094            remaining = size;
1095            PCNET_RECV_STORE();
1096            if ((remaining > 0) && CSR_NRDA(s)) {
1097                hwaddr nrda = CSR_NRDA(s);
1098#ifdef PCNET_DEBUG_RMD
1099                PRINT_RMD(&rmd);
1100#endif
1101                RMDLOAD(&rmd, PHYSADDR(s,nrda));
1102                if (GET_FIELD(rmd.status, RMDS, OWN)) {
1103                    crda = nrda;
1104                    PCNET_RECV_STORE();
1105#ifdef PCNET_DEBUG_RMD
1106                    PRINT_RMD(&rmd);
1107#endif
1108                    if ((remaining > 0) && (nrda=CSR_NNRD(s))) {
1109                        RMDLOAD(&rmd, PHYSADDR(s,nrda));
1110                        if (GET_FIELD(rmd.status, RMDS, OWN)) {
1111                            crda = nrda;
1112                            PCNET_RECV_STORE();
1113                        }
1114                    }
1115                }
1116            }
1117
1118#undef PCNET_RECV_STORE
1119
1120            RMDLOAD(&rmd, PHYSADDR(s,crda));
1121            if (remaining == 0) {
1122                SET_FIELD(&rmd.msg_length, RMDM, MCNT, size);
1123                SET_FIELD(&rmd.status, RMDS, ENP, 1);
1124                SET_FIELD(&rmd.status, RMDS, PAM, !CSR_PROM(s) && is_padr);
1125                SET_FIELD(&rmd.status, RMDS, LFAM, !CSR_PROM(s) && is_ladr);
1126                SET_FIELD(&rmd.status, RMDS, BAM, !CSR_PROM(s) && is_bcast);
1127                if (crc_err) {
1128                    SET_FIELD(&rmd.status, RMDS, CRC, 1);
1129                    SET_FIELD(&rmd.status, RMDS, ERR, 1);
1130                }
1131            } else {
1132                SET_FIELD(&rmd.status, RMDS, OFLO, 1);
1133                SET_FIELD(&rmd.status, RMDS, BUFF, 1);
1134                SET_FIELD(&rmd.status, RMDS, ERR, 1);
1135            }
1136            RMDSTORE(&rmd, PHYSADDR(s,crda));
1137            s->csr[0] |= 0x0400;
1138
1139#ifdef PCNET_DEBUG
1140            printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
1141                CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
1142#endif
1143#ifdef PCNET_DEBUG_RMD
1144            PRINT_RMD(&rmd);
1145#endif
1146
1147            while (pktcount--) {
1148                if (CSR_RCVRC(s) <= 1) {
1149                    CSR_RCVRC(s) = CSR_RCVRL(s);
1150                } else {
1151                    CSR_RCVRC(s)--;
1152                }
1153            }
1154
1155            pcnet_rdte_poll(s);
1156
1157        }
1158    }
1159
1160    pcnet_poll(s);
1161    pcnet_update_irq(s);
1162
1163    return size_;
1164}
1165
1166void pcnet_set_link_status(NetClientState *nc)
1167{
1168    PCNetState *d = qemu_get_nic_opaque(nc);
1169
1170    d->lnkst = nc->link_down ? 0 : 0x40;
1171}
1172
1173static void pcnet_transmit(PCNetState *s)
1174{
1175    hwaddr xmit_cxda = 0;
1176    int count = CSR_XMTRL(s)-1;
1177    int add_crc = 0;
1178    int bcnt;
1179    s->xmit_pos = -1;
1180
1181    if (!CSR_TXON(s)) {
1182        s->csr[0] &= ~0x0008;
1183        return;
1184    }
1185
1186    s->tx_busy = 1;
1187
1188txagain:
1189    if (pcnet_tdte_poll(s)) {
1190        struct pcnet_TMD tmd;
1191
1192        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1193
1194#ifdef PCNET_DEBUG_TMD
1195        printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
1196        PRINT_TMD(&tmd);
1197#endif
1198        if (GET_FIELD(tmd.status, TMDS, STP)) {
1199            s->xmit_pos = 0;
1200            xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
1201            if (BCR_SWSTYLE(s) != 1)
1202                add_crc = GET_FIELD(tmd.status, TMDS, ADDFCS);
1203        }
1204        if (s->lnkst == 0 &&
1205            (!CSR_LOOP(s) || (!CSR_INTL(s) && !BCR_TMAULOOP(s)))) {
1206            SET_FIELD(&tmd.misc, TMDM, LCAR, 1);
1207            SET_FIELD(&tmd.status, TMDS, ERR, 1);
1208            SET_FIELD(&tmd.status, TMDS, OWN, 0);
1209            s->csr[0] |= 0xa000; /* ERR | CERR */
1210            s->xmit_pos = -1;
1211            goto txdone;
1212        }
1213
1214        if (s->xmit_pos < 0) {
1215            goto txdone;
1216        }
1217
1218        bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1219
1220        /* if multi-tmd packet outsizes s->buffer then skip it silently.
1221         * Note: this is not what real hw does.
1222         * Last four bytes of s->buffer are used to store CRC FCS code.
1223         */
1224        if (s->xmit_pos + bcnt > sizeof(s->buffer) - 4) {
1225            s->xmit_pos = -1;
1226            goto txdone;
1227        }
1228
1229        s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1230                         s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1231        s->xmit_pos += bcnt;
1232
1233        if (!GET_FIELD(tmd.status, TMDS, ENP)) {
1234            goto txdone;
1235        }
1236
1237#ifdef PCNET_DEBUG
1238        printf("pcnet_transmit size=%d\n", s->xmit_pos);
1239#endif
1240        if (CSR_LOOP(s)) {
1241            if (BCR_SWSTYLE(s) == 1)
1242                add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
1243            s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
1244            qemu_receive_packet(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
1245            s->looptest = 0;
1246        } else {
1247            if (s->nic) {
1248                qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
1249                                 s->xmit_pos);
1250            }
1251        }
1252
1253        s->csr[0] &= ~0x0008;   /* clear TDMD */
1254        s->csr[4] |= 0x0004;    /* set TXSTRT */
1255        s->xmit_pos = -1;
1256
1257txdone:
1258        SET_FIELD(&tmd.status, TMDS, OWN, 0);
1259        TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1260        if (!CSR_TOKINTD(s)
1261            || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT))) {
1262            s->csr[0] |= 0x0200;    /* set TINT */
1263        }
1264        if (CSR_XMTRC(s) <= 1) {
1265            CSR_XMTRC(s) = CSR_XMTRL(s);
1266        } else {
1267            CSR_XMTRC(s)--;
1268        }
1269        if (count--) {
1270            goto txagain;
1271        }
1272    } else if (s->xmit_pos >= 0) {
1273        struct pcnet_TMD tmd;
1274        TMDLOAD(&tmd, xmit_cxda);
1275        SET_FIELD(&tmd.misc, TMDM, BUFF, 1);
1276        SET_FIELD(&tmd.misc, TMDM, UFLO, 1);
1277        SET_FIELD(&tmd.status, TMDS, ERR, 1);
1278        SET_FIELD(&tmd.status, TMDS, OWN, 0);
1279        TMDSTORE(&tmd, xmit_cxda);
1280        s->csr[0] |= 0x0200;    /* set TINT */
1281        if (!CSR_DXSUFLO(s)) {
1282            s->csr[0] &= ~0x0010;
1283        } else if (count--) {
1284            goto txagain;
1285        }
1286    }
1287
1288    s->tx_busy = 0;
1289}
1290
1291static void pcnet_poll(PCNetState *s)
1292{
1293    if (CSR_RXON(s)) {
1294        pcnet_rdte_poll(s);
1295    }
1296
1297    if (CSR_TDMD(s) || (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s))) {
1298        /* prevent recursion */
1299        if (s->tx_busy) {
1300            return;
1301        }
1302        pcnet_transmit(s);
1303    }
1304}
1305
1306static void pcnet_poll_timer(void *opaque)
1307{
1308    PCNetState *s = opaque;
1309
1310    timer_del(s->poll_timer);
1311
1312    if (CSR_TDMD(s)) {
1313        pcnet_transmit(s);
1314    }
1315
1316    pcnet_update_irq(s);
1317
1318    if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1319        uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) * 33;
1320        if (!s->timer || !now) {
1321            s->timer = now;
1322        } else {
1323            uint64_t t = now - s->timer + CSR_POLL(s);
1324            if (t > 0xffffLL) {
1325                pcnet_poll(s);
1326                CSR_POLL(s) = CSR_PINT(s);
1327            } else {
1328                CSR_POLL(s) = t;
1329            }
1330        }
1331        timer_mod(s->poll_timer,
1332            pcnet_get_next_poll_time(s,qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)));
1333    }
1334}
1335
1336
1337static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1338{
1339    uint16_t val = new_value;
1340#ifdef PCNET_DEBUG_CSR
1341    printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1342#endif
1343    switch (rap) {
1344    case 0:
1345        s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1346
1347        s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
1348
1349        val = (val & 0x007f) | (s->csr[0] & 0x7f00);
1350
1351        /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1352        if ((val & 7) == 7) {
1353            val &= ~3;
1354        }
1355        if (!CSR_STOP(s) && (val & 4)) {
1356            pcnet_stop(s);
1357        }
1358        if (!CSR_INIT(s) && (val & 1)) {
1359            pcnet_init(s);
1360        }
1361        if (!CSR_STRT(s) && (val & 2)) {
1362            pcnet_start(s);
1363        }
1364        if (CSR_TDMD(s)) {
1365            pcnet_transmit(s);
1366        }
1367        return;
1368    case 1:
1369    case 2:
1370    case 8:
1371    case 9:
1372    case 10:
1373    case 11:
1374    case 12:
1375    case 13:
1376    case 14:
1377    case 15:
1378    case 18: /* CRBAL */
1379    case 19: /* CRBAU */
1380    case 20: /* CXBAL */
1381    case 21: /* CXBAU */
1382    case 22: /* NRBAU */
1383    case 23: /* NRBAU */
1384    case 24:
1385    case 25:
1386    case 26:
1387    case 27:
1388    case 28:
1389    case 29:
1390    case 30:
1391    case 31:
1392    case 32:
1393    case 33:
1394    case 34:
1395    case 35:
1396    case 36:
1397    case 37:
1398    case 38:
1399    case 39:
1400    case 40: /* CRBC */
1401    case 41:
1402    case 42: /* CXBC */
1403    case 43:
1404    case 44:
1405    case 45:
1406    case 46: /* POLL */
1407    case 47: /* POLLINT */
1408    case 72:
1409    case 74:
1410        break;
1411    case 76: /* RCVRL */
1412    case 78: /* XMTRL */
1413        val = (val > 0) ? val : 512;
1414        break;
1415    case 112:
1416        if (CSR_STOP(s) || CSR_SPND(s)) {
1417            break;
1418        }
1419        return;
1420    case 3:
1421        break;
1422    case 4:
1423        s->csr[4] &= ~(val & 0x026a);
1424        val &= ~0x026a; val |= s->csr[4] & 0x026a;
1425        break;
1426    case 5:
1427        s->csr[5] &= ~(val & 0x0a90);
1428        val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
1429        break;
1430    case 16:
1431        pcnet_csr_writew(s,1,val);
1432        return;
1433    case 17:
1434        pcnet_csr_writew(s,2,val);
1435        return;
1436    case 58:
1437        pcnet_bcr_writew(s,BCR_SWS,val);
1438        break;
1439    default:
1440        return;
1441    }
1442    s->csr[rap] = val;
1443}
1444
1445static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1446{
1447    uint32_t val;
1448    switch (rap) {
1449    case 0:
1450        pcnet_update_irq(s);
1451        val = s->csr[0];
1452        val |= (val & 0x7800) ? 0x8000 : 0;
1453        break;
1454    case 16:
1455        return pcnet_csr_readw(s,1);
1456    case 17:
1457        return pcnet_csr_readw(s,2);
1458    case 58:
1459        return pcnet_bcr_readw(s,BCR_SWS);
1460    case 88:
1461        val = s->csr[89];
1462        val <<= 16;
1463        val |= s->csr[88];
1464        break;
1465    default:
1466        val = s->csr[rap];
1467    }
1468#ifdef PCNET_DEBUG_CSR
1469    printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1470#endif
1471    return val;
1472}
1473
1474static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1475{
1476    rap &= 127;
1477#ifdef PCNET_DEBUG_BCR
1478    printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1479#endif
1480    switch (rap) {
1481    case BCR_SWS:
1482        if (!(CSR_STOP(s) || CSR_SPND(s)))
1483            return;
1484        val &= ~0x0300;
1485        switch (val & 0x00ff) {
1486        case 0:
1487            val |= 0x0200;
1488            break;
1489        case 1:
1490            val |= 0x0100;
1491            break;
1492        case 2:
1493        case 3:
1494            val |= 0x0300;
1495            break;
1496        default:
1497            qemu_log_mask(LOG_GUEST_ERROR, "pcnet: Bad SWSTYLE=0x%02x\n",
1498                          val & 0xff);
1499            val = 0x0200;
1500            break;
1501        }
1502#ifdef PCNET_DEBUG
1503       printf("BCR_SWS=0x%04x\n", val);
1504#endif
1505        /* fall through */
1506    case BCR_LNKST:
1507    case BCR_LED1:
1508    case BCR_LED2:
1509    case BCR_LED3:
1510    case BCR_MC:
1511    case BCR_FDC:
1512    case BCR_BSBC:
1513    case BCR_EECAS:
1514    case BCR_PLAT:
1515        s->bcr[rap] = val;
1516        break;
1517    default:
1518        break;
1519    }
1520}
1521
1522uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1523{
1524    uint32_t val;
1525    rap &= 127;
1526    switch (rap) {
1527    case BCR_LNKST:
1528    case BCR_LED1:
1529    case BCR_LED2:
1530    case BCR_LED3:
1531        val = s->bcr[rap] & ~0x8000;
1532        val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1533        break;
1534    default:
1535        val = rap < 32 ? s->bcr[rap] : 0;
1536        break;
1537    }
1538#ifdef PCNET_DEBUG_BCR
1539    printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1540#endif
1541    return val;
1542}
1543
1544void pcnet_h_reset(void *opaque)
1545{
1546    PCNetState *s = opaque;
1547
1548    s->bcr[BCR_MSRDA] = 0x0005;
1549    s->bcr[BCR_MSWRA] = 0x0005;
1550    s->bcr[BCR_MC   ] = 0x0002;
1551    s->bcr[BCR_LNKST] = 0x00c0;
1552    s->bcr[BCR_LED1 ] = 0x0084;
1553    s->bcr[BCR_LED2 ] = 0x0088;
1554    s->bcr[BCR_LED3 ] = 0x0090;
1555    s->bcr[BCR_FDC  ] = 0x0000;
1556    s->bcr[BCR_BSBC ] = 0x9001;
1557    s->bcr[BCR_EECAS] = 0x0002;
1558    s->bcr[BCR_SWS  ] = 0x0200;
1559    s->bcr[BCR_PLAT ] = 0xff06;
1560
1561    pcnet_s_reset(s);
1562    pcnet_update_irq(s);
1563    pcnet_poll_timer(s);
1564}
1565
1566void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1567{
1568    PCNetState *s = opaque;
1569    pcnet_poll_timer(s);
1570#ifdef PCNET_DEBUG_IO
1571    printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1572#endif
1573    if (!BCR_DWIO(s)) {
1574        switch (addr & 0x0f) {
1575        case 0x00: /* RDP */
1576            pcnet_csr_writew(s, s->rap, val);
1577            break;
1578        case 0x02:
1579            s->rap = val & 0x7f;
1580            break;
1581        case 0x06:
1582            pcnet_bcr_writew(s, s->rap, val);
1583            break;
1584        }
1585    }
1586    pcnet_update_irq(s);
1587}
1588
1589uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1590{
1591    PCNetState *s = opaque;
1592    uint32_t val = -1;
1593    pcnet_poll_timer(s);
1594    if (!BCR_DWIO(s)) {
1595        switch (addr & 0x0f) {
1596        case 0x00: /* RDP */
1597            val = pcnet_csr_readw(s, s->rap);
1598            break;
1599        case 0x02:
1600            val = s->rap;
1601            break;
1602        case 0x04:
1603            pcnet_s_reset(s);
1604            val = 0;
1605            break;
1606        case 0x06:
1607            val = pcnet_bcr_readw(s, s->rap);
1608            break;
1609        }
1610    }
1611    pcnet_update_irq(s);
1612#ifdef PCNET_DEBUG_IO
1613    printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1614#endif
1615    return val;
1616}
1617
1618void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1619{
1620    PCNetState *s = opaque;
1621    pcnet_poll_timer(s);
1622#ifdef PCNET_DEBUG_IO
1623    printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1624#endif
1625    if (BCR_DWIO(s)) {
1626        switch (addr & 0x0f) {
1627        case 0x00: /* RDP */
1628            pcnet_csr_writew(s, s->rap, val & 0xffff);
1629            break;
1630        case 0x04:
1631            s->rap = val & 0x7f;
1632            break;
1633        case 0x0c:
1634            pcnet_bcr_writew(s, s->rap, val & 0xffff);
1635            break;
1636        }
1637    } else if ((addr & 0x0f) == 0) {
1638        /* switch device to dword i/o mode */
1639        pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1640#ifdef PCNET_DEBUG_IO
1641        printf("device switched into dword i/o mode\n");
1642#endif
1643    }
1644    pcnet_update_irq(s);
1645}
1646
1647uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1648{
1649    PCNetState *s = opaque;
1650    uint32_t val = -1;
1651    pcnet_poll_timer(s);
1652    if (BCR_DWIO(s)) {
1653        switch (addr & 0x0f) {
1654        case 0x00: /* RDP */
1655            val = pcnet_csr_readw(s, s->rap);
1656            break;
1657        case 0x04:
1658            val = s->rap;
1659            break;
1660        case 0x08:
1661            pcnet_s_reset(s);
1662            val = 0;
1663            break;
1664        case 0x0c:
1665            val = pcnet_bcr_readw(s, s->rap);
1666            break;
1667        }
1668    }
1669    pcnet_update_irq(s);
1670#ifdef PCNET_DEBUG_IO
1671    printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1672#endif
1673    return val;
1674}
1675
1676static bool is_version_2(void *opaque, int version_id)
1677{
1678    return version_id == 2;
1679}
1680
1681const VMStateDescription vmstate_pcnet = {
1682    .name = "pcnet",
1683    .version_id = 3,
1684    .minimum_version_id = 2,
1685    .fields = (VMStateField[]) {
1686        VMSTATE_INT32(rap, PCNetState),
1687        VMSTATE_INT32(isr, PCNetState),
1688        VMSTATE_INT32(lnkst, PCNetState),
1689        VMSTATE_UINT32(rdra, PCNetState),
1690        VMSTATE_UINT32(tdra, PCNetState),
1691        VMSTATE_BUFFER(prom, PCNetState),
1692        VMSTATE_UINT16_ARRAY(csr, PCNetState, 128),
1693        VMSTATE_UINT16_ARRAY(bcr, PCNetState, 32),
1694        VMSTATE_UINT64(timer, PCNetState),
1695        VMSTATE_INT32(xmit_pos, PCNetState),
1696        VMSTATE_BUFFER(buffer, PCNetState),
1697        VMSTATE_UNUSED_TEST(is_version_2, 4),
1698        VMSTATE_INT32(tx_busy, PCNetState),
1699        VMSTATE_TIMER_PTR(poll_timer, PCNetState),
1700        VMSTATE_END_OF_LIST()
1701    }
1702};
1703
1704void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
1705{
1706    int i;
1707    uint16_t checksum;
1708
1709    s->poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pcnet_poll_timer, s);
1710
1711    qemu_macaddr_default_if_unset(&s->conf.macaddr);
1712    s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s);
1713    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
1714
1715    /* Initialize the PROM */
1716
1717    /*
1718      Datasheet: http://pdfdata.datasheetsite.com/web/24528/AM79C970A.pdf
1719      page 95
1720    */
1721    memcpy(s->prom, s->conf.macaddr.a, 6);
1722    /* Reserved Location: must be 00h */
1723    s->prom[6] = s->prom[7] = 0x00;
1724    /* Reserved Location: must be 00h */
1725    s->prom[8] = 0x00;
1726    /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */
1727    s->prom[9] = 0x11;
1728    /* User programmable space, init with 0 */
1729    s->prom[10] = s->prom[11] = 0x00;
1730    /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh
1731       and bytes 0Eh and 0Fh, must therefore be initialized with 0! */
1732    s->prom[12] = s->prom[13] = 0x00;
1733    /* Must be ASCII W (57h) if compatibility to AMD
1734       driver software is desired */
1735    s->prom[14] = s->prom[15] = 0x57;
1736
1737    for (i = 0, checksum = 0; i < 16; i++) {
1738        checksum += s->prom[i];
1739    }
1740    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1741
1742    s->lnkst = 0x40; /* initial link state: up */
1743}
1744