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