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