ia64/xen-unstable

changeset 16411:ec0bc82cebfd

ioemu: Add e100 NIC support. Req'd for w2k3/IA64.
Signed-off-by: Zhang Xin <xing.z.zhang@intel.com>
author Keir Fraser <keir.fraser@citrix.com>
date Wed Nov 21 09:52:04 2007 +0000 (2007-11-21)
parents ae6f4c7f15cb
children 8c305873f2b8
files tools/ioemu/Makefile.target tools/ioemu/hw/e100.c tools/ioemu/hw/pci.c
line diff
     1.1 --- a/tools/ioemu/Makefile.target	Wed Nov 21 09:49:09 2007 +0000
     1.2 +++ b/tools/ioemu/Makefile.target	Wed Nov 21 09:52:04 2007 +0000
     1.3 @@ -399,7 +399,7 @@ VL_OBJS+= scsi-disk.o cdrom.o lsi53c895a
     1.4  VL_OBJS+= usb.o usb-hub.o usb-linux.o usb-hid.o usb-ohci.o usb-msd.o
     1.5  
     1.6  # PCI network cards
     1.7 -VL_OBJS+= ne2000.o rtl8139.o pcnet.o
     1.8 +VL_OBJS+= ne2000.o rtl8139.o pcnet.o e100.o
     1.9  
    1.10  ifeq ($(TARGET_BASE_ARCH), i386)
    1.11  # Hardware support
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/tools/ioemu/hw/e100.c	Wed Nov 21 09:52:04 2007 +0000
     2.3 @@ -0,0 +1,2464 @@
     2.4 +/*
     2.5 + * QEMU E100(i82557) ethernet card emulation
     2.6 + *
     2.7 + * This program is free software; you can redistribute it and/or modify
     2.8 + * it under the terms of the GNU General Public License as published by
     2.9 + * the Free Software Foundation; either version 2 of the License, or
    2.10 + * (at your option) any later version.
    2.11 + *
    2.12 + * This program is distributed in the hope that it will be useful,
    2.13 + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    2.14 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    2.15 + * GNU General Public License for more details.
    2.16 + *
    2.17 + * You should have received a copy of the GNU General Public License
    2.18 + * along with this program; if not, write to the Free Software
    2.19 + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
    2.20 + *
    2.21 + * Copyright (c) 2006-2007 Stefan Weil
    2.22 + * Copyright (c) 2006-2007 Zhang Xin(xing.z.zhang@intel.com)
    2.23 + *
    2.24 + * Support OS:
    2.25 + *      x86 linux and windows
    2.26 + *      PAE linux and windows
    2.27 + *      x86_64 linux and windows
    2.28 + *      IA64 linux and windows
    2.29 + *
    2.30 + * Untested:
    2.31 + *      Big-endian machine
    2.32 + *
    2.33 + * References:
    2.34 + *
    2.35 + * Intel 8255x 10/100 Mbps Ethernet Controller Family
    2.36 + * Open Source Software Developer Manual
    2.37 + */
    2.38 +
    2.39 +#include <assert.h>
    2.40 +#include "vl.h"
    2.41 +
    2.42 +enum
    2.43 +{
    2.44 +    E100_PCI_VENDOR_ID = 0x00,        /* 16 bits */
    2.45 +    E100_PCI_DEVICE_ID = 0x02,        /* 16 bits */
    2.46 +    E100_PCI_COMMAND = 0x04,        /* 16 bits */
    2.47 +    E100_PCI_STATUS = 0x06,            /* 16 bits */
    2.48 +    E100_PCI_REVISION_ID = 0x08,    /* 8 bits */
    2.49 +    E100_PCI_CLASS_CODE = 0x0b,        /* 8 bits */
    2.50 +    E100_PCI_SUBCLASS_CODE = 0x0a,    /* 8 bits */
    2.51 +    E100_PCI_HEADER_TYPE = 0x0e,    /* 8 bits */
    2.52 +    E100_PCI_BASE_ADDRESS_0 = 0x10,    /* 32 bits */
    2.53 +    E100_PCI_BASE_ADDRESS_1 = 0x14,    /* 32 bits */
    2.54 +    E100_PCI_BASE_ADDRESS_2 = 0x18,    /* 32 bits */
    2.55 +    E100_PCI_BASE_ADDRESS_3 = 0x1c,    /* 32 bits */
    2.56 +    E100_PCI_BASE_ADDRESS_4 = 0x20,    /* 32 bits */
    2.57 +    E100_PCI_BASE_ADDRESS_5 = 0x24    /* 32 bits */
    2.58 +}PCI_CONFIGURE_SPACE;
    2.59 +
    2.60 +#define PCI_CONFIG_8(offset, value) \
    2.61 +    (*(uint8_t *)&pci_conf[offset] = (value))
    2.62 +#define PCI_CONFIG_16(offset, value) \
    2.63 +    (*(uint16_t *)&pci_conf[offset] = cpu_to_le16(value))
    2.64 +#define PCI_CONFIG_32(offset, value) \
    2.65 +    (*(uint32_t *)&pci_conf[offset] = cpu_to_le32(value))
    2.66 +
    2.67 +// Alias for Control/Status register read/write
    2.68 +#define CSR_STATUS  scb_status
    2.69 +#define CSR_CMD scb_cmd
    2.70 +#define CSR_POINTER scb_pointer
    2.71 +#define CSR_PORT port
    2.72 +#define CSR_EEPROM eeprom_ctrl
    2.73 +#define CSR_MDI mdi_ctrl
    2.74 +#define CSR_PM pm_reg
    2.75 +
    2.76 +#define CSR(class, field)   \
    2.77 +    (s->pci_mem.csr.class.u.field)
    2.78 +#define CSR_VAL(class)  \
    2.79 +    (s->pci_mem.csr.class.val)
    2.80 +
    2.81 +#define CSR_READ(x, type)    \
    2.82 +    ({  \
    2.83 +        type t; \
    2.84 +        memcpy(&t, &s->pci_mem.mem[x], sizeof(type)); \
    2.85 +        t;  \
    2.86 +     })
    2.87 +
    2.88 +#define CSR_WRITE(x, val, type)    \
    2.89 +    ({  \
    2.90 +        type t = val; \
    2.91 +        memcpy(&s->pci_mem.mem[x], &t, sizeof(type)); \
    2.92 +     })
    2.93 +
    2.94 +#define SET_CU_STATE(val)    \
    2.95 +    (CSR(CSR_STATUS, cus) = val)
    2.96 +#define GET_CU_STATE    \
    2.97 +    (CSR(CSR_STATUS, cus))
    2.98 +
    2.99 +#define SET_RU_STATE(val)    \
   2.100 +    (CSR(CSR_STATUS, rus) = val)
   2.101 +#define GET_RU_STATE    \
   2.102 +    (CSR(CSR_STATUS, rus))
   2.103 +
   2.104 +#define KiB 1024
   2.105 +
   2.106 +#define EEPROM_SIZE     64
   2.107 +
   2.108 +#define BIT(n) (1U << (n))
   2.109 +
   2.110 +/* debug E100 card */
   2.111 +//#define DEBUG_E100
   2.112 +
   2.113 +#ifdef DEBUG_E100
   2.114 +#define logout(fmt, args...) fprintf(stderr, "EE100\t%-28s" fmt, __func__, ##args)
   2.115 +#else
   2.116 +#define logout(fmt, args...) ((void)0)
   2.117 +#endif
   2.118 +
   2.119 +#define MAX_ETH_FRAME_SIZE 1514
   2.120 +
   2.121 +/* This driver supports several different devices which are declared here. */
   2.122 +#define i82551          0x82551
   2.123 +#define i82557B         0x82557b
   2.124 +#define i82557C         0x82557c
   2.125 +#define i82558B         0x82558b
   2.126 +#define i82559C         0x82559c
   2.127 +#define i82559ER        0x82559e
   2.128 +#define i82562          0x82562
   2.129 +
   2.130 +#define PCI_MEM_SIZE            (4 * KiB)
   2.131 +#define PCI_IO_SIZE             (64)
   2.132 +#define PCI_FLASH_SIZE          (128 * KiB)
   2.133 +
   2.134 +enum
   2.135 +{
   2.136 +    OP_READ,
   2.137 +    OP_WRITE,
   2.138 +} OPERTAION_DIRECTION;
   2.139 +
   2.140 +/* The SCB accepts the following controls for the Tx and Rx units: */
   2.141 +enum
   2.142 +{
   2.143 +    CU_NOP = 0x0000,        /* No operation */
   2.144 +    CU_START = 0x0010,        /* CU start     */
   2.145 +    CU_RESUME = 0x0020,        /* CU resume    */
   2.146 +    CU_STATSADDR = 0x0040,    /* Load dump counters address */
   2.147 +    CU_SHOWSTATS = 0x0050,    /* Dump statistical counters */
   2.148 +    CU_CMD_BASE = 0x0060,    /* Load CU base address */
   2.149 +    CU_DUMPSTATS = 0x0070,    /* Dump and reset statistical counters */
   2.150 +    CU_S_RESUME = 0x00a0    /* CU static resume */
   2.151 +}CONTROL_UNIT_COMMAND;
   2.152 +
   2.153 +enum
   2.154 +{
   2.155 +    RU_NOP = 0x0000,
   2.156 +    RU_START = 0x0001,
   2.157 +    RU_RESUME = 0x0002,
   2.158 +    RU_DMA_REDIRECT = 0x0003,
   2.159 +    RU_ABORT = 0x0004,
   2.160 +    RU_LOAD_HDS = 0x0005,
   2.161 +    RU_ADDR_LOAD = 0x0006,
   2.162 +    RU_RESUMENR = 0x0007,
   2.163 +}RECEIVE_UNIT_COMMAND;
   2.164 +
   2.165 +/* SCB status word descriptions */
   2.166 +enum
   2.167 +{
   2.168 +    CU_IDLE = 0,
   2.169 +    CU_SUSPENDED = 1,
   2.170 +    CU_LPQ_ACTIVE = 2,
   2.171 +    CU_HQP_ACTIVE = 3
   2.172 +} CONTROL_UINT_STATE;
   2.173 +
   2.174 +enum
   2.175 +{
   2.176 +    RU_IDLE = 0,
   2.177 +    RU_SUSPENDED = 1,
   2.178 +    RU_NO_RESOURCES =2,
   2.179 +    RU_READY = 4
   2.180 +} RECEIVE_UNIT_STATE;
   2.181 +
   2.182 +enum
   2.183 +{
   2.184 +    PORT_SOFTWARE_RESET = 0,
   2.185 +    PORT_SELF_TEST = 1,
   2.186 +    PORT_SELECTIVE_RESET = 2,
   2.187 +    PORT_DUMP = 3,
   2.188 +    PORT_DUMP_WAKE_UP = 7,
   2.189 +}SCB_PORT_SELECTION_FUNCTION;
   2.190 +
   2.191 +enum
   2.192 +{
   2.193 +    CBL_NOP = 0,
   2.194 +    CBL_IASETUP = 1,
   2.195 +    CBL_CONFIGURE = 2,
   2.196 +    CBL_MULTCAST_ADDR_SETUP = 3,
   2.197 +    CBL_TRANSMIT = 4,
   2.198 +    CBL_LOAD_MICROCODE = 5,
   2.199 +    CBL_DUMP = 6,
   2.200 +    CBL_DIAGNOSE = 7,
   2.201 +}CBL_COMMAND;
   2.202 +
   2.203 +enum
   2.204 +{
   2.205 +    SCB_STATUS = 0,            /* SCB base + 0x00h, RU states + CU states + STAT/ACK */
   2.206 +    SCB_ACK = 1,            /* SCB ack/stat */
   2.207 +    SCB_CMD = 2,            /* RU command + CU command + S bit + M bit */
   2.208 +    SCB_INTERRUPT_MASK = 3, /* Interrupts mask bits */
   2.209 +    SCB_POINTER = 4,        /* SCB general pointer, depending on command type */
   2.210 +    SCB_PORT = 8,            /* SCB port register */
   2.211 +    SCB_EEPROM = 0xe,        /* SCB eeprom control register */
   2.212 +    SCB_MDI =0x10,            /* SCB MDI control register */
   2.213 +} CSR_OFFSETS;
   2.214 +
   2.215 +enum
   2.216 +{
   2.217 +    EEPROM_SK = 0x01,
   2.218 +    EEPROM_CS = 0x02,
   2.219 +    EEPROM_DI = 0x04,
   2.220 +    EEPROM_DO = 0x08,
   2.221 +} EEPROM_CONTROL_REGISTER;
   2.222 +
   2.223 +enum
   2.224 +{
   2.225 +    EEPROM_READ = 0x2,
   2.226 +    EEPROM_WRITE = 0x1,
   2.227 +    EEPROM_ERASE = 0x3,
   2.228 +} EEPROM_OPCODE;
   2.229 +
   2.230 +enum
   2.231 +{
   2.232 +    MDI_WRITE = 0x1,
   2.233 +    MDI_READ = 0x2,
   2.234 +} MDI_OPCODE;
   2.235 +
   2.236 +enum
   2.237 +{
   2.238 +    INT_FCP = BIT(8),
   2.239 +    INT_SWI = BIT(10),
   2.240 +    INT_MDI = BIT(11),
   2.241 +    INT_RNR = BIT(12),
   2.242 +    INT_CNA = BIT(13),
   2.243 +    INT_FR = BIT(14),
   2.244 +    INT_CX_TNO = BIT(15),
   2.245 +} E100_INTERRUPT;
   2.246 +
   2.247 +enum
   2.248 +{
   2.249 +    CSR_MEMORY_BASE,
   2.250 +    CSR_IO_BASE,
   2.251 +    FLASH_MEMORY_BASE,
   2.252 +    REGION_NUM
   2.253 +}E100_PCI_MEMORY_REGION;
   2.254 +
   2.255 +typedef struct {
   2.256 +    uint32_t tx_good_frames,        // Good frames transmitted
   2.257 +             tx_max_collisions,     // Fatal frames -- had max collisions
   2.258 +             tx_late_collisions,    // Fatal frames -- had a late coll.
   2.259 +             tx_underruns,          // Transmit underruns (fatal or re-transmit)
   2.260 +             tx_lost_crs,           // Frames transmitted without CRS
   2.261 +             tx_deferred,           // Deferred transmits
   2.262 +             tx_single_collisions,  // Transmits that had 1 and only 1 coll.
   2.263 +             tx_multiple_collisions,// Transmits that had multiple coll.
   2.264 +             tx_total_collisions,   // Transmits that had 1+ collisions.
   2.265 +
   2.266 +             rx_good_frames,        // Good frames received
   2.267 +             rx_crc_errors,         // Aligned frames that had a CRC error
   2.268 +             rx_alignment_errors,   // Receives that had alignment errors
   2.269 +             rx_resource_errors,    // Good frame dropped due to lack of resources
   2.270 +             rx_overrun_errors,     // Overrun errors - bus was busy
   2.271 +             rx_cdt_errors,         // Received frames that encountered coll.
   2.272 +             rx_short_frame_errors, // Received frames that were to short
   2.273 +
   2.274 +             complete_word;         // A005h indicates dump cmd completion,
   2.275 +                                    // A007h indicates dump and reset cmd completion.
   2.276 +
   2.277 +// TODO: Add specific field for i82558, i82559
   2.278 +} __attribute__ ((packed)) e100_stats_t;
   2.279 +
   2.280 +#define EEPROM_I82557_ADDRBIT 6
   2.281 +/* Below data is dumped from a real I82557 card */
   2.282 +static const uint16_t eeprom_i82557[] =
   2.283 +{
   2.284 +    0x300, 0xe147, 0x2fa4, 0x203, 0x0, 0x201, 0x4701, 0x0, 0x7414, 0x6207,
   2.285 +    0x4082, 0xb, 0x8086, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   2.286 +    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
   2.287 +    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x128, 0x0, 0x0, 0x0, 0x0, 0x0,
   2.288 +    0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0xc374,
   2.289 +};
   2.290 +
   2.291 +static const uint8_t e100_pci_configure[] =
   2.292 +{
   2.293 +    0x86, 0x80, 0x29, 0x12, 0x17, 0x00, 0x90, 0x02, 0x08, 0x00, 0x00, 0x02, 0x10, 0x20, 0x00, 0x00,
   2.294 +    0x00, 0x00, 0x10, 0x50, 0x01, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x50, 0x00, 0x00, 0x00, 0x00,
   2.295 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x86, 0x80, 0x0b, 0x00,
   2.296 +    0x00, 0x00, 0xf0, 0xff, 0xdc, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x01, 0x08, 0x38,
   2.297 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.298 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.299 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.300 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.301 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.302 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.303 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.304 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.305 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.306 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x22, 0xfe,
   2.307 +    0x00, 0x40, 0x00, 0x3a, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.308 +    0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
   2.309 +};
   2.310 +
   2.311 +typedef struct
   2.312 +{
   2.313 +#define OPCODE      0xb
   2.314 +#define ADDR        0xc
   2.315 +#define DATA        0xd
   2.316 +#define NOP         0xe
   2.317 +
   2.318 +#define EEPROM_RESET_ALL      0xfe
   2.319 +#define EEPROM_SELECT_RESET   0xff
   2.320 +    uint8_t  start_bit;
   2.321 +    uint8_t  opcode;
   2.322 +    uint8_t  address;
   2.323 +    uint16_t data;  //This must be 16 bit represents a register in eeprom
   2.324 +
   2.325 +    uint32_t val;
   2.326 +    uint32_t val_len;
   2.327 +    uint8_t  val_type;  // What data type is in DI. opcode?address?data?
   2.328 +
   2.329 +    uint8_t cs;
   2.330 +    uint8_t sk;
   2.331 +
   2.332 +    // This two fileds only be reset when device init
   2.333 +    uint16_t addr_len;
   2.334 +    uint16_t contents[256]; // 256 is enough to all device(i82557 ... i82559)
   2.335 +} eeprom_t;
   2.336 +
   2.337 +// Control/Status register structure
   2.338 +typedef struct
   2.339 +{
   2.340 +    /* SCB status word */
   2.341 +    union
   2.342 +    {
   2.343 +        uint16_t val;
   2.344 +        struct
   2.345 +        {
   2.346 +            uint8_t rs1:2;  // Reserved
   2.347 +            uint8_t rus:4;  // RU status
   2.348 +            uint8_t cus:2;  // CU status
   2.349 +            uint8_t stat_ack; // Stat/ACK
   2.350 +        }u;
   2.351 +    }scb_status;
   2.352 +
   2.353 +    /* SCB command word */
   2.354 +    union
   2.355 +    {
   2.356 +        uint16_t val;
   2.357 +        struct
   2.358 +        {
   2.359 +            uint8_t ru_cmd:3;   // RU command
   2.360 +            uint8_t rs1:1;      // Reserved
   2.361 +            uint8_t cu_cmd:4;   // CU command
   2.362 +            uint8_t m:1;        // Interrup mask bit(1:mask all interrupt)
   2.363 +            uint8_t si:1;       // Use for software cause interrupt
   2.364 +            uint8_t simb:6;     // Specific interrupt mask bit
   2.365 +        }u;
   2.366 +    }scb_cmd;
   2.367 +
   2.368 +    /* SCB general pointer */
   2.369 +    union
   2.370 +    {
   2.371 +        uint32_t val;
   2.372 +        struct
   2.373 +        {
   2.374 +            uint32_t scb_ptr;
   2.375 +        }u;
   2.376 +    }scb_pointer;
   2.377 +
   2.378 +    /* Port interface */
   2.379 +    union
   2.380 +    {
   2.381 +        uint32_t val;
   2.382 +        struct
   2.383 +        {
   2.384 +            uint8_t opcode:4;   // Op code for function selection
   2.385 +            uint32_t ptr:28;    // Result pointer
   2.386 +        }u;
   2.387 +    }port;
   2.388 +
   2.389 +    uint16_t rs1;               // Reserved
   2.390 +
   2.391 +    /* EEPROM control register */
   2.392 +    union
   2.393 +    {
   2.394 +        uint16_t val;
   2.395 +        struct
   2.396 +        {
   2.397 +            uint8_t eesk:1;      // Serial clock
   2.398 +            uint8_t eecs:1;      // Chip select
   2.399 +            uint8_t eedi:1;      // Serial data in
   2.400 +            uint8_t eedo:1;      // Serial data out
   2.401 +            uint8_t rs1:4;       // Reserved
   2.402 +            uint8_t data;
   2.403 +        }u;
   2.404 +    }eeprom_ctrl;
   2.405 +
   2.406 +    /* MDI control register */
   2.407 +    union
   2.408 +    {
   2.409 +        uint32_t val;
   2.410 +        struct
   2.411 +        {
   2.412 +            uint16_t data;       // Data
   2.413 +            uint8_t regaddr:5;   // PHY register address
   2.414 +            uint8_t phyaddr:5;   // PHY address
   2.415 +            uint8_t opcode:2;    // Opcode
   2.416 +            uint8_t r:1;         // Ready
   2.417 +            uint8_t ie:1;        // Interrup enable
   2.418 +            uint8_t rs1:2;       // Reserved
   2.419 +        }u;
   2.420 +    } mdi_ctrl;
   2.421 +
   2.422 +    /* Receive byte counter register */
   2.423 +    uint32_t rx_byte_counter;
   2.424 +
   2.425 +    /* Early receive interrupt register */
   2.426 +    uint8_t early_interrupt;
   2.427 +
   2.428 +    /* Flow control register */
   2.429 +    union
   2.430 +    {
   2.431 +        uint16_t val;
   2.432 +    }flow_ctrl;
   2.433 +
   2.434 +    /* Power management driver register */
   2.435 +    union
   2.436 +    {
   2.437 +        uint8_t val;
   2.438 +        struct
   2.439 +        {
   2.440 +            uint8_t pme_s:1;     // PME status
   2.441 +            uint8_t tco_r:1;     // TCO request
   2.442 +            uint8_t f_tco_i:1;   // Force TCO indication
   2.443 +            uint8_t tco_re:1;    // TCO ready
   2.444 +            uint8_t rs1:1;       // Reserved
   2.445 +            uint8_t isp:1;       // Intersting packet
   2.446 +            uint8_t mg:1;        // Magic packet
   2.447 +            uint8_t lsci:1;      // Link status change indication
   2.448 +        }u;
   2.449 +    }pm_reg;
   2.450 +
   2.451 +    /* General control register */
   2.452 +    uint8_t gen_ctrl;
   2.453 +
   2.454 +    /* General status register */
   2.455 +    uint8_t gen_status;
   2.456 +
   2.457 +    /* These are reserved or we don't support register */
   2.458 +    uint8_t others[30];
   2.459 +} __attribute__ ((packed)) csr_t;
   2.460 +
   2.461 +typedef struct
   2.462 +{
   2.463 +    uint8_t byte_count;
   2.464 +    uint8_t rx_fifo_limit:4;
   2.465 +    uint8_t tx_fifo_limit:4;
   2.466 +    uint8_t adpt_inf_spacing;
   2.467 +    uint8_t rs1;
   2.468 +    uint8_t rx_dma_max_bytes;
   2.469 +    uint8_t tx_dma_max_bytes:7;
   2.470 +    uint8_t dmbc_en:1;
   2.471 +    uint8_t late_scb:1,
   2.472 +            rs2:1,
   2.473 +            tno_intr:1,
   2.474 +            ci_intr:1,
   2.475 +            rs3:1,
   2.476 +            rs4:1,
   2.477 +            dis_overrun_rx:1,
   2.478 +            save_bad_frame:1;
   2.479 +    uint8_t dis_short_rx:1,
   2.480 +            underrun_retry:2,
   2.481 +            rs5:5;
   2.482 +    uint8_t mii:1,
   2.483 +            rs6:7;
   2.484 +    uint8_t rs7;
   2.485 +    uint8_t rs8:3,
   2.486 +            nsai:1,
   2.487 +            preamble_len:2,
   2.488 +            loopback:2;
   2.489 +    uint8_t linear_prio:3,
   2.490 +            rs9:5;
   2.491 +    uint8_t pri_mode:1,
   2.492 +            rs10:3,
   2.493 +            interframe_spacing:4;
   2.494 +    uint16_t rs11;
   2.495 +    uint8_t promiscuous:1,
   2.496 +            broadcast_dis:1,
   2.497 +            rs12:5,
   2.498 +            crs_cdt:1;
   2.499 +    uint16_t rs13;
   2.500 +    uint8_t strip:1,
   2.501 +            padding:1,
   2.502 +            rx_crc:1,
   2.503 +            rs14:5;
   2.504 +    uint8_t rs15:6,
   2.505 +            force_fdx:1,
   2.506 +            fdx_en:1;
   2.507 +    uint8_t rs16:6,
   2.508 +            mul_ia:2;
   2.509 +    uint8_t rs17:3,
   2.510 +            mul_all:1,
   2.511 +            rs18:4;
   2.512 +} __attribute__ ((packed)) i82557_cfg_t;
   2.513 +
   2.514 +typedef struct {
   2.515 +    VLANClientState *vc;
   2.516 +    PCIDevice *pci_dev;
   2.517 +    int mmio_index;
   2.518 +    uint8_t scb_stat;           /* SCB stat/ack byte */
   2.519 +    uint32_t region_base_addr[REGION_NUM];         /* PCI region addresses */
   2.520 +    uint8_t macaddr[6];
   2.521 +    uint16_t mdimem[32];
   2.522 +    eeprom_t eeprom;
   2.523 +    uint32_t device;            /* device variant */
   2.524 +
   2.525 +    uint8_t mult_list[8];       /* Multicast address list */
   2.526 +    int is_multcast_enable;
   2.527 +
   2.528 +    /* (cu_base + cu_offset) address the next command block in the command block list. */
   2.529 +    uint32_t cu_base;           /* CU base address */
   2.530 +    uint32_t cu_offset;         /* CU address offset */
   2.531 +    uint32_t cu_next;           /* Point to next command when CU go to suspend */
   2.532 +
   2.533 +    /* (ru_base + ru_offset) address the RFD in the Receive Frame Area. */
   2.534 +    uint32_t ru_base;           /* RU base address */
   2.535 +    uint32_t ru_offset;         /* RU address offset */
   2.536 +
   2.537 +    uint32_t statsaddr;         /* pointer to e100_stats_t */
   2.538 +
   2.539 +    e100_stats_t statistics;        /* statistical counters */
   2.540 +
   2.541 +    /* Configuration bytes. */
   2.542 +    i82557_cfg_t config;
   2.543 +
   2.544 +    /* FIFO buffer of card. The packet that need to be sent buffered in it */
   2.545 +    uint8_t pkt_buf[MAX_ETH_FRAME_SIZE+4];
   2.546 +    /* Data length in FIFO buffer */
   2.547 +    int pkt_buf_len;
   2.548 +
   2.549 +    /* Data in mem is always in the byte order of the controller (le). */
   2.550 +    union
   2.551 +    {
   2.552 +        csr_t csr;
   2.553 +        uint8_t mem[PCI_MEM_SIZE];
   2.554 +    }pci_mem;
   2.555 +
   2.556 +} E100State;
   2.557 +
   2.558 +/* CB structure, filled by device driver
   2.559 + * This is a common structure of CB. In some
   2.560 + * special case such as TRANSMIT command, the
   2.561 + * reserved field will be used.
   2.562 + */
   2.563 +struct  control_block
   2.564 +{
   2.565 +    uint16_t rs1:13;            /* reserved */
   2.566 +    uint8_t ok:1;               /* 1:command executed without error, otherwise 0 */
   2.567 +    uint8_t rs2:1;
   2.568 +    uint8_t c:1;                /* execution status. set by device, clean by software */
   2.569 +    uint8_t cmd:3;              /* command */
   2.570 +    uint16_t rs3:10;            /* most time equal to 0 */
   2.571 +    uint8_t i:1;                /* whether trigger interrupt after execution. 1:yes; 0:no */
   2.572 +    uint8_t s:1;                /* suspend */
   2.573 +    uint8_t el:1;               /* end flag */
   2.574 +    uint32_t link_addr;
   2.575 +} __attribute__ ((packed));
   2.576 +
   2.577 +typedef struct
   2.578 +{
   2.579 +    uint32_t tx_desc_addr;      /* transmit buffer decsriptor array address. */
   2.580 +    uint16_t tcb_bytes:14;         /* transmit command block byte count (in lower 14 bits)*/
   2.581 +    uint8_t rs1:1;
   2.582 +    uint8_t eof:1;
   2.583 +    uint8_t tx_threshold;       /* transmit threshold */
   2.584 +    uint8_t tbd_num;          /* TBD number */
   2.585 +} __attribute__ ((packed)) tbd_t;
   2.586 +
   2.587 +/* Receive frame descriptore structure */
   2.588 +typedef struct
   2.589 +{
   2.590 +    uint16_t status:13;     // Result of receive opration
   2.591 +    uint8_t ok:1;           // 1:receive without error, otherwise 0
   2.592 +    uint8_t rs1:1;
   2.593 +    uint8_t c:1;            // 1:receive complete
   2.594 +    uint8_t rs2:3;
   2.595 +    uint8_t sf:1;           // 0:simplified mode
   2.596 +    uint8_t h:1;            // 1:header RFD
   2.597 +    uint16_t rs3:9;
   2.598 +    uint8_t s:1;            // 1:go to suspend
   2.599 +    uint8_t el:1;           // 1:last RFD
   2.600 +    uint32_t link_addr;     // Add on RU base point to next RFD
   2.601 +    uint32_t rs4;
   2.602 +    uint16_t count:14;      // Number of bytes written into data area
   2.603 +    uint8_t f:1;            // Set by device when count field update
   2.604 +    uint8_t eof:1;          // Set by device when placing data into data area complete
   2.605 +    uint16_t size:14;       // Buffer size (even number)
   2.606 +    uint8_t rs5:2;
   2.607 +} __attribute__ ((packed)) rfd_t;
   2.608 +
   2.609 +enum
   2.610 +{
   2.611 +    RX_COLLISION = BIT(0),  // 1:Receive collision detected
   2.612 +    RX_IA_MATCH = BIT(1),      // 0:Receive frame match individual address
   2.613 +    RX_NO_MATCH = BIT(2), // 1:Receive frame match no address
   2.614 +    RX_ERR = BIT(4),        // 1:Receive frame error
   2.615 +    RX_TYPE = BIT(5),       // 1:Receive frame is a type frame
   2.616 +    RX_SHORT = BIT(7),      // 1:Receive frame is too short
   2.617 +    RX_DMA_ERR = BIT(8),
   2.618 +    RX_LARGE = BIT(9),      // 1:Receive frame is too large
   2.619 +    RX_CRC_ERR = BIT(10),
   2.620 +} RFD_STATUS;
   2.621 +
   2.622 +typedef struct PCIE100State {
   2.623 +    PCIDevice dev;
   2.624 +    E100State e100;
   2.625 +} PCIE100State;
   2.626 +
   2.627 +/* Default values for MDI (PHY) registers */
   2.628 +static const uint16_t e100_mdi_default[] = {
   2.629 +    /* MDI Registers 0 - 6, 7 */
   2.630 +    0x3000, 0x780d, 0x02a8, 0x0154, 0x05e1, 0x0000, 0x0000, 0x0000,
   2.631 +    /* MDI Registers 8 - 15 */
   2.632 +    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   2.633 +    /* MDI Registers 16 - 31 */
   2.634 +    0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   2.635 +    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
   2.636 +};
   2.637 +
   2.638 +static const uint8_t broadcast_macaddr[6] =
   2.639 +    { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
   2.640 +
   2.641 +/* Debugging codes */
   2.642 +#ifdef  DEBUG_E100
   2.643 +
   2.644 +static void e100_dump(char *comment, uint8_t *info, int len)
   2.645 +{
   2.646 +    int i;
   2.647 +
   2.648 +    if ( !comment || !info )
   2.649 +        return;
   2.650 +
   2.651 +    fprintf(stderr, "EE100\t%-24s%s", __func__, comment);
   2.652 +    for ( i=0; i<len; i++ )
   2.653 +        fprintf(stderr, "%x ", info[i]);
   2.654 +
   2.655 +    fprintf(stderr, "\n");
   2.656 +}
   2.657 +
   2.658 +static const char *regname[] =
   2.659 +{
   2.660 +    [0] = "SCB Status", [1] = "SCB Ack",
   2.661 +    [2] = "SCB Cmd", [3] = "SCB Interrupt Mask",
   2.662 +    [4] = "SCB Pointer", [8] = "SCB Port",
   2.663 +    [0xc] = "SCB Flash", [0xe] = "SCB Eeprom",
   2.664 +    [0x10] = "SCB Ctrl MDI", [0x14] = "SCB Early RX",
   2.665 +};
   2.666 +#define SCBNAME(x)    \
   2.667 +    ( (x) < (sizeof(regname) / sizeof(regname[0])) ? regname[(x)] : "Unknown SCB Register" )
   2.668 +
   2.669 +static const char *cb_cmd_name[] =
   2.670 +{
   2.671 +    [CBL_NOP] = "NOP", [CBL_IASETUP] = "Individual address setup",
   2.672 +    [CBL_CONFIGURE] = "Configure", [CBL_MULTCAST_ADDR_SETUP] = "Set Multcast address list",
   2.673 +    [CBL_TRANSMIT] = "Transmit", [CBL_LOAD_MICROCODE] = "Load microcode",
   2.674 +    [CBL_DUMP] = "Dump", [CBL_DIAGNOSE] = "Diagnose",
   2.675 +};
   2.676 +#define CB_CMD_NAME(x)  \
   2.677 +    ( (x) < (sizeof(cb_cmd_name) / sizeof(cb_cmd_name[0])) ? cb_cmd_name[(x)] : "Unknown CB command" )
   2.678 +
   2.679 +static const char *eeprom_opcode_name[] =
   2.680 +{
   2.681 +    [0] = "Unknow", [EEPROM_WRITE] = "Write",
   2.682 +    [EEPROM_READ] = "Read", [EEPROM_ERASE] = "Erase",
   2.683 +};
   2.684 +#define EEPROM_OPCODE_NAME(x)   \
   2.685 +    ( (x) < (sizeof(eeprom_opcode_name) / sizeof(eeprom_opcode_name[0])) ?  \
   2.686 +      eeprom_opcode_name[(x)] : "Unknown" )
   2.687 +
   2.688 +static struct eeprom_trace_data
   2.689 +{
   2.690 +    uint8_t eedo[256];
   2.691 +    uint8_t di[256];
   2.692 +    int op;
   2.693 +    int i;
   2.694 +    uint32_t data;
   2.695 +}etd = {.op = NOP};
   2.696 +
   2.697 +static void eeprom_trace(int eedo, int di, int dir, int next_op, int clr)
   2.698 +{
   2.699 +    int i;
   2.700 +
   2.701 +    if ( clr )
   2.702 +    {
   2.703 +        char *opname = NULL;
   2.704 +
   2.705 +        switch ( etd.op )
   2.706 +        {
   2.707 +            case NOP:
   2.708 +                break;
   2.709 +            case OPCODE:
   2.710 +                opname = "opcode";
   2.711 +                break;
   2.712 +            case ADDR:
   2.713 +                opname = "address";
   2.714 +                break;
   2.715 +            case DATA:
   2.716 +                opname = "data transfer";
   2.717 +                break;
   2.718 +            default:
   2.719 +                opname = "Unknown";
   2.720 +        }
   2.721 +
   2.722 +        if ( opname )
   2.723 +        {
   2.724 +            logout("EEPROM trace:\n");
   2.725 +            fprintf(stderr, "\toperation: %s\n", opname);
   2.726 +            fprintf(stderr, "\tDI track:");
   2.727 +            for ( i=0; i<etd.i; i++ )
   2.728 +                fprintf(stderr, "%x ", etd.di[i]);
   2.729 +            fprintf(stderr, "\n\tDO track:");
   2.730 +            for ( i=0; i<etd.i; i++ )
   2.731 +                fprintf(stderr, "%x ", etd.eedo[i]);
   2.732 +            fprintf(stderr, "\n\tData:%#x\n", etd.data);
   2.733 +        }
   2.734 +
   2.735 +
   2.736 +        memset(&etd, 0x0, sizeof(etd));
   2.737 +        etd.op = next_op;
   2.738 +
   2.739 +        return;
   2.740 +    }
   2.741 +
   2.742 +    etd.eedo[etd.i] = eedo;
   2.743 +    etd.di[etd.i] = di;
   2.744 +    etd.i ++;
   2.745 +    if ( dir == EEPROM_READ && etd.op == DATA )
   2.746 +        etd.data = (etd.data << 1) | eedo;
   2.747 +    else
   2.748 +        etd.data = (etd.data << 1) | di;
   2.749 +}
   2.750 +
   2.751 +#define INT_NAME(x) \
   2.752 +    ({  \
   2.753 +     char *name = NULL; \
   2.754 +     switch (x) \
   2.755 +     {  \
   2.756 +     case INT_FCP:  \
   2.757 +            name = "FCP";   \
   2.758 +            break;  \
   2.759 +     case INT_SWI:  \
   2.760 +            name = "SWI";   \
   2.761 +            break;  \
   2.762 +     case INT_MDI:  \
   2.763 +            name = "MDI";   \
   2.764 +            break;  \
   2.765 +     case INT_RNR:  \
   2.766 +            name = "RNR";   \
   2.767 +            break;  \
   2.768 +     case INT_CNA:  \
   2.769 +            name = "CNA";   \
   2.770 +            break;  \
   2.771 +     case INT_FR:   \
   2.772 +            name = "FR";    \
   2.773 +            break;  \
   2.774 +     case INT_CX_TNO:   \
   2.775 +            name ="CX/TNO"; \
   2.776 +            break;  \
   2.777 +     default:   \
   2.778 +            name ="Unknown"; \
   2.779 +     }  \
   2.780 +     name;  \
   2.781 +     })
   2.782 +
   2.783 +#else
   2.784 +static void e100_dump(char *comment, uint8_t *info, int len) {}
   2.785 +static void eeprom_trace(int eedo, int di, int dir, int next_op, int clr) {}
   2.786 +#endif
   2.787 +
   2.788 +static void pci_reset(E100State * s)
   2.789 +{
   2.790 +    uint8_t *pci_conf = s->pci_dev->config;
   2.791 +
   2.792 +    memcpy(pci_conf, &e100_pci_configure[0], sizeof(e100_pci_configure));
   2.793 +    logout("%p\n", s);
   2.794 +
   2.795 +    /* I82557 */
   2.796 +    PCI_CONFIG_8(E100_PCI_REVISION_ID, 0x01);
   2.797 +
   2.798 +    PCI_CONFIG_8(0x3c, 0x0);
   2.799 +
   2.800 +}
   2.801 +
   2.802 +static void e100_selective_reset(E100State * s)
   2.803 +{
   2.804 +
   2.805 +    memset(s->pci_mem.mem, 0x0, sizeof(s->pci_mem.mem));
   2.806 +    // Set RU/CU to idle, maintain the register mentioned in spec,
   2.807 +    SET_CU_STATE(CU_IDLE);
   2.808 +    SET_RU_STATE(RU_IDLE);
   2.809 +    logout("CU and RU go to idle\n");
   2.810 +
   2.811 +    s->ru_offset = 0;
   2.812 +    s->cu_offset = 0;
   2.813 +    s->cu_next = 0;
   2.814 +
   2.815 +    // For 82557, special interrupt bits are all 1
   2.816 +    CSR(CSR_CMD, simb) = 0x3f;
   2.817 +    // Set PHY to 1
   2.818 +    CSR_VAL(CSR_MDI) |= BIT(21);
   2.819 +
   2.820 +    /* Initialize EEDO bit to 1. Due to driver would detect dummy 0 at
   2.821 +     * EEDO bit, so initialize it to 1 is safety a way.
   2.822 +     */
   2.823 +    CSR(CSR_EEPROM, eedo) = 1;
   2.824 +    // no pending interrupts
   2.825 +    s->scb_stat = 0;
   2.826 +
   2.827 +    return;
   2.828 +}
   2.829 +
   2.830 +static void e100_software_reset(E100State *s)
   2.831 +{
   2.832 +    memset(s->pci_mem.mem, 0x0, sizeof(s->pci_mem.mem));
   2.833 +    // Clear multicast list
   2.834 +    memset(s->mult_list, 0x0, sizeof(s->mult_list));
   2.835 +    // Set MDI register to default value
   2.836 +    memcpy(&s->mdimem[0], &e100_mdi_default[0], sizeof(s->mdimem));
   2.837 +    s->is_multcast_enable = 1;
   2.838 +    /* Clean FIFO buffer */
   2.839 +    memset(s->pkt_buf, 0x0, sizeof(s->pkt_buf));
   2.840 +    s->pkt_buf_len = 0;
   2.841 +
   2.842 +    memset(&s->statistics, 0x0, sizeof(s->statistics));
   2.843 +    e100_selective_reset(s);
   2.844 +    return;
   2.845 +}
   2.846 +
   2.847 +static void e100_reset(void *opaque)
   2.848 +{
   2.849 +    E100State *s = (E100State *) opaque;
   2.850 +    logout("%p\n", s);
   2.851 +    e100_software_reset(s);
   2.852 +}
   2.853 +
   2.854 +
   2.855 +static void e100_save(QEMUFile * f, void *opaque)
   2.856 +{
   2.857 +    //TODO
   2.858 +    return;
   2.859 +}
   2.860 +
   2.861 +static int e100_load(QEMUFile * f, void *opaque, int version_id)
   2.862 +{
   2.863 +    //TODO
   2.864 +    return 0;
   2.865 +}
   2.866 +
   2.867 +/* Interrupt functions */
   2.868 +static void e100_interrupt(E100State *s, uint16_t int_type)
   2.869 +{
   2.870 +
   2.871 +    //TODO: Add another i8255x card supported mask bit
   2.872 +    if ( !CSR(CSR_CMD,m) )
   2.873 +    {
   2.874 +        //Set bit in stat/ack, so driver can no what interrupt happen
   2.875 +        CSR_VAL(CSR_STATUS) |= int_type;
   2.876 +        s->scb_stat = CSR(CSR_STATUS, stat_ack);
   2.877 +
   2.878 +        /* SCB maske and SCB Bit M do not disable interrupt. */
   2.879 +        logout("Trigger an interrupt(type = %s(%#x), SCB Status = %#x)\n",
   2.880 +                INT_NAME(int_type), int_type, CSR_VAL(CSR_STATUS));
   2.881 +        pci_set_irq(s->pci_dev, 0, 1);
   2.882 +    }
   2.883 +}
   2.884 +
   2.885 +static void e100_interrupt_ack(E100State * s, uint8_t ack)
   2.886 +{
   2.887 +
   2.888 +    /* Ignore acknowledege if driver write 0 to ack or
   2.889 +     * according interrupt bit is not set
   2.890 +     */
   2.891 +    if ( !ack || !(s->scb_stat & ack) )
   2.892 +    {
   2.893 +        logout("Illegal interrupt ack(ack=%#x, SCB Stat/Ack=%#x), ignore it\n",
   2.894 +                ack, s->scb_stat);
   2.895 +        // Due to we do write operation before e100_execute(), so
   2.896 +        // we must restore value of ack field here
   2.897 +        CSR(CSR_STATUS, stat_ack) = s->scb_stat;
   2.898 +        return;
   2.899 +    }
   2.900 +
   2.901 +    s->scb_stat &= ~ack;
   2.902 +    CSR(CSR_STATUS, stat_ack) = s->scb_stat;
   2.903 +
   2.904 +    logout("Interrupt ack(name=%s,val=%#x)\n", INT_NAME(({uint16_t bit = ack<<8;bit;})),ack);
   2.905 +    if ( !s->scb_stat )
   2.906 +    {
   2.907 +        logout("All interrupts are acknowledeged, de-assert interrupt line\n");
   2.908 +        pci_set_irq(s->pci_dev, 0, 0);
   2.909 +    }
   2.910 +}
   2.911 +
   2.912 +static void e100_self_test(uint32_t res_addr)
   2.913 +{
   2.914 +    struct
   2.915 +    {
   2.916 +        uint32_t st_sign;           /* Self Test Signature */
   2.917 +        uint32_t st_result;         /* Self Test Results */
   2.918 +    } test_res;
   2.919 +
   2.920 +    test_res.st_sign = (uint32_t)-1;
   2.921 +    test_res.st_result = 0; // Our self test always success
   2.922 +    cpu_physical_memory_write(res_addr, (uint8_t *)&test_res, sizeof(test_res));
   2.923 +
   2.924 +    logout("Write self test result to %#x\n", res_addr);
   2.925 +}
   2.926 +
   2.927 +static void scb_port_func(E100State *s, uint32_t val, int dir)
   2.928 +{
   2.929 +#define PORT_SELECTION_MASK 0xfU
   2.930 +
   2.931 +    uint32_t sel = val & PORT_SELECTION_MASK;
   2.932 +
   2.933 +    switch ( sel )
   2.934 +    {
   2.935 +        case PORT_SOFTWARE_RESET:
   2.936 +            logout("do PORT_SOFTWARE_RESET!\n");
   2.937 +            e100_software_reset(s);
   2.938 +            break;
   2.939 +        case PORT_SELF_TEST:
   2.940 +            e100_self_test(val & ~PORT_SELECTION_MASK);
   2.941 +            logout("do PORT_SELF_TEST!\n");
   2.942 +            break;
   2.943 +        case PORT_SELECTIVE_RESET:
   2.944 +            logout("do PORT_SELECTIVE_RESET!\n");
   2.945 +            e100_selective_reset(s);
   2.946 +            break;
   2.947 +        case PORT_DUMP:
   2.948 +            logout("do PORT_SOFTWARE_RESET!\n");
   2.949 +            break;
   2.950 +        case PORT_DUMP_WAKE_UP:
   2.951 +            logout("do PORT_SOFTWARE_RESET!\n");
   2.952 +            break;
   2.953 +        default:
   2.954 +            logout("Unkonw SCB port command(selection function = %#x)\n", sel);
   2.955 +    }
   2.956 +}
   2.957 +
   2.958 +static void e100_write_mdi(E100State *s, uint32_t val)
   2.959 +{
   2.960 +    uint32_t ie = (val & 0x20000000) >> 29;
   2.961 +    uint32_t opcode = (val & 0x0c000000) >> 26;
   2.962 +    uint32_t phyaddr = (val & 0x03e00000) >> 21;
   2.963 +    uint32_t regaddr = (val & 0x001f0000) >> 16;
   2.964 +    uint32_t data = val & 0x0000ffff;
   2.965 +
   2.966 +    logout("Write MDI:\n"
   2.967 +           "\topcode:%#x\n"
   2.968 +           "\tphy address:%#x\n"
   2.969 +           "\treg address:%#x\n"
   2.970 +           "\tie:%#x\n"
   2.971 +           "\tdata:%#x\n",
   2.972 +           opcode, phyaddr, regaddr, ie, data);
   2.973 +
   2.974 +    /* We use default value --- PHY1
   2.975 +     * If driver operate on other PHYs, do nothing and
   2.976 +     * deceive it that the operation is finished
   2.977 +     */
   2.978 +    if ( phyaddr != 1 )
   2.979 +    {
   2.980 +        logout("Unsupport PHY address(phy = %#x)\n", phyaddr);
   2.981 +        goto done;
   2.982 +    }
   2.983 +
   2.984 +    // 1: MDI write
   2.985 +    // 2: MDI read
   2.986 +    if ( opcode != MDI_WRITE && opcode != MDI_READ )
   2.987 +    {
   2.988 +        logout("Invalid Opcode(opcode = %#x)\n", opcode);
   2.989 +        return;
   2.990 +    }
   2.991 +
   2.992 +    // Current only support MDI generic registers.
   2.993 +    if ( regaddr > 6 )
   2.994 +    {
   2.995 +        logout("Invalid phy register index( phy register addr = %#x)\n", regaddr);
   2.996 +    }
   2.997 +
   2.998 +    if ( opcode == MDI_WRITE )
   2.999 +    {
  2.1000 +        // MDI write
  2.1001 +        switch ( regaddr )
  2.1002 +        {
  2.1003 +            case 0:    // Control Register
  2.1004 +                if ( data & 0x8000 ) // Reset
  2.1005 +                {
  2.1006 +                    /* Reset status and control registers to default. */
  2.1007 +                    s->mdimem[0] = e100_mdi_default[0];
  2.1008 +                    s->mdimem[1] = e100_mdi_default[1];
  2.1009 +                    data = s->mdimem[regaddr];
  2.1010 +                }
  2.1011 +                else
  2.1012 +                {
  2.1013 +                    /* Restart Auto Configuration = Normal Operation */
  2.1014 +                    data &= ~0x0200;
  2.1015 +                }
  2.1016 +                break;
  2.1017 +            case 1:    // Status Register
  2.1018 +                logout("Invalid write on readonly register(opcode = %#x)\n", opcode);
  2.1019 +                data = s->mdimem[regaddr];
  2.1020 +                break;
  2.1021 +            case 2:
  2.1022 +            case 3:
  2.1023 +            case 4:
  2.1024 +            case 5:
  2.1025 +            case 6:
  2.1026 +                break;
  2.1027 +        }
  2.1028 +        s->mdimem[regaddr] = data;
  2.1029 +        logout("MDI WRITE: reg = %#x, data = %#x\n", regaddr, data);
  2.1030 +    }
  2.1031 +    else if ( opcode == MDI_READ )
  2.1032 +    {
  2.1033 +        // MDI read
  2.1034 +        switch ( regaddr )
  2.1035 +        {
  2.1036 +            case 0: // Control Register
  2.1037 +                if ( data & 0x8000 ) // Reset
  2.1038 +                {
  2.1039 +                    /* Reset status and control registers to default. */
  2.1040 +                    s->mdimem[0] = e100_mdi_default[0];
  2.1041 +                    s->mdimem[1] = e100_mdi_default[1];
  2.1042 +                }
  2.1043 +                break;
  2.1044 +            case 1: // Status Register
  2.1045 +                // Auto Negotiation complete, set sticky bit to 1
  2.1046 +                s->mdimem[regaddr] |= 0x0026;
  2.1047 +                break;
  2.1048 +            case 2: // PHY Identification Register (Word 1)
  2.1049 +            case 3: // PHY Identification Register (Word 2)
  2.1050 +                break;
  2.1051 +            case 5: // Auto-Negotiation Link Partner Ability Register
  2.1052 +                s->mdimem[regaddr] = 0x41fe;
  2.1053 +                break;
  2.1054 +            case 6: // Auto-Negotiation Expansion Register
  2.1055 +                s->mdimem[regaddr] = 0x0001;
  2.1056 +                break;
  2.1057 +        }
  2.1058 +        data = s->mdimem[regaddr];
  2.1059 +        logout("MDI READ: reg = %#x, data = %#x\n", regaddr, data);
  2.1060 +    }
  2.1061 +
  2.1062 +    /* Emulation takes no time to finish MDI transaction.
  2.1063 +     * Set MDI bit in SCB status register. */
  2.1064 +done:
  2.1065 +    val |= BIT(28);
  2.1066 +    val = (val & 0xffff0000) + data;
  2.1067 +    CSR_WRITE(SCB_MDI, val, uint32_t);
  2.1068 +
  2.1069 +    if ( ie )
  2.1070 +        e100_interrupt(s, (uint16_t)INT_MDI);
  2.1071 +}
  2.1072 +
  2.1073 +static void scb_mdi_func(E100State *s, uint32_t val, int dir)
  2.1074 +{
  2.1075 +    if ( dir == OP_READ )
  2.1076 +        // Do nothing, just tell driver we are ready
  2.1077 +        CSR_VAL(CSR_MDI) |= BIT(28);
  2.1078 +    else if ( dir == OP_WRITE )
  2.1079 +        e100_write_mdi(s, val);
  2.1080 +    else
  2.1081 +        logout("Invalid operation direction(dir=%x)\n", dir);
  2.1082 +
  2.1083 +}
  2.1084 +
  2.1085 +static void eeprom_reset(E100State *s, int type)
  2.1086 +{
  2.1087 +    eeprom_t *e = &s->eeprom;
  2.1088 +
  2.1089 +    if ( type == EEPROM_RESET_ALL )
  2.1090 +    {
  2.1091 +        memset(e, 0x0, sizeof(eeprom_t));
  2.1092 +        e->val_type = NOP;
  2.1093 +        logout("EEPROM reset all\n");
  2.1094 +        return;
  2.1095 +    }
  2.1096 +
  2.1097 +    CSR(CSR_EEPROM, eedo) = 1;
  2.1098 +    e->start_bit = 0;
  2.1099 +    e->opcode = 0;
  2.1100 +    e->address = 0;
  2.1101 +    e->data = 0;
  2.1102 +
  2.1103 +    e->val = 0;
  2.1104 +    e->val_len = 0;
  2.1105 +    e->val_type = NOP;
  2.1106 +
  2.1107 +    e->cs = 0;
  2.1108 +    e->sk = 0;
  2.1109 +    logout("EEPROM select reset\n");
  2.1110 +}
  2.1111 +
  2.1112 +static void do_eeprom_op(E100State *s, eeprom_t *e, int cs, int sk, int di, int dir)
  2.1113 +{
  2.1114 +    int assert_cs = (cs == 1 && e->cs == 0);
  2.1115 +    int de_assert_cs = (cs == 0 && e->cs == 1);
  2.1116 +    int de_assert_sk = (sk == 0 && e->sk == 1);
  2.1117 +
  2.1118 +    // Chip select is not be enabled
  2.1119 +    if ( cs == 0 && e->cs == 0 )
  2.1120 +    {
  2.1121 +        logout("Invalid EECS signal\n");
  2.1122 +        return;
  2.1123 +    }
  2.1124 +
  2.1125 +    // update state
  2.1126 +    e->cs = cs;
  2.1127 +    e->sk = sk;
  2.1128 +
  2.1129 +    // Do nothing
  2.1130 +    if ( assert_cs )
  2.1131 +    {
  2.1132 +        logout("EECS assert\n");
  2.1133 +        return;
  2.1134 +    }
  2.1135 +
  2.1136 +    // Complete one command
  2.1137 +    if ( de_assert_cs )
  2.1138 +    {
  2.1139 +        if ( e->val_type == DATA && e->opcode == EEPROM_WRITE )
  2.1140 +        {
  2.1141 +            e->data = e->val;
  2.1142 +            memcpy((void *)((unsigned long)e->contents + e->address),
  2.1143 +                    &e->data, sizeof(e->data));
  2.1144 +            logout("EEPROM write complete(data=%#x)\n", e->data);
  2.1145 +        }
  2.1146 +        eeprom_trace(0,0,0,NOP,1);
  2.1147 +        eeprom_reset(s, EEPROM_SELECT_RESET);
  2.1148 +        logout("EECS de-asserted\n");
  2.1149 +        return;
  2.1150 +    }
  2.1151 +
  2.1152 +    // Chip is selected and serial clock is change, so the operation is vaild
  2.1153 +    if ( cs == 1 && de_assert_sk == 1)
  2.1154 +    {
  2.1155 +        // Set start bit
  2.1156 +        if ( e->start_bit == 0 && di == 1 )
  2.1157 +        {
  2.1158 +             e->start_bit = di;
  2.1159 +             e->val_len = 0;
  2.1160 +             e->val = 0;
  2.1161 +             e->val_type = OPCODE;
  2.1162 +
  2.1163 +             eeprom_trace(0,0,0,OPCODE,1);
  2.1164 +             logout("EEPROM start bit set\n");
  2.1165 +             return;
  2.1166 +        }
  2.1167 +        // Data in DI is vaild
  2.1168 +        else if ( e->start_bit == 1 )
  2.1169 +        {
  2.1170 +            // If current operation is eeprom read, ignore DI
  2.1171 +            if ( !(e->val_type == DATA && e->opcode == EEPROM_READ) )
  2.1172 +            {
  2.1173 +                e->val = (e->val << 1) | di;
  2.1174 +                e->val_len ++;
  2.1175 +            }
  2.1176 +
  2.1177 +            switch ( e->val_type )
  2.1178 +            {
  2.1179 +                // Get the opcode.
  2.1180 +                case OPCODE:
  2.1181 +                    eeprom_trace(CSR(CSR_EEPROM, eedo), di, e->opcode, 0, 0);
  2.1182 +                    if ( e->val_len  == 2 )
  2.1183 +                    {
  2.1184 +                        e->opcode = e->val;
  2.1185 +                        e->val = 0;
  2.1186 +                        e->val_len = 0;
  2.1187 +                        e->val_type = ADDR;
  2.1188 +
  2.1189 +                        eeprom_trace(0,0,0,ADDR,1);
  2.1190 +                        logout("EEPROM get opcode(opcode name=%s,opcode=%#x )\n",
  2.1191 +                                EEPROM_OPCODE_NAME(e->opcode), e->opcode);
  2.1192 +                    }
  2.1193 +                    break;
  2.1194 +                // Get address
  2.1195 +                case ADDR:
  2.1196 +                    eeprom_trace(CSR(CSR_EEPROM, eedo), di, e->opcode, 0, 0);
  2.1197 +                    if ( e->val_len == e->addr_len )
  2.1198 +                    {
  2.1199 +                        e->address = e->val;
  2.1200 +                        e->val = 0;
  2.1201 +                        e->val_len = 0;
  2.1202 +                        e->val_type = DATA;
  2.1203 +
  2.1204 +                        // We prepare data eary for later read operation
  2.1205 +                        if ( e->opcode == EEPROM_READ )
  2.1206 +                        {
  2.1207 +                            memcpy(&e->data, (void *)(e->contents + e->address),
  2.1208 +                                    sizeof(e->data));
  2.1209 +                            logout("EEPROM prepare data to read(addr=%#x,data=%#x)\n", 
  2.1210 +                                    e->address, e->data);
  2.1211 +                        }
  2.1212 +
  2.1213 +                        // Write dummy 0 to response to driver the address is written complete
  2.1214 +                        CSR(CSR_EEPROM, eedo) = 0;
  2.1215 +                        eeprom_trace(0,0,0,DATA,1);
  2.1216 +                        logout("EEPROM get address(addr=%#x)\n", e->address);
  2.1217 +                    }
  2.1218 +                    break;
  2.1219 +                // Only do data out operation
  2.1220 +                case DATA:
  2.1221 +                    if ( e->opcode == EEPROM_READ )
  2.1222 +                    {
  2.1223 +                        // Start from the most significant bit
  2.1224 +                        //uint16_t t = ((e->data & (1<<(sizeof(e->data)*8 - e->val_len - 1))) != 0);
  2.1225 +                        uint16_t t = !!(e->data & (0x8000U >> e->val_len));
  2.1226 +
  2.1227 +                        CSR(CSR_EEPROM, eedo) = t;
  2.1228 +
  2.1229 +                        logout("EEPROM read(reg address=%#x, reg val=%#x, do=%#x, len=%#x)\n", 
  2.1230 +                                e->address, e->data, t, e->val_len);
  2.1231 +
  2.1232 +                        if ( e->val_len > sizeof(e->data)*8 )
  2.1233 +                        {
  2.1234 +                            /* Driver may do more write op to de-assert EESK,
  2.1235 +                             * So we let EEPROM go to idle after a register be
  2.1236 +                             * read complete
  2.1237 +                             */
  2.1238 +                            e->val_type = NOP;
  2.1239 +                            logout("Read complete\n");
  2.1240 +
  2.1241 +                            break;
  2.1242 +                        }
  2.1243 +
  2.1244 +                        e->val_len ++;
  2.1245 +                    }
  2.1246 +                    eeprom_trace(CSR(CSR_EEPROM, eedo), di, e->opcode, 0, 0);
  2.1247 +                    // Do eerpom write when CS de-assert
  2.1248 +                    break;
  2.1249 +                default:
  2.1250 +                    break;
  2.1251 +            }
  2.1252 +        }
  2.1253 +    }
  2.1254 +
  2.1255 +    return;
  2.1256 +}
  2.1257 +
  2.1258 +
  2.1259 +static void scb_eeprom_func(E100State *s, uint32_t val, int dir)
  2.1260 +{
  2.1261 +    int eecs = ((val & EEPROM_CS) != 0);
  2.1262 +    int eesk = ((val & EEPROM_SK) != 0);
  2.1263 +    int eedi = ((val & EEPROM_DI) != 0);
  2.1264 +
  2.1265 +    logout("EEPROM: Old(cs=%#x, sk=%#x), New(cs=%#x, sk=%#x, di=%#x)\n", 
  2.1266 +            s->eeprom.cs, s->eeprom.sk, eecs, eesk, eedi);
  2.1267 +
  2.1268 +    do_eeprom_op(s, &s->eeprom, eecs, eesk, eedi, dir);
  2.1269 +
  2.1270 +    return;
  2.1271 +}
  2.1272 +
  2.1273 +static void e100_ru_command(E100State *s, uint8_t val)
  2.1274 +{
  2.1275 +    switch ( val )
  2.1276 +    {
  2.1277 +        case RU_NOP:
  2.1278 +            /* Will not be here */
  2.1279 +            break;
  2.1280 +        case RU_START:
  2.1281 +            /* RU start */
  2.1282 +
  2.1283 +            SET_RU_STATE(RU_READY);
  2.1284 +            logout("RU is set to ready\n");
  2.1285 +            s->ru_offset = CSR_VAL(CSR_POINTER);
  2.1286 +            logout("RFD offset is at %#x\n", s->ru_offset);
  2.1287 +            break;
  2.1288 +        case RU_RESUME:
  2.1289 +            /* RU Resume */
  2.1290 +            if ( GET_RU_STATE == RU_SUSPENDED )
  2.1291 +                SET_RU_STATE(RU_READY);
  2.1292 +            logout("RU resume to ready\n");
  2.1293 +            break;
  2.1294 +        case RU_ADDR_LOAD:
  2.1295 +            /* Load RU base */
  2.1296 +            s->ru_base = CSR_VAL(CSR_POINTER);
  2.1297 +            logout("Load RU base address at %#x\n", s->ru_base);
  2.1298 +            break;
  2.1299 +        case RU_DMA_REDIRECT:
  2.1300 +            logout("RU DMA redirect not implemented\n");
  2.1301 +            break;
  2.1302 +        case RU_ABORT:
  2.1303 +            e100_interrupt(s, INT_RNR);
  2.1304 +            SET_RU_STATE(RU_IDLE);
  2.1305 +            logout("RU abort, go to idle\n");
  2.1306 +            break;
  2.1307 +        case RU_LOAD_HDS:
  2.1308 +            logout("RU load header data size(HDS) not implemented\n");
  2.1309 +        default:
  2.1310 +            break;
  2.1311 +    }
  2.1312 +}
  2.1313 +
  2.1314 +// This function will change CU's state, so CU start and
  2.1315 +// CU resume must set CU's state before it
  2.1316 +static void e100_execute_cb_list(E100State *s, int is_resume)
  2.1317 +{
  2.1318 +
  2.1319 +    struct control_block cb = {0};
  2.1320 +    uint32_t cb_addr;
  2.1321 +
  2.1322 +    if ( !is_resume )
  2.1323 +        s->cu_offset = CSR_VAL(CSR_POINTER);
  2.1324 +
  2.1325 +    /* If call from CU resume, cu_offset has been set */
  2.1326 +
  2.1327 +    while (1)
  2.1328 +    {
  2.1329 +        cb_addr = s->cu_base + s->cu_offset;
  2.1330 +        cpu_physical_memory_read(cb_addr, (uint8_t *)&cb, sizeof(cb));
  2.1331 +
  2.1332 +
  2.1333 +        switch ( cb.cmd )
  2.1334 +        {
  2.1335 +            case CBL_NOP:
  2.1336 +                /* Do nothing */
  2.1337 +                break;
  2.1338 +            case CBL_IASETUP:
  2.1339 +                cpu_physical_memory_read(cb_addr + 8, &s->macaddr[0], sizeof(s->macaddr));
  2.1340 +                e100_dump("Setup Individual Address:", &s->macaddr[0], 6);
  2.1341 +                break;
  2.1342 +            case CBL_CONFIGURE:
  2.1343 +                {
  2.1344 +                    i82557_cfg_t *cfg = &s->config;
  2.1345 +
  2.1346 +                    assert(sizeof(s->config) == 22);
  2.1347 +                    cpu_physical_memory_read(cb_addr + 8, (uint8_t *)cfg, sizeof(s->config));
  2.1348 +                    logout("Setup card configuration:"
  2.1349 +                            "\tbyte count:%d\n"
  2.1350 +                            "\tRx FIFO limit:%d\n"
  2.1351 +                            "\tTx FIFO limit:%d\n"
  2.1352 +                            "\tAdaptive interframe spacing:%d\n"
  2.1353 +                            "\tRx DMA max:%d\n"
  2.1354 +                            "\tTX DMA max:%d\n"
  2.1355 +                            "\tDMBC enable:%d\n"
  2.1356 +                            "\tLate SCB:%d\n"
  2.1357 +                            "\tTNO:%d\n"
  2.1358 +                            "\tCI:%d\n"
  2.1359 +                            "\tDiscard overrun RX:%d\n"
  2.1360 +                            "\tSave bad frame:%d\n"
  2.1361 +                            "\tDiscard short RX:%d\n"
  2.1362 +                            "\tunderrun retry:%d\n"
  2.1363 +                            "\tMII:%d\n"
  2.1364 +                            "\tNSAI:%d\n"
  2.1365 +                            "\tPreamble len:%d\n"
  2.1366 +                            "\tloopback:%d\n"
  2.1367 +                            "\tliner pro:%d\n"
  2.1368 +                            "\tPRI mode:%d\n"
  2.1369 +                            "\tinterframe spacing:%d\n"
  2.1370 +                            "\tpromiscuous:%d\n"
  2.1371 +                            "\tbroadcast dis:%d\n"
  2.1372 +                            "\tCRS CDT:%d\n"
  2.1373 +                            "\tstripping:%d\n"
  2.1374 +                            "\tpadding:%d\n"
  2.1375 +                            "\tRX crc:%d\n"
  2.1376 +                            "\tforce fdx:%d\n"
  2.1377 +                            "\tfdx enable:%d\n"
  2.1378 +                            "\tmultiple IA:%d\n"
  2.1379 +                            "\tmulticast all:%d\n",
  2.1380 +                        cfg->byte_count, cfg->rx_fifo_limit, cfg->tx_fifo_limit,
  2.1381 +                        cfg->adpt_inf_spacing, cfg->rx_dma_max_bytes, cfg->tx_dma_max_bytes,
  2.1382 +                        cfg->dmbc_en, cfg->late_scb, cfg->tno_intr, cfg->ci_intr,
  2.1383 +                        cfg->dis_overrun_rx, cfg->save_bad_frame, cfg->dis_short_rx,
  2.1384 +                        cfg->underrun_retry, cfg->mii, cfg->nsai, cfg->preamble_len,
  2.1385 +                        cfg->loopback, cfg->linear_prio, cfg->pri_mode, cfg->interframe_spacing,
  2.1386 +                        cfg->promiscuous, cfg->broadcast_dis, cfg->crs_cdt, cfg->strip,
  2.1387 +                        cfg->padding, cfg->rx_crc, cfg->force_fdx, cfg->fdx_en,
  2.1388 +                        cfg->mul_ia, cfg->mul_all);
  2.1389 +                }
  2.1390 +                break;
  2.1391 +            case CBL_MULTCAST_ADDR_SETUP:
  2.1392 +                {
  2.1393 +                    uint16_t mult_list_count = 0;
  2.1394 +                    uint16_t size = 0;
  2.1395 +
  2.1396 +                    cpu_physical_memory_read(cb_addr + 8, (uint8_t *)&mult_list_count, 2);
  2.1397 +                    mult_list_count = (mult_list_count << 2) >> 2;
  2.1398 +
  2.1399 +                    if ( !mult_list_count )
  2.1400 +                    {
  2.1401 +                        logout("Multcast disabled(multicast count=0)\n");
  2.1402 +                        s->is_multcast_enable = 0;
  2.1403 +                        memset(s->mult_list, 0x0, sizeof(s->mult_list));
  2.1404 +                        break;
  2.1405 +                    }
  2.1406 +                    size = mult_list_count > sizeof(s->mult_list) ?
  2.1407 +                        sizeof(s->mult_list) : mult_list_count;
  2.1408 +                    cpu_physical_memory_read(cb_addr + 12, &s->mult_list[0], size);
  2.1409 +
  2.1410 +                    e100_dump("Setup Multicast list: ", &s->mult_list[0], size);
  2.1411 +                    break;
  2.1412 +                }
  2.1413 +            case CBL_TRANSMIT:
  2.1414 +                {
  2.1415 +                    struct
  2.1416 +                    {
  2.1417 +                        struct control_block cb;
  2.1418 +                        tbd_t tbd;
  2.1419 +                    } __attribute__ ((packed)) tx;
  2.1420 +
  2.1421 +                    struct
  2.1422 +                    {
  2.1423 +                        uint32_t addr;
  2.1424 +                        uint16_t size;
  2.1425 +                        uint16_t is_el_set;
  2.1426 +                    } tx_buf = {0};
  2.1427 +
  2.1428 +                    uint32_t tbd_array;
  2.1429 +                    uint16_t tcb_bytes;
  2.1430 +                    uint8_t sf;
  2.1431 +                    int len = s->pkt_buf_len;
  2.1432 +
  2.1433 +                    assert( len < sizeof(s->pkt_buf));
  2.1434 +
  2.1435 +                    cpu_physical_memory_read(cb_addr, (uint8_t *)&tx, sizeof(tx));
  2.1436 +                    tbd_array = le32_to_cpu(tx.tbd.tx_desc_addr);
  2.1437 +                    tcb_bytes = le16_to_cpu(tx.tbd.tcb_bytes);
  2.1438 +                    // Indicate use what mode to transmit(simple or flexible)
  2.1439 +                    sf = tx.cb.rs3 & 0x1;
  2.1440 +
  2.1441 +                    logout("Get a TBD:\n"
  2.1442 +                            "\tTBD array address:%#x\n"
  2.1443 +                            "\tTCB byte count:%#x\n"
  2.1444 +                            "\tEOF:%#x\n"
  2.1445 +                            "\tTransmit Threshold:%#x\n"
  2.1446 +                            "\tTBD number:%#x\n"
  2.1447 +                            "\tUse %s mode to send frame\n",
  2.1448 +                            tbd_array, tcb_bytes, tx.tbd.eof,
  2.1449 +                            tx.tbd.tx_threshold, tx.tbd.tbd_num,
  2.1450 +                            sf ? "Flexible" : "Simple");
  2.1451 +
  2.1452 +                    if ( !sf || tbd_array == (uint32_t)-1 )
  2.1453 +                    {
  2.1454 +                        /* Simple mode */
  2.1455 +
  2.1456 +                        /* For simple mode, TCB bytes should not be zero.
  2.1457 +                         * But we still check here for safety
  2.1458 +                         */
  2.1459 +                        if ( !tcb_bytes || tcb_bytes > sizeof(s->pkt_buf) )
  2.1460 +                            break;
  2.1461 +
  2.1462 +                        cpu_physical_memory_read(cb_addr+16, &s->pkt_buf[0], tcb_bytes);
  2.1463 +                        len = tcb_bytes;
  2.1464 +                        logout("simple mode(size=%d)\n", len);
  2.1465 +
  2.1466 +                    }
  2.1467 +                    else
  2.1468 +                    {
  2.1469 +                        /* Flexible mode */
  2.1470 +
  2.1471 +                        /* For flexible mode, TBD num should not be zero.
  2.1472 +                         * But we still check here for safety
  2.1473 +                         */
  2.1474 +                        if ( !tx.tbd.tbd_num )
  2.1475 +                            break;
  2.1476 +
  2.1477 +                        // I82557 don't support extend TCB
  2.1478 +                        if ( s->device == i82557C || s->device == i82557B )
  2.1479 +                        {
  2.1480 +                            /* Standard TCB mode */
  2.1481 +
  2.1482 +                            int i;
  2.1483 +
  2.1484 +                            for ( i=0; i<tx.tbd.tbd_num; i++ )
  2.1485 +                            {
  2.1486 +
  2.1487 +                                cpu_physical_memory_read(tbd_array, (uint8_t *)&tx_buf,
  2.1488 +                                        sizeof(tx_buf));
  2.1489 +                                tx_buf.is_el_set &= 0x1;
  2.1490 +                                tx_buf.size &= 0x7fff;
  2.1491 +                                tbd_array += 8;
  2.1492 +
  2.1493 +                                if ( tx_buf.size > sizeof(s->pkt_buf) - len )
  2.1494 +                                {
  2.1495 +                                    logout("Warning: Get a too big TBD, ignore it"
  2.1496 +                                            "(buf addr %#x, size %d, el:%#x)\n",
  2.1497 +                                            tx_buf.addr, tx_buf.size, tx_buf.is_el_set);
  2.1498 +                                    continue;
  2.1499 +                                }
  2.1500 +
  2.1501 +                                cpu_physical_memory_read(tx_buf.addr, &s->pkt_buf[len],
  2.1502 +                                        tx_buf.size);
  2.1503 +
  2.1504 +                                logout("TBD (standard mode): buf addr %#x, size %d, el:%#x\n",
  2.1505 +                                        tx_buf.addr, tx_buf.size, tx_buf.is_el_set);
  2.1506 +                                len += tx_buf.size;
  2.1507 +
  2.1508 +                                if ( tx_buf.is_el_set )
  2.1509 +                                    break;
  2.1510 +                            }
  2.1511 +
  2.1512 +                        }
  2.1513 +                        //FIXME: Extend mode is not be tested
  2.1514 +                        else
  2.1515 +                        {
  2.1516 +                            /* Extend TCB mode */
  2.1517 +
  2.1518 +                            /* A strandard TCB followed by two TBDs */
  2.1519 +                            uint32_t tbd_addr = cb_addr+16;
  2.1520 +                            int i = 0;
  2.1521 +
  2.1522 +
  2.1523 +                            for ( ; i<2 && i<tx.tbd.tbd_num; i++ )
  2.1524 +                            {
  2.1525 +
  2.1526 +                                cpu_physical_memory_read(tbd_array, (uint8_t *)&tx_buf,
  2.1527 +                                        sizeof(tx_buf));
  2.1528 +                                tx_buf.is_el_set &= 0x1;
  2.1529 +                                tbd_addr += 8;
  2.1530 +
  2.1531 +                                /* From Intel's spec, size of TBD equal to zero
  2.1532 +                                 * has same effect with EL bit set
  2.1533 +                                 */
  2.1534 +                                if ( tx_buf.size == 0 )
  2.1535 +                                {
  2.1536 +                                    tx_buf.is_el_set = 1;
  2.1537 +                                    break;
  2.1538 +                                }
  2.1539 +
  2.1540 +                                if ( tx_buf.size + len > sizeof(s->pkt_buf) )
  2.1541 +                                {
  2.1542 +                                    logout("TX frame is too large, discarding it"
  2.1543 +                                            "(buf addr=%#x, size=%#x)\n", tx_buf.addr,
  2.1544 +                                            tx_buf.size);
  2.1545 +                                    //continue;
  2.1546 +                                    break;
  2.1547 +                                }
  2.1548 +
  2.1549 +                                logout("TBD (extended mode): buf addr %#08x, size %#04x, el:%#x\n",
  2.1550 +                                        tx_buf.addr, tx_buf.size, tx_buf.is_el_set);
  2.1551 +                                cpu_physical_memory_read(tx_buf.addr, &s->pkt_buf[len],
  2.1552 +                                        tx_buf.size);
  2.1553 +
  2.1554 +                                len += tx_buf.size;
  2.1555 +
  2.1556 +                                if ( tx_buf.is_el_set )
  2.1557 +                                    break;
  2.1558 +                            }
  2.1559 +
  2.1560 +                            /* In extend TCB mode, TDB array point to the thrid TBD
  2.1561 +                             * if it is not NULL(0xffffffff) and EL bit of before
  2.1562 +                             * two TBDs is not set
  2.1563 +                             */
  2.1564 +                            if ( tbd_array != (uint32_t)-1 && !tx_buf.is_el_set )
  2.1565 +                            {
  2.1566 +                                tbd_addr = tbd_array;
  2.1567 +
  2.1568 +                                /* TBD number includes first two TBDs, so don't
  2.1569 +                                 * initialize i here
  2.1570 +                                 */
  2.1571 +                                for ( ; i<tx.tbd.tbd_num; i++ )
  2.1572 +                                {
  2.1573 +                                    cpu_physical_memory_read(tbd_addr, (uint8_t *)&tx_buf,
  2.1574 +                                            sizeof(tx_buf));
  2.1575 +                                    tx_buf.is_el_set &= 0x1;
  2.1576 +                                    tbd_addr += 8;
  2.1577 +
  2.1578 +                                    cpu_physical_memory_read(tx_buf.addr, &s->pkt_buf[len],
  2.1579 +                                            tx_buf.size);
  2.1580 +                                    logout("TBD (extended mode): buf addr 0x%#08x, size 0x%#04x\n",
  2.1581 +                                            tx_buf.addr, tx_buf.size);
  2.1582 +
  2.1583 +                                    len += tx_buf.size;
  2.1584 +
  2.1585 +                                    if ( tx_buf.is_el_set )
  2.1586 +                                        break;
  2.1587 +                                }
  2.1588 +                            }
  2.1589 +                        }
  2.1590 +                    }
  2.1591 +
  2.1592 +
  2.1593 +                    s->pkt_buf_len = len;
  2.1594 +
  2.1595 +/* Below codes are used for Threshold. But with these logic, network of guest
  2.1596 + * getting bad performance. So I comment it and leave codes here to hope anyone
  2.1597 + * fix it
  2.1598 + */
  2.1599 +#if 0
  2.1600 +                    /* If threshold is set, only send packet when threshold
  2.1601 +                     * bytes are read
  2.1602 +                     */
  2.1603 +                    if ( tx.tbd.tx_threshold && s->pkt_buf_len < tx.tbd.tx_threshold * 8 )
  2.1604 +                    {
  2.1605 +                        logout("Current data length in FIFO buffer:%d\n", s->pkt_buf_len);
  2.1606 +                        break;
  2.1607 +                    }
  2.1608 +#endif
  2.1609 +
  2.1610 +                    if ( s->pkt_buf_len )
  2.1611 +                    {
  2.1612 +                        qemu_send_packet(s->vc, s->pkt_buf, s->pkt_buf_len);
  2.1613 +                        s->statistics.tx_good_frames ++;
  2.1614 +                        logout("Send out frame successful(size=%d,"
  2.1615 +                                "already sent %d frames)\n", s->pkt_buf_len,
  2.1616 +                                s->statistics.tx_good_frames);
  2.1617 +                        s->pkt_buf_len = 0;
  2.1618 +                    }
  2.1619 +
  2.1620 +                    e100_dump("Dest addr:", (uint8_t *)s->pkt_buf, 6);
  2.1621 +                    e100_dump("Src addr:", (uint8_t *)(s->pkt_buf+6), 6);
  2.1622 +                    e100_dump("type:", (uint8_t *)(s->pkt_buf+8), 2);
  2.1623 +
  2.1624 +                    break;
  2.1625 +                }
  2.1626 +            case CBL_LOAD_MICROCODE:
  2.1627 +#ifdef DEBUG_E100
  2.1628 +                {
  2.1629 +                    /* Don't support load marco code, just dump it */
  2.1630 +                    #define MICRO_CODE_LEN 256
  2.1631 +                    uint8_t micro_code[MICRO_CODE_LEN] = {0};
  2.1632 +                    cpu_physical_memory_read(cb_addr+8, micro_code, MICRO_CODE_LEN);
  2.1633 +                    e100_dump("Load micro code:", micro_code, MICRO_CODE_LEN);
  2.1634 +                }
  2.1635 +#endif
  2.1636 +                break;
  2.1637 +            case CBL_DUMP:
  2.1638 +                logout("Control block dump\n");
  2.1639 +                break;
  2.1640 +            case CBL_DIAGNOSE:
  2.1641 +                logout("Control block diagnose\n");
  2.1642 +                break;
  2.1643 +            default:
  2.1644 +                logout("Unknown Control block command(val=%#x)\n", cb.cmd);
  2.1645 +                break;
  2.1646 +        }
  2.1647 +
  2.1648 +        /* Now, we finished executing a command, update status of CB.
  2.1649 +         * We always success
  2.1650 +         */
  2.1651 +        cb.c = 1;
  2.1652 +        cb.ok = 1;
  2.1653 +        // Only update C bit and OK bit field in TCB
  2.1654 +        cpu_physical_memory_write(cb_addr, (uint8_t *)&cb, 2);
  2.1655 +
  2.1656 +        logout("Finished a command from CB list:\n"
  2.1657 +                "\tok:%d\n"
  2.1658 +                "\tc:%d\n"
  2.1659 +                "\tcommand name:%s(cmd=%#x)\n"
  2.1660 +                "\ti:%d\n"
  2.1661 +                "\ts:%d\n"
  2.1662 +                "\tel:%d\n"
  2.1663 +                "\tlink address:%#x\n",
  2.1664 +                cb.ok, cb.c, CB_CMD_NAME(cb.cmd), cb.cmd,
  2.1665 +                cb.i, cb.s, cb.el, cb.link_addr);
  2.1666 +
  2.1667 +        if ( cb.i )
  2.1668 +            e100_interrupt(s, (uint16_t)INT_CX_TNO);
  2.1669 +
  2.1670 +        // Suspend CU
  2.1671 +        if ( cb.s )
  2.1672 +        {
  2.1673 +            logout("CU go to suspend\n");
  2.1674 +            SET_CU_STATE(CU_SUSPENDED);
  2.1675 +            s->cu_next = cb.link_addr; // Save it for go on executing when resume
  2.1676 +
  2.1677 +            // Trigger CNA interrupt only when CNA mode is configured
  2.1678 +            if ( !(s->config.ci_intr) && cb.i )
  2.1679 +                e100_interrupt(s, (uint16_t)INT_CNA);
  2.1680 +
  2.1681 +            return;
  2.1682 +        }
  2.1683 +
  2.1684 +        // This is last command in CB list, CU go back to IDLE
  2.1685 +        if ( cb.el )
  2.1686 +        {
  2.1687 +            logout("Command block list is empty, CU go to idle\n");
  2.1688 +            SET_CU_STATE(CU_IDLE);
  2.1689 +            /* Either in CNA mode or CI mode, interrupt need be triggered
  2.1690 +             * when CU go to idle.
  2.1691 +             */
  2.1692 +            if ( cb.i )
  2.1693 +                e100_interrupt(s, (uint16_t)INT_CNA);
  2.1694 +
  2.1695 +            return;
  2.1696 +        }
  2.1697 +
  2.1698 +        s->cu_offset = le32_to_cpu(cb.link_addr); // get next CB offset
  2.1699 +    }
  2.1700 +}
  2.1701 +
  2.1702 +static void dump_statistics(E100State * s, uint32_t complete_word)
  2.1703 +{
  2.1704 +    /* Dump statistical data. Most data is never changed by the emulation
  2.1705 +     * and always 0.
  2.1706 +     */
  2.1707 +    s->statistics.complete_word = complete_word;
  2.1708 +    cpu_physical_memory_write(s->statsaddr, (uint8_t *)&s->statistics, sizeof(s->statistics));
  2.1709 +
  2.1710 +}
  2.1711 +
  2.1712 +static void e100_cu_command(E100State *s, uint8_t val)
  2.1713 +{
  2.1714 +
  2.1715 +    switch ( val )
  2.1716 +    {
  2.1717 +        case CU_NOP:
  2.1718 +            /* Will not be here */
  2.1719 +            break;
  2.1720 +        case CU_START:
  2.1721 +            /* This strictly follow Intel's spec */
  2.1722 +            if ( GET_CU_STATE != CU_IDLE && GET_CU_STATE != CU_SUSPENDED )
  2.1723 +            {
  2.1724 +                logout("Illegal CU start command. Device is not idle or suspend\n");
  2.1725 +                return;
  2.1726 +            }
  2.1727 +
  2.1728 +            SET_CU_STATE(CU_LPQ_ACTIVE);
  2.1729 +            logout("CU start\n");
  2.1730 +
  2.1731 +            e100_execute_cb_list(s, 0);
  2.1732 +            break;
  2.1733 +        case CU_RESUME:
  2.1734 +            {
  2.1735 +                uint32_t previous_cb = s->cu_base + s->cu_offset;
  2.1736 +                struct control_block cb;
  2.1737 +
  2.1738 +                /* Resume from suspend */
  2.1739 +
  2.1740 +                /* FIXME:From Intel's spec, CU resume from idle is
  2.1741 +                 * forbidden, but e100 drive in linux
  2.1742 +                 * indeed do this.
  2.1743 +                 */
  2.1744 +                if ( GET_CU_STATE == CU_IDLE )
  2.1745 +                {
  2.1746 +                    logout("Illegal resume form IDLE\n");
  2.1747 +                }
  2.1748 +
  2.1749 +                cpu_physical_memory_read(previous_cb, (uint8_t *)&cb,
  2.1750 +                                        sizeof(cb));
  2.1751 +
  2.1752 +                //FIXME: Need any speical handle when CU is active ?
  2.1753 +
  2.1754 +                /* Driver must clean S bit in previous CB when
  2.1755 +                 * it issue CU resume command
  2.1756 +                 */
  2.1757 +                if ( cb.s )
  2.1758 +                {
  2.1759 +                    logout("CU still in suspend\n");
  2.1760 +                    break;
  2.1761 +                }
  2.1762 +
  2.1763 +                SET_CU_STATE(CU_LPQ_ACTIVE);
  2.1764 +                if ( cb.el )
  2.1765 +                {
  2.1766 +                    logout("CB list is empty, CU just go to active\n");
  2.1767 +                    break;
  2.1768 +                }
  2.1769 +
  2.1770 +                // Continue next command
  2.1771 +                s->cu_offset = s->cu_next;
  2.1772 +
  2.1773 +                e100_execute_cb_list(s, 1);
  2.1774 +
  2.1775 +                logout("CU resume\n");
  2.1776 +            }
  2.1777 +            break;
  2.1778 +        case CU_STATSADDR:
  2.1779 +            /* Load dump counters address */
  2.1780 +            s->statsaddr = CSR_VAL(CSR_POINTER);
  2.1781 +            logout("Load Stats address at %#x\n", s->statsaddr);
  2.1782 +            break;
  2.1783 +        case CU_SHOWSTATS:
  2.1784 +            /* Dump statistical counters */
  2.1785 +            dump_statistics(s, 0xa005);
  2.1786 +            logout("Execute dump statistics\n");
  2.1787 +            break;
  2.1788 +        case CU_CMD_BASE:
  2.1789 +            /* Load CU base */
  2.1790 +            s->cu_base = CSR_VAL(CSR_POINTER);
  2.1791 +            logout("Load CU base at %x\n", s->cu_base);
  2.1792 +            break;
  2.1793 +        case CU_DUMPSTATS:
  2.1794 +            /* Dump statistical counters and reset counters. */
  2.1795 +            dump_statistics(s, 0xa007);
  2.1796 +            memset(&s->statistics, 0x0, sizeof(s->statistics));
  2.1797 +            logout("Execute dump and reset statistics\n");
  2.1798 +            break;
  2.1799 +        case CU_S_RESUME:
  2.1800 +            /* CU static resume */
  2.1801 +            logout("CU static resume is not implemented\n");
  2.1802 +            break;
  2.1803 +        default:
  2.1804 +            logout("Unknown CU command(val=%#x)\n", val);
  2.1805 +            break;
  2.1806 +    }
  2.1807 +
  2.1808 +}
  2.1809 +
  2.1810 +static void scb_cmd_func(E100State *s, uint16_t val, int dir)
  2.1811 +{
  2.1812 +    /* ignore NOP operation */
  2.1813 +    if ( val & 0x0f )
  2.1814 +    {
  2.1815 +        e100_ru_command(s, val & 0x0f);
  2.1816 +        CSR(CSR_CMD, ru_cmd) = 0;
  2.1817 +    }
  2.1818 +    else if ( val & 0xf0 )
  2.1819 +    {
  2.1820 +        e100_cu_command(s, val & 0xf0);
  2.1821 +        CSR(CSR_CMD, cu_cmd) = 0;
  2.1822 +    }
  2.1823 +
  2.1824 +}
  2.1825 +
  2.1826 +enum
  2.1827 +{
  2.1828 +    WRITEB,
  2.1829 +    WRITEW,
  2.1830 +    WRITEL,
  2.1831 +    OP_IS_READ,
  2.1832 +} WRITE_BYTES;
  2.1833 +
  2.1834 +/* Driver may issue a command by writting one 32bit-entry,
  2.1835 + * two 16bit-entries or four 8bit-entries. In late two case, we
  2.1836 + * must wait until driver finish writting to the highest byte. The parameter
  2.1837 + * 'bytes' means write action of driver(writeb, wirtew, wirtel)
  2.1838 + */
  2.1839 +static void e100_execute(E100State *s, uint32_t addr_offset,
  2.1840 +        uint32_t val, int dir, int bytes)
  2.1841 +{
  2.1842 +
  2.1843 +    switch ( addr_offset )
  2.1844 +    {
  2.1845 +        case SCB_STATUS:
  2.1846 +            if ( bytes == WRITEB )
  2.1847 +                break;
  2.1848 +        case SCB_ACK:
  2.1849 +            if ( dir == OP_WRITE )
  2.1850 +            {
  2.1851 +                uint8_t _val = 0;
  2.1852 +                if ( bytes == WRITEB )
  2.1853 +                    _val = (uint8_t)val;
  2.1854 +                else if ( bytes == WRITEW )
  2.1855 +                    _val = ((uint16_t)val) >> 8;
  2.1856 +                else if ( bytes == WRITEL)
  2.1857 +                {
  2.1858 +                    // This should not be happen
  2.1859 +                    _val = ((uint16_t)val) >> 8;
  2.1860 +                    logout("WARNNING: Drvier write 4 bytes to CSR register at offset %d,"
  2.1861 +                           "emulator may do things wrong!!!\n", addr_offset);
  2.1862 +                }
  2.1863 +
  2.1864 +                e100_interrupt_ack(s, _val);
  2.1865 +            }
  2.1866 +            break;
  2.1867 +        case SCB_CMD:
  2.1868 +            if ( dir == OP_WRITE )
  2.1869 +                scb_cmd_func(s, val, dir);
  2.1870 +
  2.1871 +/* I don't know whether there is any driver writes command words and
  2.1872 + * interrupt mask at same time by two bytes. This is not a regular operation.
  2.1873 + * but if we meet the case, below codes could copy with it. As far
  2.1874 + * as I know. windows's and linux's driver don't do this thing.
  2.1875 + */
  2.1876 +#if 0
  2.1877 +            if ( bytes == WRITEW && (val&0xff00) != 0 )
  2.1878 +                ;
  2.1879 +            else
  2.1880 +                break;
  2.1881 +#endif
  2.1882 +            break;
  2.1883 +        case SCB_INTERRUPT_MASK:
  2.1884 +            if ( dir == OP_WRITE )
  2.1885 +            {
  2.1886 +                uint8_t _val = 0;
  2.1887 +                if ( bytes == WRITEB )
  2.1888 +                    _val = (uint8_t)val;
  2.1889 +                else if ( bytes == WRITEW )
  2.1890 +                    _val = (val & 0xff00) >> 8;
  2.1891 +                else
  2.1892 +                    logout("WARNNING: Drvier write 4 bytes to CSR register at offset %d,"
  2.1893 +                           "emulator may do things wrong!!!\n", addr_offset);
  2.1894 +
  2.1895 +                // Driver generates a software interrupt
  2.1896 +                if ( _val & BIT(1) )
  2.1897 +                    e100_interrupt(s, INT_SWI);
  2.1898 +            }
  2.1899 +            break;
  2.1900 +        case SCB_PORT ... SCB_PORT + 3:
  2.1901 +            if ( dir == OP_WRITE )
  2.1902 +            {
  2.1903 +                // Waitting for driver write to the highest byte
  2.1904 +                if ( (bytes == WRITEB && addr_offset != SCB_PORT + 3) ||
  2.1905 +                     (bytes == WRITEW && addr_offset != SCB_PORT + 2) )
  2.1906 +                    break;
  2.1907 +
  2.1908 +                scb_port_func(s, CSR_VAL(CSR_PORT), dir);
  2.1909 +            }
  2.1910 +            break;
  2.1911 +        case SCB_MDI ... SCB_MDI + 3:
  2.1912 +            if ( dir == OP_WRITE )
  2.1913 +            {
  2.1914 +                // Waitting for driver write to the highest byte
  2.1915 +                if ( (bytes == WRITEB && addr_offset != SCB_MDI + 3) ||
  2.1916 +                     (bytes == WRITEW && addr_offset != SCB_MDI + 2) )
  2.1917 +                    break;
  2.1918 +            }
  2.1919 +
  2.1920 +            scb_mdi_func(s, CSR_VAL(CSR_MDI), dir);
  2.1921 +            break;
  2.1922 +        case SCB_EEPROM:
  2.1923 +            if ( dir == OP_WRITE )
  2.1924 +                scb_eeprom_func(s, val, dir);
  2.1925 +            // Nothing need do when driver read EEPROM registers of CSR
  2.1926 +            break;
  2.1927 +        case SCB_POINTER:
  2.1928 +            break;
  2.1929 +        default:
  2.1930 +            logout("Driver operate on CSR reg(offset=%#x,dir=%s,val=%#x)\n",
  2.1931 +                    addr_offset, dir==OP_WRITE?"write":"read", val);
  2.1932 +    }
  2.1933 +
  2.1934 +}
  2.1935 +
  2.1936 +/* MMIO access functions */
  2.1937 +static uint8_t e100_read1(E100State * s, uint32_t addr_offset)
  2.1938 +{
  2.1939 +    uint8_t val = -1;
  2.1940 +
  2.1941 +    if ( addr_offset + sizeof(val) >= sizeof(s->pci_mem.mem) )
  2.1942 +    {
  2.1943 +        logout("Invaild read, beyond memory boundary(addr:%#x)\n", addr_offset
  2.1944 +                + s->region_base_addr[CSR_MEMORY_BASE]);
  2.1945 +        return val;
  2.1946 +    }
  2.1947 +
  2.1948 +
  2.1949 +    e100_execute(s, addr_offset, val, OP_READ, OP_IS_READ);
  2.1950 +    val = CSR_READ(addr_offset, uint8_t);
  2.1951 +    logout("READ1: Register name = %s, addr_offset = %#x, val=%#x\n", SCBNAME(addr_offset), addr_offset, val);
  2.1952 +
  2.1953 +    return val;
  2.1954 +}
  2.1955 +
  2.1956 +static uint16_t e100_read2(E100State * s, uint32_t addr_offset)
  2.1957 +{
  2.1958 +    uint16_t val = -1;
  2.1959 +
  2.1960 +    if ( addr_offset + sizeof(val) >= sizeof(s->pci_mem.mem) )
  2.1961 +    {
  2.1962 +        logout("Invaild read, beyond memory boundary(addr:%#x)\n", addr_offset 
  2.1963 +                + s->region_base_addr[CSR_MEMORY_BASE]);
  2.1964 +        return val;
  2.1965 +    }
  2.1966 +
  2.1967 +    e100_execute(s, addr_offset, val, OP_READ, OP_IS_READ);
  2.1968 +    val = CSR_READ(addr_offset, uint16_t);
  2.1969 +    logout("READ2: Register name = %s, addr_offset = %#x, val=%#x\n", SCBNAME(addr_offset), addr_offset, val);
  2.1970 +
  2.1971 +    return val;
  2.1972 +
  2.1973 +}
  2.1974 +
  2.1975 +static uint32_t e100_read4(E100State * s, uint32_t addr_offset)
  2.1976 +{
  2.1977 +    uint32_t val = -1;
  2.1978 +
  2.1979 +    if ( addr_offset + sizeof(val) >= sizeof(s->pci_mem.mem) )
  2.1980 +    {
  2.1981 +        logout("Invaild read, beyond memory boundary(addr:%#x)\n", addr_offset 
  2.1982 +                + s->region_base_addr[CSR_MEMORY_BASE]);
  2.1983 +        return val;
  2.1984 +    }
  2.1985 +
  2.1986 +    e100_execute(s, addr_offset, val, OP_READ, OP_IS_READ);
  2.1987 +    val = CSR_READ(addr_offset, uint32_t);
  2.1988 +    logout("READ4: Register name = %s, addr_offset = %#x, val=%#x\n", SCBNAME(addr_offset), addr_offset, val);
  2.1989 +
  2.1990 +    return val;
  2.1991 +
  2.1992 +}
  2.1993 +
  2.1994 +static uint32_t pci_mmio_readb(void *opaque, target_phys_addr_t addr)
  2.1995 +{
  2.1996 +    E100State *s = opaque;
  2.1997 +    addr -= s->region_base_addr[CSR_MEMORY_BASE];
  2.1998 +    return e100_read1(s, addr);
  2.1999 +}
  2.2000 +
  2.2001 +static uint32_t pci_mmio_readw(void *opaque, target_phys_addr_t addr)
  2.2002 +{
  2.2003 +    E100State *s = opaque;
  2.2004 +    addr -= s->region_base_addr[CSR_MEMORY_BASE];
  2.2005 +    return e100_read2(s, addr);
  2.2006 +}
  2.2007 +
  2.2008 +static uint32_t pci_mmio_readl(void *opaque, target_phys_addr_t addr)
  2.2009 +{
  2.2010 +    E100State *s = opaque;
  2.2011 +    addr -= s->region_base_addr[CSR_MEMORY_BASE];
  2.2012 +    return e100_read4(s, addr);
  2.2013 +}
  2.2014 +
  2.2015 +static CPUReadMemoryFunc *pci_mmio_read[] = {
  2.2016 +    pci_mmio_readb,
  2.2017 +    pci_mmio_readw,
  2.2018 +    pci_mmio_readl
  2.2019 +};
  2.2020 +
  2.2021 +static void e100_write1(E100State * s, uint32_t addr_offset, uint8_t val)
  2.2022 +{
  2.2023 +    if ( addr_offset + sizeof(val) >= sizeof(s->pci_mem.mem) )
  2.2024 +    {
  2.2025 +        logout("Invaild write, beyond memory boundary(addr = %#x, val = %#x\n", addr_offset
  2.2026 +                + s->region_base_addr[CSR_MEMORY_BASE], val);
  2.2027 +        return;
  2.2028 +    }
  2.2029 +
  2.2030 +    // SCB stauts is read-only word, can not be directly write
  2.2031 +    if ( addr_offset == SCB_STATUS )
  2.2032 +    {
  2.2033 +        return;
  2.2034 +    }
  2.2035 +    // EEDO bit of eeprom register is read-only, can not be written;
  2.2036 +    else if ( addr_offset == SCB_EEPROM )
  2.2037 +    {
  2.2038 +        int eedo = BIT(3) & CSR_VAL(CSR_EEPROM);
  2.2039 +        CSR_WRITE(addr_offset, val, uint8_t);
  2.2040 +        CSR(CSR_EEPROM, eedo) = !!(eedo & EEPROM_DO);
  2.2041 +
  2.2042 +        logout("WRITE1: Register name = %s, addr_offset = %#x, val = %#x\n", SCBNAME(addr_offset),addr_offset, (uint8_t)CSR_VAL(CSR_EEPROM));
  2.2043 +        return;
  2.2044 +    }
  2.2045 +    else
  2.2046 +    {
  2.2047 +        CSR_WRITE(addr_offset, val, uint8_t);
  2.2048 +    }
  2.2049 +
  2.2050 +    logout("WRITE1: Register name = %s, addr_offset = %#x, val = %#x\n", SCBNAME(addr_offset),addr_offset, val);
  2.2051 +    return;
  2.2052 +}
  2.2053 +
  2.2054 +static void e100_write2(E100State * s, uint32_t addr_offset, uint16_t val)
  2.2055 +{
  2.2056 +    if ( addr_offset + sizeof(val) >= sizeof(s->pci_mem.mem) )
  2.2057 +    {
  2.2058 +        logout("Invaild write, beyond memory boundary(addr = %#x, val = %#x\n", addr_offset
  2.2059 +                + s->region_base_addr[CSR_MEMORY_BASE], val);
  2.2060 +        return;
  2.2061 +    }
  2.2062 +
  2.2063 +    // SCB stauts is readonly word, can not be directly write
  2.2064 +    if ( addr_offset == SCB_STATUS )
  2.2065 +    {
  2.2066 +        uint8_t __val = val >> 8;
  2.2067 +        CSR_WRITE(addr_offset+1, __val, uint8_t);
  2.2068 +    }
  2.2069 +    // EEDO bit of eeprom register is read-only, can not be written;
  2.2070 +    else if ( addr_offset == SCB_EEPROM )
  2.2071 +    {
  2.2072 +        int eedo = BIT(3) & CSR_VAL(CSR_EEPROM);
  2.2073 +        CSR_WRITE(addr_offset, val, uint16_t);
  2.2074 +        CSR(CSR_EEPROM, eedo) = !!(eedo & EEPROM_DO);
  2.2075 +
  2.2076 +        logout("WRITE1: Register name = %s, addr_offset = %#x, val = %#x\n", SCBNAME(addr_offset),addr_offset, CSR_VAL(CSR_EEPROM));
  2.2077 +        return;
  2.2078 +    }
  2.2079 +    else
  2.2080 +    {
  2.2081 +        CSR_WRITE(addr_offset, val, uint16_t);
  2.2082 +    }
  2.2083 +
  2.2084 +    logout("WRITE2: Register name = %s, addr_offset = %#x, val = %#x\n", SCBNAME(addr_offset),addr_offset, val);
  2.2085 +    return;
  2.2086 +}
  2.2087 +
  2.2088 +static void e100_write4(E100State * s, uint32_t addr_offset, uint32_t val)
  2.2089 +{
  2.2090 +    if ( addr_offset + sizeof(val) >= sizeof(s->pci_mem.mem) )
  2.2091 +    {
  2.2092 +        logout("Invaild write, beyond memory boundary(addr = %#x, val = %#x\n", addr_offset 
  2.2093 +                + s->region_base_addr[CSR_MEMORY_BASE], val);
  2.2094 +        return;
  2.2095 +    }
  2.2096 +
  2.2097 +    // SCB stauts is readonly word, can not be directly write
  2.2098 +    if ( addr_offset == SCB_STATUS )
  2.2099 +    {
  2.2100 +        uint8_t __val[4] = {0};
  2.2101 +
  2.2102 +        //FIXME: any un-aligned reference ?
  2.2103 +        *(uint32_t *)&__val = val;
  2.2104 +
  2.2105 +        CSR_WRITE(addr_offset+1, __val[1], uint8_t);
  2.2106 +        CSR_WRITE(addr_offset+2, __val[2], uint8_t);
  2.2107 +        CSR_WRITE(addr_offset+3, __val[3], uint8_t);
  2.2108 +    }
  2.2109 +    /* No write4 opertaion on EEPROM register */
  2.2110 +    else
  2.2111 +    {
  2.2112 +        CSR_WRITE(addr_offset, val, uint32_t);
  2.2113 +    }
  2.2114 +
  2.2115 +    logout("WRITE4: Register name = %s, addr_offset = %#x, val = %#x\n", SCBNAME(addr_offset),addr_offset, val);
  2.2116 +    return;
  2.2117 +}
  2.2118 +
  2.2119 +static void pci_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
  2.2120 +{
  2.2121 +    E100State *s = opaque;
  2.2122 +    addr -= s->region_base_addr[CSR_MEMORY_BASE];
  2.2123 +    e100_write1(s, addr, val);
  2.2124 +    e100_execute(s, addr, val, OP_WRITE, WRITEB);
  2.2125 +}
  2.2126 +
  2.2127 +static void pci_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
  2.2128 +{
  2.2129 +    E100State *s = opaque;
  2.2130 +    addr -= s->region_base_addr[CSR_MEMORY_BASE];
  2.2131 +    e100_write2(s, addr, val);
  2.2132 +    e100_execute(s, addr, val, OP_WRITE, WRITEW);
  2.2133 +}
  2.2134 +
  2.2135 +static void pci_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
  2.2136 +{
  2.2137 +    E100State *s = opaque;
  2.2138 +    addr -= s->region_base_addr[CSR_MEMORY_BASE];
  2.2139 +    e100_write4(s, addr, val);
  2.2140 +    (void)e100_execute(s, addr, val, OP_WRITE, WRITEL);
  2.2141 +}
  2.2142 +
  2.2143 +static CPUWriteMemoryFunc *pci_mmio_write[] = {
  2.2144 +    pci_mmio_writeb,
  2.2145 +    pci_mmio_writew,
  2.2146 +    pci_mmio_writel
  2.2147 +};
  2.2148 +
  2.2149 +static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
  2.2150 +                         uint32_t addr, uint32_t size, int type)
  2.2151 +{
  2.2152 +    PCIE100State *d = (PCIE100State *) pci_dev;
  2.2153 +
  2.2154 +    logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
  2.2155 +           region_num, addr, size, type);
  2.2156 +
  2.2157 +    if ( region_num == CSR_MEMORY_BASE ) {
  2.2158 +        /* Map control / status registers. */
  2.2159 +        cpu_register_physical_memory(addr, size, d->e100.mmio_index);
  2.2160 +        d->e100.region_base_addr[region_num] = addr;
  2.2161 +    }
  2.2162 +}
  2.2163 +
  2.2164 +/* IO access functions */
  2.2165 +static void ioport_write1(void *opaque, uint32_t addr, uint32_t val)
  2.2166 +{
  2.2167 +    E100State *s = opaque;
  2.2168 +    addr -= s->region_base_addr[CSR_IO_BASE];
  2.2169 +    e100_write1(s, addr, val);
  2.2170 +    (void)e100_execute(s, addr, (uint32_t)val, OP_WRITE, WRITEB);
  2.2171 +}
  2.2172 +
  2.2173 +static void ioport_write2(void *opaque, uint32_t addr, uint32_t val)
  2.2174 +{
  2.2175 +    E100State *s = opaque;
  2.2176 +    addr -= s->region_base_addr[CSR_IO_BASE];
  2.2177 +    e100_write2(s, addr, val);
  2.2178 +    (void)e100_execute(s, addr, (uint32_t)val, OP_WRITE, WRITEW);
  2.2179 +}
  2.2180 +
  2.2181 +static void ioport_write4(void *opaque, uint32_t addr, uint32_t val)
  2.2182 +{
  2.2183 +    E100State *s = opaque;
  2.2184 +    addr -= s->region_base_addr[CSR_IO_BASE];
  2.2185 +    e100_write4(s, addr, val);
  2.2186 +    (void)e100_execute(s, addr, (uint32_t)val, OP_WRITE, WRITEL);
  2.2187 +}
  2.2188 +
  2.2189 +static uint32_t ioport_read1(void *opaque, uint32_t addr)
  2.2190 +{
  2.2191 +    E100State *s = opaque;
  2.2192 +    addr -= s->region_base_addr[CSR_IO_BASE];
  2.2193 +    return e100_read1(s, addr);
  2.2194 +}
  2.2195 +
  2.2196 +static uint32_t ioport_read2(void *opaque, uint32_t addr)
  2.2197 +{
  2.2198 +    E100State *s = opaque;
  2.2199 +    addr -= s->region_base_addr[CSR_IO_BASE];
  2.2200 +    return e100_read2(s, addr);
  2.2201 +}
  2.2202 +
  2.2203 +static uint32_t ioport_read4(void *opaque, uint32_t addr)
  2.2204 +{
  2.2205 +    E100State *s = opaque;
  2.2206 +    addr -= s->region_base_addr[CSR_IO_BASE];
  2.2207 +    return e100_read4(s, addr);
  2.2208 +}
  2.2209 +
  2.2210 +static void pci_ioport_map(PCIDevice * pci_dev, int region_num,
  2.2211 +                    uint32_t addr, uint32_t size, int type)
  2.2212 +{
  2.2213 +    PCIE100State *d = (PCIE100State *) pci_dev;
  2.2214 +    E100State *s = &d->e100;
  2.2215 +
  2.2216 +    logout("region %d, addr=0x%08x, size=0x%08x, type=%d\n",
  2.2217 +           region_num, addr, size, type);
  2.2218 +
  2.2219 +    if ( region_num != 1 )
  2.2220 +    {
  2.2221 +        logout("Invaid region number!\n");
  2.2222 +        return;
  2.2223 +    }
  2.2224 +
  2.2225 +    register_ioport_write(addr, size, 1, ioport_write1, s);
  2.2226 +    register_ioport_read(addr, size, 1, ioport_read1, s);
  2.2227 +    register_ioport_write(addr, size, 2, ioport_write2, s);
  2.2228 +    register_ioport_read(addr, size, 2, ioport_read2, s);
  2.2229 +    register_ioport_write(addr, size, 4, ioport_write4, s);
  2.2230 +    register_ioport_read(addr, size, 4, ioport_read4, s);
  2.2231 +
  2.2232 +    s->region_base_addr[region_num] = addr;
  2.2233 +}
  2.2234 +
  2.2235 +/* From FreeBSD */
  2.2236 +#define POLYNOMIAL 0x04c11db6
  2.2237 +static int compute_mcast_idx(const uint8_t *ep)
  2.2238 +{
  2.2239 +    uint32_t crc;
  2.2240 +    int carry, i, j;
  2.2241 +    uint8_t b;
  2.2242 +
  2.2243 +    crc = 0xffffffff;
  2.2244 +    for (i = 0; i < 6; i++) {
  2.2245 +        b = *ep++;
  2.2246 +        for (j = 0; j < 8; j++) {
  2.2247 +            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
  2.2248 +            crc <<= 1;
  2.2249 +            b >>= 1;
  2.2250 +            if (carry)
  2.2251 +                crc = ((crc ^ POLYNOMIAL) | carry);
  2.2252 +        }
  2.2253 +    }
  2.2254 +    return (crc >> 26);
  2.2255 +}
  2.2256 +
  2.2257 +/* Eerpro100 receive functions */
  2.2258 +static int e100_can_receive(void *opaque)
  2.2259 +{
  2.2260 +    E100State *s = opaque;
  2.2261 +
  2.2262 +    int is_ready = (GET_RU_STATE == RU_READY);
  2.2263 +    logout("%s\n", is_ready ? "EEPro100 receiver is ready"
  2.2264 +            : "EEPro100 receiver is not ready");
  2.2265 +    return is_ready;
  2.2266 +}
  2.2267 +
  2.2268 +static void e100_receive(void *opaque, const uint8_t * buf, int size)
  2.2269 +{
  2.2270 +    E100State *s = opaque;
  2.2271 +    uint32_t rfd_addr = 0;
  2.2272 +    rfd_t rfd = {0};
  2.2273 +
  2.2274 +
  2.2275 +    if ( GET_RU_STATE != RU_READY )
  2.2276 +    {
  2.2277 +        //logout("RU is not ready. Begin discarding frame(state=%x)\n", GET_RU_STATE);
  2.2278 +        return;
  2.2279 +    }
  2.2280 +
  2.2281 +    rfd_addr = s->ru_base + s->ru_offset;
  2.2282 +    cpu_physical_memory_read(rfd_addr, (uint8_t *)&rfd, sizeof(rfd_t));
  2.2283 +
  2.2284 +    if ( (size > MAX_ETH_FRAME_SIZE+4) )
  2.2285 +    {
  2.2286 +        /* Long frame and configuration byte 18/3 (long receive ok) not set:
  2.2287 +         * Long frames are discarded. */
  2.2288 +        logout("Discard long frame(size=%d)\n", size);
  2.2289 +
  2.2290 +        return;
  2.2291 +    }
  2.2292 +    else if ( !memcmp(buf, s->macaddr, sizeof(s->macaddr)) )
  2.2293 +    {
  2.2294 +        /* The frame is for me */
  2.2295 +        logout("Receive a frame for me(size=%d)\n", size);
  2.2296 +        e100_dump("FRAME:", (uint8_t *)buf, size);
  2.2297 +    }
  2.2298 +    else if ( !memcmp(buf, broadcast_macaddr, sizeof(broadcast_macaddr)) )
  2.2299 +    {
  2.2300 +        if ( s->config.broadcast_dis && !s->config.promiscuous )
  2.2301 +        {
  2.2302 +            logout("Discard a broadcast frame\n");
  2.2303 +            return;
  2.2304 +        }
  2.2305 +
  2.2306 +        /* Broadcast frame */
  2.2307 +        rfd.status |= RX_IA_MATCH;
  2.2308 +        logout("Receive a broadcast frame(size=%d)\n", size);
  2.2309 +    }
  2.2310 +    else if ( s->is_multcast_enable && buf[0] & 0x1 )
  2.2311 +    {
  2.2312 +        int mcast_idx = compute_mcast_idx(buf);
  2.2313 +        if ( !(s->mult_list[mcast_idx >> 3] & (1 << (mcast_idx & 7))) )
  2.2314 +        {
  2.2315 +            logout("Multicast address mismatch, discard\n");
  2.2316 +            return;
  2.2317 +        }
  2.2318 +        logout("Receive a multicast frame(size=%d)\n", size);
  2.2319 +    }
  2.2320 +    else if ( size < 64 && (s->config.dis_short_rx) )
  2.2321 +    {
  2.2322 +        /* From Intel's spec, short frame should be discarded
  2.2323 +         * when configuration byte 7/0 (discard short receive) set.
  2.2324 +         * But this will cause frame lossing such as ICMP frame, ARP frame.
  2.2325 +         * So we check is the frame for me before discarding short frame
  2.2326 +         */
  2.2327 +
  2.2328 +        /* Save Bad Frame bit */
  2.2329 +        if ( s->config.save_bad_frame )
  2.2330 +        {
  2.2331 +            rfd.status |= RX_SHORT;
  2.2332 +            s->statistics.rx_short_frame_errors ++;
  2.2333 +        }
  2.2334 +        logout("Receive a short frame(size=%d), discard it\n", size);
  2.2335 +        return;
  2.2336 +    }
  2.2337 +    else if ( s->config.promiscuous )
  2.2338 +    {
  2.2339 +        /* Promiscuous: receive all. No address match */
  2.2340 +        logout("Received frame in promiscuous mode(size=%d)\n", size);
  2.2341 +        rfd.status |= RX_NO_MATCH;
  2.2342 +    }
  2.2343 +    else
  2.2344 +    {
  2.2345 +        e100_dump("Unknown frame, MAC = ", (uint8_t *)buf, 6);
  2.2346 +        return;
  2.2347 +    }
  2.2348 +    e100_dump("Get frame, MAC = ", (uint8_t *)buf, 6);
  2.2349 +
  2.2350 +    rfd.c = 1;
  2.2351 +    rfd.ok = 1;
  2.2352 +    rfd.f = 1;
  2.2353 +    rfd.eof = 1;
  2.2354 +    rfd.status &= ~RX_COLLISION;
  2.2355 +    rfd.count = size;
  2.2356 +
  2.2357 +    logout("Get a RFD configure:\n"
  2.2358 +            "\tstatus:%#x\n"
  2.2359 +            "\tok:%#x\n" "\tc:%#x\n" "\tsf:%#x\n"
  2.2360 +            "\th:%#x\n" "\ts:%#x\n" "\tel:%#x\n"
  2.2361 +            "\tlink add:%#x\n" "\tactual count:%#x\n"
  2.2362 +            "\tf:%#x\n" "\teof:%#x\n" "\tsize:%#x\n",
  2.2363 +            rfd.status, rfd.ok, rfd.c, rfd.sf, rfd.h,
  2.2364 +            rfd.s, rfd.el, rfd.link_addr, rfd.count,
  2.2365 +            rfd.f, rfd.eof, rfd.size);
  2.2366 +
  2.2367 +    cpu_physical_memory_write(rfd_addr, (uint8_t *)&rfd, sizeof(rfd));
  2.2368 +    cpu_physical_memory_write(rfd_addr + sizeof(rfd_t), buf, size);
  2.2369 +    s->statistics.rx_good_frames ++;
  2.2370 +    s->ru_offset = le32_to_cpu(rfd.link_addr);
  2.2371 +
  2.2372 +    e100_interrupt(s, INT_FR);
  2.2373 +
  2.2374 +    if ( rfd.el || rfd.s )
  2.2375 +    {
  2.2376 +        /* Go to suspend */
  2.2377 +        SET_RU_STATE(RU_SUSPENDED);
  2.2378 +        e100_interrupt(s, INT_RNR);
  2.2379 +        logout("RFD met S or EL bit set, RU go to suspend\n");
  2.2380 +        return;
  2.2381 +    }
  2.2382 +
  2.2383 +    logout("Complete a frame receive(size = %d)\n", size);
  2.2384 +    return;
  2.2385 +}
  2.2386 +
  2.2387 +static void eeprom_init(E100State *s)
  2.2388 +{
  2.2389 +    int i;
  2.2390 +    int chksum = 0;
  2.2391 +    /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
  2.2392 +     * i82559 and later support 64 or 256 word EEPROM. */
  2.2393 +    eeprom_reset(s, EEPROM_RESET_ALL);
  2.2394 +    s->eeprom.addr_len = EEPROM_I82557_ADDRBIT;
  2.2395 +    memcpy(s->eeprom.contents, eeprom_i82557, sizeof(eeprom_i82557));
  2.2396 +    /* Dirver is going to get MAC from eeprom*/
  2.2397 +    memcpy((uint8_t *)s->eeprom.contents, s->macaddr, sizeof(s->macaddr));
  2.2398 +
  2.2399 +    /* The last word in eeprom saving checksum value.
  2.2400 +     * After we update MAC in eeprom, the checksum need be re-calculate
  2.2401 +     * and saved at the end of eeprom
  2.2402 +     */
  2.2403 +    for ( i=0; i<(1<<s->eeprom.addr_len)-1; i++ )
  2.2404 +        chksum += s->eeprom.contents[i];
  2.2405 +    s->eeprom.contents[i] = 0xBABA - chksum;
  2.2406 +
  2.2407 +}
  2.2408 +
  2.2409 +static void e100_init(PCIBus * bus, NICInfo * nd,
  2.2410 +        const char *name, uint32_t device)
  2.2411 +{
  2.2412 +    PCIE100State *d;
  2.2413 +    E100State *s;
  2.2414 +
  2.2415 +    logout("\n");
  2.2416 +
  2.2417 +    d = (PCIE100State *) pci_register_device(bus, name,
  2.2418 +            sizeof(PCIE100State), -1,
  2.2419 +            NULL, NULL);
  2.2420 +
  2.2421 +    s = &d->e100;
  2.2422 +    s->device = device;
  2.2423 +    s->pci_dev = &d->dev;
  2.2424 +
  2.2425 +    pci_reset(s);
  2.2426 +
  2.2427 +
  2.2428 +    /* Handler for memory-mapped I/O */
  2.2429 +    d->e100.mmio_index =
  2.2430 +        cpu_register_io_memory(0, pci_mmio_read, pci_mmio_write, s);
  2.2431 +
  2.2432 +    //CSR Memory mapped base
  2.2433 +    pci_register_io_region(&d->dev, 0, PCI_MEM_SIZE,
  2.2434 +            PCI_ADDRESS_SPACE_MEM | PCI_ADDRESS_SPACE_MEM_PREFETCH,
  2.2435 +            pci_mmio_map);
  2.2436 +    //CSR I/O mapped base
  2.2437 +    pci_register_io_region(&d->dev, 1, PCI_IO_SIZE, PCI_ADDRESS_SPACE_IO,
  2.2438 +            pci_ioport_map);
  2.2439 +    //Flash memory mapped base
  2.2440 +    pci_register_io_region(&d->dev, 2, PCI_FLASH_SIZE, PCI_ADDRESS_SPACE_MEM,
  2.2441 +            pci_mmio_map);
  2.2442 +
  2.2443 +    memcpy(s->macaddr, nd->macaddr, 6);
  2.2444 +    e100_dump("MAC ADDR", (uint8_t *)&s->macaddr[0], 6);
  2.2445 +
  2.2446 +    eeprom_init(s);
  2.2447 +
  2.2448 +    e100_reset(s);
  2.2449 +
  2.2450 +    s->vc = qemu_new_vlan_client(nd->vlan, e100_receive, e100_can_receive, s);
  2.2451 +
  2.2452 +    snprintf(s->vc->info_str, sizeof(s->vc->info_str),
  2.2453 +            "e100 pci macaddr=%02x:%02x:%02x:%02x:%02x:%02x",
  2.2454 +            s->macaddr[0],
  2.2455 +            s->macaddr[1],
  2.2456 +            s->macaddr[2], s->macaddr[3], s->macaddr[4], s->macaddr[5]);
  2.2457 +
  2.2458 +    qemu_register_reset(e100_reset, s);
  2.2459 +
  2.2460 +    register_savevm(name, 0, 3, e100_save, e100_load, s);
  2.2461 +}
  2.2462 +
  2.2463 +void pci_e100_init(PCIBus * bus, NICInfo * nd)
  2.2464 +{
  2.2465 +    e100_init(bus, nd, "e100", i82557C);
  2.2466 +}
  2.2467 +
     3.1 --- a/tools/ioemu/hw/pci.c	Wed Nov 21 09:49:09 2007 +0000
     3.2 +++ b/tools/ioemu/hw/pci.c	Wed Nov 21 09:52:04 2007 +0000
     3.3 @@ -565,6 +565,8 @@ void pci_nic_init(PCIBus *bus, NICInfo *
     3.4          pci_rtl8139_init(bus, nd, devfn);
     3.5      } else if (strcmp(nd->model, "pcnet") == 0) {
     3.6          pci_pcnet_init(bus, nd, devfn);
     3.7 +    } else if (strcmp(nd->model, "e100") == 0) {
     3.8 +        pci_e100_init(bus, nd);
     3.9      } else {
    3.10          fprintf(stderr, "qemu: Unsupported NIC: %s\n", nd->model);
    3.11          exit (1);