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 "qemu/timer.h"
  42#include "qemu/sockets.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        do {                                    \
 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        } while (0);                            \
 465        break;                                  \
 466    case 0x01:                                  \
 467    case 0x02:                                  \
 468        do {                                    \
 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        } while (0);                            \
 475        break;                                  \
 476    case 0x03:                                  \
 477        do {                                    \
 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        } while (0);                            \
 484        break;                                  \
 485    }                                           \
 486} while (0)
 487
 488#define CHECK_TMD(ADDR,RES) do {                \
 489    switch (BCR_SWSTYLE(s)) {                   \
 490    case 0x00:                                  \
 491        do {                                    \
 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        } while (0);                            \
 497        break;                                  \
 498    case 0x01:                                  \
 499    case 0x02:                                  \
 500    case 0x03:                                  \
 501        do {                                    \
 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        } while (0);                            \
 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 MULTICAST_FILTER_LEN 8
 526
 527static inline uint32_t lnc_mchash(const uint8_t *ether_addr)
 528{
 529#define LNC_POLYNOMIAL          0xEDB88320UL
 530    uint32_t crc = 0xFFFFFFFF;
 531    int idx, bit;
 532    uint8_t data;
 533
 534    for (idx = 0; idx < 6; idx++) {
 535        for (data = *ether_addr++, bit = 0; bit < MULTICAST_FILTER_LEN; bit++) {
 536            crc = (crc >> 1) ^ (((crc ^ data) & 1) ? LNC_POLYNOMIAL : 0);
 537            data >>= 1;
 538        }
 539    }
 540    return crc;
 541#undef LNC_POLYNOMIAL
 542}
 543
 544#define CRC(crc, ch)     (crc = (crc >> 8) ^ crctab[(crc ^ (ch)) & 0xff])
 545
 546/* generated using the AUTODIN II polynomial
 547 *      x^32 + x^26 + x^23 + x^22 + x^16 +
 548 *      x^12 + x^11 + x^10 + x^8 + x^7 + x^5 + x^4 + x^2 + x^1 + 1
 549 */
 550static const uint32_t crctab[256] = {
 551        0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
 552        0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
 553        0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
 554        0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
 555        0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
 556        0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
 557        0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
 558        0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
 559        0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
 560        0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
 561        0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
 562        0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
 563        0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
 564        0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
 565        0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
 566        0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
 567        0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
 568        0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
 569        0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
 570        0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
 571        0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
 572        0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
 573        0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
 574        0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
 575        0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
 576        0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
 577        0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
 578        0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
 579        0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
 580        0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
 581        0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
 582        0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
 583        0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
 584        0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
 585        0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
 586        0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
 587        0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
 588        0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
 589        0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
 590        0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
 591        0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
 592        0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
 593        0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
 594        0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
 595        0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
 596        0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
 597        0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
 598        0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
 599        0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
 600        0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
 601        0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
 602        0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
 603        0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
 604        0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
 605        0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
 606        0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
 607        0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
 608        0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
 609        0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
 610        0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
 611        0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
 612        0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
 613        0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
 614        0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
 615};
 616
 617static inline int padr_match(PCNetState *s, const uint8_t *buf, int size)
 618{
 619    struct qemu_ether_header *hdr = (void *)buf;
 620    uint8_t padr[6] = {
 621        s->csr[12] & 0xff, s->csr[12] >> 8,
 622        s->csr[13] & 0xff, s->csr[13] >> 8,
 623        s->csr[14] & 0xff, s->csr[14] >> 8
 624    };
 625    int result = (!CSR_DRCVPA(s)) && !memcmp(hdr->ether_dhost, padr, 6);
 626#ifdef PCNET_DEBUG_MATCH
 627    printf("packet dhost=%02x:%02x:%02x:%02x:%02x:%02x, "
 628           "padr=%02x:%02x:%02x:%02x:%02x:%02x\n",
 629           hdr->ether_dhost[0],hdr->ether_dhost[1],hdr->ether_dhost[2],
 630           hdr->ether_dhost[3],hdr->ether_dhost[4],hdr->ether_dhost[5],
 631           padr[0],padr[1],padr[2],padr[3],padr[4],padr[5]);
 632    printf("padr_match result=%d\n", result);
 633#endif
 634    return result;
 635}
 636
 637static inline int padr_bcast(PCNetState *s, const uint8_t *buf, int size)
 638{
 639    static const uint8_t BCAST[6] = { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 640    struct qemu_ether_header *hdr = (void *)buf;
 641    int result = !CSR_DRCVBC(s) && !memcmp(hdr->ether_dhost, BCAST, 6);
 642#ifdef PCNET_DEBUG_MATCH
 643    printf("padr_bcast result=%d\n", result);
 644#endif
 645    return result;
 646}
 647
 648static inline int ladr_match(PCNetState *s, const uint8_t *buf, int size)
 649{
 650    struct qemu_ether_header *hdr = (void *)buf;
 651    if ((*(hdr->ether_dhost)&0x01) &&
 652        ((uint64_t *)&s->csr[8])[0] != 0LL) {
 653        uint8_t ladr[8] = {
 654            s->csr[8] & 0xff, s->csr[8] >> 8,
 655            s->csr[9] & 0xff, s->csr[9] >> 8,
 656            s->csr[10] & 0xff, s->csr[10] >> 8,
 657            s->csr[11] & 0xff, s->csr[11] >> 8
 658        };
 659        int index = lnc_mchash(hdr->ether_dhost) >> 26;
 660        return !!(ladr[index >> 3] & (1 << (index & 7)));
 661    }
 662    return 0;
 663}
 664
 665static inline hwaddr pcnet_rdra_addr(PCNetState *s, int idx)
 666{
 667    while (idx < 1) idx += CSR_RCVRL(s);
 668    return s->rdra + ((CSR_RCVRL(s) - idx) * (BCR_SWSTYLE(s) ? 16 : 8));
 669}
 670
 671static inline int64_t pcnet_get_next_poll_time(PCNetState *s, int64_t current_time)
 672{
 673    int64_t next_time = current_time +
 674                        (65536 - (CSR_SPND(s) ? 0 : CSR_POLL(s))) * 30;
 675    if (next_time <= current_time)
 676        next_time = current_time + 1;
 677    return next_time;
 678}
 679
 680static void pcnet_poll(PCNetState *s);
 681static void pcnet_poll_timer(void *opaque);
 682
 683static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap);
 684static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value);
 685static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val);
 686
 687static void pcnet_s_reset(PCNetState *s)
 688{
 689    trace_pcnet_s_reset(s);
 690
 691    s->rdra = 0;
 692    s->tdra = 0;
 693    s->rap = 0;
 694
 695    s->bcr[BCR_BSBC] &= ~0x0080;
 696
 697    s->csr[0]   = 0x0004;
 698    s->csr[3]   = 0x0000;
 699    s->csr[4]   = 0x0115;
 700    s->csr[5]   = 0x0000;
 701    s->csr[6]   = 0x0000;
 702    s->csr[8]   = 0;
 703    s->csr[9]   = 0;
 704    s->csr[10]  = 0;
 705    s->csr[11]  = 0;
 706    s->csr[12]  = le16_to_cpu(((uint16_t *)&s->prom[0])[0]);
 707    s->csr[13]  = le16_to_cpu(((uint16_t *)&s->prom[0])[1]);
 708    s->csr[14]  = le16_to_cpu(((uint16_t *)&s->prom[0])[2]);
 709    s->csr[15] &= 0x21c4;
 710    s->csr[72]  = 1;
 711    s->csr[74]  = 1;
 712    s->csr[76]  = 1;
 713    s->csr[78]  = 1;
 714    s->csr[80]  = 0x1410;
 715    s->csr[88]  = 0x1003;
 716    s->csr[89]  = 0x0262;
 717    s->csr[94]  = 0x0000;
 718    s->csr[100] = 0x0200;
 719    s->csr[103] = 0x0105;
 720    s->csr[112] = 0x0000;
 721    s->csr[114] = 0x0000;
 722    s->csr[122] = 0x0000;
 723    s->csr[124] = 0x0000;
 724
 725    s->tx_busy = 0;
 726}
 727
 728static void pcnet_update_irq(PCNetState *s)
 729{
 730    int isr = 0;
 731    s->csr[0] &= ~0x0080;
 732
 733#if 1
 734    if (((s->csr[0] & ~s->csr[3]) & 0x5f00) ||
 735        (((s->csr[4]>>1) & ~s->csr[4]) & 0x0115) ||
 736        (((s->csr[5]>>1) & s->csr[5]) & 0x0048))
 737#else
 738    if ((!(s->csr[3] & 0x4000) && !!(s->csr[0] & 0x4000)) /* BABL */ ||
 739        (!(s->csr[3] & 0x1000) && !!(s->csr[0] & 0x1000)) /* MISS */ ||
 740        (!(s->csr[3] & 0x0100) && !!(s->csr[0] & 0x0100)) /* IDON */ ||
 741        (!(s->csr[3] & 0x0200) && !!(s->csr[0] & 0x0200)) /* TINT */ ||
 742        (!(s->csr[3] & 0x0400) && !!(s->csr[0] & 0x0400)) /* RINT */ ||
 743        (!(s->csr[3] & 0x0800) && !!(s->csr[0] & 0x0800)) /* MERR */ ||
 744        (!(s->csr[4] & 0x0001) && !!(s->csr[4] & 0x0002)) /* JAB */ ||
 745        (!(s->csr[4] & 0x0004) && !!(s->csr[4] & 0x0008)) /* TXSTRT */ ||
 746        (!(s->csr[4] & 0x0010) && !!(s->csr[4] & 0x0020)) /* RCVO */ ||
 747        (!(s->csr[4] & 0x0100) && !!(s->csr[4] & 0x0200)) /* MFCO */ ||
 748        (!!(s->csr[5] & 0x0040) && !!(s->csr[5] & 0x0080)) /* EXDINT */ ||
 749        (!!(s->csr[5] & 0x0008) && !!(s->csr[5] & 0x0010)) /* MPINT */)
 750#endif
 751    {
 752
 753        isr = CSR_INEA(s);
 754        s->csr[0] |= 0x0080;
 755    }
 756
 757    if (!!(s->csr[4] & 0x0080) && CSR_INEA(s)) { /* UINT */
 758        s->csr[4] &= ~0x0080;
 759        s->csr[4] |= 0x0040;
 760        s->csr[0] |= 0x0080;
 761        isr = 1;
 762        trace_pcnet_user_int(s);
 763    }
 764
 765#if 1
 766    if (((s->csr[5]>>1) & s->csr[5]) & 0x0500)
 767#else
 768    if ((!!(s->csr[5] & 0x0400) && !!(s->csr[5] & 0x0800)) /* SINT */ ||
 769        (!!(s->csr[5] & 0x0100) && !!(s->csr[5] & 0x0200)) /* SLPINT */ )
 770#endif
 771    {
 772        isr = 1;
 773        s->csr[0] |= 0x0080;
 774    }
 775
 776    if (isr != s->isr) {
 777        trace_pcnet_isr_change(s, isr, s->isr);
 778    }
 779    qemu_set_irq(s->irq, isr);
 780    s->isr = isr;
 781}
 782
 783static void pcnet_init(PCNetState *s)
 784{
 785    int rlen, tlen;
 786    uint16_t padr[3], ladrf[4], mode;
 787    uint32_t rdra, tdra;
 788
 789    trace_pcnet_init(s, PHYSADDR(s, CSR_IADR(s)));
 790
 791    if (BCR_SSIZE32(s)) {
 792        struct pcnet_initblk32 initblk;
 793        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
 794                (uint8_t *)&initblk, sizeof(initblk), 0);
 795        mode = le16_to_cpu(initblk.mode);
 796        rlen = initblk.rlen >> 4;
 797        tlen = initblk.tlen >> 4;
 798        ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
 799        ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
 800        ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
 801        ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
 802        padr[0] = le16_to_cpu(initblk.padr[0]);
 803        padr[1] = le16_to_cpu(initblk.padr[1]);
 804        padr[2] = le16_to_cpu(initblk.padr[2]);
 805        rdra = le32_to_cpu(initblk.rdra);
 806        tdra = le32_to_cpu(initblk.tdra);
 807    } else {
 808        struct pcnet_initblk16 initblk;
 809        s->phys_mem_read(s->dma_opaque, PHYSADDR(s,CSR_IADR(s)),
 810                (uint8_t *)&initblk, sizeof(initblk), 0);
 811        mode = le16_to_cpu(initblk.mode);
 812        ladrf[0] = le16_to_cpu(initblk.ladrf[0]);
 813        ladrf[1] = le16_to_cpu(initblk.ladrf[1]);
 814        ladrf[2] = le16_to_cpu(initblk.ladrf[2]);
 815        ladrf[3] = le16_to_cpu(initblk.ladrf[3]);
 816        padr[0] = le16_to_cpu(initblk.padr[0]);
 817        padr[1] = le16_to_cpu(initblk.padr[1]);
 818        padr[2] = le16_to_cpu(initblk.padr[2]);
 819        rdra = le32_to_cpu(initblk.rdra);
 820        tdra = le32_to_cpu(initblk.tdra);
 821        rlen = rdra >> 29;
 822        tlen = tdra >> 29;
 823        rdra &= 0x00ffffff;
 824        tdra &= 0x00ffffff;
 825    }
 826
 827    trace_pcnet_rlen_tlen(s, rlen, tlen);
 828
 829    CSR_RCVRL(s) = (rlen < 9) ? (1 << rlen) : 512;
 830    CSR_XMTRL(s) = (tlen < 9) ? (1 << tlen) : 512;
 831    s->csr[ 6] = (tlen << 12) | (rlen << 8);
 832    s->csr[15] = mode;
 833    s->csr[ 8] = ladrf[0];
 834    s->csr[ 9] = ladrf[1];
 835    s->csr[10] = ladrf[2];
 836    s->csr[11] = ladrf[3];
 837    s->csr[12] = padr[0];
 838    s->csr[13] = padr[1];
 839    s->csr[14] = padr[2];
 840    s->rdra = PHYSADDR(s, rdra);
 841    s->tdra = PHYSADDR(s, tdra);
 842
 843    CSR_RCVRC(s) = CSR_RCVRL(s);
 844    CSR_XMTRC(s) = CSR_XMTRL(s);
 845
 846    trace_pcnet_ss32_rdra_tdra(s, BCR_SSIZE32(s),
 847                               s->rdra, CSR_RCVRL(s), s->tdra, CSR_XMTRL(s));
 848
 849    s->csr[0] |= 0x0101;
 850    s->csr[0] &= ~0x0004;       /* clear STOP bit */
 851
 852    qemu_flush_queued_packets(qemu_get_queue(s->nic));
 853}
 854
 855static void pcnet_start(PCNetState *s)
 856{
 857#ifdef PCNET_DEBUG
 858    printf("pcnet_start\n");
 859#endif
 860
 861    if (!CSR_DTX(s))
 862        s->csr[0] |= 0x0010;    /* set TXON */
 863
 864    if (!CSR_DRX(s))
 865        s->csr[0] |= 0x0020;    /* set RXON */
 866
 867    s->csr[0] &= ~0x0004;       /* clear STOP bit */
 868    s->csr[0] |= 0x0002;
 869    pcnet_poll_timer(s);
 870
 871    qemu_flush_queued_packets(qemu_get_queue(s->nic));
 872}
 873
 874static void pcnet_stop(PCNetState *s)
 875{
 876#ifdef PCNET_DEBUG
 877    printf("pcnet_stop\n");
 878#endif
 879    s->csr[0] &= ~0xffeb;
 880    s->csr[0] |= 0x0014;
 881    s->csr[4] &= ~0x02c2;
 882    s->csr[5] &= ~0x0011;
 883    pcnet_poll_timer(s);
 884}
 885
 886static void pcnet_rdte_poll(PCNetState *s)
 887{
 888    s->csr[28] = s->csr[29] = 0;
 889    if (s->rdra) {
 890        int bad = 0;
 891#if 1
 892        hwaddr crda = pcnet_rdra_addr(s, CSR_RCVRC(s));
 893        hwaddr nrda = pcnet_rdra_addr(s, -1 + CSR_RCVRC(s));
 894        hwaddr nnrd = pcnet_rdra_addr(s, -2 + CSR_RCVRC(s));
 895#else
 896        hwaddr crda = s->rdra +
 897            (CSR_RCVRL(s) - CSR_RCVRC(s)) *
 898            (BCR_SWSTYLE(s) ? 16 : 8 );
 899        int nrdc = CSR_RCVRC(s)<=1 ? CSR_RCVRL(s) : CSR_RCVRC(s)-1;
 900        hwaddr nrda = s->rdra +
 901            (CSR_RCVRL(s) - nrdc) *
 902            (BCR_SWSTYLE(s) ? 16 : 8 );
 903        int nnrc = nrdc<=1 ? CSR_RCVRL(s) : nrdc-1;
 904        hwaddr nnrd = s->rdra +
 905            (CSR_RCVRL(s) - nnrc) *
 906            (BCR_SWSTYLE(s) ? 16 : 8 );
 907#endif
 908
 909        CHECK_RMD(crda, bad);
 910        if (!bad) {
 911            CHECK_RMD(nrda, bad);
 912            if (bad || (nrda == crda)) nrda = 0;
 913            CHECK_RMD(nnrd, bad);
 914            if (bad || (nnrd == crda)) nnrd = 0;
 915
 916            s->csr[28] = crda & 0xffff;
 917            s->csr[29] = crda >> 16;
 918            s->csr[26] = nrda & 0xffff;
 919            s->csr[27] = nrda >> 16;
 920            s->csr[36] = nnrd & 0xffff;
 921            s->csr[37] = nnrd >> 16;
 922#ifdef PCNET_DEBUG
 923            if (bad) {
 924                printf("pcnet: BAD RMD RECORDS AFTER 0x" TARGET_FMT_plx "\n",
 925                       crda);
 926            }
 927        } else {
 928            printf("pcnet: BAD RMD RDA=0x" TARGET_FMT_plx "\n",
 929                   crda);
 930#endif
 931        }
 932    }
 933
 934    if (CSR_CRDA(s)) {
 935        struct pcnet_RMD rmd;
 936        RMDLOAD(&rmd, PHYSADDR(s,CSR_CRDA(s)));
 937        CSR_CRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
 938        CSR_CRST(s) = rmd.status;
 939#ifdef PCNET_DEBUG_RMD_X
 940        printf("CRDA=0x%08x CRST=0x%04x RCVRC=%d RMDL=0x%04x RMDS=0x%04x RMDM=0x%08x\n",
 941                PHYSADDR(s,CSR_CRDA(s)), CSR_CRST(s), CSR_RCVRC(s),
 942                rmd.buf_length, rmd.status, rmd.msg_length);
 943        PRINT_RMD(&rmd);
 944#endif
 945    } else {
 946        CSR_CRBC(s) = CSR_CRST(s) = 0;
 947    }
 948
 949    if (CSR_NRDA(s)) {
 950        struct pcnet_RMD rmd;
 951        RMDLOAD(&rmd, PHYSADDR(s,CSR_NRDA(s)));
 952        CSR_NRBC(s) = GET_FIELD(rmd.buf_length, RMDL, BCNT);
 953        CSR_NRST(s) = rmd.status;
 954    } else {
 955        CSR_NRBC(s) = CSR_NRST(s) = 0;
 956    }
 957
 958}
 959
 960static int pcnet_tdte_poll(PCNetState *s)
 961{
 962    s->csr[34] = s->csr[35] = 0;
 963    if (s->tdra) {
 964        hwaddr cxda = s->tdra +
 965            (CSR_XMTRL(s) - CSR_XMTRC(s)) *
 966            (BCR_SWSTYLE(s) ? 16 : 8);
 967        int bad = 0;
 968        CHECK_TMD(cxda, bad);
 969        if (!bad) {
 970            if (CSR_CXDA(s) != cxda) {
 971                s->csr[60] = s->csr[34];
 972                s->csr[61] = s->csr[35];
 973                s->csr[62] = CSR_CXBC(s);
 974                s->csr[63] = CSR_CXST(s);
 975            }
 976            s->csr[34] = cxda & 0xffff;
 977            s->csr[35] = cxda >> 16;
 978#ifdef PCNET_DEBUG_X
 979            printf("pcnet: BAD TMD XDA=0x%08x\n", cxda);
 980#endif
 981        }
 982    }
 983
 984    if (CSR_CXDA(s)) {
 985        struct pcnet_TMD tmd;
 986
 987        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
 988
 989        CSR_CXBC(s) = GET_FIELD(tmd.length, TMDL, BCNT);
 990        CSR_CXST(s) = tmd.status;
 991    } else {
 992        CSR_CXBC(s) = CSR_CXST(s) = 0;
 993    }
 994
 995    return !!(CSR_CXST(s) & 0x8000);
 996}
 997
 998#define MIN_BUF_SIZE 60
 999
1000ssize_t pcnet_receive(NetClientState *nc, const uint8_t *buf, size_t size_)
1001{
1002    PCNetState *s = qemu_get_nic_opaque(nc);
1003    int is_padr = 0, is_bcast = 0, is_ladr = 0;
1004    uint8_t buf1[60];
1005    int remaining;
1006    int crc_err = 0;
1007    int size = size_;
1008
1009    if (CSR_DRX(s) || CSR_STOP(s) || CSR_SPND(s) || !size ||
1010        (CSR_LOOP(s) && !s->looptest)) {
1011        return -1;
1012    }
1013#ifdef PCNET_DEBUG
1014    printf("pcnet_receive size=%d\n", size);
1015#endif
1016
1017    /* if too small buffer, then expand it */
1018    if (size < MIN_BUF_SIZE) {
1019        memcpy(buf1, buf, size);
1020        memset(buf1 + size, 0, MIN_BUF_SIZE - size);
1021        buf = buf1;
1022        size = MIN_BUF_SIZE;
1023    }
1024
1025    if (CSR_PROM(s)
1026        || (is_padr=padr_match(s, buf, size))
1027        || (is_bcast=padr_bcast(s, buf, size))
1028        || (is_ladr=ladr_match(s, buf, size))) {
1029
1030        pcnet_rdte_poll(s);
1031
1032        if (!(CSR_CRST(s) & 0x8000) && s->rdra) {
1033            struct pcnet_RMD rmd;
1034            int rcvrc = CSR_RCVRC(s)-1,i;
1035            hwaddr nrda;
1036            for (i = CSR_RCVRL(s)-1; i > 0; i--, rcvrc--) {
1037                if (rcvrc <= 1)
1038                    rcvrc = CSR_RCVRL(s);
1039                nrda = s->rdra +
1040                    (CSR_RCVRL(s) - rcvrc) *
1041                    (BCR_SWSTYLE(s) ? 16 : 8 );
1042                RMDLOAD(&rmd, nrda);
1043                if (GET_FIELD(rmd.status, RMDS, OWN)) {
1044#ifdef PCNET_DEBUG_RMD
1045                    printf("pcnet - scan buffer: RCVRC=%d PREV_RCVRC=%d\n",
1046                                rcvrc, CSR_RCVRC(s));
1047#endif
1048                    CSR_RCVRC(s) = rcvrc;
1049                    pcnet_rdte_poll(s);
1050                    break;
1051                }
1052            }
1053        }
1054
1055        if (!(CSR_CRST(s) & 0x8000)) {
1056#ifdef PCNET_DEBUG_RMD
1057            printf("pcnet - no buffer: RCVRC=%d\n", CSR_RCVRC(s));
1058#endif
1059            s->csr[0] |= 0x1000; /* Set MISS flag */
1060            CSR_MISSC(s)++;
1061        } else {
1062            uint8_t *src = s->buffer;
1063            hwaddr crda = CSR_CRDA(s);
1064            struct pcnet_RMD rmd;
1065            int pktcount = 0;
1066
1067            if (!s->looptest) {
1068                if (size > 4092) {
1069#ifdef PCNET_DEBUG_RMD
1070                    fprintf(stderr, "pcnet: truncates rx packet.\n");
1071#endif
1072                    size = 4092;
1073                }
1074                memcpy(src, buf, size);
1075                /* no need to compute the CRC */
1076                src[size] = 0;
1077                src[size + 1] = 0;
1078                src[size + 2] = 0;
1079                src[size + 3] = 0;
1080                size += 4;
1081            } else if (s->looptest == PCNET_LOOPTEST_CRC ||
1082                       !CSR_DXMTFCS(s) || size < MIN_BUF_SIZE+4) {
1083                uint32_t fcs = ~0;
1084                uint8_t *p = src;
1085
1086                while (p != &src[size])
1087                    CRC(fcs, *p++);
1088                *(uint32_t *)p = htonl(fcs);
1089                size += 4;
1090            } else {
1091                uint32_t fcs = ~0;
1092                uint8_t *p = src;
1093
1094                while (p != &src[size])
1095                    CRC(fcs, *p++);
1096                crc_err = (*(uint32_t *)p != htonl(fcs));
1097            }
1098
1099#ifdef PCNET_DEBUG_MATCH
1100            PRINT_PKTHDR(buf);
1101#endif
1102
1103            RMDLOAD(&rmd, PHYSADDR(s,crda));
1104            /*if (!CSR_LAPPEN(s))*/
1105                SET_FIELD(&rmd.status, RMDS, STP, 1);
1106
1107#define PCNET_RECV_STORE() do {                                 \
1108    int count = MIN(4096 - GET_FIELD(rmd.buf_length, RMDL, BCNT),remaining); \
1109    hwaddr rbadr = PHYSADDR(s, rmd.rbadr);          \
1110    s->phys_mem_write(s->dma_opaque, rbadr, src, count, CSR_BSWP(s)); \
1111    src += count; remaining -= count;                           \
1112    SET_FIELD(&rmd.status, RMDS, OWN, 0);                       \
1113    RMDSTORE(&rmd, PHYSADDR(s,crda));                           \
1114    pktcount++;                                                 \
1115} while (0)
1116
1117            remaining = size;
1118            PCNET_RECV_STORE();
1119            if ((remaining > 0) && CSR_NRDA(s)) {
1120                hwaddr nrda = CSR_NRDA(s);
1121#ifdef PCNET_DEBUG_RMD
1122                PRINT_RMD(&rmd);
1123#endif
1124                RMDLOAD(&rmd, PHYSADDR(s,nrda));
1125                if (GET_FIELD(rmd.status, RMDS, OWN)) {
1126                    crda = nrda;
1127                    PCNET_RECV_STORE();
1128#ifdef PCNET_DEBUG_RMD
1129                    PRINT_RMD(&rmd);
1130#endif
1131                    if ((remaining > 0) && (nrda=CSR_NNRD(s))) {
1132                        RMDLOAD(&rmd, PHYSADDR(s,nrda));
1133                        if (GET_FIELD(rmd.status, RMDS, OWN)) {
1134                            crda = nrda;
1135                            PCNET_RECV_STORE();
1136                        }
1137                    }
1138                }
1139            }
1140
1141#undef PCNET_RECV_STORE
1142
1143            RMDLOAD(&rmd, PHYSADDR(s,crda));
1144            if (remaining == 0) {
1145                SET_FIELD(&rmd.msg_length, RMDM, MCNT, size);
1146                SET_FIELD(&rmd.status, RMDS, ENP, 1);
1147                SET_FIELD(&rmd.status, RMDS, PAM, !CSR_PROM(s) && is_padr);
1148                SET_FIELD(&rmd.status, RMDS, LFAM, !CSR_PROM(s) && is_ladr);
1149                SET_FIELD(&rmd.status, RMDS, BAM, !CSR_PROM(s) && is_bcast);
1150                if (crc_err) {
1151                    SET_FIELD(&rmd.status, RMDS, CRC, 1);
1152                    SET_FIELD(&rmd.status, RMDS, ERR, 1);
1153                }
1154            } else {
1155                SET_FIELD(&rmd.status, RMDS, OFLO, 1);
1156                SET_FIELD(&rmd.status, RMDS, BUFF, 1);
1157                SET_FIELD(&rmd.status, RMDS, ERR, 1);
1158            }
1159            RMDSTORE(&rmd, PHYSADDR(s,crda));
1160            s->csr[0] |= 0x0400;
1161
1162#ifdef PCNET_DEBUG
1163            printf("RCVRC=%d CRDA=0x%08x BLKS=%d\n",
1164                CSR_RCVRC(s), PHYSADDR(s,CSR_CRDA(s)), pktcount);
1165#endif
1166#ifdef PCNET_DEBUG_RMD
1167            PRINT_RMD(&rmd);
1168#endif
1169
1170            while (pktcount--) {
1171                if (CSR_RCVRC(s) <= 1)
1172                    CSR_RCVRC(s) = CSR_RCVRL(s);
1173                else
1174                    CSR_RCVRC(s)--;
1175            }
1176
1177            pcnet_rdte_poll(s);
1178
1179        }
1180    }
1181
1182    pcnet_poll(s);
1183    pcnet_update_irq(s);
1184
1185    return size_;
1186}
1187
1188void pcnet_set_link_status(NetClientState *nc)
1189{
1190    PCNetState *d = qemu_get_nic_opaque(nc);
1191
1192    d->lnkst = nc->link_down ? 0 : 0x40;
1193}
1194
1195static void pcnet_transmit(PCNetState *s)
1196{
1197    hwaddr xmit_cxda = 0;
1198    int count = CSR_XMTRL(s)-1;
1199    int add_crc = 0;
1200    int bcnt;
1201    s->xmit_pos = -1;
1202
1203    if (!CSR_TXON(s)) {
1204        s->csr[0] &= ~0x0008;
1205        return;
1206    }
1207
1208    s->tx_busy = 1;
1209
1210    txagain:
1211    if (pcnet_tdte_poll(s)) {
1212        struct pcnet_TMD tmd;
1213
1214        TMDLOAD(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1215
1216#ifdef PCNET_DEBUG_TMD
1217        printf("  TMDLOAD 0x%08x\n", PHYSADDR(s,CSR_CXDA(s)));
1218        PRINT_TMD(&tmd);
1219#endif
1220        if (GET_FIELD(tmd.status, TMDS, STP)) {
1221            s->xmit_pos = 0;
1222            xmit_cxda = PHYSADDR(s,CSR_CXDA(s));
1223            if (BCR_SWSTYLE(s) != 1)
1224                add_crc = GET_FIELD(tmd.status, TMDS, ADDFCS);
1225        }
1226        if (s->lnkst == 0 &&
1227            (!CSR_LOOP(s) || (!CSR_INTL(s) && !BCR_TMAULOOP(s)))) {
1228            SET_FIELD(&tmd.misc, TMDM, LCAR, 1);
1229            SET_FIELD(&tmd.status, TMDS, ERR, 1);
1230            SET_FIELD(&tmd.status, TMDS, OWN, 0);
1231            s->csr[0] |= 0xa000; /* ERR | CERR */
1232            s->xmit_pos = -1;
1233            goto txdone;
1234        }
1235
1236        if (s->xmit_pos < 0) {
1237            goto txdone;
1238        }
1239
1240        bcnt = 4096 - GET_FIELD(tmd.length, TMDL, BCNT);
1241
1242        /* if multi-tmd packet outsizes s->buffer then skip it silently.
1243         * Note: this is not what real hw does.
1244         * Last four bytes of s->buffer are used to store CRC FCS code.
1245         */
1246        if (s->xmit_pos + bcnt > sizeof(s->buffer) - 4) {
1247            s->xmit_pos = -1;
1248            goto txdone;
1249        }
1250
1251        s->phys_mem_read(s->dma_opaque, PHYSADDR(s, tmd.tbadr),
1252                         s->buffer + s->xmit_pos, bcnt, CSR_BSWP(s));
1253        s->xmit_pos += bcnt;
1254        
1255        if (!GET_FIELD(tmd.status, TMDS, ENP)) {
1256            goto txdone;
1257        }
1258
1259#ifdef PCNET_DEBUG
1260        printf("pcnet_transmit size=%d\n", s->xmit_pos);
1261#endif
1262        if (CSR_LOOP(s)) {
1263            if (BCR_SWSTYLE(s) == 1)
1264                add_crc = !GET_FIELD(tmd.status, TMDS, NOFCS);
1265            s->looptest = add_crc ? PCNET_LOOPTEST_CRC : PCNET_LOOPTEST_NOCRC;
1266            pcnet_receive(qemu_get_queue(s->nic), s->buffer, s->xmit_pos);
1267            s->looptest = 0;
1268        } else {
1269            if (s->nic) {
1270                qemu_send_packet(qemu_get_queue(s->nic), s->buffer,
1271                                 s->xmit_pos);
1272            }
1273        }
1274
1275        s->csr[0] &= ~0x0008;   /* clear TDMD */
1276        s->csr[4] |= 0x0004;    /* set TXSTRT */
1277        s->xmit_pos = -1;
1278
1279    txdone:
1280        SET_FIELD(&tmd.status, TMDS, OWN, 0);
1281        TMDSTORE(&tmd, PHYSADDR(s,CSR_CXDA(s)));
1282        if (!CSR_TOKINTD(s) || (CSR_LTINTEN(s) && GET_FIELD(tmd.status, TMDS, LTINT)))
1283            s->csr[0] |= 0x0200;    /* set TINT */
1284
1285        if (CSR_XMTRC(s)<=1)
1286            CSR_XMTRC(s) = CSR_XMTRL(s);
1287        else
1288            CSR_XMTRC(s)--;
1289        if (count--)
1290            goto txagain;
1291
1292    } else
1293    if (s->xmit_pos >= 0) {
1294        struct pcnet_TMD tmd;
1295        TMDLOAD(&tmd, xmit_cxda);
1296        SET_FIELD(&tmd.misc, TMDM, BUFF, 1);
1297        SET_FIELD(&tmd.misc, TMDM, UFLO, 1);
1298        SET_FIELD(&tmd.status, TMDS, ERR, 1);
1299        SET_FIELD(&tmd.status, TMDS, OWN, 0);
1300        TMDSTORE(&tmd, xmit_cxda);
1301        s->csr[0] |= 0x0200;    /* set TINT */
1302        if (!CSR_DXSUFLO(s)) {
1303            s->csr[0] &= ~0x0010;
1304        } else
1305        if (count--)
1306          goto txagain;
1307    }
1308
1309    s->tx_busy = 0;
1310}
1311
1312static void pcnet_poll(PCNetState *s)
1313{
1314    if (CSR_RXON(s)) {
1315        pcnet_rdte_poll(s);
1316    }
1317
1318    if (CSR_TDMD(s) ||
1319        (CSR_TXON(s) && !CSR_DPOLL(s) && pcnet_tdte_poll(s)))
1320    {
1321        /* prevent recursion */
1322        if (s->tx_busy)
1323            return;
1324
1325        pcnet_transmit(s);
1326    }
1327}
1328
1329static void pcnet_poll_timer(void *opaque)
1330{
1331    PCNetState *s = opaque;
1332
1333    timer_del(s->poll_timer);
1334
1335    if (CSR_TDMD(s)) {
1336        pcnet_transmit(s);
1337    }
1338
1339    pcnet_update_irq(s);
1340
1341    if (!CSR_STOP(s) && !CSR_SPND(s) && !CSR_DPOLL(s)) {
1342        uint64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) * 33;
1343        if (!s->timer || !now)
1344            s->timer = now;
1345        else {
1346            uint64_t t = now - s->timer + CSR_POLL(s);
1347            if (t > 0xffffLL) {
1348                pcnet_poll(s);
1349                CSR_POLL(s) = CSR_PINT(s);
1350            } else
1351                CSR_POLL(s) = t;
1352        }
1353        timer_mod(s->poll_timer,
1354            pcnet_get_next_poll_time(s,qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL)));
1355    }
1356}
1357
1358
1359static void pcnet_csr_writew(PCNetState *s, uint32_t rap, uint32_t new_value)
1360{
1361    uint16_t val = new_value;
1362#ifdef PCNET_DEBUG_CSR
1363    printf("pcnet_csr_writew rap=%d val=0x%04x\n", rap, val);
1364#endif
1365    switch (rap) {
1366    case 0:
1367        s->csr[0] &= ~(val & 0x7f00); /* Clear any interrupt flags */
1368
1369        s->csr[0] = (s->csr[0] & ~0x0040) | (val & 0x0048);
1370
1371        val = (val & 0x007f) | (s->csr[0] & 0x7f00);
1372
1373        /* IFF STOP, STRT and INIT are set, clear STRT and INIT */
1374        if ((val&7) == 7)
1375          val &= ~3;
1376
1377        if (!CSR_STOP(s) && (val & 4))
1378            pcnet_stop(s);
1379
1380        if (!CSR_INIT(s) && (val & 1))
1381            pcnet_init(s);
1382
1383        if (!CSR_STRT(s) && (val & 2))
1384            pcnet_start(s);
1385
1386        if (CSR_TDMD(s))
1387            pcnet_transmit(s);
1388
1389        return;
1390    case 1:
1391    case 2:
1392    case 8:
1393    case 9:
1394    case 10:
1395    case 11:
1396    case 12:
1397    case 13:
1398    case 14:
1399    case 15:
1400    case 18: /* CRBAL */
1401    case 19: /* CRBAU */
1402    case 20: /* CXBAL */
1403    case 21: /* CXBAU */
1404    case 22: /* NRBAU */
1405    case 23: /* NRBAU */
1406    case 24:
1407    case 25:
1408    case 26:
1409    case 27:
1410    case 28:
1411    case 29:
1412    case 30:
1413    case 31:
1414    case 32:
1415    case 33:
1416    case 34:
1417    case 35:
1418    case 36:
1419    case 37:
1420    case 38:
1421    case 39:
1422    case 40: /* CRBC */
1423    case 41:
1424    case 42: /* CXBC */
1425    case 43:
1426    case 44:
1427    case 45:
1428    case 46: /* POLL */
1429    case 47: /* POLLINT */
1430    case 72:
1431    case 74:
1432    case 76: /* RCVRL */
1433    case 78: /* XMTRL */
1434    case 112:
1435       if (CSR_STOP(s) || CSR_SPND(s))
1436           break;
1437       return;
1438    case 3:
1439        break;
1440    case 4:
1441        s->csr[4] &= ~(val & 0x026a);
1442        val &= ~0x026a; val |= s->csr[4] & 0x026a;
1443        break;
1444    case 5:
1445        s->csr[5] &= ~(val & 0x0a90);
1446        val &= ~0x0a90; val |= s->csr[5] & 0x0a90;
1447        break;
1448    case 16:
1449        pcnet_csr_writew(s,1,val);
1450        return;
1451    case 17:
1452        pcnet_csr_writew(s,2,val);
1453        return;
1454    case 58:
1455        pcnet_bcr_writew(s,BCR_SWS,val);
1456        break;
1457    default:
1458        return;
1459    }
1460    s->csr[rap] = val;
1461}
1462
1463static uint32_t pcnet_csr_readw(PCNetState *s, uint32_t rap)
1464{
1465    uint32_t val;
1466    switch (rap) {
1467    case 0:
1468        pcnet_update_irq(s);
1469        val = s->csr[0];
1470        val |= (val & 0x7800) ? 0x8000 : 0;
1471        break;
1472    case 16:
1473        return pcnet_csr_readw(s,1);
1474    case 17:
1475        return pcnet_csr_readw(s,2);
1476    case 58:
1477        return pcnet_bcr_readw(s,BCR_SWS);
1478    case 88:
1479        val = s->csr[89];
1480        val <<= 16;
1481        val |= s->csr[88];
1482        break;
1483    default:
1484        val = s->csr[rap];
1485    }
1486#ifdef PCNET_DEBUG_CSR
1487    printf("pcnet_csr_readw rap=%d val=0x%04x\n", rap, val);
1488#endif
1489    return val;
1490}
1491
1492static void pcnet_bcr_writew(PCNetState *s, uint32_t rap, uint32_t val)
1493{
1494    rap &= 127;
1495#ifdef PCNET_DEBUG_BCR
1496    printf("pcnet_bcr_writew rap=%d val=0x%04x\n", rap, val);
1497#endif
1498    switch (rap) {
1499    case BCR_SWS:
1500        if (!(CSR_STOP(s) || CSR_SPND(s)))
1501            return;
1502        val &= ~0x0300;
1503        switch (val & 0x00ff) {
1504        case 0:
1505            val |= 0x0200;
1506            break;
1507        case 1:
1508            val |= 0x0100;
1509            break;
1510        case 2:
1511        case 3:
1512            val |= 0x0300;
1513            break;
1514        default:
1515            printf("Bad SWSTYLE=0x%02x\n", val & 0xff);
1516            val = 0x0200;
1517            break;
1518        }
1519#ifdef PCNET_DEBUG
1520       printf("BCR_SWS=0x%04x\n", val);
1521#endif
1522        /* fall through */
1523    case BCR_LNKST:
1524    case BCR_LED1:
1525    case BCR_LED2:
1526    case BCR_LED3:
1527    case BCR_MC:
1528    case BCR_FDC:
1529    case BCR_BSBC:
1530    case BCR_EECAS:
1531    case BCR_PLAT:
1532        s->bcr[rap] = val;
1533        break;
1534    default:
1535        break;
1536    }
1537}
1538
1539uint32_t pcnet_bcr_readw(PCNetState *s, uint32_t rap)
1540{
1541    uint32_t val;
1542    rap &= 127;
1543    switch (rap) {
1544    case BCR_LNKST:
1545    case BCR_LED1:
1546    case BCR_LED2:
1547    case BCR_LED3:
1548        val = s->bcr[rap] & ~0x8000;
1549        val |= (val & 0x017f & s->lnkst) ? 0x8000 : 0;
1550        break;
1551    default:
1552        val = rap < 32 ? s->bcr[rap] : 0;
1553        break;
1554    }
1555#ifdef PCNET_DEBUG_BCR
1556    printf("pcnet_bcr_readw rap=%d val=0x%04x\n", rap, val);
1557#endif
1558    return val;
1559}
1560
1561void pcnet_h_reset(void *opaque)
1562{
1563    PCNetState *s = opaque;
1564
1565    s->bcr[BCR_MSRDA] = 0x0005;
1566    s->bcr[BCR_MSWRA] = 0x0005;
1567    s->bcr[BCR_MC   ] = 0x0002;
1568    s->bcr[BCR_LNKST] = 0x00c0;
1569    s->bcr[BCR_LED1 ] = 0x0084;
1570    s->bcr[BCR_LED2 ] = 0x0088;
1571    s->bcr[BCR_LED3 ] = 0x0090;
1572    s->bcr[BCR_FDC  ] = 0x0000;
1573    s->bcr[BCR_BSBC ] = 0x9001;
1574    s->bcr[BCR_EECAS] = 0x0002;
1575    s->bcr[BCR_SWS  ] = 0x0200;
1576    s->bcr[BCR_PLAT ] = 0xff06;
1577
1578    pcnet_s_reset(s);
1579    pcnet_update_irq(s);
1580    pcnet_poll_timer(s);
1581}
1582
1583void pcnet_ioport_writew(void *opaque, uint32_t addr, uint32_t val)
1584{
1585    PCNetState *s = opaque;
1586    pcnet_poll_timer(s);
1587#ifdef PCNET_DEBUG_IO
1588    printf("pcnet_ioport_writew addr=0x%08x val=0x%04x\n", addr, val);
1589#endif
1590    if (!BCR_DWIO(s)) {
1591        switch (addr & 0x0f) {
1592        case 0x00: /* RDP */
1593            pcnet_csr_writew(s, s->rap, val);
1594            break;
1595        case 0x02:
1596            s->rap = val & 0x7f;
1597            break;
1598        case 0x06:
1599            pcnet_bcr_writew(s, s->rap, val);
1600            break;
1601        }
1602    }
1603    pcnet_update_irq(s);
1604}
1605
1606uint32_t pcnet_ioport_readw(void *opaque, uint32_t addr)
1607{
1608    PCNetState *s = opaque;
1609    uint32_t val = -1;
1610    pcnet_poll_timer(s);
1611    if (!BCR_DWIO(s)) {
1612        switch (addr & 0x0f) {
1613        case 0x00: /* RDP */
1614            val = pcnet_csr_readw(s, s->rap);
1615            break;
1616        case 0x02:
1617            val = s->rap;
1618            break;
1619        case 0x04:
1620            pcnet_s_reset(s);
1621            val = 0;
1622            break;
1623        case 0x06:
1624            val = pcnet_bcr_readw(s, s->rap);
1625            break;
1626        }
1627    }
1628    pcnet_update_irq(s);
1629#ifdef PCNET_DEBUG_IO
1630    printf("pcnet_ioport_readw addr=0x%08x val=0x%04x\n", addr, val & 0xffff);
1631#endif
1632    return val;
1633}
1634
1635void pcnet_ioport_writel(void *opaque, uint32_t addr, uint32_t val)
1636{
1637    PCNetState *s = opaque;
1638    pcnet_poll_timer(s);
1639#ifdef PCNET_DEBUG_IO
1640    printf("pcnet_ioport_writel addr=0x%08x val=0x%08x\n", addr, val);
1641#endif
1642    if (BCR_DWIO(s)) {
1643        switch (addr & 0x0f) {
1644        case 0x00: /* RDP */
1645            pcnet_csr_writew(s, s->rap, val & 0xffff);
1646            break;
1647        case 0x04:
1648            s->rap = val & 0x7f;
1649            break;
1650        case 0x0c:
1651            pcnet_bcr_writew(s, s->rap, val & 0xffff);
1652            break;
1653        }
1654    } else
1655    if ((addr & 0x0f) == 0) {
1656        /* switch device to dword i/o mode */
1657        pcnet_bcr_writew(s, BCR_BSBC, pcnet_bcr_readw(s, BCR_BSBC) | 0x0080);
1658#ifdef PCNET_DEBUG_IO
1659        printf("device switched into dword i/o mode\n");
1660#endif
1661    }
1662    pcnet_update_irq(s);
1663}
1664
1665uint32_t pcnet_ioport_readl(void *opaque, uint32_t addr)
1666{
1667    PCNetState *s = opaque;
1668    uint32_t val = -1;
1669    pcnet_poll_timer(s);
1670    if (BCR_DWIO(s)) {
1671        switch (addr & 0x0f) {
1672        case 0x00: /* RDP */
1673            val = pcnet_csr_readw(s, s->rap);
1674            break;
1675        case 0x04:
1676            val = s->rap;
1677            break;
1678        case 0x08:
1679            pcnet_s_reset(s);
1680            val = 0;
1681            break;
1682        case 0x0c:
1683            val = pcnet_bcr_readw(s, s->rap);
1684            break;
1685        }
1686    }
1687    pcnet_update_irq(s);
1688#ifdef PCNET_DEBUG_IO
1689    printf("pcnet_ioport_readl addr=0x%08x val=0x%08x\n", addr, val);
1690#endif
1691    return val;
1692}
1693
1694static bool is_version_2(void *opaque, int version_id)
1695{
1696    return version_id == 2;
1697}
1698
1699const VMStateDescription vmstate_pcnet = {
1700    .name = "pcnet",
1701    .version_id = 3,
1702    .minimum_version_id = 2,
1703    .fields = (VMStateField[]) {
1704        VMSTATE_INT32(rap, PCNetState),
1705        VMSTATE_INT32(isr, PCNetState),
1706        VMSTATE_INT32(lnkst, PCNetState),
1707        VMSTATE_UINT32(rdra, PCNetState),
1708        VMSTATE_UINT32(tdra, PCNetState),
1709        VMSTATE_BUFFER(prom, PCNetState),
1710        VMSTATE_UINT16_ARRAY(csr, PCNetState, 128),
1711        VMSTATE_UINT16_ARRAY(bcr, PCNetState, 32),
1712        VMSTATE_UINT64(timer, PCNetState),
1713        VMSTATE_INT32(xmit_pos, PCNetState),
1714        VMSTATE_BUFFER(buffer, PCNetState),
1715        VMSTATE_UNUSED_TEST(is_version_2, 4),
1716        VMSTATE_INT32(tx_busy, PCNetState),
1717        VMSTATE_TIMER_PTR(poll_timer, PCNetState),
1718        VMSTATE_END_OF_LIST()
1719    }
1720};
1721
1722void pcnet_common_init(DeviceState *dev, PCNetState *s, NetClientInfo *info)
1723{
1724    int i;
1725    uint16_t checksum;
1726
1727    s->poll_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, pcnet_poll_timer, s);
1728
1729    qemu_macaddr_default_if_unset(&s->conf.macaddr);
1730    s->nic = qemu_new_nic(info, &s->conf, object_get_typename(OBJECT(dev)), dev->id, s);
1731    qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
1732
1733    /* Initialize the PROM */
1734
1735    /*
1736      Datasheet: http://pdfdata.datasheetsite.com/web/24528/AM79C970A.pdf
1737      page 95
1738    */
1739    memcpy(s->prom, s->conf.macaddr.a, 6);
1740    /* Reserved Location: must be 00h */
1741    s->prom[6] = s->prom[7] = 0x00;
1742    /* Reserved Location: must be 00h */
1743    s->prom[8] = 0x00;
1744    /* Hardware ID: must be 11h if compatibility to AMD drivers is desired */
1745    s->prom[9] = 0x11;
1746    /* User programmable space, init with 0 */
1747    s->prom[10] = s->prom[11] = 0x00;
1748    /* LSByte of two-byte checksum, which is the sum of bytes 00h-0Bh
1749       and bytes 0Eh and 0Fh, must therefore be initialized with 0! */
1750    s->prom[12] = s->prom[13] = 0x00;
1751    /* Must be ASCII W (57h) if compatibility to AMD
1752       driver software is desired */
1753    s->prom[14] = s->prom[15] = 0x57;
1754
1755    for (i = 0, checksum = 0; i < 16; i++) {
1756        checksum += s->prom[i];
1757    }
1758    *(uint16_t *)&s->prom[12] = cpu_to_le16(checksum);
1759
1760    s->lnkst = 0x40; /* initial link state: up */
1761}
1762