Statistics
| Branch: | Revision:

root / hw / eepro100.c @ da726e5e

History | View | Annotate | Download (67.5 kB)

1 663e8e51 ths
/*
2 663e8e51 ths
 * QEMU i8255x (PRO100) emulation
3 663e8e51 ths
 *
4 1b4f97d6 Stefan Weil
 * Copyright (C) 2006-2011 Stefan Weil
5 663e8e51 ths
 *
6 663e8e51 ths
 * Portions of the code are copies from grub / etherboot eepro100.c
7 663e8e51 ths
 * and linux e100.c.
8 663e8e51 ths
 *
9 230a167c Stefan Weil
 * This program is free software: you can redistribute it and/or modify
10 663e8e51 ths
 * it under the terms of the GNU General Public License as published by
11 230a167c Stefan Weil
 * the Free Software Foundation, either version 2 of the License, or
12 230a167c Stefan Weil
 * (at your option) version 3 or any later version.
13 663e8e51 ths
 *
14 663e8e51 ths
 * This program is distributed in the hope that it will be useful,
15 663e8e51 ths
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 663e8e51 ths
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 663e8e51 ths
 * GNU General Public License for more details.
18 663e8e51 ths
 *
19 663e8e51 ths
 * You should have received a copy of the GNU General Public License
20 230a167c Stefan Weil
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 663e8e51 ths
 *
22 663e8e51 ths
 * Tested features (i82559):
23 e5e23ab8 Stefan Weil
 *      PXE boot (i386 guest, i386 / mips / mipsel / ppc host) ok
24 663e8e51 ths
 *      Linux networking (i386) ok
25 663e8e51 ths
 *
26 663e8e51 ths
 * Untested:
27 663e8e51 ths
 *      Windows networking
28 663e8e51 ths
 *
29 663e8e51 ths
 * References:
30 663e8e51 ths
 *
31 663e8e51 ths
 * Intel 8255x 10/100 Mbps Ethernet Controller Family
32 663e8e51 ths
 * Open Source Software Developer Manual
33 ba19f2de Stefan Weil
 *
34 ba19f2de Stefan Weil
 * TODO:
35 ba19f2de Stefan Weil
 *      * PHY emulation should be separated from nic emulation.
36 ba19f2de Stefan Weil
 *        Most nic emulations could share the same phy code.
37 ba19f2de Stefan Weil
 *      * i82550 is untested. It is programmed like the i82559.
38 ba19f2de Stefan Weil
 *      * i82562 is untested. It is programmed like the i82559.
39 ba19f2de Stefan Weil
 *      * Power management (i82558 and later) is not implemented.
40 ba19f2de Stefan Weil
 *      * Wake-on-LAN is not implemented.
41 663e8e51 ths
 */
42 663e8e51 ths
43 663e8e51 ths
#include <stddef.h>             /* offsetof */
44 87ecb68b pbrook
#include "hw.h"
45 87ecb68b pbrook
#include "pci.h"
46 87ecb68b pbrook
#include "net.h"
47 663e8e51 ths
#include "eeprom93xx.h"
48 1ca4d09a Gleb Natapov
#include "sysemu.h"
49 16ef60c9 Eduard - Gabriel Munteanu
#include "dma.h"
50 663e8e51 ths
51 792f1d63 Stefan Weil
/* QEMU sends frames smaller than 60 bytes to ethernet nics.
52 792f1d63 Stefan Weil
 * Such frames are rejected by real nics and their emulations.
53 792f1d63 Stefan Weil
 * To avoid this behaviour, other nic emulations pad received
54 792f1d63 Stefan Weil
 * frames. The following definition enables this padding for
55 792f1d63 Stefan Weil
 * eepro100, too. We keep the define around in case it might
56 792f1d63 Stefan Weil
 * become useful the future if the core networking is ever
57 792f1d63 Stefan Weil
 * changed to pad short packets itself. */
58 792f1d63 Stefan Weil
#define CONFIG_PAD_RECEIVED_FRAMES
59 792f1d63 Stefan Weil
60 663e8e51 ths
#define KiB 1024
61 663e8e51 ths
62 aac443e6 Stefan Weil
/* Debug EEPRO100 card. */
63 ce0e58b3 Stefan Weil
#if 0
64 ce0e58b3 Stefan Weil
# define DEBUG_EEPRO100
65 ce0e58b3 Stefan Weil
#endif
66 663e8e51 ths
67 663e8e51 ths
#ifdef DEBUG_EEPRO100
68 001faf32 Blue Swirl
#define logout(fmt, ...) fprintf(stderr, "EE100\t%-24s" fmt, __func__, ## __VA_ARGS__)
69 663e8e51 ths
#else
70 001faf32 Blue Swirl
#define logout(fmt, ...) ((void)0)
71 663e8e51 ths
#endif
72 663e8e51 ths
73 663e8e51 ths
/* Set flags to 0 to disable debug output. */
74 aac443e6 Stefan Weil
#define INT     1       /* interrupt related actions */
75 aac443e6 Stefan Weil
#define MDI     1       /* mdi related actions */
76 aac443e6 Stefan Weil
#define OTHER   1
77 aac443e6 Stefan Weil
#define RXTX    1
78 aac443e6 Stefan Weil
#define EEPROM  1       /* eeprom related actions */
79 663e8e51 ths
80 663e8e51 ths
#define TRACE(flag, command) ((flag) ? (command) : (void)0)
81 663e8e51 ths
82 7f1e9d4e Kevin Wolf
#define missing(text) fprintf(stderr, "eepro100: feature is missing in this emulation: " text "\n")
83 663e8e51 ths
84 663e8e51 ths
#define MAX_ETH_FRAME_SIZE 1514
85 663e8e51 ths
86 663e8e51 ths
/* This driver supports several different devices which are declared here. */
87 c4c270e2 Stefan Weil
#define i82550          0x82550
88 663e8e51 ths
#define i82551          0x82551
89 c4c270e2 Stefan Weil
#define i82557A         0x82557a
90 663e8e51 ths
#define i82557B         0x82557b
91 663e8e51 ths
#define i82557C         0x82557c
92 c4c270e2 Stefan Weil
#define i82558A         0x82558a
93 663e8e51 ths
#define i82558B         0x82558b
94 c4c270e2 Stefan Weil
#define i82559A         0x82559a
95 c4c270e2 Stefan Weil
#define i82559B         0x82559b
96 663e8e51 ths
#define i82559C         0x82559c
97 663e8e51 ths
#define i82559ER        0x82559e
98 663e8e51 ths
#define i82562          0x82562
99 db667a12 Stefan Weil
#define i82801          0x82801
100 663e8e51 ths
101 aac443e6 Stefan Weil
/* Use 64 word EEPROM. TODO: could be a runtime option. */
102 663e8e51 ths
#define EEPROM_SIZE     64
103 663e8e51 ths
104 663e8e51 ths
#define PCI_MEM_SIZE            (4 * KiB)
105 663e8e51 ths
#define PCI_IO_SIZE             64
106 663e8e51 ths
#define PCI_FLASH_SIZE          (128 * KiB)
107 663e8e51 ths
108 663e8e51 ths
#define BIT(n) (1 << (n))
109 663e8e51 ths
#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
110 663e8e51 ths
111 663e8e51 ths
/* The SCB accepts the following controls for the Tx and Rx units: */
112 663e8e51 ths
#define  CU_NOP         0x0000  /* No operation. */
113 663e8e51 ths
#define  CU_START       0x0010  /* CU start. */
114 663e8e51 ths
#define  CU_RESUME      0x0020  /* CU resume. */
115 663e8e51 ths
#define  CU_STATSADDR   0x0040  /* Load dump counters address. */
116 663e8e51 ths
#define  CU_SHOWSTATS   0x0050  /* Dump statistical counters. */
117 663e8e51 ths
#define  CU_CMD_BASE    0x0060  /* Load CU base address. */
118 663e8e51 ths
#define  CU_DUMPSTATS   0x0070  /* Dump and reset statistical counters. */
119 663e8e51 ths
#define  CU_SRESUME     0x00a0  /* CU static resume. */
120 663e8e51 ths
121 663e8e51 ths
#define  RU_NOP         0x0000
122 663e8e51 ths
#define  RX_START       0x0001
123 663e8e51 ths
#define  RX_RESUME      0x0002
124 e824012b Stefan Weil
#define  RU_ABORT       0x0004
125 663e8e51 ths
#define  RX_ADDR_LOAD   0x0006
126 663e8e51 ths
#define  RX_RESUMENR    0x0007
127 663e8e51 ths
#define INT_MASK        0x0100
128 663e8e51 ths
#define DRVR_INT        0x0200  /* Driver generated interrupt. */
129 663e8e51 ths
130 558c8634 Stefan Weil
typedef struct {
131 558c8634 Stefan Weil
    PCIDeviceInfo pci;
132 558c8634 Stefan Weil
    uint32_t device;
133 558c8634 Stefan Weil
    uint8_t stats_size;
134 558c8634 Stefan Weil
    bool has_extended_tcb_support;
135 558c8634 Stefan Weil
    bool power_management;
136 558c8634 Stefan Weil
} E100PCIDeviceInfo;
137 558c8634 Stefan Weil
138 663e8e51 ths
/* Offsets to the various registers.
139 663e8e51 ths
   All accesses need not be longword aligned. */
140 e5e23ab8 Stefan Weil
typedef enum {
141 0908bba1 Stefan Weil
    SCBStatus = 0,              /* Status Word. */
142 663e8e51 ths
    SCBAck = 1,
143 663e8e51 ths
    SCBCmd = 2,                 /* Rx/Command Unit command and status. */
144 663e8e51 ths
    SCBIntmask = 3,
145 663e8e51 ths
    SCBPointer = 4,             /* General purpose pointer. */
146 663e8e51 ths
    SCBPort = 8,                /* Misc. commands and operands.  */
147 0908bba1 Stefan Weil
    SCBflash = 12,              /* Flash memory control. */
148 0908bba1 Stefan Weil
    SCBeeprom = 14,             /* EEPROM control. */
149 663e8e51 ths
    SCBCtrlMDI = 16,            /* MDI interface control. */
150 663e8e51 ths
    SCBEarlyRx = 20,            /* Early receive byte count. */
151 0908bba1 Stefan Weil
    SCBFlow = 24,               /* Flow Control. */
152 0908bba1 Stefan Weil
    SCBpmdr = 27,               /* Power Management Driver. */
153 0908bba1 Stefan Weil
    SCBgctrl = 28,              /* General Control. */
154 0908bba1 Stefan Weil
    SCBgstat = 29,              /* General Status. */
155 e5e23ab8 Stefan Weil
} E100RegisterOffset;
156 663e8e51 ths
157 663e8e51 ths
/* A speedo3 transmit buffer descriptor with two buffers... */
158 663e8e51 ths
typedef struct {
159 663e8e51 ths
    uint16_t status;
160 663e8e51 ths
    uint16_t command;
161 663e8e51 ths
    uint32_t link;              /* void * */
162 7b8737de Stefan Weil
    uint32_t tbd_array_addr;    /* transmit buffer descriptor array address. */
163 663e8e51 ths
    uint16_t tcb_bytes;         /* transmit command block byte count (in lower 14 bits */
164 663e8e51 ths
    uint8_t tx_threshold;       /* transmit threshold */
165 663e8e51 ths
    uint8_t tbd_count;          /* TBD number */
166 e7493b25 Stefan Weil
#if 0
167 e7493b25 Stefan Weil
    /* This constitutes two "TBD" entries: hdr and data */
168 e7493b25 Stefan Weil
    uint32_t tx_buf_addr0;  /* void *, header of frame to be transmitted.  */
169 e7493b25 Stefan Weil
    int32_t  tx_buf_size0;  /* Length of Tx hdr. */
170 e7493b25 Stefan Weil
    uint32_t tx_buf_addr1;  /* void *, data to be transmitted.  */
171 e7493b25 Stefan Weil
    int32_t  tx_buf_size1;  /* Length of Tx data. */
172 e7493b25 Stefan Weil
#endif
173 c227f099 Anthony Liguori
} eepro100_tx_t;
174 663e8e51 ths
175 663e8e51 ths
/* Receive frame descriptor. */
176 663e8e51 ths
typedef struct {
177 663e8e51 ths
    int16_t status;
178 663e8e51 ths
    uint16_t command;
179 663e8e51 ths
    uint32_t link;              /* struct RxFD * */
180 663e8e51 ths
    uint32_t rx_buf_addr;       /* void * */
181 663e8e51 ths
    uint16_t count;
182 663e8e51 ths
    uint16_t size;
183 27112f18 Stefan Weil
    /* Ethernet frame data follows. */
184 c227f099 Anthony Liguori
} eepro100_rx_t;
185 663e8e51 ths
186 ced5296a Stefan Weil
typedef enum {
187 ced5296a Stefan Weil
    COMMAND_EL = BIT(15),
188 ced5296a Stefan Weil
    COMMAND_S = BIT(14),
189 ced5296a Stefan Weil
    COMMAND_I = BIT(13),
190 ced5296a Stefan Weil
    COMMAND_NC = BIT(4),
191 ced5296a Stefan Weil
    COMMAND_SF = BIT(3),
192 ced5296a Stefan Weil
    COMMAND_CMD = BITS(2, 0),
193 ced5296a Stefan Weil
} scb_command_bit;
194 ced5296a Stefan Weil
195 ced5296a Stefan Weil
typedef enum {
196 ced5296a Stefan Weil
    STATUS_C = BIT(15),
197 ced5296a Stefan Weil
    STATUS_OK = BIT(13),
198 ced5296a Stefan Weil
} scb_status_bit;
199 ced5296a Stefan Weil
200 663e8e51 ths
typedef struct {
201 663e8e51 ths
    uint32_t tx_good_frames, tx_max_collisions, tx_late_collisions,
202 cc02c66c Stefan Weil
             tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
203 cc02c66c Stefan Weil
             tx_multiple_collisions, tx_total_collisions;
204 663e8e51 ths
    uint32_t rx_good_frames, rx_crc_errors, rx_alignment_errors,
205 cc02c66c Stefan Weil
             rx_resource_errors, rx_overrun_errors, rx_cdt_errors,
206 cc02c66c Stefan Weil
             rx_short_frame_errors;
207 663e8e51 ths
    uint32_t fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
208 663e8e51 ths
    uint16_t xmt_tco_frames, rcv_tco_frames;
209 ba42b646 Stefan Weil
    /* TODO: i82559 has six reserved statistics but a total of 24 dwords. */
210 ba42b646 Stefan Weil
    uint32_t reserved[4];
211 c227f099 Anthony Liguori
} eepro100_stats_t;
212 663e8e51 ths
213 663e8e51 ths
typedef enum {
214 663e8e51 ths
    cu_idle = 0,
215 663e8e51 ths
    cu_suspended = 1,
216 663e8e51 ths
    cu_active = 2,
217 663e8e51 ths
    cu_lpq_active = 2,
218 663e8e51 ths
    cu_hqp_active = 3
219 c227f099 Anthony Liguori
} cu_state_t;
220 663e8e51 ths
221 663e8e51 ths
typedef enum {
222 663e8e51 ths
    ru_idle = 0,
223 663e8e51 ths
    ru_suspended = 1,
224 663e8e51 ths
    ru_no_resources = 2,
225 663e8e51 ths
    ru_ready = 4
226 c227f099 Anthony Liguori
} ru_state_t;
227 663e8e51 ths
228 663e8e51 ths
typedef struct {
229 273a2142 Juan Quintela
    PCIDevice dev;
230 010ec629 Stefan Weil
    /* Hash register (multicast mask array, multiple individual addresses). */
231 010ec629 Stefan Weil
    uint8_t mult[8];
232 5e6ffdde Avi Kivity
    MemoryRegion mmio_bar;
233 5e6ffdde Avi Kivity
    MemoryRegion io_bar;
234 5e6ffdde Avi Kivity
    MemoryRegion flash_bar;
235 e00e365e Mark McLoughlin
    NICState *nic;
236 508ef936 Gerd Hoffmann
    NICConf conf;
237 663e8e51 ths
    uint8_t scb_stat;           /* SCB stat/ack byte */
238 663e8e51 ths
    uint8_t int_stat;           /* PCI interrupt status */
239 3706c43f Stefan Weil
    /* region must not be saved by nic_save. */
240 663e8e51 ths
    uint16_t mdimem[32];
241 c227f099 Anthony Liguori
    eeprom_t *eeprom;
242 663e8e51 ths
    uint32_t device;            /* device variant */
243 663e8e51 ths
    /* (cu_base + cu_offset) address the next command block in the command block list. */
244 663e8e51 ths
    uint32_t cu_base;           /* CU base address */
245 663e8e51 ths
    uint32_t cu_offset;         /* CU address offset */
246 663e8e51 ths
    /* (ru_base + ru_offset) address the RFD in the Receive Frame Area. */
247 663e8e51 ths
    uint32_t ru_base;           /* RU base address */
248 663e8e51 ths
    uint32_t ru_offset;         /* RU address offset */
249 c227f099 Anthony Liguori
    uint32_t statsaddr;         /* pointer to eepro100_stats_t */
250 ba42b646 Stefan Weil
251 f3a52e50 Stefan Weil
    /* Temporary status information (no need to save these values),
252 f3a52e50 Stefan Weil
     * used while processing CU commands. */
253 f3a52e50 Stefan Weil
    eepro100_tx_t tx;           /* transmit buffer descriptor */
254 f3a52e50 Stefan Weil
    uint32_t cb_address;        /* = cu_base + cu_offset */
255 f3a52e50 Stefan Weil
256 ba42b646 Stefan Weil
    /* Statistical counters. Also used for wake-up packet (i82559). */
257 ba42b646 Stefan Weil
    eepro100_stats_t statistics;
258 ba42b646 Stefan Weil
259 e5e23ab8 Stefan Weil
    /* Data in mem is always in the byte order of the controller (le).
260 e5e23ab8 Stefan Weil
     * It must be dword aligned to allow direct access to 32 bit values. */
261 e5e23ab8 Stefan Weil
    uint8_t mem[PCI_MEM_SIZE] __attribute__((aligned(8)));;
262 e5e23ab8 Stefan Weil
263 663e8e51 ths
    /* Configuration bytes. */
264 663e8e51 ths
    uint8_t configuration[22];
265 663e8e51 ths
266 151b2986 Juan Quintela
    /* vmstate for each particular nic */
267 151b2986 Juan Quintela
    VMStateDescription *vmstate;
268 ba42b646 Stefan Weil
269 ba42b646 Stefan Weil
    /* Quasi static device properties (no need to save them). */
270 ba42b646 Stefan Weil
    uint16_t stats_size;
271 ba42b646 Stefan Weil
    bool has_extended_tcb_support;
272 663e8e51 ths
} EEPRO100State;
273 663e8e51 ths
274 6cded3a4 Stefan Weil
/* Word indices in EEPROM. */
275 6cded3a4 Stefan Weil
typedef enum {
276 6cded3a4 Stefan Weil
    EEPROM_CNFG_MDIX  = 0x03,
277 6cded3a4 Stefan Weil
    EEPROM_ID         = 0x05,
278 6cded3a4 Stefan Weil
    EEPROM_PHY_ID     = 0x06,
279 6cded3a4 Stefan Weil
    EEPROM_VENDOR_ID  = 0x0c,
280 6cded3a4 Stefan Weil
    EEPROM_CONFIG_ASF = 0x0d,
281 6cded3a4 Stefan Weil
    EEPROM_DEVICE_ID  = 0x23,
282 6cded3a4 Stefan Weil
    EEPROM_SMBUS_ADDR = 0x90,
283 6cded3a4 Stefan Weil
} EEPROMOffset;
284 6cded3a4 Stefan Weil
285 b1e87018 Stefan Weil
/* Bit values for EEPROM ID word. */
286 b1e87018 Stefan Weil
typedef enum {
287 b1e87018 Stefan Weil
    EEPROM_ID_MDM = BIT(0),     /* Modem */
288 b1e87018 Stefan Weil
    EEPROM_ID_STB = BIT(1),     /* Standby Enable */
289 b1e87018 Stefan Weil
    EEPROM_ID_WMR = BIT(2),     /* ??? */
290 b1e87018 Stefan Weil
    EEPROM_ID_WOL = BIT(5),     /* Wake on LAN */
291 b1e87018 Stefan Weil
    EEPROM_ID_DPD = BIT(6),     /* Deep Power Down */
292 b1e87018 Stefan Weil
    EEPROM_ID_ALT = BIT(7),     /* */
293 b1e87018 Stefan Weil
    /* BITS(10, 8) device revision */
294 b1e87018 Stefan Weil
    EEPROM_ID_BD = BIT(11),     /* boot disable */
295 b1e87018 Stefan Weil
    EEPROM_ID_ID = BIT(13),     /* id bit */
296 b1e87018 Stefan Weil
    /* BITS(15, 14) signature */
297 b1e87018 Stefan Weil
    EEPROM_ID_VALID = BIT(14),  /* signature for valid eeprom */
298 b1e87018 Stefan Weil
} eeprom_id_bit;
299 b1e87018 Stefan Weil
300 663e8e51 ths
/* Default values for MDI (PHY) registers */
301 663e8e51 ths
static const uint16_t eepro100_mdi_default[] = {
302 663e8e51 ths
    /* MDI Registers 0 - 6, 7 */
303 663e8e51 ths
    0x3000, 0x780d, 0x02a8, 0x0154, 0x05e1, 0x0000, 0x0000, 0x0000,
304 663e8e51 ths
    /* MDI Registers 8 - 15 */
305 663e8e51 ths
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
306 663e8e51 ths
    /* MDI Registers 16 - 31 */
307 663e8e51 ths
    0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
308 663e8e51 ths
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
309 663e8e51 ths
};
310 663e8e51 ths
311 663e8e51 ths
/* Readonly mask for MDI (PHY) registers */
312 663e8e51 ths
static const uint16_t eepro100_mdi_mask[] = {
313 663e8e51 ths
    0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000,
314 663e8e51 ths
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
315 663e8e51 ths
    0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
316 663e8e51 ths
    0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
317 663e8e51 ths
};
318 663e8e51 ths
319 663e8e51 ths
#define POLYNOMIAL 0x04c11db6
320 663e8e51 ths
321 663e8e51 ths
/* From FreeBSD */
322 663e8e51 ths
/* XXX: optimize */
323 7b8737de Stefan Weil
static unsigned compute_mcast_idx(const uint8_t * ep)
324 663e8e51 ths
{
325 663e8e51 ths
    uint32_t crc;
326 663e8e51 ths
    int carry, i, j;
327 663e8e51 ths
    uint8_t b;
328 663e8e51 ths
329 663e8e51 ths
    crc = 0xffffffff;
330 663e8e51 ths
    for (i = 0; i < 6; i++) {
331 663e8e51 ths
        b = *ep++;
332 663e8e51 ths
        for (j = 0; j < 8; j++) {
333 663e8e51 ths
            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
334 663e8e51 ths
            crc <<= 1;
335 663e8e51 ths
            b >>= 1;
336 aac443e6 Stefan Weil
            if (carry) {
337 663e8e51 ths
                crc = ((crc ^ POLYNOMIAL) | carry);
338 aac443e6 Stefan Weil
            }
339 663e8e51 ths
        }
340 663e8e51 ths
    }
341 7b8737de Stefan Weil
    return (crc & BITS(7, 2)) >> 2;
342 663e8e51 ths
}
343 663e8e51 ths
344 e5e23ab8 Stefan Weil
/* Read a 16 bit control/status (CSR) register. */
345 e5e23ab8 Stefan Weil
static uint16_t e100_read_reg2(EEPRO100State *s, E100RegisterOffset addr)
346 e5e23ab8 Stefan Weil
{
347 e5e23ab8 Stefan Weil
    assert(!((uintptr_t)&s->mem[addr] & 1));
348 e5e23ab8 Stefan Weil
    return le16_to_cpup((uint16_t *)&s->mem[addr]);
349 e5e23ab8 Stefan Weil
}
350 e5e23ab8 Stefan Weil
351 e5e23ab8 Stefan Weil
/* Read a 32 bit control/status (CSR) register. */
352 e5e23ab8 Stefan Weil
static uint32_t e100_read_reg4(EEPRO100State *s, E100RegisterOffset addr)
353 e5e23ab8 Stefan Weil
{
354 e5e23ab8 Stefan Weil
    assert(!((uintptr_t)&s->mem[addr] & 3));
355 e5e23ab8 Stefan Weil
    return le32_to_cpup((uint32_t *)&s->mem[addr]);
356 e5e23ab8 Stefan Weil
}
357 e5e23ab8 Stefan Weil
358 e5e23ab8 Stefan Weil
/* Write a 16 bit control/status (CSR) register. */
359 e5e23ab8 Stefan Weil
static void e100_write_reg2(EEPRO100State *s, E100RegisterOffset addr,
360 e5e23ab8 Stefan Weil
                            uint16_t val)
361 e5e23ab8 Stefan Weil
{
362 e5e23ab8 Stefan Weil
    assert(!((uintptr_t)&s->mem[addr] & 1));
363 e5e23ab8 Stefan Weil
    cpu_to_le16w((uint16_t *)&s->mem[addr], val);
364 e5e23ab8 Stefan Weil
}
365 e5e23ab8 Stefan Weil
366 e5e23ab8 Stefan Weil
/* Read a 32 bit control/status (CSR) register. */
367 e5e23ab8 Stefan Weil
static void e100_write_reg4(EEPRO100State *s, E100RegisterOffset addr,
368 e5e23ab8 Stefan Weil
                            uint32_t val)
369 e5e23ab8 Stefan Weil
{
370 e5e23ab8 Stefan Weil
    assert(!((uintptr_t)&s->mem[addr] & 3));
371 e5e23ab8 Stefan Weil
    cpu_to_le32w((uint32_t *)&s->mem[addr], val);
372 e5e23ab8 Stefan Weil
}
373 e5e23ab8 Stefan Weil
374 663e8e51 ths
#if defined(DEBUG_EEPRO100)
375 663e8e51 ths
static const char *nic_dump(const uint8_t * buf, unsigned size)
376 663e8e51 ths
{
377 663e8e51 ths
    static char dump[3 * 16 + 1];
378 663e8e51 ths
    char *p = &dump[0];
379 aac443e6 Stefan Weil
    if (size > 16) {
380 663e8e51 ths
        size = 16;
381 aac443e6 Stefan Weil
    }
382 663e8e51 ths
    while (size-- > 0) {
383 663e8e51 ths
        p += sprintf(p, " %02x", *buf++);
384 663e8e51 ths
    }
385 663e8e51 ths
    return dump;
386 663e8e51 ths
}
387 663e8e51 ths
#endif                          /* DEBUG_EEPRO100 */
388 663e8e51 ths
389 663e8e51 ths
enum scb_stat_ack {
390 663e8e51 ths
    stat_ack_not_ours = 0x00,
391 663e8e51 ths
    stat_ack_sw_gen = 0x04,
392 663e8e51 ths
    stat_ack_rnr = 0x10,
393 663e8e51 ths
    stat_ack_cu_idle = 0x20,
394 663e8e51 ths
    stat_ack_frame_rx = 0x40,
395 663e8e51 ths
    stat_ack_cu_cmd_done = 0x80,
396 663e8e51 ths
    stat_ack_not_present = 0xFF,
397 663e8e51 ths
    stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx),
398 663e8e51 ths
    stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done),
399 663e8e51 ths
};
400 663e8e51 ths
401 663e8e51 ths
static void disable_interrupt(EEPRO100State * s)
402 663e8e51 ths
{
403 663e8e51 ths
    if (s->int_stat) {
404 aac443e6 Stefan Weil
        TRACE(INT, logout("interrupt disabled\n"));
405 273a2142 Juan Quintela
        qemu_irq_lower(s->dev.irq[0]);
406 663e8e51 ths
        s->int_stat = 0;
407 663e8e51 ths
    }
408 663e8e51 ths
}
409 663e8e51 ths
410 663e8e51 ths
static void enable_interrupt(EEPRO100State * s)
411 663e8e51 ths
{
412 663e8e51 ths
    if (!s->int_stat) {
413 aac443e6 Stefan Weil
        TRACE(INT, logout("interrupt enabled\n"));
414 273a2142 Juan Quintela
        qemu_irq_raise(s->dev.irq[0]);
415 663e8e51 ths
        s->int_stat = 1;
416 663e8e51 ths
    }
417 663e8e51 ths
}
418 663e8e51 ths
419 663e8e51 ths
static void eepro100_acknowledge(EEPRO100State * s)
420 663e8e51 ths
{
421 663e8e51 ths
    s->scb_stat &= ~s->mem[SCBAck];
422 663e8e51 ths
    s->mem[SCBAck] = s->scb_stat;
423 663e8e51 ths
    if (s->scb_stat == 0) {
424 663e8e51 ths
        disable_interrupt(s);
425 663e8e51 ths
    }
426 663e8e51 ths
}
427 663e8e51 ths
428 e715c8e8 Stefan Weil
static void eepro100_interrupt(EEPRO100State * s, uint8_t status)
429 663e8e51 ths
{
430 663e8e51 ths
    uint8_t mask = ~s->mem[SCBIntmask];
431 e715c8e8 Stefan Weil
    s->mem[SCBAck] |= status;
432 e715c8e8 Stefan Weil
    status = s->scb_stat = s->mem[SCBAck];
433 e715c8e8 Stefan Weil
    status &= (mask | 0x0f);
434 e7493b25 Stefan Weil
#if 0
435 e7493b25 Stefan Weil
    status &= (~s->mem[SCBIntmask] | 0x0xf);
436 e7493b25 Stefan Weil
#endif
437 e715c8e8 Stefan Weil
    if (status && (mask & 0x01)) {
438 663e8e51 ths
        /* SCB mask and SCB Bit M do not disable interrupt. */
439 663e8e51 ths
        enable_interrupt(s);
440 663e8e51 ths
    } else if (s->int_stat) {
441 663e8e51 ths
        disable_interrupt(s);
442 663e8e51 ths
    }
443 663e8e51 ths
}
444 663e8e51 ths
445 663e8e51 ths
static void eepro100_cx_interrupt(EEPRO100State * s)
446 663e8e51 ths
{
447 663e8e51 ths
    /* CU completed action command. */
448 663e8e51 ths
    /* Transmit not ok (82557 only, not in emulation). */
449 663e8e51 ths
    eepro100_interrupt(s, 0x80);
450 663e8e51 ths
}
451 663e8e51 ths
452 663e8e51 ths
static void eepro100_cna_interrupt(EEPRO100State * s)
453 663e8e51 ths
{
454 663e8e51 ths
    /* CU left the active state. */
455 663e8e51 ths
    eepro100_interrupt(s, 0x20);
456 663e8e51 ths
}
457 663e8e51 ths
458 663e8e51 ths
static void eepro100_fr_interrupt(EEPRO100State * s)
459 663e8e51 ths
{
460 663e8e51 ths
    /* RU received a complete frame. */
461 663e8e51 ths
    eepro100_interrupt(s, 0x40);
462 663e8e51 ths
}
463 663e8e51 ths
464 663e8e51 ths
static void eepro100_rnr_interrupt(EEPRO100State * s)
465 663e8e51 ths
{
466 663e8e51 ths
    /* RU is not ready. */
467 663e8e51 ths
    eepro100_interrupt(s, 0x10);
468 663e8e51 ths
}
469 663e8e51 ths
470 663e8e51 ths
static void eepro100_mdi_interrupt(EEPRO100State * s)
471 663e8e51 ths
{
472 663e8e51 ths
    /* MDI completed read or write cycle. */
473 663e8e51 ths
    eepro100_interrupt(s, 0x08);
474 663e8e51 ths
}
475 663e8e51 ths
476 663e8e51 ths
static void eepro100_swi_interrupt(EEPRO100State * s)
477 663e8e51 ths
{
478 663e8e51 ths
    /* Software has requested an interrupt. */
479 663e8e51 ths
    eepro100_interrupt(s, 0x04);
480 663e8e51 ths
}
481 663e8e51 ths
482 663e8e51 ths
#if 0
483 663e8e51 ths
static void eepro100_fcp_interrupt(EEPRO100State * s)
484 663e8e51 ths
{
485 663e8e51 ths
    /* Flow control pause interrupt (82558 and later). */
486 663e8e51 ths
    eepro100_interrupt(s, 0x01);
487 663e8e51 ths
}
488 663e8e51 ths
#endif
489 663e8e51 ths
490 558c8634 Stefan Weil
static void e100_pci_reset(EEPRO100State * s, E100PCIDeviceInfo *e100_device)
491 663e8e51 ths
{
492 663e8e51 ths
    uint32_t device = s->device;
493 273a2142 Juan Quintela
    uint8_t *pci_conf = s->dev.config;
494 663e8e51 ths
495 aac443e6 Stefan Weil
    TRACE(OTHER, logout("%p\n", s));
496 663e8e51 ths
497 663e8e51 ths
    /* PCI Status */
498 ae543b49 Stefan Weil
    pci_set_word(pci_conf + PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
499 ae543b49 Stefan Weil
                                        PCI_STATUS_FAST_BACK);
500 663e8e51 ths
    /* PCI Latency Timer */
501 15e89f59 Michael S. Tsirkin
    pci_set_byte(pci_conf + PCI_LATENCY_TIMER, 0x20);   /* latency timer = 32 clocks */
502 ae543b49 Stefan Weil
    /* Capability Pointer is set by PCI framework. */
503 f62719ca Stefan Weil
    /* Interrupt Line */
504 f62719ca Stefan Weil
    /* Interrupt Pin */
505 f62719ca Stefan Weil
    pci_set_byte(pci_conf + PCI_INTERRUPT_PIN, 1);      /* interrupt pin A */
506 663e8e51 ths
    /* Minimum Grant */
507 15e89f59 Michael S. Tsirkin
    pci_set_byte(pci_conf + PCI_MIN_GNT, 0x08);
508 663e8e51 ths
    /* Maximum Latency */
509 15e89f59 Michael S. Tsirkin
    pci_set_byte(pci_conf + PCI_MAX_LAT, 0x18);
510 663e8e51 ths
511 558c8634 Stefan Weil
    s->stats_size = e100_device->stats_size;
512 558c8634 Stefan Weil
    s->has_extended_tcb_support = e100_device->has_extended_tcb_support;
513 558c8634 Stefan Weil
514 663e8e51 ths
    switch (device) {
515 ba42b646 Stefan Weil
    case i82550:
516 663e8e51 ths
    case i82551:
517 ba42b646 Stefan Weil
    case i82557A:
518 663e8e51 ths
    case i82557B:
519 663e8e51 ths
    case i82557C:
520 ba42b646 Stefan Weil
    case i82558A:
521 663e8e51 ths
    case i82558B:
522 ba42b646 Stefan Weil
    case i82559A:
523 ba42b646 Stefan Weil
    case i82559B:
524 558c8634 Stefan Weil
    case i82559ER:
525 558c8634 Stefan Weil
    case i82562:
526 db667a12 Stefan Weil
    case i82801:
527 663e8e51 ths
    case i82559C:
528 663e8e51 ths
        break;
529 663e8e51 ths
    default:
530 663e8e51 ths
        logout("Device %X is undefined!\n", device);
531 663e8e51 ths
    }
532 663e8e51 ths
533 3dec59a1 Stefan Weil
    /* Standard TxCB. */
534 3dec59a1 Stefan Weil
    s->configuration[6] |= BIT(4);
535 3dec59a1 Stefan Weil
536 558c8634 Stefan Weil
    /* Standard statistical counters. */
537 ba42b646 Stefan Weil
    s->configuration[6] |= BIT(5);
538 ba42b646 Stefan Weil
539 ba42b646 Stefan Weil
    if (s->stats_size == 80) {
540 ba42b646 Stefan Weil
        /* TODO: check TCO Statistical Counters bit. Documentation not clear. */
541 ba42b646 Stefan Weil
        if (s->configuration[6] & BIT(2)) {
542 ba42b646 Stefan Weil
            /* TCO statistical counters. */
543 ba42b646 Stefan Weil
            assert(s->configuration[6] & BIT(5));
544 ba42b646 Stefan Weil
        } else {
545 ba42b646 Stefan Weil
            if (s->configuration[6] & BIT(5)) {
546 ba42b646 Stefan Weil
                /* No extended statistical counters, i82557 compatible. */
547 ba42b646 Stefan Weil
                s->stats_size = 64;
548 ba42b646 Stefan Weil
            } else {
549 ba42b646 Stefan Weil
                /* i82558 compatible. */
550 ba42b646 Stefan Weil
                s->stats_size = 76;
551 ba42b646 Stefan Weil
            }
552 ba42b646 Stefan Weil
        }
553 ba42b646 Stefan Weil
    } else {
554 ba42b646 Stefan Weil
        if (s->configuration[6] & BIT(5)) {
555 ba42b646 Stefan Weil
            /* No extended statistical counters. */
556 ba42b646 Stefan Weil
            s->stats_size = 64;
557 ba42b646 Stefan Weil
        }
558 ba42b646 Stefan Weil
    }
559 ba42b646 Stefan Weil
    assert(s->stats_size > 0 && s->stats_size <= sizeof(s->statistics));
560 ba42b646 Stefan Weil
561 558c8634 Stefan Weil
    if (e100_device->power_management) {
562 ba42b646 Stefan Weil
        /* Power Management Capabilities */
563 8bbd1ce2 Michael S. Tsirkin
        int cfg_offset = 0xdc;
564 ca77089d Isaku Yamahata
        int r = pci_add_capability(&s->dev, PCI_CAP_ID_PM,
565 ca77089d Isaku Yamahata
                                   cfg_offset, PCI_PM_SIZEOF);
566 8bbd1ce2 Michael S. Tsirkin
        assert(r >= 0);
567 8bbd1ce2 Michael S. Tsirkin
        pci_set_word(pci_conf + cfg_offset + PCI_PM_PMC, 0x7e21);
568 ae543b49 Stefan Weil
#if 0 /* TODO: replace dummy code for power management emulation. */
569 8bbd1ce2 Michael S. Tsirkin
        /* TODO: Power Management Control / Status. */
570 8bbd1ce2 Michael S. Tsirkin
        pci_set_word(pci_conf + cfg_offset + PCI_PM_CTRL, 0x0000);
571 8bbd1ce2 Michael S. Tsirkin
        /* TODO: Ethernet Power Consumption Registers (i82559 and later). */
572 8bbd1ce2 Michael S. Tsirkin
        pci_set_byte(pci_conf + cfg_offset + PCI_PM_PPB_EXTENSIONS, 0x0000);
573 ae543b49 Stefan Weil
#endif
574 ba42b646 Stefan Weil
    }
575 ba42b646 Stefan Weil
576 ba42b646 Stefan Weil
#if EEPROM_SIZE > 0
577 663e8e51 ths
    if (device == i82557C || device == i82558B || device == i82559C) {
578 e7493b25 Stefan Weil
        /*
579 e7493b25 Stefan Weil
        TODO: get vendor id from EEPROM for i82557C or later.
580 e7493b25 Stefan Weil
        TODO: get device id from EEPROM for i82557C or later.
581 e7493b25 Stefan Weil
        TODO: status bit 4 can be disabled by EEPROM for i82558, i82559.
582 e7493b25 Stefan Weil
        TODO: header type is determined by EEPROM for i82559.
583 e7493b25 Stefan Weil
        TODO: get subsystem id from EEPROM for i82557C or later.
584 e7493b25 Stefan Weil
        TODO: get subsystem vendor id from EEPROM for i82557C or later.
585 e7493b25 Stefan Weil
        TODO: exp. rom baddr depends on a bit in EEPROM for i82558 or later.
586 e7493b25 Stefan Weil
        TODO: capability pointer depends on EEPROM for i82558.
587 e7493b25 Stefan Weil
        */
588 663e8e51 ths
        logout("Get device id and revision from EEPROM!!!\n");
589 663e8e51 ths
    }
590 ba42b646 Stefan Weil
#endif /* EEPROM_SIZE > 0 */
591 663e8e51 ths
}
592 663e8e51 ths
593 663e8e51 ths
static void nic_selective_reset(EEPRO100State * s)
594 663e8e51 ths
{
595 663e8e51 ths
    size_t i;
596 663e8e51 ths
    uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom);
597 e7493b25 Stefan Weil
#if 0
598 e7493b25 Stefan Weil
    eeprom93xx_reset(s->eeprom);
599 e7493b25 Stefan Weil
#endif
600 508ef936 Gerd Hoffmann
    memcpy(eeprom_contents, s->conf.macaddr.a, 6);
601 b1e87018 Stefan Weil
    eeprom_contents[EEPROM_ID] = EEPROM_ID_VALID;
602 f4e94dfe =?UTF-8?q?Reimar=20D=C3=B6ffinger?=
    if (s->device == i82557B || s->device == i82557C)
603 f4e94dfe =?UTF-8?q?Reimar=20D=C3=B6ffinger?=
        eeprom_contents[5] = 0x0100;
604 6cded3a4 Stefan Weil
    eeprom_contents[EEPROM_PHY_ID] = 1;
605 663e8e51 ths
    uint16_t sum = 0;
606 663e8e51 ths
    for (i = 0; i < EEPROM_SIZE - 1; i++) {
607 663e8e51 ths
        sum += eeprom_contents[i];
608 663e8e51 ths
    }
609 663e8e51 ths
    eeprom_contents[EEPROM_SIZE - 1] = 0xbaba - sum;
610 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("checksum=0x%04x\n", eeprom_contents[EEPROM_SIZE - 1]));
611 663e8e51 ths
612 663e8e51 ths
    memset(s->mem, 0, sizeof(s->mem));
613 e5e23ab8 Stefan Weil
    e100_write_reg4(s, SCBCtrlMDI, BIT(21));
614 663e8e51 ths
615 663e8e51 ths
    assert(sizeof(s->mdimem) == sizeof(eepro100_mdi_default));
616 663e8e51 ths
    memcpy(&s->mdimem[0], &eepro100_mdi_default[0], sizeof(s->mdimem));
617 663e8e51 ths
}
618 663e8e51 ths
619 663e8e51 ths
static void nic_reset(void *opaque)
620 663e8e51 ths
{
621 769cf7a5 Juan Quintela
    EEPRO100State *s = opaque;
622 aac443e6 Stefan Weil
    TRACE(OTHER, logout("%p\n", s));
623 010ec629 Stefan Weil
    /* TODO: Clearing of hash register for selective reset, too? */
624 7b8737de Stefan Weil
    memset(&s->mult[0], 0, sizeof(s->mult));
625 663e8e51 ths
    nic_selective_reset(s);
626 663e8e51 ths
}
627 663e8e51 ths
628 663e8e51 ths
#if defined(DEBUG_EEPRO100)
629 b8f6ba0d Stefan Weil
static const char * const e100_reg[PCI_IO_SIZE / 4] = {
630 663e8e51 ths
    "Command/Status",
631 663e8e51 ths
    "General Pointer",
632 663e8e51 ths
    "Port",
633 663e8e51 ths
    "EEPROM/Flash Control",
634 663e8e51 ths
    "MDI Control",
635 663e8e51 ths
    "Receive DMA Byte Count",
636 b8f6ba0d Stefan Weil
    "Flow Control",
637 663e8e51 ths
    "General Status/Control"
638 663e8e51 ths
};
639 663e8e51 ths
640 663e8e51 ths
static char *regname(uint32_t addr)
641 663e8e51 ths
{
642 ec169288 David Benjamin
    static char buf[32];
643 663e8e51 ths
    if (addr < PCI_IO_SIZE) {
644 b8f6ba0d Stefan Weil
        const char *r = e100_reg[addr / 4];
645 663e8e51 ths
        if (r != 0) {
646 41cbc23c Stefan Weil
            snprintf(buf, sizeof(buf), "%s+%u", r, addr % 4);
647 663e8e51 ths
        } else {
648 41cbc23c Stefan Weil
            snprintf(buf, sizeof(buf), "0x%02x", addr);
649 663e8e51 ths
        }
650 663e8e51 ths
    } else {
651 41cbc23c Stefan Weil
        snprintf(buf, sizeof(buf), "??? 0x%08x", addr);
652 663e8e51 ths
    }
653 663e8e51 ths
    return buf;
654 663e8e51 ths
}
655 663e8e51 ths
#endif                          /* DEBUG_EEPRO100 */
656 663e8e51 ths
657 663e8e51 ths
/*****************************************************************************
658 663e8e51 ths
 *
659 663e8e51 ths
 * Command emulation.
660 663e8e51 ths
 *
661 663e8e51 ths
 ****************************************************************************/
662 663e8e51 ths
663 663e8e51 ths
#if 0
664 663e8e51 ths
static uint16_t eepro100_read_command(EEPRO100State * s)
665 663e8e51 ths
{
666 663e8e51 ths
    uint16_t val = 0xffff;
667 e7493b25 Stefan Weil
    TRACE(OTHER, logout("val=0x%04x\n", val));
668 663e8e51 ths
    return val;
669 663e8e51 ths
}
670 663e8e51 ths
#endif
671 663e8e51 ths
672 663e8e51 ths
/* Commands that can be put in a command list entry. */
673 663e8e51 ths
enum commands {
674 663e8e51 ths
    CmdNOp = 0,
675 663e8e51 ths
    CmdIASetup = 1,
676 663e8e51 ths
    CmdConfigure = 2,
677 663e8e51 ths
    CmdMulticastList = 3,
678 663e8e51 ths
    CmdTx = 4,
679 663e8e51 ths
    CmdTDR = 5,                 /* load microcode */
680 663e8e51 ths
    CmdDump = 6,
681 663e8e51 ths
    CmdDiagnose = 7,
682 663e8e51 ths
683 663e8e51 ths
    /* And some extra flags: */
684 663e8e51 ths
    CmdSuspend = 0x4000,        /* Suspend after completion. */
685 663e8e51 ths
    CmdIntr = 0x2000,           /* Interrupt after completion. */
686 663e8e51 ths
    CmdTxFlex = 0x0008,         /* Use "Flexible mode" for CmdTx command. */
687 663e8e51 ths
};
688 663e8e51 ths
689 c227f099 Anthony Liguori
static cu_state_t get_cu_state(EEPRO100State * s)
690 663e8e51 ths
{
691 ced5296a Stefan Weil
    return ((s->mem[SCBStatus] & BITS(7, 6)) >> 6);
692 663e8e51 ths
}
693 663e8e51 ths
694 c227f099 Anthony Liguori
static void set_cu_state(EEPRO100State * s, cu_state_t state)
695 663e8e51 ths
{
696 ced5296a Stefan Weil
    s->mem[SCBStatus] = (s->mem[SCBStatus] & ~BITS(7, 6)) + (state << 6);
697 663e8e51 ths
}
698 663e8e51 ths
699 c227f099 Anthony Liguori
static ru_state_t get_ru_state(EEPRO100State * s)
700 663e8e51 ths
{
701 ced5296a Stefan Weil
    return ((s->mem[SCBStatus] & BITS(5, 2)) >> 2);
702 663e8e51 ths
}
703 663e8e51 ths
704 c227f099 Anthony Liguori
static void set_ru_state(EEPRO100State * s, ru_state_t state)
705 663e8e51 ths
{
706 ced5296a Stefan Weil
    s->mem[SCBStatus] = (s->mem[SCBStatus] & ~BITS(5, 2)) + (state << 2);
707 663e8e51 ths
}
708 663e8e51 ths
709 663e8e51 ths
static void dump_statistics(EEPRO100State * s)
710 663e8e51 ths
{
711 663e8e51 ths
    /* Dump statistical data. Most data is never changed by the emulation
712 663e8e51 ths
     * and always 0, so we first just copy the whole block and then those
713 663e8e51 ths
     * values which really matter.
714 663e8e51 ths
     * Number of data should check configuration!!!
715 663e8e51 ths
     */
716 16ef60c9 Eduard - Gabriel Munteanu
    pci_dma_write(&s->dev, s->statsaddr,
717 16ef60c9 Eduard - Gabriel Munteanu
                  (uint8_t *) &s->statistics, s->stats_size);
718 16ef60c9 Eduard - Gabriel Munteanu
    stl_le_pci_dma(&s->dev, s->statsaddr + 0,
719 16ef60c9 Eduard - Gabriel Munteanu
                   s->statistics.tx_good_frames);
720 16ef60c9 Eduard - Gabriel Munteanu
    stl_le_pci_dma(&s->dev, s->statsaddr + 36,
721 16ef60c9 Eduard - Gabriel Munteanu
                   s->statistics.rx_good_frames);
722 16ef60c9 Eduard - Gabriel Munteanu
    stl_le_pci_dma(&s->dev, s->statsaddr + 48,
723 16ef60c9 Eduard - Gabriel Munteanu
                   s->statistics.rx_resource_errors);
724 16ef60c9 Eduard - Gabriel Munteanu
    stl_le_pci_dma(&s->dev, s->statsaddr + 60,
725 16ef60c9 Eduard - Gabriel Munteanu
                   s->statistics.rx_short_frame_errors);
726 e7493b25 Stefan Weil
#if 0
727 16ef60c9 Eduard - Gabriel Munteanu
    stw_le_pci_dma(&s->dev, s->statsaddr + 76, s->statistics.xmt_tco_frames);
728 16ef60c9 Eduard - Gabriel Munteanu
    stw_le_pci_dma(&s->dev, s->statsaddr + 78, s->statistics.rcv_tco_frames);
729 e7493b25 Stefan Weil
    missing("CU dump statistical counters");
730 e7493b25 Stefan Weil
#endif
731 663e8e51 ths
}
732 663e8e51 ths
733 3d0f4b9b Stefan Weil
static void read_cb(EEPRO100State *s)
734 3d0f4b9b Stefan Weil
{
735 16ef60c9 Eduard - Gabriel Munteanu
    pci_dma_read(&s->dev, s->cb_address, (uint8_t *) &s->tx, sizeof(s->tx));
736 3d0f4b9b Stefan Weil
    s->tx.status = le16_to_cpu(s->tx.status);
737 3d0f4b9b Stefan Weil
    s->tx.command = le16_to_cpu(s->tx.command);
738 3d0f4b9b Stefan Weil
    s->tx.link = le32_to_cpu(s->tx.link);
739 3d0f4b9b Stefan Weil
    s->tx.tbd_array_addr = le32_to_cpu(s->tx.tbd_array_addr);
740 3d0f4b9b Stefan Weil
    s->tx.tcb_bytes = le16_to_cpu(s->tx.tcb_bytes);
741 3d0f4b9b Stefan Weil
}
742 3d0f4b9b Stefan Weil
743 f3a52e50 Stefan Weil
static void tx_command(EEPRO100State *s)
744 f3a52e50 Stefan Weil
{
745 7b8737de Stefan Weil
    uint32_t tbd_array = le32_to_cpu(s->tx.tbd_array_addr);
746 f3a52e50 Stefan Weil
    uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff);
747 f3a52e50 Stefan Weil
    /* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */
748 f3a52e50 Stefan Weil
    uint8_t buf[2600];
749 f3a52e50 Stefan Weil
    uint16_t size = 0;
750 f3a52e50 Stefan Weil
    uint32_t tbd_address = s->cb_address + 0x10;
751 f3a52e50 Stefan Weil
    TRACE(RXTX, logout
752 f3a52e50 Stefan Weil
        ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
753 f3a52e50 Stefan Weil
         tbd_array, tcb_bytes, s->tx.tbd_count));
754 f3a52e50 Stefan Weil
755 f3a52e50 Stefan Weil
    if (tcb_bytes > 2600) {
756 f3a52e50 Stefan Weil
        logout("TCB byte count too large, using 2600\n");
757 f3a52e50 Stefan Weil
        tcb_bytes = 2600;
758 f3a52e50 Stefan Weil
    }
759 f3a52e50 Stefan Weil
    if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
760 f3a52e50 Stefan Weil
        logout
761 f3a52e50 Stefan Weil
            ("illegal values of TBD array address and TCB byte count!\n");
762 f3a52e50 Stefan Weil
    }
763 f3a52e50 Stefan Weil
    assert(tcb_bytes <= sizeof(buf));
764 f3a52e50 Stefan Weil
    while (size < tcb_bytes) {
765 16ef60c9 Eduard - Gabriel Munteanu
        uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address);
766 16ef60c9 Eduard - Gabriel Munteanu
        uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4);
767 e7493b25 Stefan Weil
#if 0
768 16ef60c9 Eduard - Gabriel Munteanu
        uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6);
769 e7493b25 Stefan Weil
#endif
770 f3a52e50 Stefan Weil
        tbd_address += 8;
771 f3a52e50 Stefan Weil
        TRACE(RXTX, logout
772 f3a52e50 Stefan Weil
            ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
773 f3a52e50 Stefan Weil
             tx_buffer_address, tx_buffer_size));
774 f3a52e50 Stefan Weil
        tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
775 16ef60c9 Eduard - Gabriel Munteanu
        pci_dma_read(&s->dev, tx_buffer_address, &buf[size], tx_buffer_size);
776 f3a52e50 Stefan Weil
        size += tx_buffer_size;
777 f3a52e50 Stefan Weil
    }
778 f3a52e50 Stefan Weil
    if (tbd_array == 0xffffffff) {
779 f3a52e50 Stefan Weil
        /* Simplified mode. Was already handled by code above. */
780 f3a52e50 Stefan Weil
    } else {
781 f3a52e50 Stefan Weil
        /* Flexible mode. */
782 f3a52e50 Stefan Weil
        uint8_t tbd_count = 0;
783 f3a52e50 Stefan Weil
        if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
784 f3a52e50 Stefan Weil
            /* Extended Flexible TCB. */
785 f3a52e50 Stefan Weil
            for (; tbd_count < 2; tbd_count++) {
786 16ef60c9 Eduard - Gabriel Munteanu
                uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev,
787 16ef60c9 Eduard - Gabriel Munteanu
                                                            tbd_address);
788 16ef60c9 Eduard - Gabriel Munteanu
                uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev,
789 16ef60c9 Eduard - Gabriel Munteanu
                                                          tbd_address + 4);
790 16ef60c9 Eduard - Gabriel Munteanu
                uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev,
791 16ef60c9 Eduard - Gabriel Munteanu
                                                        tbd_address + 6);
792 f3a52e50 Stefan Weil
                tbd_address += 8;
793 f3a52e50 Stefan Weil
                TRACE(RXTX, logout
794 f3a52e50 Stefan Weil
                    ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
795 f3a52e50 Stefan Weil
                     tx_buffer_address, tx_buffer_size));
796 f3a52e50 Stefan Weil
                tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
797 16ef60c9 Eduard - Gabriel Munteanu
                pci_dma_read(&s->dev, tx_buffer_address,
798 16ef60c9 Eduard - Gabriel Munteanu
                             &buf[size], tx_buffer_size);
799 f3a52e50 Stefan Weil
                size += tx_buffer_size;
800 f3a52e50 Stefan Weil
                if (tx_buffer_el & 1) {
801 f3a52e50 Stefan Weil
                    break;
802 f3a52e50 Stefan Weil
                }
803 f3a52e50 Stefan Weil
            }
804 f3a52e50 Stefan Weil
        }
805 f3a52e50 Stefan Weil
        tbd_address = tbd_array;
806 f3a52e50 Stefan Weil
        for (; tbd_count < s->tx.tbd_count; tbd_count++) {
807 16ef60c9 Eduard - Gabriel Munteanu
            uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address);
808 16ef60c9 Eduard - Gabriel Munteanu
            uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4);
809 16ef60c9 Eduard - Gabriel Munteanu
            uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6);
810 f3a52e50 Stefan Weil
            tbd_address += 8;
811 f3a52e50 Stefan Weil
            TRACE(RXTX, logout
812 f3a52e50 Stefan Weil
                ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
813 f3a52e50 Stefan Weil
                 tx_buffer_address, tx_buffer_size));
814 f3a52e50 Stefan Weil
            tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
815 16ef60c9 Eduard - Gabriel Munteanu
            pci_dma_read(&s->dev, tx_buffer_address,
816 16ef60c9 Eduard - Gabriel Munteanu
                         &buf[size], tx_buffer_size);
817 f3a52e50 Stefan Weil
            size += tx_buffer_size;
818 f3a52e50 Stefan Weil
            if (tx_buffer_el & 1) {
819 f3a52e50 Stefan Weil
                break;
820 f3a52e50 Stefan Weil
            }
821 f3a52e50 Stefan Weil
        }
822 f3a52e50 Stefan Weil
    }
823 f3a52e50 Stefan Weil
    TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));
824 f3a52e50 Stefan Weil
    qemu_send_packet(&s->nic->nc, buf, size);
825 f3a52e50 Stefan Weil
    s->statistics.tx_good_frames++;
826 f3a52e50 Stefan Weil
    /* Transmit with bad status would raise an CX/TNO interrupt.
827 f3a52e50 Stefan Weil
     * (82557 only). Emulation never has bad status. */
828 e7493b25 Stefan Weil
#if 0
829 e7493b25 Stefan Weil
    eepro100_cx_interrupt(s);
830 e7493b25 Stefan Weil
#endif
831 f3a52e50 Stefan Weil
}
832 f3a52e50 Stefan Weil
833 7b8737de Stefan Weil
static void set_multicast_list(EEPRO100State *s)
834 7b8737de Stefan Weil
{
835 7b8737de Stefan Weil
    uint16_t multicast_count = s->tx.tbd_array_addr & BITS(13, 0);
836 7b8737de Stefan Weil
    uint16_t i;
837 7b8737de Stefan Weil
    memset(&s->mult[0], 0, sizeof(s->mult));
838 7b8737de Stefan Weil
    TRACE(OTHER, logout("multicast list, multicast count = %u\n", multicast_count));
839 7b8737de Stefan Weil
    for (i = 0; i < multicast_count; i += 6) {
840 7b8737de Stefan Weil
        uint8_t multicast_addr[6];
841 16ef60c9 Eduard - Gabriel Munteanu
        pci_dma_read(&s->dev, s->cb_address + 10 + i, multicast_addr, 6);
842 7b8737de Stefan Weil
        TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6)));
843 7b8737de Stefan Weil
        unsigned mcast_idx = compute_mcast_idx(multicast_addr);
844 7b8737de Stefan Weil
        assert(mcast_idx < 64);
845 7b8737de Stefan Weil
        s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7));
846 7b8737de Stefan Weil
    }
847 7b8737de Stefan Weil
}
848 7b8737de Stefan Weil
849 5fa9a0ae Stefan Weil
static void action_command(EEPRO100State *s)
850 663e8e51 ths
{
851 5fa9a0ae Stefan Weil
    for (;;) {
852 3d0f4b9b Stefan Weil
        bool bit_el;
853 3d0f4b9b Stefan Weil
        bool bit_s;
854 3d0f4b9b Stefan Weil
        bool bit_i;
855 3d0f4b9b Stefan Weil
        bool bit_nc;
856 75f5a6cc Stefan Weil
        uint16_t ok_status = STATUS_OK;
857 3d0f4b9b Stefan Weil
        s->cb_address = s->cu_base + s->cu_offset;
858 3d0f4b9b Stefan Weil
        read_cb(s);
859 3d0f4b9b Stefan Weil
        bit_el = ((s->tx.command & COMMAND_EL) != 0);
860 3d0f4b9b Stefan Weil
        bit_s = ((s->tx.command & COMMAND_S) != 0);
861 3d0f4b9b Stefan Weil
        bit_i = ((s->tx.command & COMMAND_I) != 0);
862 3d0f4b9b Stefan Weil
        bit_nc = ((s->tx.command & COMMAND_NC) != 0);
863 3d0f4b9b Stefan Weil
#if 0
864 3d0f4b9b Stefan Weil
        bool bit_sf = ((s->tx.command & COMMAND_SF) != 0);
865 3d0f4b9b Stefan Weil
#endif
866 3d0f4b9b Stefan Weil
        s->cu_offset = s->tx.link;
867 3d0f4b9b Stefan Weil
        TRACE(OTHER,
868 3d0f4b9b Stefan Weil
              logout("val=(cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",
869 3d0f4b9b Stefan Weil
                     s->tx.status, s->tx.command, s->tx.link));
870 3d0f4b9b Stefan Weil
        switch (s->tx.command & COMMAND_CMD) {
871 663e8e51 ths
        case CmdNOp:
872 663e8e51 ths
            /* Do nothing. */
873 663e8e51 ths
            break;
874 663e8e51 ths
        case CmdIASetup:
875 16ef60c9 Eduard - Gabriel Munteanu
            pci_dma_read(&s->dev, s->cb_address + 8, &s->conf.macaddr.a[0], 6);
876 ce0e58b3 Stefan Weil
            TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6)));
877 663e8e51 ths
            break;
878 663e8e51 ths
        case CmdConfigure:
879 16ef60c9 Eduard - Gabriel Munteanu
            pci_dma_read(&s->dev, s->cb_address + 8,
880 16ef60c9 Eduard - Gabriel Munteanu
                         &s->configuration[0], sizeof(s->configuration));
881 010ec629 Stefan Weil
            TRACE(OTHER, logout("configuration: %s\n",
882 010ec629 Stefan Weil
                                nic_dump(&s->configuration[0], 16)));
883 010ec629 Stefan Weil
            TRACE(OTHER, logout("configuration: %s\n",
884 010ec629 Stefan Weil
                                nic_dump(&s->configuration[16],
885 010ec629 Stefan Weil
                                ARRAY_SIZE(s->configuration) - 16)));
886 010ec629 Stefan Weil
            if (s->configuration[20] & BIT(6)) {
887 010ec629 Stefan Weil
                TRACE(OTHER, logout("Multiple IA bit\n"));
888 010ec629 Stefan Weil
            }
889 663e8e51 ths
            break;
890 663e8e51 ths
        case CmdMulticastList:
891 7b8737de Stefan Weil
            set_multicast_list(s);
892 663e8e51 ths
            break;
893 663e8e51 ths
        case CmdTx:
894 7f1e9d4e Kevin Wolf
            if (bit_nc) {
895 7f1e9d4e Kevin Wolf
                missing("CmdTx: NC = 0");
896 75f5a6cc Stefan Weil
                ok_status = 0;
897 7f1e9d4e Kevin Wolf
                break;
898 7f1e9d4e Kevin Wolf
            }
899 f3a52e50 Stefan Weil
            tx_command(s);
900 663e8e51 ths
            break;
901 663e8e51 ths
        case CmdTDR:
902 aac443e6 Stefan Weil
            TRACE(OTHER, logout("load microcode\n"));
903 663e8e51 ths
            /* Starting with offset 8, the command contains
904 663e8e51 ths
             * 64 dwords microcode which we just ignore here. */
905 663e8e51 ths
            break;
906 f80a7fc3 Stefan Weil
        case CmdDiagnose:
907 f80a7fc3 Stefan Weil
            TRACE(OTHER, logout("diagnose\n"));
908 f80a7fc3 Stefan Weil
            /* Make sure error flag is not set. */
909 f80a7fc3 Stefan Weil
            s->tx.status = 0;
910 f80a7fc3 Stefan Weil
            break;
911 663e8e51 ths
        default:
912 663e8e51 ths
            missing("undefined command");
913 75f5a6cc Stefan Weil
            ok_status = 0;
914 7f1e9d4e Kevin Wolf
            break;
915 663e8e51 ths
        }
916 7f1e9d4e Kevin Wolf
        /* Write new status. */
917 16ef60c9 Eduard - Gabriel Munteanu
        stw_le_pci_dma(&s->dev, s->cb_address,
918 16ef60c9 Eduard - Gabriel Munteanu
                       s->tx.status | ok_status | STATUS_C);
919 663e8e51 ths
        if (bit_i) {
920 663e8e51 ths
            /* CU completed action. */
921 663e8e51 ths
            eepro100_cx_interrupt(s);
922 663e8e51 ths
        }
923 663e8e51 ths
        if (bit_el) {
924 aac443e6 Stefan Weil
            /* CU becomes idle. Terminate command loop. */
925 663e8e51 ths
            set_cu_state(s, cu_idle);
926 663e8e51 ths
            eepro100_cna_interrupt(s);
927 5fa9a0ae Stefan Weil
            break;
928 663e8e51 ths
        } else if (bit_s) {
929 5fa9a0ae Stefan Weil
            /* CU becomes suspended. Terminate command loop. */
930 663e8e51 ths
            set_cu_state(s, cu_suspended);
931 663e8e51 ths
            eepro100_cna_interrupt(s);
932 5fa9a0ae Stefan Weil
            break;
933 663e8e51 ths
        } else {
934 663e8e51 ths
            /* More entries in list. */
935 aac443e6 Stefan Weil
            TRACE(OTHER, logout("CU list with at least one more entry\n"));
936 663e8e51 ths
        }
937 5fa9a0ae Stefan Weil
    }
938 5fa9a0ae Stefan Weil
    TRACE(OTHER, logout("CU list empty\n"));
939 5fa9a0ae Stefan Weil
    /* List is empty. Now CU is idle or suspended. */
940 5fa9a0ae Stefan Weil
}
941 5fa9a0ae Stefan Weil
942 5fa9a0ae Stefan Weil
static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
943 5fa9a0ae Stefan Weil
{
944 cb25a3fb Stefan Weil
    cu_state_t cu_state;
945 5fa9a0ae Stefan Weil
    switch (val) {
946 5fa9a0ae Stefan Weil
    case CU_NOP:
947 5fa9a0ae Stefan Weil
        /* No operation. */
948 5fa9a0ae Stefan Weil
        break;
949 5fa9a0ae Stefan Weil
    case CU_START:
950 cb25a3fb Stefan Weil
        cu_state = get_cu_state(s);
951 cb25a3fb Stefan Weil
        if (cu_state != cu_idle && cu_state != cu_suspended) {
952 cb25a3fb Stefan Weil
            /* Intel documentation says that CU must be idle or suspended
953 cb25a3fb Stefan Weil
             * for the CU start command. */
954 cb25a3fb Stefan Weil
            logout("unexpected CU state is %u\n", cu_state);
955 5fa9a0ae Stefan Weil
        }
956 5fa9a0ae Stefan Weil
        set_cu_state(s, cu_active);
957 27a05006 Stefan Weil
        s->cu_offset = e100_read_reg4(s, SCBPointer);
958 5fa9a0ae Stefan Weil
        action_command(s);
959 663e8e51 ths
        break;
960 663e8e51 ths
    case CU_RESUME:
961 663e8e51 ths
        if (get_cu_state(s) != cu_suspended) {
962 663e8e51 ths
            logout("bad CU resume from CU state %u\n", get_cu_state(s));
963 663e8e51 ths
            /* Workaround for bad Linux eepro100 driver which resumes
964 663e8e51 ths
             * from idle state. */
965 e7493b25 Stefan Weil
#if 0
966 e7493b25 Stefan Weil
            missing("cu resume");
967 e7493b25 Stefan Weil
#endif
968 663e8e51 ths
            set_cu_state(s, cu_suspended);
969 663e8e51 ths
        }
970 663e8e51 ths
        if (get_cu_state(s) == cu_suspended) {
971 aac443e6 Stefan Weil
            TRACE(OTHER, logout("CU resuming\n"));
972 663e8e51 ths
            set_cu_state(s, cu_active);
973 5fa9a0ae Stefan Weil
            action_command(s);
974 663e8e51 ths
        }
975 663e8e51 ths
        break;
976 663e8e51 ths
    case CU_STATSADDR:
977 663e8e51 ths
        /* Load dump counters address. */
978 27a05006 Stefan Weil
        s->statsaddr = e100_read_reg4(s, SCBPointer);
979 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (status address)\n", val));
980 663e8e51 ths
        break;
981 663e8e51 ths
    case CU_SHOWSTATS:
982 663e8e51 ths
        /* Dump statistical counters. */
983 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val));
984 663e8e51 ths
        dump_statistics(s);
985 16ef60c9 Eduard - Gabriel Munteanu
        stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa005);
986 663e8e51 ths
        break;
987 663e8e51 ths
    case CU_CMD_BASE:
988 663e8e51 ths
        /* Load CU base. */
989 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (CU base address)\n", val));
990 27a05006 Stefan Weil
        s->cu_base = e100_read_reg4(s, SCBPointer);
991 663e8e51 ths
        break;
992 663e8e51 ths
    case CU_DUMPSTATS:
993 663e8e51 ths
        /* Dump and reset statistical counters. */
994 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val));
995 663e8e51 ths
        dump_statistics(s);
996 16ef60c9 Eduard - Gabriel Munteanu
        stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa007);
997 663e8e51 ths
        memset(&s->statistics, 0, sizeof(s->statistics));
998 663e8e51 ths
        break;
999 663e8e51 ths
    case CU_SRESUME:
1000 663e8e51 ths
        /* CU static resume. */
1001 663e8e51 ths
        missing("CU static resume");
1002 663e8e51 ths
        break;
1003 663e8e51 ths
    default:
1004 663e8e51 ths
        missing("Undefined CU command");
1005 663e8e51 ths
    }
1006 663e8e51 ths
}
1007 663e8e51 ths
1008 663e8e51 ths
static void eepro100_ru_command(EEPRO100State * s, uint8_t val)
1009 663e8e51 ths
{
1010 663e8e51 ths
    switch (val) {
1011 663e8e51 ths
    case RU_NOP:
1012 663e8e51 ths
        /* No operation. */
1013 663e8e51 ths
        break;
1014 663e8e51 ths
    case RX_START:
1015 663e8e51 ths
        /* RU start. */
1016 663e8e51 ths
        if (get_ru_state(s) != ru_idle) {
1017 663e8e51 ths
            logout("RU state is %u, should be %u\n", get_ru_state(s), ru_idle);
1018 e7493b25 Stefan Weil
#if 0
1019 e7493b25 Stefan Weil
            assert(!"wrong RU state");
1020 e7493b25 Stefan Weil
#endif
1021 663e8e51 ths
        }
1022 663e8e51 ths
        set_ru_state(s, ru_ready);
1023 27a05006 Stefan Weil
        s->ru_offset = e100_read_reg4(s, SCBPointer);
1024 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (rx start)\n", val));
1025 663e8e51 ths
        break;
1026 663e8e51 ths
    case RX_RESUME:
1027 663e8e51 ths
        /* Restart RU. */
1028 663e8e51 ths
        if (get_ru_state(s) != ru_suspended) {
1029 663e8e51 ths
            logout("RU state is %u, should be %u\n", get_ru_state(s),
1030 663e8e51 ths
                   ru_suspended);
1031 e7493b25 Stefan Weil
#if 0
1032 e7493b25 Stefan Weil
            assert(!"wrong RU state");
1033 e7493b25 Stefan Weil
#endif
1034 663e8e51 ths
        }
1035 663e8e51 ths
        set_ru_state(s, ru_ready);
1036 663e8e51 ths
        break;
1037 e824012b Stefan Weil
    case RU_ABORT:
1038 e824012b Stefan Weil
        /* RU abort. */
1039 e824012b Stefan Weil
        if (get_ru_state(s) == ru_ready) {
1040 e824012b Stefan Weil
            eepro100_rnr_interrupt(s);
1041 e824012b Stefan Weil
        }
1042 e824012b Stefan Weil
        set_ru_state(s, ru_idle);
1043 e824012b Stefan Weil
        break;
1044 663e8e51 ths
    case RX_ADDR_LOAD:
1045 663e8e51 ths
        /* Load RU base. */
1046 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (RU base address)\n", val));
1047 27a05006 Stefan Weil
        s->ru_base = e100_read_reg4(s, SCBPointer);
1048 663e8e51 ths
        break;
1049 663e8e51 ths
    default:
1050 663e8e51 ths
        logout("val=0x%02x (undefined RU command)\n", val);
1051 663e8e51 ths
        missing("Undefined SU command");
1052 663e8e51 ths
    }
1053 663e8e51 ths
}
1054 663e8e51 ths
1055 663e8e51 ths
static void eepro100_write_command(EEPRO100State * s, uint8_t val)
1056 663e8e51 ths
{
1057 663e8e51 ths
    eepro100_ru_command(s, val & 0x0f);
1058 663e8e51 ths
    eepro100_cu_command(s, val & 0xf0);
1059 663e8e51 ths
    if ((val) == 0) {
1060 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x\n", val));
1061 663e8e51 ths
    }
1062 663e8e51 ths
    /* Clear command byte after command was accepted. */
1063 663e8e51 ths
    s->mem[SCBCmd] = 0;
1064 663e8e51 ths
}
1065 663e8e51 ths
1066 663e8e51 ths
/*****************************************************************************
1067 663e8e51 ths
 *
1068 663e8e51 ths
 * EEPROM emulation.
1069 663e8e51 ths
 *
1070 663e8e51 ths
 ****************************************************************************/
1071 663e8e51 ths
1072 663e8e51 ths
#define EEPROM_CS       0x02
1073 663e8e51 ths
#define EEPROM_SK       0x01
1074 663e8e51 ths
#define EEPROM_DI       0x04
1075 663e8e51 ths
#define EEPROM_DO       0x08
1076 663e8e51 ths
1077 663e8e51 ths
static uint16_t eepro100_read_eeprom(EEPRO100State * s)
1078 663e8e51 ths
{
1079 e5e23ab8 Stefan Weil
    uint16_t val = e100_read_reg2(s, SCBeeprom);
1080 663e8e51 ths
    if (eeprom93xx_read(s->eeprom)) {
1081 663e8e51 ths
        val |= EEPROM_DO;
1082 663e8e51 ths
    } else {
1083 663e8e51 ths
        val &= ~EEPROM_DO;
1084 663e8e51 ths
    }
1085 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("val=0x%04x\n", val));
1086 663e8e51 ths
    return val;
1087 663e8e51 ths
}
1088 663e8e51 ths
1089 c227f099 Anthony Liguori
static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val)
1090 663e8e51 ths
{
1091 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("val=0x%02x\n", val));
1092 663e8e51 ths
1093 ebabb67a Stefan Weil
    /* mask unwritable bits */
1094 e7493b25 Stefan Weil
#if 0
1095 e7493b25 Stefan Weil
    val = SET_MASKED(val, 0x31, eeprom->value);
1096 e7493b25 Stefan Weil
#endif
1097 663e8e51 ths
1098 663e8e51 ths
    int eecs = ((val & EEPROM_CS) != 0);
1099 663e8e51 ths
    int eesk = ((val & EEPROM_SK) != 0);
1100 663e8e51 ths
    int eedi = ((val & EEPROM_DI) != 0);
1101 663e8e51 ths
    eeprom93xx_write(eeprom, eecs, eesk, eedi);
1102 663e8e51 ths
}
1103 663e8e51 ths
1104 663e8e51 ths
/*****************************************************************************
1105 663e8e51 ths
 *
1106 663e8e51 ths
 * MDI emulation.
1107 663e8e51 ths
 *
1108 663e8e51 ths
 ****************************************************************************/
1109 663e8e51 ths
1110 663e8e51 ths
#if defined(DEBUG_EEPRO100)
1111 6a0b9cc9 Reimar Dรถffinger
static const char * const mdi_op_name[] = {
1112 663e8e51 ths
    "opcode 0",
1113 663e8e51 ths
    "write",
1114 663e8e51 ths
    "read",
1115 663e8e51 ths
    "opcode 3"
1116 663e8e51 ths
};
1117 663e8e51 ths
1118 6a0b9cc9 Reimar Dรถffinger
static const char * const mdi_reg_name[] = {
1119 663e8e51 ths
    "Control",
1120 663e8e51 ths
    "Status",
1121 663e8e51 ths
    "PHY Identification (Word 1)",
1122 663e8e51 ths
    "PHY Identification (Word 2)",
1123 663e8e51 ths
    "Auto-Negotiation Advertisement",
1124 663e8e51 ths
    "Auto-Negotiation Link Partner Ability",
1125 663e8e51 ths
    "Auto-Negotiation Expansion"
1126 663e8e51 ths
};
1127 aac443e6 Stefan Weil
1128 aac443e6 Stefan Weil
static const char *reg2name(uint8_t reg)
1129 aac443e6 Stefan Weil
{
1130 aac443e6 Stefan Weil
    static char buffer[10];
1131 aac443e6 Stefan Weil
    const char *p = buffer;
1132 aac443e6 Stefan Weil
    if (reg < ARRAY_SIZE(mdi_reg_name)) {
1133 aac443e6 Stefan Weil
        p = mdi_reg_name[reg];
1134 aac443e6 Stefan Weil
    } else {
1135 aac443e6 Stefan Weil
        snprintf(buffer, sizeof(buffer), "reg=0x%02x", reg);
1136 aac443e6 Stefan Weil
    }
1137 aac443e6 Stefan Weil
    return p;
1138 aac443e6 Stefan Weil
}
1139 663e8e51 ths
#endif                          /* DEBUG_EEPRO100 */
1140 663e8e51 ths
1141 663e8e51 ths
static uint32_t eepro100_read_mdi(EEPRO100State * s)
1142 663e8e51 ths
{
1143 e5e23ab8 Stefan Weil
    uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
1144 663e8e51 ths
1145 663e8e51 ths
#ifdef DEBUG_EEPRO100
1146 663e8e51 ths
    uint8_t raiseint = (val & BIT(29)) >> 29;
1147 663e8e51 ths
    uint8_t opcode = (val & BITS(27, 26)) >> 26;
1148 663e8e51 ths
    uint8_t phy = (val & BITS(25, 21)) >> 21;
1149 663e8e51 ths
    uint8_t reg = (val & BITS(20, 16)) >> 16;
1150 663e8e51 ths
    uint16_t data = (val & BITS(15, 0));
1151 663e8e51 ths
#endif
1152 663e8e51 ths
    /* Emulation takes no time to finish MDI transaction. */
1153 663e8e51 ths
    val |= BIT(28);
1154 663e8e51 ths
    TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1155 663e8e51 ths
                      val, raiseint, mdi_op_name[opcode], phy,
1156 aac443e6 Stefan Weil
                      reg2name(reg), data));
1157 663e8e51 ths
    return val;
1158 663e8e51 ths
}
1159 663e8e51 ths
1160 0113f48d Stefan Weil
static void eepro100_write_mdi(EEPRO100State *s)
1161 663e8e51 ths
{
1162 0113f48d Stefan Weil
    uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
1163 663e8e51 ths
    uint8_t raiseint = (val & BIT(29)) >> 29;
1164 663e8e51 ths
    uint8_t opcode = (val & BITS(27, 26)) >> 26;
1165 663e8e51 ths
    uint8_t phy = (val & BITS(25, 21)) >> 21;
1166 663e8e51 ths
    uint8_t reg = (val & BITS(20, 16)) >> 16;
1167 663e8e51 ths
    uint16_t data = (val & BITS(15, 0));
1168 aac443e6 Stefan Weil
    TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1169 aac443e6 Stefan Weil
          val, raiseint, mdi_op_name[opcode], phy, reg2name(reg), data));
1170 663e8e51 ths
    if (phy != 1) {
1171 663e8e51 ths
        /* Unsupported PHY address. */
1172 e7493b25 Stefan Weil
#if 0
1173 e7493b25 Stefan Weil
        logout("phy must be 1 but is %u\n", phy);
1174 e7493b25 Stefan Weil
#endif
1175 663e8e51 ths
        data = 0;
1176 663e8e51 ths
    } else if (opcode != 1 && opcode != 2) {
1177 663e8e51 ths
        /* Unsupported opcode. */
1178 663e8e51 ths
        logout("opcode must be 1 or 2 but is %u\n", opcode);
1179 663e8e51 ths
        data = 0;
1180 663e8e51 ths
    } else if (reg > 6) {
1181 663e8e51 ths
        /* Unsupported register. */
1182 663e8e51 ths
        logout("register must be 0...6 but is %u\n", reg);
1183 663e8e51 ths
        data = 0;
1184 663e8e51 ths
    } else {
1185 663e8e51 ths
        TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1186 663e8e51 ths
                          val, raiseint, mdi_op_name[opcode], phy,
1187 aac443e6 Stefan Weil
                          reg2name(reg), data));
1188 663e8e51 ths
        if (opcode == 1) {
1189 663e8e51 ths
            /* MDI write */
1190 663e8e51 ths
            switch (reg) {
1191 663e8e51 ths
            case 0:            /* Control Register */
1192 663e8e51 ths
                if (data & 0x8000) {
1193 663e8e51 ths
                    /* Reset status and control registers to default. */
1194 663e8e51 ths
                    s->mdimem[0] = eepro100_mdi_default[0];
1195 663e8e51 ths
                    s->mdimem[1] = eepro100_mdi_default[1];
1196 663e8e51 ths
                    data = s->mdimem[reg];
1197 663e8e51 ths
                } else {
1198 663e8e51 ths
                    /* Restart Auto Configuration = Normal Operation */
1199 663e8e51 ths
                    data &= ~0x0200;
1200 663e8e51 ths
                }
1201 663e8e51 ths
                break;
1202 663e8e51 ths
            case 1:            /* Status Register */
1203 663e8e51 ths
                missing("not writable");
1204 663e8e51 ths
                data = s->mdimem[reg];
1205 663e8e51 ths
                break;
1206 663e8e51 ths
            case 2:            /* PHY Identification Register (Word 1) */
1207 663e8e51 ths
            case 3:            /* PHY Identification Register (Word 2) */
1208 663e8e51 ths
                missing("not implemented");
1209 663e8e51 ths
                break;
1210 663e8e51 ths
            case 4:            /* Auto-Negotiation Advertisement Register */
1211 663e8e51 ths
            case 5:            /* Auto-Negotiation Link Partner Ability Register */
1212 663e8e51 ths
                break;
1213 663e8e51 ths
            case 6:            /* Auto-Negotiation Expansion Register */
1214 663e8e51 ths
            default:
1215 663e8e51 ths
                missing("not implemented");
1216 663e8e51 ths
            }
1217 663e8e51 ths
            s->mdimem[reg] = data;
1218 663e8e51 ths
        } else if (opcode == 2) {
1219 663e8e51 ths
            /* MDI read */
1220 663e8e51 ths
            switch (reg) {
1221 663e8e51 ths
            case 0:            /* Control Register */
1222 663e8e51 ths
                if (data & 0x8000) {
1223 663e8e51 ths
                    /* Reset status and control registers to default. */
1224 663e8e51 ths
                    s->mdimem[0] = eepro100_mdi_default[0];
1225 663e8e51 ths
                    s->mdimem[1] = eepro100_mdi_default[1];
1226 663e8e51 ths
                }
1227 663e8e51 ths
                break;
1228 663e8e51 ths
            case 1:            /* Status Register */
1229 663e8e51 ths
                s->mdimem[reg] |= 0x0020;
1230 663e8e51 ths
                break;
1231 663e8e51 ths
            case 2:            /* PHY Identification Register (Word 1) */
1232 663e8e51 ths
            case 3:            /* PHY Identification Register (Word 2) */
1233 663e8e51 ths
            case 4:            /* Auto-Negotiation Advertisement Register */
1234 663e8e51 ths
                break;
1235 663e8e51 ths
            case 5:            /* Auto-Negotiation Link Partner Ability Register */
1236 663e8e51 ths
                s->mdimem[reg] = 0x41fe;
1237 663e8e51 ths
                break;
1238 663e8e51 ths
            case 6:            /* Auto-Negotiation Expansion Register */
1239 663e8e51 ths
                s->mdimem[reg] = 0x0001;
1240 663e8e51 ths
                break;
1241 663e8e51 ths
            }
1242 663e8e51 ths
            data = s->mdimem[reg];
1243 663e8e51 ths
        }
1244 663e8e51 ths
        /* Emulation takes no time to finish MDI transaction.
1245 663e8e51 ths
         * Set MDI bit in SCB status register. */
1246 663e8e51 ths
        s->mem[SCBAck] |= 0x08;
1247 663e8e51 ths
        val |= BIT(28);
1248 663e8e51 ths
        if (raiseint) {
1249 663e8e51 ths
            eepro100_mdi_interrupt(s);
1250 663e8e51 ths
        }
1251 663e8e51 ths
    }
1252 663e8e51 ths
    val = (val & 0xffff0000) + data;
1253 e5e23ab8 Stefan Weil
    e100_write_reg4(s, SCBCtrlMDI, val);
1254 663e8e51 ths
}
1255 663e8e51 ths
1256 663e8e51 ths
/*****************************************************************************
1257 663e8e51 ths
 *
1258 663e8e51 ths
 * Port emulation.
1259 663e8e51 ths
 *
1260 663e8e51 ths
 ****************************************************************************/
1261 663e8e51 ths
1262 663e8e51 ths
#define PORT_SOFTWARE_RESET     0
1263 663e8e51 ths
#define PORT_SELFTEST           1
1264 663e8e51 ths
#define PORT_SELECTIVE_RESET    2
1265 663e8e51 ths
#define PORT_DUMP               3
1266 663e8e51 ths
#define PORT_SELECTION_MASK     3
1267 663e8e51 ths
1268 663e8e51 ths
typedef struct {
1269 663e8e51 ths
    uint32_t st_sign;           /* Self Test Signature */
1270 663e8e51 ths
    uint32_t st_result;         /* Self Test Results */
1271 c227f099 Anthony Liguori
} eepro100_selftest_t;
1272 663e8e51 ths
1273 663e8e51 ths
static uint32_t eepro100_read_port(EEPRO100State * s)
1274 663e8e51 ths
{
1275 663e8e51 ths
    return 0;
1276 663e8e51 ths
}
1277 663e8e51 ths
1278 3fd3d0b4 Stefan Weil
static void eepro100_write_port(EEPRO100State *s)
1279 663e8e51 ths
{
1280 3fd3d0b4 Stefan Weil
    uint32_t val = e100_read_reg4(s, SCBPort);
1281 663e8e51 ths
    uint32_t address = (val & ~PORT_SELECTION_MASK);
1282 663e8e51 ths
    uint8_t selection = (val & PORT_SELECTION_MASK);
1283 663e8e51 ths
    switch (selection) {
1284 663e8e51 ths
    case PORT_SOFTWARE_RESET:
1285 663e8e51 ths
        nic_reset(s);
1286 663e8e51 ths
        break;
1287 663e8e51 ths
    case PORT_SELFTEST:
1288 aac443e6 Stefan Weil
        TRACE(OTHER, logout("selftest address=0x%08x\n", address));
1289 c227f099 Anthony Liguori
        eepro100_selftest_t data;
1290 16ef60c9 Eduard - Gabriel Munteanu
        pci_dma_read(&s->dev, address, (uint8_t *) &data, sizeof(data));
1291 663e8e51 ths
        data.st_sign = 0xffffffff;
1292 663e8e51 ths
        data.st_result = 0;
1293 16ef60c9 Eduard - Gabriel Munteanu
        pci_dma_write(&s->dev, address, (uint8_t *) &data, sizeof(data));
1294 663e8e51 ths
        break;
1295 663e8e51 ths
    case PORT_SELECTIVE_RESET:
1296 aac443e6 Stefan Weil
        TRACE(OTHER, logout("selective reset, selftest address=0x%08x\n", address));
1297 663e8e51 ths
        nic_selective_reset(s);
1298 663e8e51 ths
        break;
1299 663e8e51 ths
    default:
1300 663e8e51 ths
        logout("val=0x%08x\n", val);
1301 663e8e51 ths
        missing("unknown port selection");
1302 663e8e51 ths
    }
1303 663e8e51 ths
}
1304 663e8e51 ths
1305 663e8e51 ths
/*****************************************************************************
1306 663e8e51 ths
 *
1307 663e8e51 ths
 * General hardware emulation.
1308 663e8e51 ths
 *
1309 663e8e51 ths
 ****************************************************************************/
1310 663e8e51 ths
1311 663e8e51 ths
static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
1312 663e8e51 ths
{
1313 ef476062 Blue Swirl
    uint8_t val = 0;
1314 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1315 e5e23ab8 Stefan Weil
        val = s->mem[addr];
1316 663e8e51 ths
    }
1317 663e8e51 ths
1318 663e8e51 ths
    switch (addr) {
1319 663e8e51 ths
    case SCBStatus:
1320 663e8e51 ths
    case SCBAck:
1321 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1322 663e8e51 ths
        break;
1323 663e8e51 ths
    case SCBCmd:
1324 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1325 e7493b25 Stefan Weil
#if 0
1326 e7493b25 Stefan Weil
        val = eepro100_read_command(s);
1327 e7493b25 Stefan Weil
#endif
1328 663e8e51 ths
        break;
1329 663e8e51 ths
    case SCBIntmask:
1330 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1331 663e8e51 ths
        break;
1332 663e8e51 ths
    case SCBPort + 3:
1333 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1334 663e8e51 ths
        break;
1335 663e8e51 ths
    case SCBeeprom:
1336 663e8e51 ths
        val = eepro100_read_eeprom(s);
1337 663e8e51 ths
        break;
1338 0113f48d Stefan Weil
    case SCBCtrlMDI:
1339 0113f48d Stefan Weil
    case SCBCtrlMDI + 1:
1340 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1341 0113f48d Stefan Weil
    case SCBCtrlMDI + 3:
1342 0113f48d Stefan Weil
        val = (uint8_t)(eepro100_read_mdi(s) >> (8 * (addr & 3)));
1343 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1344 0113f48d Stefan Weil
        break;
1345 0908bba1 Stefan Weil
    case SCBpmdr:       /* Power Management Driver Register */
1346 663e8e51 ths
        val = 0;
1347 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1348 663e8e51 ths
        break;
1349 a39bd017 Stefan Weil
    case SCBgctrl:      /* General Control Register */
1350 a39bd017 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1351 a39bd017 Stefan Weil
        break;
1352 0908bba1 Stefan Weil
    case SCBgstat:      /* General Status Register */
1353 663e8e51 ths
        /* 100 Mbps full duplex, valid link */
1354 663e8e51 ths
        val = 0x07;
1355 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=General Status val=%02x\n", val));
1356 663e8e51 ths
        break;
1357 663e8e51 ths
    default:
1358 663e8e51 ths
        logout("addr=%s val=0x%02x\n", regname(addr), val);
1359 663e8e51 ths
        missing("unknown byte read");
1360 663e8e51 ths
    }
1361 663e8e51 ths
    return val;
1362 663e8e51 ths
}
1363 663e8e51 ths
1364 663e8e51 ths
static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr)
1365 663e8e51 ths
{
1366 ef476062 Blue Swirl
    uint16_t val = 0;
1367 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1368 e5e23ab8 Stefan Weil
        val = e100_read_reg2(s, addr);
1369 663e8e51 ths
    }
1370 663e8e51 ths
1371 663e8e51 ths
    switch (addr) {
1372 663e8e51 ths
    case SCBStatus:
1373 dbbaaff6 =?UTF-8?q?Reimar=20D=C3=B6ffinger?=
    case SCBCmd:
1374 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1375 663e8e51 ths
        break;
1376 663e8e51 ths
    case SCBeeprom:
1377 663e8e51 ths
        val = eepro100_read_eeprom(s);
1378 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1379 663e8e51 ths
        break;
1380 0113f48d Stefan Weil
    case SCBCtrlMDI:
1381 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1382 0113f48d Stefan Weil
        val = (uint16_t)(eepro100_read_mdi(s) >> (8 * (addr & 3)));
1383 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1384 0113f48d Stefan Weil
        break;
1385 663e8e51 ths
    default:
1386 663e8e51 ths
        logout("addr=%s val=0x%04x\n", regname(addr), val);
1387 663e8e51 ths
        missing("unknown word read");
1388 663e8e51 ths
    }
1389 663e8e51 ths
    return val;
1390 663e8e51 ths
}
1391 663e8e51 ths
1392 663e8e51 ths
static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
1393 663e8e51 ths
{
1394 ef476062 Blue Swirl
    uint32_t val = 0;
1395 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1396 e5e23ab8 Stefan Weil
        val = e100_read_reg4(s, addr);
1397 663e8e51 ths
    }
1398 663e8e51 ths
1399 663e8e51 ths
    switch (addr) {
1400 663e8e51 ths
    case SCBStatus:
1401 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1402 663e8e51 ths
        break;
1403 663e8e51 ths
    case SCBPointer:
1404 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1405 663e8e51 ths
        break;
1406 663e8e51 ths
    case SCBPort:
1407 663e8e51 ths
        val = eepro100_read_port(s);
1408 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1409 663e8e51 ths
        break;
1410 072476ea Stefan Weil
    case SCBflash:
1411 072476ea Stefan Weil
        val = eepro100_read_eeprom(s);
1412 072476ea Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1413 072476ea Stefan Weil
        break;
1414 663e8e51 ths
    case SCBCtrlMDI:
1415 663e8e51 ths
        val = eepro100_read_mdi(s);
1416 663e8e51 ths
        break;
1417 663e8e51 ths
    default:
1418 663e8e51 ths
        logout("addr=%s val=0x%08x\n", regname(addr), val);
1419 663e8e51 ths
        missing("unknown longword read");
1420 663e8e51 ths
    }
1421 663e8e51 ths
    return val;
1422 663e8e51 ths
}
1423 663e8e51 ths
1424 663e8e51 ths
static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
1425 663e8e51 ths
{
1426 e74818f3 Stefan Weil
    /* SCBStatus is readonly. */
1427 e74818f3 Stefan Weil
    if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
1428 e5e23ab8 Stefan Weil
        s->mem[addr] = val;
1429 663e8e51 ths
    }
1430 663e8e51 ths
1431 663e8e51 ths
    switch (addr) {
1432 663e8e51 ths
    case SCBStatus:
1433 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1434 663e8e51 ths
        break;
1435 663e8e51 ths
    case SCBAck:
1436 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1437 663e8e51 ths
        eepro100_acknowledge(s);
1438 663e8e51 ths
        break;
1439 663e8e51 ths
    case SCBCmd:
1440 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1441 663e8e51 ths
        eepro100_write_command(s, val);
1442 663e8e51 ths
        break;
1443 663e8e51 ths
    case SCBIntmask:
1444 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1445 663e8e51 ths
        if (val & BIT(1)) {
1446 663e8e51 ths
            eepro100_swi_interrupt(s);
1447 663e8e51 ths
        }
1448 663e8e51 ths
        eepro100_interrupt(s, 0);
1449 663e8e51 ths
        break;
1450 27a05006 Stefan Weil
    case SCBPointer:
1451 27a05006 Stefan Weil
    case SCBPointer + 1:
1452 27a05006 Stefan Weil
    case SCBPointer + 2:
1453 27a05006 Stefan Weil
    case SCBPointer + 3:
1454 27a05006 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1455 27a05006 Stefan Weil
        break;
1456 3fd3d0b4 Stefan Weil
    case SCBPort:
1457 3fd3d0b4 Stefan Weil
    case SCBPort + 1:
1458 3fd3d0b4 Stefan Weil
    case SCBPort + 2:
1459 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1460 3fd3d0b4 Stefan Weil
        break;
1461 663e8e51 ths
    case SCBPort + 3:
1462 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1463 3fd3d0b4 Stefan Weil
        eepro100_write_port(s);
1464 3fd3d0b4 Stefan Weil
        break;
1465 aac443e6 Stefan Weil
    case SCBFlow:       /* does not exist on 82557 */
1466 3257d2b6 ths
    case SCBFlow + 1:
1467 3257d2b6 ths
    case SCBFlow + 2:
1468 0908bba1 Stefan Weil
    case SCBpmdr:       /* does not exist on 82557 */
1469 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1470 663e8e51 ths
        break;
1471 663e8e51 ths
    case SCBeeprom:
1472 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1473 663e8e51 ths
        eepro100_write_eeprom(s->eeprom, val);
1474 663e8e51 ths
        break;
1475 0113f48d Stefan Weil
    case SCBCtrlMDI:
1476 0113f48d Stefan Weil
    case SCBCtrlMDI + 1:
1477 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1478 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1479 0113f48d Stefan Weil
        break;
1480 0113f48d Stefan Weil
    case SCBCtrlMDI + 3:
1481 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1482 0113f48d Stefan Weil
        eepro100_write_mdi(s);
1483 0113f48d Stefan Weil
        break;
1484 663e8e51 ths
    default:
1485 663e8e51 ths
        logout("addr=%s val=0x%02x\n", regname(addr), val);
1486 663e8e51 ths
        missing("unknown byte write");
1487 663e8e51 ths
    }
1488 663e8e51 ths
}
1489 663e8e51 ths
1490 663e8e51 ths
static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
1491 663e8e51 ths
{
1492 e74818f3 Stefan Weil
    /* SCBStatus is readonly. */
1493 e74818f3 Stefan Weil
    if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
1494 e5e23ab8 Stefan Weil
        e100_write_reg2(s, addr, val);
1495 663e8e51 ths
    }
1496 663e8e51 ths
1497 663e8e51 ths
    switch (addr) {
1498 663e8e51 ths
    case SCBStatus:
1499 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1500 e74818f3 Stefan Weil
        s->mem[SCBAck] = (val >> 8);
1501 663e8e51 ths
        eepro100_acknowledge(s);
1502 663e8e51 ths
        break;
1503 663e8e51 ths
    case SCBCmd:
1504 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1505 663e8e51 ths
        eepro100_write_command(s, val);
1506 663e8e51 ths
        eepro100_write1(s, SCBIntmask, val >> 8);
1507 663e8e51 ths
        break;
1508 27a05006 Stefan Weil
    case SCBPointer:
1509 27a05006 Stefan Weil
    case SCBPointer + 2:
1510 27a05006 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1511 27a05006 Stefan Weil
        break;
1512 3fd3d0b4 Stefan Weil
    case SCBPort:
1513 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1514 3fd3d0b4 Stefan Weil
        break;
1515 3fd3d0b4 Stefan Weil
    case SCBPort + 2:
1516 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1517 3fd3d0b4 Stefan Weil
        eepro100_write_port(s);
1518 3fd3d0b4 Stefan Weil
        break;
1519 663e8e51 ths
    case SCBeeprom:
1520 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1521 663e8e51 ths
        eepro100_write_eeprom(s->eeprom, val);
1522 663e8e51 ths
        break;
1523 0113f48d Stefan Weil
    case SCBCtrlMDI:
1524 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1525 0113f48d Stefan Weil
        break;
1526 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1527 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1528 0113f48d Stefan Weil
        eepro100_write_mdi(s);
1529 0113f48d Stefan Weil
        break;
1530 663e8e51 ths
    default:
1531 663e8e51 ths
        logout("addr=%s val=0x%04x\n", regname(addr), val);
1532 663e8e51 ths
        missing("unknown word write");
1533 663e8e51 ths
    }
1534 663e8e51 ths
}
1535 663e8e51 ths
1536 663e8e51 ths
static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
1537 663e8e51 ths
{
1538 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1539 e5e23ab8 Stefan Weil
        e100_write_reg4(s, addr, val);
1540 663e8e51 ths
    }
1541 663e8e51 ths
1542 663e8e51 ths
    switch (addr) {
1543 663e8e51 ths
    case SCBPointer:
1544 27a05006 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1545 663e8e51 ths
        break;
1546 663e8e51 ths
    case SCBPort:
1547 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1548 3fd3d0b4 Stefan Weil
        eepro100_write_port(s);
1549 663e8e51 ths
        break;
1550 072476ea Stefan Weil
    case SCBflash:
1551 072476ea Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1552 072476ea Stefan Weil
        val = val >> 16;
1553 072476ea Stefan Weil
        eepro100_write_eeprom(s->eeprom, val);
1554 072476ea Stefan Weil
        break;
1555 663e8e51 ths
    case SCBCtrlMDI:
1556 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1557 0113f48d Stefan Weil
        eepro100_write_mdi(s);
1558 663e8e51 ths
        break;
1559 663e8e51 ths
    default:
1560 663e8e51 ths
        logout("addr=%s val=0x%08x\n", regname(addr), val);
1561 663e8e51 ths
        missing("unknown longword write");
1562 663e8e51 ths
    }
1563 663e8e51 ths
}
1564 663e8e51 ths
1565 5e6ffdde Avi Kivity
static uint64_t eepro100_read(void *opaque, target_phys_addr_t addr,
1566 5e6ffdde Avi Kivity
                              unsigned size)
1567 663e8e51 ths
{
1568 663e8e51 ths
    EEPRO100State *s = opaque;
1569 663e8e51 ths
1570 5e6ffdde Avi Kivity
    switch (size) {
1571 5e6ffdde Avi Kivity
    case 1: return eepro100_read1(s, addr);
1572 5e6ffdde Avi Kivity
    case 2: return eepro100_read2(s, addr);
1573 5e6ffdde Avi Kivity
    case 4: return eepro100_read4(s, addr);
1574 5e6ffdde Avi Kivity
    default: abort();
1575 5e6ffdde Avi Kivity
    }
1576 663e8e51 ths
}
1577 663e8e51 ths
1578 5e6ffdde Avi Kivity
static void eepro100_write(void *opaque, target_phys_addr_t addr,
1579 5e6ffdde Avi Kivity
                           uint64_t data, unsigned size)
1580 663e8e51 ths
{
1581 663e8e51 ths
    EEPRO100State *s = opaque;
1582 663e8e51 ths
1583 5e6ffdde Avi Kivity
    switch (size) {
1584 5e6ffdde Avi Kivity
    case 1: return eepro100_write1(s, addr, data);
1585 5e6ffdde Avi Kivity
    case 2: return eepro100_write2(s, addr, data);
1586 5e6ffdde Avi Kivity
    case 4: return eepro100_write4(s, addr, data);
1587 5e6ffdde Avi Kivity
    default: abort();
1588 5e6ffdde Avi Kivity
    }
1589 663e8e51 ths
}
1590 663e8e51 ths
1591 5e6ffdde Avi Kivity
static const MemoryRegionOps eepro100_ops = {
1592 5e6ffdde Avi Kivity
    .read = eepro100_read,
1593 5e6ffdde Avi Kivity
    .write = eepro100_write,
1594 5e6ffdde Avi Kivity
    .endianness = DEVICE_LITTLE_ENDIAN,
1595 663e8e51 ths
};
1596 663e8e51 ths
1597 e00e365e Mark McLoughlin
static int nic_can_receive(VLANClientState *nc)
1598 663e8e51 ths
{
1599 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1600 aac443e6 Stefan Weil
    TRACE(RXTX, logout("%p\n", s));
1601 663e8e51 ths
    return get_ru_state(s) == ru_ready;
1602 e7493b25 Stefan Weil
#if 0
1603 e7493b25 Stefan Weil
    return !eepro100_buffer_full(s);
1604 e7493b25 Stefan Weil
#endif
1605 663e8e51 ths
}
1606 663e8e51 ths
1607 e00e365e Mark McLoughlin
static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size)
1608 663e8e51 ths
{
1609 663e8e51 ths
    /* TODO:
1610 663e8e51 ths
     * - Magic packets should set bit 30 in power management driver register.
1611 663e8e51 ths
     * - Interesting packets should set bit 29 in power management driver register.
1612 663e8e51 ths
     */
1613 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1614 663e8e51 ths
    uint16_t rfd_status = 0xa000;
1615 792f1d63 Stefan Weil
#if defined(CONFIG_PAD_RECEIVED_FRAMES)
1616 792f1d63 Stefan Weil
    uint8_t min_buf[60];
1617 792f1d63 Stefan Weil
#endif
1618 663e8e51 ths
    static const uint8_t broadcast_macaddr[6] =
1619 663e8e51 ths
        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1620 663e8e51 ths
1621 792f1d63 Stefan Weil
#if defined(CONFIG_PAD_RECEIVED_FRAMES)
1622 792f1d63 Stefan Weil
    /* Pad to minimum Ethernet frame length */
1623 792f1d63 Stefan Weil
    if (size < sizeof(min_buf)) {
1624 792f1d63 Stefan Weil
        memcpy(min_buf, buf, size);
1625 792f1d63 Stefan Weil
        memset(&min_buf[size], 0, sizeof(min_buf) - size);
1626 792f1d63 Stefan Weil
        buf = min_buf;
1627 792f1d63 Stefan Weil
        size = sizeof(min_buf);
1628 792f1d63 Stefan Weil
    }
1629 792f1d63 Stefan Weil
#endif
1630 792f1d63 Stefan Weil
1631 663e8e51 ths
    if (s->configuration[8] & 0x80) {
1632 663e8e51 ths
        /* CSMA is disabled. */
1633 663e8e51 ths
        logout("%p received while CSMA is disabled\n", s);
1634 4f1c942b Mark McLoughlin
        return -1;
1635 792f1d63 Stefan Weil
#if !defined(CONFIG_PAD_RECEIVED_FRAMES)
1636 ced5296a Stefan Weil
    } else if (size < 64 && (s->configuration[7] & BIT(0))) {
1637 663e8e51 ths
        /* Short frame and configuration byte 7/0 (discard short receive) set:
1638 663e8e51 ths
         * Short frame is discarded */
1639 067d01de Stefan Weil
        logout("%p received short frame (%zu byte)\n", s, size);
1640 663e8e51 ths
        s->statistics.rx_short_frame_errors++;
1641 e7493b25 Stefan Weil
        return -1;
1642 e7493b25 Stefan Weil
#endif
1643 ced5296a Stefan Weil
    } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & BIT(3))) {
1644 663e8e51 ths
        /* Long frame and configuration byte 18/3 (long receive ok) not set:
1645 663e8e51 ths
         * Long frames are discarded. */
1646 067d01de Stefan Weil
        logout("%p received long frame (%zu byte), ignored\n", s, size);
1647 4f1c942b Mark McLoughlin
        return -1;
1648 e7493b25 Stefan Weil
    } else if (memcmp(buf, s->conf.macaddr.a, 6) == 0) {       /* !!! */
1649 663e8e51 ths
        /* Frame matches individual address. */
1650 663e8e51 ths
        /* TODO: check configuration byte 15/4 (ignore U/L). */
1651 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame for me, len=%zu\n", s, size));
1652 663e8e51 ths
    } else if (memcmp(buf, broadcast_macaddr, 6) == 0) {
1653 663e8e51 ths
        /* Broadcast frame. */
1654 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received broadcast, len=%zu\n", s, size));
1655 663e8e51 ths
        rfd_status |= 0x0002;
1656 7b8737de Stefan Weil
    } else if (buf[0] & 0x01) {
1657 663e8e51 ths
        /* Multicast frame. */
1658 7b8737de Stefan Weil
        TRACE(RXTX, logout("%p received multicast, len=%zu,%s\n", s, size, nic_dump(buf, size)));
1659 7f1e9d4e Kevin Wolf
        if (s->configuration[21] & BIT(3)) {
1660 7b8737de Stefan Weil
          /* Multicast all bit is set, receive all multicast frames. */
1661 7b8737de Stefan Weil
        } else {
1662 7b8737de Stefan Weil
          unsigned mcast_idx = compute_mcast_idx(buf);
1663 7b8737de Stefan Weil
          assert(mcast_idx < 64);
1664 7b8737de Stefan Weil
          if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
1665 7b8737de Stefan Weil
            /* Multicast frame is allowed in hash table. */
1666 ced5296a Stefan Weil
          } else if (s->configuration[15] & BIT(0)) {
1667 7b8737de Stefan Weil
              /* Promiscuous: receive all. */
1668 7b8737de Stefan Weil
              rfd_status |= 0x0004;
1669 7b8737de Stefan Weil
          } else {
1670 7b8737de Stefan Weil
              TRACE(RXTX, logout("%p multicast ignored\n", s));
1671 7b8737de Stefan Weil
              return -1;
1672 7b8737de Stefan Weil
          }
1673 663e8e51 ths
        }
1674 7b8737de Stefan Weil
        /* TODO: Next not for promiscuous mode? */
1675 663e8e51 ths
        rfd_status |= 0x0002;
1676 ced5296a Stefan Weil
    } else if (s->configuration[15] & BIT(0)) {
1677 663e8e51 ths
        /* Promiscuous: receive all. */
1678 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame in promiscuous mode, len=%zu\n", s, size));
1679 663e8e51 ths
        rfd_status |= 0x0004;
1680 010ec629 Stefan Weil
    } else if (s->configuration[20] & BIT(6)) {
1681 010ec629 Stefan Weil
        /* Multiple IA bit set. */
1682 010ec629 Stefan Weil
        unsigned mcast_idx = compute_mcast_idx(buf);
1683 010ec629 Stefan Weil
        assert(mcast_idx < 64);
1684 010ec629 Stefan Weil
        if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
1685 010ec629 Stefan Weil
            TRACE(RXTX, logout("%p accepted, multiple IA bit set\n", s));
1686 010ec629 Stefan Weil
        } else {
1687 010ec629 Stefan Weil
            TRACE(RXTX, logout("%p frame ignored, multiple IA bit set\n", s));
1688 010ec629 Stefan Weil
            return -1;
1689 010ec629 Stefan Weil
        }
1690 663e8e51 ths
    } else {
1691 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame, ignored, len=%zu,%s\n", s, size,
1692 aac443e6 Stefan Weil
              nic_dump(buf, size)));
1693 4f1c942b Mark McLoughlin
        return size;
1694 663e8e51 ths
    }
1695 663e8e51 ths
1696 663e8e51 ths
    if (get_ru_state(s) != ru_ready) {
1697 aac443e6 Stefan Weil
        /* No resources available. */
1698 aac443e6 Stefan Weil
        logout("no resources, state=%u\n", get_ru_state(s));
1699 e824012b Stefan Weil
        /* TODO: RNR interrupt only at first failed frame? */
1700 e824012b Stefan Weil
        eepro100_rnr_interrupt(s);
1701 663e8e51 ths
        s->statistics.rx_resource_errors++;
1702 e7493b25 Stefan Weil
#if 0
1703 e7493b25 Stefan Weil
        assert(!"no resources");
1704 e7493b25 Stefan Weil
#endif
1705 4f1c942b Mark McLoughlin
        return -1;
1706 663e8e51 ths
    }
1707 e7493b25 Stefan Weil
    /* !!! */
1708 c227f099 Anthony Liguori
    eepro100_rx_t rx;
1709 16ef60c9 Eduard - Gabriel Munteanu
    pci_dma_read(&s->dev, s->ru_base + s->ru_offset,
1710 16ef60c9 Eduard - Gabriel Munteanu
                 (uint8_t *) &rx, sizeof(eepro100_rx_t));
1711 663e8e51 ths
    uint16_t rfd_command = le16_to_cpu(rx.command);
1712 663e8e51 ths
    uint16_t rfd_size = le16_to_cpu(rx.size);
1713 7f1e9d4e Kevin Wolf
1714 7f1e9d4e Kevin Wolf
    if (size > rfd_size) {
1715 7f1e9d4e Kevin Wolf
        logout("Receive buffer (%" PRId16 " bytes) too small for data "
1716 7f1e9d4e Kevin Wolf
            "(%zu bytes); data truncated\n", rfd_size, size);
1717 7f1e9d4e Kevin Wolf
        size = rfd_size;
1718 7f1e9d4e Kevin Wolf
    }
1719 792f1d63 Stefan Weil
#if !defined(CONFIG_PAD_RECEIVED_FRAMES)
1720 663e8e51 ths
    if (size < 64) {
1721 663e8e51 ths
        rfd_status |= 0x0080;
1722 663e8e51 ths
    }
1723 792f1d63 Stefan Weil
#endif
1724 aac443e6 Stefan Weil
    TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n",
1725 aac443e6 Stefan Weil
          rfd_command, rx.link, rx.rx_buf_addr, rfd_size));
1726 16ef60c9 Eduard - Gabriel Munteanu
    stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset +
1727 16ef60c9 Eduard - Gabriel Munteanu
                offsetof(eepro100_rx_t, status), rfd_status);
1728 16ef60c9 Eduard - Gabriel Munteanu
    stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset +
1729 16ef60c9 Eduard - Gabriel Munteanu
                offsetof(eepro100_rx_t, count), size);
1730 663e8e51 ths
    /* Early receive interrupt not supported. */
1731 e7493b25 Stefan Weil
#if 0
1732 e7493b25 Stefan Weil
    eepro100_er_interrupt(s);
1733 e7493b25 Stefan Weil
#endif
1734 663e8e51 ths
    /* Receive CRC Transfer not supported. */
1735 ced5296a Stefan Weil
    if (s->configuration[18] & BIT(2)) {
1736 7f1e9d4e Kevin Wolf
        missing("Receive CRC Transfer");
1737 7f1e9d4e Kevin Wolf
        return -1;
1738 7f1e9d4e Kevin Wolf
    }
1739 663e8e51 ths
    /* TODO: check stripping enable bit. */
1740 e7493b25 Stefan Weil
#if 0
1741 e7493b25 Stefan Weil
    assert(!(s->configuration[17] & BIT(0)));
1742 e7493b25 Stefan Weil
#endif
1743 16ef60c9 Eduard - Gabriel Munteanu
    pci_dma_write(&s->dev, s->ru_base + s->ru_offset +
1744 16ef60c9 Eduard - Gabriel Munteanu
                  sizeof(eepro100_rx_t), buf, size);
1745 663e8e51 ths
    s->statistics.rx_good_frames++;
1746 663e8e51 ths
    eepro100_fr_interrupt(s);
1747 663e8e51 ths
    s->ru_offset = le32_to_cpu(rx.link);
1748 ced5296a Stefan Weil
    if (rfd_command & COMMAND_EL) {
1749 663e8e51 ths
        /* EL bit is set, so this was the last frame. */
1750 7f1e9d4e Kevin Wolf
        logout("receive: Running out of frames\n");
1751 7f1e9d4e Kevin Wolf
        set_ru_state(s, ru_suspended);
1752 663e8e51 ths
    }
1753 ced5296a Stefan Weil
    if (rfd_command & COMMAND_S) {
1754 663e8e51 ths
        /* S bit is set. */
1755 663e8e51 ths
        set_ru_state(s, ru_suspended);
1756 663e8e51 ths
    }
1757 4f1c942b Mark McLoughlin
    return size;
1758 663e8e51 ths
}
1759 663e8e51 ths
1760 151b2986 Juan Quintela
static const VMStateDescription vmstate_eepro100 = {
1761 151b2986 Juan Quintela
    .version_id = 3,
1762 151b2986 Juan Quintela
    .minimum_version_id = 2,
1763 151b2986 Juan Quintela
    .minimum_version_id_old = 2,
1764 151b2986 Juan Quintela
    .fields      = (VMStateField []) {
1765 151b2986 Juan Quintela
        VMSTATE_PCI_DEVICE(dev, EEPRO100State),
1766 151b2986 Juan Quintela
        VMSTATE_UNUSED(32),
1767 151b2986 Juan Quintela
        VMSTATE_BUFFER(mult, EEPRO100State),
1768 151b2986 Juan Quintela
        VMSTATE_BUFFER(mem, EEPRO100State),
1769 151b2986 Juan Quintela
        /* Save all members of struct between scb_stat and mem. */
1770 151b2986 Juan Quintela
        VMSTATE_UINT8(scb_stat, EEPRO100State),
1771 151b2986 Juan Quintela
        VMSTATE_UINT8(int_stat, EEPRO100State),
1772 151b2986 Juan Quintela
        VMSTATE_UNUSED(3*4),
1773 151b2986 Juan Quintela
        VMSTATE_MACADDR(conf.macaddr, EEPRO100State),
1774 151b2986 Juan Quintela
        VMSTATE_UNUSED(19*4),
1775 151b2986 Juan Quintela
        VMSTATE_UINT16_ARRAY(mdimem, EEPRO100State, 32),
1776 151b2986 Juan Quintela
        /* The eeprom should be saved and restored by its own routines. */
1777 151b2986 Juan Quintela
        VMSTATE_UINT32(device, EEPRO100State),
1778 151b2986 Juan Quintela
        /* TODO check device. */
1779 151b2986 Juan Quintela
        VMSTATE_UINT32(cu_base, EEPRO100State),
1780 151b2986 Juan Quintela
        VMSTATE_UINT32(cu_offset, EEPRO100State),
1781 151b2986 Juan Quintela
        VMSTATE_UINT32(ru_base, EEPRO100State),
1782 151b2986 Juan Quintela
        VMSTATE_UINT32(ru_offset, EEPRO100State),
1783 151b2986 Juan Quintela
        VMSTATE_UINT32(statsaddr, EEPRO100State),
1784 ba42b646 Stefan Weil
        /* Save eepro100_stats_t statistics. */
1785 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_good_frames, EEPRO100State),
1786 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_max_collisions, EEPRO100State),
1787 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_late_collisions, EEPRO100State),
1788 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_underruns, EEPRO100State),
1789 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_lost_crs, EEPRO100State),
1790 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_deferred, EEPRO100State),
1791 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_single_collisions, EEPRO100State),
1792 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_multiple_collisions, EEPRO100State),
1793 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_total_collisions, EEPRO100State),
1794 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_good_frames, EEPRO100State),
1795 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_crc_errors, EEPRO100State),
1796 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_alignment_errors, EEPRO100State),
1797 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_resource_errors, EEPRO100State),
1798 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_overrun_errors, EEPRO100State),
1799 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_cdt_errors, EEPRO100State),
1800 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_short_frame_errors, EEPRO100State),
1801 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_xmt_pause, EEPRO100State),
1802 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_rcv_pause, EEPRO100State),
1803 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_rcv_unsupported, EEPRO100State),
1804 151b2986 Juan Quintela
        VMSTATE_UINT16(statistics.xmt_tco_frames, EEPRO100State),
1805 151b2986 Juan Quintela
        VMSTATE_UINT16(statistics.rcv_tco_frames, EEPRO100State),
1806 151b2986 Juan Quintela
        /* Configuration bytes. */
1807 151b2986 Juan Quintela
        VMSTATE_BUFFER(configuration, EEPRO100State),
1808 151b2986 Juan Quintela
        VMSTATE_END_OF_LIST()
1809 aac443e6 Stefan Weil
    }
1810 151b2986 Juan Quintela
};
1811 663e8e51 ths
1812 e00e365e Mark McLoughlin
static void nic_cleanup(VLANClientState *nc)
1813 b946a153 aliguori
{
1814 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1815 b946a153 aliguori
1816 e00e365e Mark McLoughlin
    s->nic = NULL;
1817 b946a153 aliguori
}
1818 b946a153 aliguori
1819 c4c270e2 Stefan Weil
static int pci_nic_uninit(PCIDevice *pci_dev)
1820 b946a153 aliguori
{
1821 c4c270e2 Stefan Weil
    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
1822 b946a153 aliguori
1823 5e6ffdde Avi Kivity
    memory_region_destroy(&s->mmio_bar);
1824 5e6ffdde Avi Kivity
    memory_region_destroy(&s->io_bar);
1825 5e6ffdde Avi Kivity
    memory_region_destroy(&s->flash_bar);
1826 0be71e32 Alex Williamson
    vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
1827 5fce2b3e Alex Williamson
    eeprom93xx_free(&pci_dev->qdev, s->eeprom);
1828 e00e365e Mark McLoughlin
    qemu_del_vlan_client(&s->nic->nc);
1829 b946a153 aliguori
    return 0;
1830 b946a153 aliguori
}
1831 b946a153 aliguori
1832 e00e365e Mark McLoughlin
static NetClientInfo net_eepro100_info = {
1833 e00e365e Mark McLoughlin
    .type = NET_CLIENT_TYPE_NIC,
1834 e00e365e Mark McLoughlin
    .size = sizeof(NICState),
1835 e00e365e Mark McLoughlin
    .can_receive = nic_can_receive,
1836 e00e365e Mark McLoughlin
    .receive = nic_receive,
1837 e00e365e Mark McLoughlin
    .cleanup = nic_cleanup,
1838 e00e365e Mark McLoughlin
};
1839 e00e365e Mark McLoughlin
1840 558c8634 Stefan Weil
static int e100_nic_init(PCIDevice *pci_dev)
1841 663e8e51 ths
{
1842 273a2142 Juan Quintela
    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
1843 558c8634 Stefan Weil
    E100PCIDeviceInfo *e100_device = DO_UPCAST(E100PCIDeviceInfo, pci.qdev,
1844 558c8634 Stefan Weil
                                               pci_dev->qdev.info);
1845 663e8e51 ths
1846 aac443e6 Stefan Weil
    TRACE(OTHER, logout("\n"));
1847 663e8e51 ths
1848 558c8634 Stefan Weil
    s->device = e100_device->device;
1849 663e8e51 ths
1850 558c8634 Stefan Weil
    e100_pci_reset(s, e100_device);
1851 663e8e51 ths
1852 663e8e51 ths
    /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
1853 663e8e51 ths
     * i82559 and later support 64 or 256 word EEPROM. */
1854 5fce2b3e Alex Williamson
    s->eeprom = eeprom93xx_new(&pci_dev->qdev, EEPROM_SIZE);
1855 663e8e51 ths
1856 663e8e51 ths
    /* Handler for memory-mapped I/O */
1857 5e6ffdde Avi Kivity
    memory_region_init_io(&s->mmio_bar, &eepro100_ops, s, "eepro100-mmio",
1858 5e6ffdde Avi Kivity
                          PCI_MEM_SIZE);
1859 e824b2cc Avi Kivity
    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->mmio_bar);
1860 5e6ffdde Avi Kivity
    memory_region_init_io(&s->io_bar, &eepro100_ops, s, "eepro100-io",
1861 5e6ffdde Avi Kivity
                          PCI_IO_SIZE);
1862 e824b2cc Avi Kivity
    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
1863 5e6ffdde Avi Kivity
    /* FIXME: flash aliases to mmio?! */
1864 5e6ffdde Avi Kivity
    memory_region_init_io(&s->flash_bar, &eepro100_ops, s, "eepro100-flash",
1865 5e6ffdde Avi Kivity
                          PCI_FLASH_SIZE);
1866 e824b2cc Avi Kivity
    pci_register_bar(&s->dev, 2, 0, &s->flash_bar);
1867 663e8e51 ths
1868 508ef936 Gerd Hoffmann
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
1869 ce0e58b3 Stefan Weil
    logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6));
1870 663e8e51 ths
1871 663e8e51 ths
    nic_reset(s);
1872 663e8e51 ths
1873 e00e365e Mark McLoughlin
    s->nic = qemu_new_nic(&net_eepro100_info, &s->conf,
1874 e00e365e Mark McLoughlin
                          pci_dev->qdev.info->name, pci_dev->qdev.id, s);
1875 663e8e51 ths
1876 e00e365e Mark McLoughlin
    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
1877 e00e365e Mark McLoughlin
    TRACE(OTHER, logout("%s\n", s->nic->nc.info_str));
1878 663e8e51 ths
1879 a08d4367 Jan Kiszka
    qemu_register_reset(nic_reset, s);
1880 663e8e51 ths
1881 7267c094 Anthony Liguori
    s->vmstate = g_malloc(sizeof(vmstate_eepro100));
1882 151b2986 Juan Quintela
    memcpy(s->vmstate, &vmstate_eepro100, sizeof(vmstate_eepro100));
1883 e00e365e Mark McLoughlin
    s->vmstate->name = s->nic->nc.model;
1884 0be71e32 Alex Williamson
    vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
1885 4e9df06a Stefan Weil
1886 1ca4d09a Gleb Natapov
    add_boot_device_path(s->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
1887 1ca4d09a Gleb Natapov
1888 81a322d4 Gerd Hoffmann
    return 0;
1889 663e8e51 ths
}
1890 663e8e51 ths
1891 558c8634 Stefan Weil
static E100PCIDeviceInfo e100_devices[] = {
1892 0aab0d3a Gerd Hoffmann
    {
1893 558c8634 Stefan Weil
        .pci.qdev.name = "i82550",
1894 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82550 Ethernet",
1895 558c8634 Stefan Weil
        .device = i82550,
1896 558c8634 Stefan Weil
        /* TODO: check device id. */
1897 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
1898 558c8634 Stefan Weil
        /* Revision ID: 0x0c, 0x0d, 0x0e. */
1899 ad03502b Isaku Yamahata
        .pci.revision = 0x0e,
1900 558c8634 Stefan Weil
        /* TODO: check size of statistical counters. */
1901 558c8634 Stefan Weil
        .stats_size = 80,
1902 558c8634 Stefan Weil
        /* TODO: check extended tcb support. */
1903 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1904 558c8634 Stefan Weil
        .power_management = true,
1905 0aab0d3a Gerd Hoffmann
    },{
1906 558c8634 Stefan Weil
        .pci.qdev.name = "i82551",
1907 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82551 Ethernet",
1908 558c8634 Stefan Weil
        .device = i82551,
1909 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
1910 558c8634 Stefan Weil
        /* Revision ID: 0x0f, 0x10. */
1911 ad03502b Isaku Yamahata
        .pci.revision = 0x0f,
1912 558c8634 Stefan Weil
        /* TODO: check size of statistical counters. */
1913 558c8634 Stefan Weil
        .stats_size = 80,
1914 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1915 558c8634 Stefan Weil
        .power_management = true,
1916 c4c270e2 Stefan Weil
    },{
1917 558c8634 Stefan Weil
        .pci.qdev.name = "i82557a",
1918 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82557A Ethernet",
1919 558c8634 Stefan Weil
        .device = i82557A,
1920 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1921 ad03502b Isaku Yamahata
        .pci.revision = 0x01,
1922 558c8634 Stefan Weil
        .power_management = false,
1923 0aab0d3a Gerd Hoffmann
    },{
1924 558c8634 Stefan Weil
        .pci.qdev.name = "i82557b",
1925 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82557B Ethernet",
1926 558c8634 Stefan Weil
        .device = i82557B,
1927 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1928 ad03502b Isaku Yamahata
        .pci.revision = 0x02,
1929 558c8634 Stefan Weil
        .power_management = false,
1930 c4c270e2 Stefan Weil
    },{
1931 558c8634 Stefan Weil
        .pci.qdev.name = "i82557c",
1932 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82557C Ethernet",
1933 558c8634 Stefan Weil
        .device = i82557C,
1934 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1935 ad03502b Isaku Yamahata
        .pci.revision = 0x03,
1936 558c8634 Stefan Weil
        .power_management = false,
1937 c4c270e2 Stefan Weil
    },{
1938 558c8634 Stefan Weil
        .pci.qdev.name = "i82558a",
1939 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82558A Ethernet",
1940 558c8634 Stefan Weil
        .device = i82558A,
1941 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1942 ad03502b Isaku Yamahata
        .pci.revision = 0x04,
1943 558c8634 Stefan Weil
        .stats_size = 76,
1944 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1945 558c8634 Stefan Weil
        .power_management = true,
1946 c4c270e2 Stefan Weil
    },{
1947 558c8634 Stefan Weil
        .pci.qdev.name = "i82558b",
1948 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82558B Ethernet",
1949 558c8634 Stefan Weil
        .device = i82558B,
1950 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1951 ad03502b Isaku Yamahata
        .pci.revision = 0x05,
1952 558c8634 Stefan Weil
        .stats_size = 76,
1953 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1954 558c8634 Stefan Weil
        .power_management = true,
1955 c4c270e2 Stefan Weil
    },{
1956 558c8634 Stefan Weil
        .pci.qdev.name = "i82559a",
1957 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82559A Ethernet",
1958 558c8634 Stefan Weil
        .device = i82559A,
1959 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1960 ad03502b Isaku Yamahata
        .pci.revision = 0x06,
1961 558c8634 Stefan Weil
        .stats_size = 80,
1962 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1963 558c8634 Stefan Weil
        .power_management = true,
1964 c4c270e2 Stefan Weil
    },{
1965 558c8634 Stefan Weil
        .pci.qdev.name = "i82559b",
1966 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82559B Ethernet",
1967 558c8634 Stefan Weil
        .device = i82559B,
1968 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1969 ad03502b Isaku Yamahata
        .pci.revision = 0x07,
1970 558c8634 Stefan Weil
        .stats_size = 80,
1971 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1972 558c8634 Stefan Weil
        .power_management = true,
1973 c4c270e2 Stefan Weil
    },{
1974 558c8634 Stefan Weil
        .pci.qdev.name = "i82559c",
1975 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82559C Ethernet",
1976 558c8634 Stefan Weil
        .device = i82559C,
1977 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1978 558c8634 Stefan Weil
#if 0
1979 ad03502b Isaku Yamahata
        .pci.revision = 0x08,
1980 558c8634 Stefan Weil
#endif
1981 558c8634 Stefan Weil
        /* TODO: Windows wants revision id 0x0c. */
1982 ad03502b Isaku Yamahata
        .pci.revision = 0x0c,
1983 ad03502b Isaku Yamahata
#if EEPROM_SIZE > 0
1984 ad03502b Isaku Yamahata
        .pci.subsystem_vendor_id = PCI_VENDOR_ID_INTEL,
1985 ad03502b Isaku Yamahata
        .pci.subsystem_id = 0x0040,
1986 ad03502b Isaku Yamahata
#endif
1987 558c8634 Stefan Weil
        .stats_size = 80,
1988 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1989 558c8634 Stefan Weil
        .power_management = true,
1990 0aab0d3a Gerd Hoffmann
    },{
1991 558c8634 Stefan Weil
        .pci.qdev.name = "i82559er",
1992 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82559ER Ethernet",
1993 558c8634 Stefan Weil
        .device = i82559ER,
1994 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
1995 ad03502b Isaku Yamahata
        .pci.revision = 0x09,
1996 558c8634 Stefan Weil
        .stats_size = 80,
1997 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1998 558c8634 Stefan Weil
        .power_management = true,
1999 c4c270e2 Stefan Weil
    },{
2000 558c8634 Stefan Weil
        .pci.qdev.name = "i82562",
2001 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82562 Ethernet",
2002 558c8634 Stefan Weil
        .device = i82562,
2003 558c8634 Stefan Weil
        /* TODO: check device id. */
2004 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
2005 558c8634 Stefan Weil
        /* TODO: wrong revision id. */
2006 ad03502b Isaku Yamahata
        .pci.revision = 0x0e,
2007 558c8634 Stefan Weil
        .stats_size = 80,
2008 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
2009 558c8634 Stefan Weil
        .power_management = true,
2010 db667a12 Stefan Weil
    },{
2011 db667a12 Stefan Weil
        /* Toshiba Tecra 8200. */
2012 db667a12 Stefan Weil
        .pci.qdev.name = "i82801",
2013 db667a12 Stefan Weil
        .pci.qdev.desc = "Intel i82801 Ethernet",
2014 db667a12 Stefan Weil
        .device = i82801,
2015 ad03502b Isaku Yamahata
        .pci.device_id = 0x2449,
2016 ad03502b Isaku Yamahata
        .pci.revision = 0x03,
2017 db667a12 Stefan Weil
        .stats_size = 80,
2018 db667a12 Stefan Weil
        .has_extended_tcb_support = true,
2019 db667a12 Stefan Weil
        .power_management = true,
2020 0aab0d3a Gerd Hoffmann
    }
2021 0aab0d3a Gerd Hoffmann
};
2022 0aab0d3a Gerd Hoffmann
2023 558c8634 Stefan Weil
static Property e100_properties[] = {
2024 558c8634 Stefan Weil
    DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2025 558c8634 Stefan Weil
    DEFINE_PROP_END_OF_LIST(),
2026 558c8634 Stefan Weil
};
2027 558c8634 Stefan Weil
2028 9d07d757 Paul Brook
static void eepro100_register_devices(void)
2029 663e8e51 ths
{
2030 558c8634 Stefan Weil
    size_t i;
2031 558c8634 Stefan Weil
    for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
2032 558c8634 Stefan Weil
        PCIDeviceInfo *pci_dev = &e100_devices[i].pci;
2033 0389ced4 Stefan Weil
        /* We use the same rom file for all device ids.
2034 0389ced4 Stefan Weil
           QEMU fixes the device id during rom load. */
2035 ad03502b Isaku Yamahata
        pci_dev->vendor_id = PCI_VENDOR_ID_INTEL;
2036 ad03502b Isaku Yamahata
        pci_dev->class_id = PCI_CLASS_NETWORK_ETHERNET;
2037 5ee8ad71 Alex Williamson
        pci_dev->romfile = "pxe-eepro100.rom";
2038 558c8634 Stefan Weil
        pci_dev->init = e100_nic_init;
2039 558c8634 Stefan Weil
        pci_dev->exit = pci_nic_uninit;
2040 558c8634 Stefan Weil
        pci_dev->qdev.props = e100_properties;
2041 558c8634 Stefan Weil
        pci_dev->qdev.size = sizeof(EEPRO100State);
2042 558c8634 Stefan Weil
        pci_qdev_register(pci_dev);
2043 558c8634 Stefan Weil
    }
2044 663e8e51 ths
}
2045 663e8e51 ths
2046 9d07d757 Paul Brook
device_init(eepro100_register_devices)