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