Statistics
| Branch: | Revision:

root / hw / eepro100.c @ a0f42610

History | View | Annotate | Download (67.8 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 3a93113a Dong Xu Wang
    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 e965d4bc David Gibson
    pci_dma_write(&s->dev, s->statsaddr, &s->statistics, s->stats_size);
717 16ef60c9 Eduard - Gabriel Munteanu
    stl_le_pci_dma(&s->dev, s->statsaddr + 0,
718 16ef60c9 Eduard - Gabriel Munteanu
                   s->statistics.tx_good_frames);
719 16ef60c9 Eduard - Gabriel Munteanu
    stl_le_pci_dma(&s->dev, s->statsaddr + 36,
720 16ef60c9 Eduard - Gabriel Munteanu
                   s->statistics.rx_good_frames);
721 16ef60c9 Eduard - Gabriel Munteanu
    stl_le_pci_dma(&s->dev, s->statsaddr + 48,
722 16ef60c9 Eduard - Gabriel Munteanu
                   s->statistics.rx_resource_errors);
723 16ef60c9 Eduard - Gabriel Munteanu
    stl_le_pci_dma(&s->dev, s->statsaddr + 60,
724 16ef60c9 Eduard - Gabriel Munteanu
                   s->statistics.rx_short_frame_errors);
725 e7493b25 Stefan Weil
#if 0
726 16ef60c9 Eduard - Gabriel Munteanu
    stw_le_pci_dma(&s->dev, s->statsaddr + 76, s->statistics.xmt_tco_frames);
727 16ef60c9 Eduard - Gabriel Munteanu
    stw_le_pci_dma(&s->dev, s->statsaddr + 78, s->statistics.rcv_tco_frames);
728 e7493b25 Stefan Weil
    missing("CU dump statistical counters");
729 e7493b25 Stefan Weil
#endif
730 663e8e51 ths
}
731 663e8e51 ths
732 3d0f4b9b Stefan Weil
static void read_cb(EEPRO100State *s)
733 3d0f4b9b Stefan Weil
{
734 e965d4bc David Gibson
    pci_dma_read(&s->dev, s->cb_address, &s->tx, sizeof(s->tx));
735 3d0f4b9b Stefan Weil
    s->tx.status = le16_to_cpu(s->tx.status);
736 3d0f4b9b Stefan Weil
    s->tx.command = le16_to_cpu(s->tx.command);
737 3d0f4b9b Stefan Weil
    s->tx.link = le32_to_cpu(s->tx.link);
738 3d0f4b9b Stefan Weil
    s->tx.tbd_array_addr = le32_to_cpu(s->tx.tbd_array_addr);
739 3d0f4b9b Stefan Weil
    s->tx.tcb_bytes = le16_to_cpu(s->tx.tcb_bytes);
740 3d0f4b9b Stefan Weil
}
741 3d0f4b9b Stefan Weil
742 f3a52e50 Stefan Weil
static void tx_command(EEPRO100State *s)
743 f3a52e50 Stefan Weil
{
744 7b8737de Stefan Weil
    uint32_t tbd_array = le32_to_cpu(s->tx.tbd_array_addr);
745 f3a52e50 Stefan Weil
    uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff);
746 f3a52e50 Stefan Weil
    /* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */
747 f3a52e50 Stefan Weil
    uint8_t buf[2600];
748 f3a52e50 Stefan Weil
    uint16_t size = 0;
749 f3a52e50 Stefan Weil
    uint32_t tbd_address = s->cb_address + 0x10;
750 f3a52e50 Stefan Weil
    TRACE(RXTX, logout
751 f3a52e50 Stefan Weil
        ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
752 f3a52e50 Stefan Weil
         tbd_array, tcb_bytes, s->tx.tbd_count));
753 f3a52e50 Stefan Weil
754 f3a52e50 Stefan Weil
    if (tcb_bytes > 2600) {
755 f3a52e50 Stefan Weil
        logout("TCB byte count too large, using 2600\n");
756 f3a52e50 Stefan Weil
        tcb_bytes = 2600;
757 f3a52e50 Stefan Weil
    }
758 f3a52e50 Stefan Weil
    if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
759 f3a52e50 Stefan Weil
        logout
760 f3a52e50 Stefan Weil
            ("illegal values of TBD array address and TCB byte count!\n");
761 f3a52e50 Stefan Weil
    }
762 f3a52e50 Stefan Weil
    assert(tcb_bytes <= sizeof(buf));
763 f3a52e50 Stefan Weil
    while (size < tcb_bytes) {
764 16ef60c9 Eduard - Gabriel Munteanu
        uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address);
765 16ef60c9 Eduard - Gabriel Munteanu
        uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4);
766 e7493b25 Stefan Weil
#if 0
767 16ef60c9 Eduard - Gabriel Munteanu
        uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6);
768 e7493b25 Stefan Weil
#endif
769 f3a52e50 Stefan Weil
        tbd_address += 8;
770 f3a52e50 Stefan Weil
        TRACE(RXTX, logout
771 f3a52e50 Stefan Weil
            ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
772 f3a52e50 Stefan Weil
             tx_buffer_address, tx_buffer_size));
773 f3a52e50 Stefan Weil
        tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
774 16ef60c9 Eduard - Gabriel Munteanu
        pci_dma_read(&s->dev, tx_buffer_address, &buf[size], tx_buffer_size);
775 f3a52e50 Stefan Weil
        size += tx_buffer_size;
776 f3a52e50 Stefan Weil
    }
777 f3a52e50 Stefan Weil
    if (tbd_array == 0xffffffff) {
778 f3a52e50 Stefan Weil
        /* Simplified mode. Was already handled by code above. */
779 f3a52e50 Stefan Weil
    } else {
780 f3a52e50 Stefan Weil
        /* Flexible mode. */
781 f3a52e50 Stefan Weil
        uint8_t tbd_count = 0;
782 f3a52e50 Stefan Weil
        if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
783 f3a52e50 Stefan Weil
            /* Extended Flexible TCB. */
784 f3a52e50 Stefan Weil
            for (; tbd_count < 2; tbd_count++) {
785 16ef60c9 Eduard - Gabriel Munteanu
                uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev,
786 16ef60c9 Eduard - Gabriel Munteanu
                                                            tbd_address);
787 16ef60c9 Eduard - Gabriel Munteanu
                uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev,
788 16ef60c9 Eduard - Gabriel Munteanu
                                                          tbd_address + 4);
789 16ef60c9 Eduard - Gabriel Munteanu
                uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev,
790 16ef60c9 Eduard - Gabriel Munteanu
                                                        tbd_address + 6);
791 f3a52e50 Stefan Weil
                tbd_address += 8;
792 f3a52e50 Stefan Weil
                TRACE(RXTX, logout
793 f3a52e50 Stefan Weil
                    ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
794 f3a52e50 Stefan Weil
                     tx_buffer_address, tx_buffer_size));
795 f3a52e50 Stefan Weil
                tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
796 16ef60c9 Eduard - Gabriel Munteanu
                pci_dma_read(&s->dev, tx_buffer_address,
797 16ef60c9 Eduard - Gabriel Munteanu
                             &buf[size], tx_buffer_size);
798 f3a52e50 Stefan Weil
                size += tx_buffer_size;
799 f3a52e50 Stefan Weil
                if (tx_buffer_el & 1) {
800 f3a52e50 Stefan Weil
                    break;
801 f3a52e50 Stefan Weil
                }
802 f3a52e50 Stefan Weil
            }
803 f3a52e50 Stefan Weil
        }
804 f3a52e50 Stefan Weil
        tbd_address = tbd_array;
805 f3a52e50 Stefan Weil
        for (; tbd_count < s->tx.tbd_count; tbd_count++) {
806 16ef60c9 Eduard - Gabriel Munteanu
            uint32_t tx_buffer_address = ldl_le_pci_dma(&s->dev, tbd_address);
807 16ef60c9 Eduard - Gabriel Munteanu
            uint16_t tx_buffer_size = lduw_le_pci_dma(&s->dev, tbd_address + 4);
808 16ef60c9 Eduard - Gabriel Munteanu
            uint16_t tx_buffer_el = lduw_le_pci_dma(&s->dev, tbd_address + 6);
809 f3a52e50 Stefan Weil
            tbd_address += 8;
810 f3a52e50 Stefan Weil
            TRACE(RXTX, logout
811 f3a52e50 Stefan Weil
                ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
812 f3a52e50 Stefan Weil
                 tx_buffer_address, tx_buffer_size));
813 f3a52e50 Stefan Weil
            tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
814 16ef60c9 Eduard - Gabriel Munteanu
            pci_dma_read(&s->dev, tx_buffer_address,
815 16ef60c9 Eduard - Gabriel Munteanu
                         &buf[size], tx_buffer_size);
816 f3a52e50 Stefan Weil
            size += tx_buffer_size;
817 f3a52e50 Stefan Weil
            if (tx_buffer_el & 1) {
818 f3a52e50 Stefan Weil
                break;
819 f3a52e50 Stefan Weil
            }
820 f3a52e50 Stefan Weil
        }
821 f3a52e50 Stefan Weil
    }
822 f3a52e50 Stefan Weil
    TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));
823 f3a52e50 Stefan Weil
    qemu_send_packet(&s->nic->nc, buf, size);
824 f3a52e50 Stefan Weil
    s->statistics.tx_good_frames++;
825 f3a52e50 Stefan Weil
    /* Transmit with bad status would raise an CX/TNO interrupt.
826 f3a52e50 Stefan Weil
     * (82557 only). Emulation never has bad status. */
827 e7493b25 Stefan Weil
#if 0
828 e7493b25 Stefan Weil
    eepro100_cx_interrupt(s);
829 e7493b25 Stefan Weil
#endif
830 f3a52e50 Stefan Weil
}
831 f3a52e50 Stefan Weil
832 7b8737de Stefan Weil
static void set_multicast_list(EEPRO100State *s)
833 7b8737de Stefan Weil
{
834 7b8737de Stefan Weil
    uint16_t multicast_count = s->tx.tbd_array_addr & BITS(13, 0);
835 7b8737de Stefan Weil
    uint16_t i;
836 7b8737de Stefan Weil
    memset(&s->mult[0], 0, sizeof(s->mult));
837 7b8737de Stefan Weil
    TRACE(OTHER, logout("multicast list, multicast count = %u\n", multicast_count));
838 7b8737de Stefan Weil
    for (i = 0; i < multicast_count; i += 6) {
839 7b8737de Stefan Weil
        uint8_t multicast_addr[6];
840 16ef60c9 Eduard - Gabriel Munteanu
        pci_dma_read(&s->dev, s->cb_address + 10 + i, multicast_addr, 6);
841 7b8737de Stefan Weil
        TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6)));
842 7b8737de Stefan Weil
        unsigned mcast_idx = compute_mcast_idx(multicast_addr);
843 7b8737de Stefan Weil
        assert(mcast_idx < 64);
844 7b8737de Stefan Weil
        s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7));
845 7b8737de Stefan Weil
    }
846 7b8737de Stefan Weil
}
847 7b8737de Stefan Weil
848 5fa9a0ae Stefan Weil
static void action_command(EEPRO100State *s)
849 663e8e51 ths
{
850 5fa9a0ae Stefan Weil
    for (;;) {
851 3d0f4b9b Stefan Weil
        bool bit_el;
852 3d0f4b9b Stefan Weil
        bool bit_s;
853 3d0f4b9b Stefan Weil
        bool bit_i;
854 3d0f4b9b Stefan Weil
        bool bit_nc;
855 75f5a6cc Stefan Weil
        uint16_t ok_status = STATUS_OK;
856 3d0f4b9b Stefan Weil
        s->cb_address = s->cu_base + s->cu_offset;
857 3d0f4b9b Stefan Weil
        read_cb(s);
858 3d0f4b9b Stefan Weil
        bit_el = ((s->tx.command & COMMAND_EL) != 0);
859 3d0f4b9b Stefan Weil
        bit_s = ((s->tx.command & COMMAND_S) != 0);
860 3d0f4b9b Stefan Weil
        bit_i = ((s->tx.command & COMMAND_I) != 0);
861 3d0f4b9b Stefan Weil
        bit_nc = ((s->tx.command & COMMAND_NC) != 0);
862 3d0f4b9b Stefan Weil
#if 0
863 3d0f4b9b Stefan Weil
        bool bit_sf = ((s->tx.command & COMMAND_SF) != 0);
864 3d0f4b9b Stefan Weil
#endif
865 3d0f4b9b Stefan Weil
        s->cu_offset = s->tx.link;
866 3d0f4b9b Stefan Weil
        TRACE(OTHER,
867 3d0f4b9b Stefan Weil
              logout("val=(cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",
868 3d0f4b9b Stefan Weil
                     s->tx.status, s->tx.command, s->tx.link));
869 3d0f4b9b Stefan Weil
        switch (s->tx.command & COMMAND_CMD) {
870 663e8e51 ths
        case CmdNOp:
871 663e8e51 ths
            /* Do nothing. */
872 663e8e51 ths
            break;
873 663e8e51 ths
        case CmdIASetup:
874 16ef60c9 Eduard - Gabriel Munteanu
            pci_dma_read(&s->dev, s->cb_address + 8, &s->conf.macaddr.a[0], 6);
875 ce0e58b3 Stefan Weil
            TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6)));
876 663e8e51 ths
            break;
877 663e8e51 ths
        case CmdConfigure:
878 16ef60c9 Eduard - Gabriel Munteanu
            pci_dma_read(&s->dev, s->cb_address + 8,
879 16ef60c9 Eduard - Gabriel Munteanu
                         &s->configuration[0], sizeof(s->configuration));
880 010ec629 Stefan Weil
            TRACE(OTHER, logout("configuration: %s\n",
881 010ec629 Stefan Weil
                                nic_dump(&s->configuration[0], 16)));
882 010ec629 Stefan Weil
            TRACE(OTHER, logout("configuration: %s\n",
883 010ec629 Stefan Weil
                                nic_dump(&s->configuration[16],
884 010ec629 Stefan Weil
                                ARRAY_SIZE(s->configuration) - 16)));
885 010ec629 Stefan Weil
            if (s->configuration[20] & BIT(6)) {
886 010ec629 Stefan Weil
                TRACE(OTHER, logout("Multiple IA bit\n"));
887 010ec629 Stefan Weil
            }
888 663e8e51 ths
            break;
889 663e8e51 ths
        case CmdMulticastList:
890 7b8737de Stefan Weil
            set_multicast_list(s);
891 663e8e51 ths
            break;
892 663e8e51 ths
        case CmdTx:
893 7f1e9d4e Kevin Wolf
            if (bit_nc) {
894 7f1e9d4e Kevin Wolf
                missing("CmdTx: NC = 0");
895 75f5a6cc Stefan Weil
                ok_status = 0;
896 7f1e9d4e Kevin Wolf
                break;
897 7f1e9d4e Kevin Wolf
            }
898 f3a52e50 Stefan Weil
            tx_command(s);
899 663e8e51 ths
            break;
900 663e8e51 ths
        case CmdTDR:
901 aac443e6 Stefan Weil
            TRACE(OTHER, logout("load microcode\n"));
902 663e8e51 ths
            /* Starting with offset 8, the command contains
903 663e8e51 ths
             * 64 dwords microcode which we just ignore here. */
904 663e8e51 ths
            break;
905 f80a7fc3 Stefan Weil
        case CmdDiagnose:
906 f80a7fc3 Stefan Weil
            TRACE(OTHER, logout("diagnose\n"));
907 f80a7fc3 Stefan Weil
            /* Make sure error flag is not set. */
908 f80a7fc3 Stefan Weil
            s->tx.status = 0;
909 f80a7fc3 Stefan Weil
            break;
910 663e8e51 ths
        default:
911 663e8e51 ths
            missing("undefined command");
912 75f5a6cc Stefan Weil
            ok_status = 0;
913 7f1e9d4e Kevin Wolf
            break;
914 663e8e51 ths
        }
915 7f1e9d4e Kevin Wolf
        /* Write new status. */
916 16ef60c9 Eduard - Gabriel Munteanu
        stw_le_pci_dma(&s->dev, s->cb_address,
917 16ef60c9 Eduard - Gabriel Munteanu
                       s->tx.status | ok_status | STATUS_C);
918 663e8e51 ths
        if (bit_i) {
919 663e8e51 ths
            /* CU completed action. */
920 663e8e51 ths
            eepro100_cx_interrupt(s);
921 663e8e51 ths
        }
922 663e8e51 ths
        if (bit_el) {
923 aac443e6 Stefan Weil
            /* CU becomes idle. Terminate command loop. */
924 663e8e51 ths
            set_cu_state(s, cu_idle);
925 663e8e51 ths
            eepro100_cna_interrupt(s);
926 5fa9a0ae Stefan Weil
            break;
927 663e8e51 ths
        } else if (bit_s) {
928 5fa9a0ae Stefan Weil
            /* CU becomes suspended. Terminate command loop. */
929 663e8e51 ths
            set_cu_state(s, cu_suspended);
930 663e8e51 ths
            eepro100_cna_interrupt(s);
931 5fa9a0ae Stefan Weil
            break;
932 663e8e51 ths
        } else {
933 663e8e51 ths
            /* More entries in list. */
934 aac443e6 Stefan Weil
            TRACE(OTHER, logout("CU list with at least one more entry\n"));
935 663e8e51 ths
        }
936 5fa9a0ae Stefan Weil
    }
937 5fa9a0ae Stefan Weil
    TRACE(OTHER, logout("CU list empty\n"));
938 5fa9a0ae Stefan Weil
    /* List is empty. Now CU is idle or suspended. */
939 5fa9a0ae Stefan Weil
}
940 5fa9a0ae Stefan Weil
941 5fa9a0ae Stefan Weil
static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
942 5fa9a0ae Stefan Weil
{
943 cb25a3fb Stefan Weil
    cu_state_t cu_state;
944 5fa9a0ae Stefan Weil
    switch (val) {
945 5fa9a0ae Stefan Weil
    case CU_NOP:
946 5fa9a0ae Stefan Weil
        /* No operation. */
947 5fa9a0ae Stefan Weil
        break;
948 5fa9a0ae Stefan Weil
    case CU_START:
949 cb25a3fb Stefan Weil
        cu_state = get_cu_state(s);
950 cb25a3fb Stefan Weil
        if (cu_state != cu_idle && cu_state != cu_suspended) {
951 cb25a3fb Stefan Weil
            /* Intel documentation says that CU must be idle or suspended
952 cb25a3fb Stefan Weil
             * for the CU start command. */
953 cb25a3fb Stefan Weil
            logout("unexpected CU state is %u\n", cu_state);
954 5fa9a0ae Stefan Weil
        }
955 5fa9a0ae Stefan Weil
        set_cu_state(s, cu_active);
956 27a05006 Stefan Weil
        s->cu_offset = e100_read_reg4(s, SCBPointer);
957 5fa9a0ae Stefan Weil
        action_command(s);
958 663e8e51 ths
        break;
959 663e8e51 ths
    case CU_RESUME:
960 663e8e51 ths
        if (get_cu_state(s) != cu_suspended) {
961 663e8e51 ths
            logout("bad CU resume from CU state %u\n", get_cu_state(s));
962 663e8e51 ths
            /* Workaround for bad Linux eepro100 driver which resumes
963 663e8e51 ths
             * from idle state. */
964 e7493b25 Stefan Weil
#if 0
965 e7493b25 Stefan Weil
            missing("cu resume");
966 e7493b25 Stefan Weil
#endif
967 663e8e51 ths
            set_cu_state(s, cu_suspended);
968 663e8e51 ths
        }
969 663e8e51 ths
        if (get_cu_state(s) == cu_suspended) {
970 aac443e6 Stefan Weil
            TRACE(OTHER, logout("CU resuming\n"));
971 663e8e51 ths
            set_cu_state(s, cu_active);
972 5fa9a0ae Stefan Weil
            action_command(s);
973 663e8e51 ths
        }
974 663e8e51 ths
        break;
975 663e8e51 ths
    case CU_STATSADDR:
976 663e8e51 ths
        /* Load dump counters address. */
977 27a05006 Stefan Weil
        s->statsaddr = e100_read_reg4(s, SCBPointer);
978 c16ada98 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (dump counters address)\n", val));
979 c16ada98 Stefan Weil
        if (s->statsaddr & 3) {
980 c16ada98 Stefan Weil
            /* Memory must be Dword aligned. */
981 c16ada98 Stefan Weil
            logout("unaligned dump counters address\n");
982 c16ada98 Stefan Weil
            /* Handling of misaligned addresses is undefined.
983 c16ada98 Stefan Weil
             * Here we align the address by ignoring the lower bits. */
984 c16ada98 Stefan Weil
            /* TODO: Test unaligned dump counter address on real hardware. */
985 c16ada98 Stefan Weil
            s->statsaddr &= ~3;
986 c16ada98 Stefan Weil
        }
987 663e8e51 ths
        break;
988 663e8e51 ths
    case CU_SHOWSTATS:
989 663e8e51 ths
        /* Dump statistical counters. */
990 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val));
991 663e8e51 ths
        dump_statistics(s);
992 16ef60c9 Eduard - Gabriel Munteanu
        stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa005);
993 663e8e51 ths
        break;
994 663e8e51 ths
    case CU_CMD_BASE:
995 663e8e51 ths
        /* Load CU base. */
996 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (CU base address)\n", val));
997 27a05006 Stefan Weil
        s->cu_base = e100_read_reg4(s, SCBPointer);
998 663e8e51 ths
        break;
999 663e8e51 ths
    case CU_DUMPSTATS:
1000 663e8e51 ths
        /* Dump and reset statistical counters. */
1001 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val));
1002 663e8e51 ths
        dump_statistics(s);
1003 16ef60c9 Eduard - Gabriel Munteanu
        stl_le_pci_dma(&s->dev, s->statsaddr + s->stats_size, 0xa007);
1004 663e8e51 ths
        memset(&s->statistics, 0, sizeof(s->statistics));
1005 663e8e51 ths
        break;
1006 663e8e51 ths
    case CU_SRESUME:
1007 663e8e51 ths
        /* CU static resume. */
1008 663e8e51 ths
        missing("CU static resume");
1009 663e8e51 ths
        break;
1010 663e8e51 ths
    default:
1011 663e8e51 ths
        missing("Undefined CU command");
1012 663e8e51 ths
    }
1013 663e8e51 ths
}
1014 663e8e51 ths
1015 663e8e51 ths
static void eepro100_ru_command(EEPRO100State * s, uint8_t val)
1016 663e8e51 ths
{
1017 663e8e51 ths
    switch (val) {
1018 663e8e51 ths
    case RU_NOP:
1019 663e8e51 ths
        /* No operation. */
1020 663e8e51 ths
        break;
1021 663e8e51 ths
    case RX_START:
1022 663e8e51 ths
        /* RU start. */
1023 663e8e51 ths
        if (get_ru_state(s) != ru_idle) {
1024 663e8e51 ths
            logout("RU state is %u, should be %u\n", get_ru_state(s), ru_idle);
1025 e7493b25 Stefan Weil
#if 0
1026 e7493b25 Stefan Weil
            assert(!"wrong RU state");
1027 e7493b25 Stefan Weil
#endif
1028 663e8e51 ths
        }
1029 663e8e51 ths
        set_ru_state(s, ru_ready);
1030 27a05006 Stefan Weil
        s->ru_offset = e100_read_reg4(s, SCBPointer);
1031 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (rx start)\n", val));
1032 663e8e51 ths
        break;
1033 663e8e51 ths
    case RX_RESUME:
1034 663e8e51 ths
        /* Restart RU. */
1035 663e8e51 ths
        if (get_ru_state(s) != ru_suspended) {
1036 663e8e51 ths
            logout("RU state is %u, should be %u\n", get_ru_state(s),
1037 663e8e51 ths
                   ru_suspended);
1038 e7493b25 Stefan Weil
#if 0
1039 e7493b25 Stefan Weil
            assert(!"wrong RU state");
1040 e7493b25 Stefan Weil
#endif
1041 663e8e51 ths
        }
1042 663e8e51 ths
        set_ru_state(s, ru_ready);
1043 663e8e51 ths
        break;
1044 e824012b Stefan Weil
    case RU_ABORT:
1045 e824012b Stefan Weil
        /* RU abort. */
1046 e824012b Stefan Weil
        if (get_ru_state(s) == ru_ready) {
1047 e824012b Stefan Weil
            eepro100_rnr_interrupt(s);
1048 e824012b Stefan Weil
        }
1049 e824012b Stefan Weil
        set_ru_state(s, ru_idle);
1050 e824012b Stefan Weil
        break;
1051 663e8e51 ths
    case RX_ADDR_LOAD:
1052 663e8e51 ths
        /* Load RU base. */
1053 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (RU base address)\n", val));
1054 27a05006 Stefan Weil
        s->ru_base = e100_read_reg4(s, SCBPointer);
1055 663e8e51 ths
        break;
1056 663e8e51 ths
    default:
1057 663e8e51 ths
        logout("val=0x%02x (undefined RU command)\n", val);
1058 663e8e51 ths
        missing("Undefined SU command");
1059 663e8e51 ths
    }
1060 663e8e51 ths
}
1061 663e8e51 ths
1062 663e8e51 ths
static void eepro100_write_command(EEPRO100State * s, uint8_t val)
1063 663e8e51 ths
{
1064 663e8e51 ths
    eepro100_ru_command(s, val & 0x0f);
1065 663e8e51 ths
    eepro100_cu_command(s, val & 0xf0);
1066 663e8e51 ths
    if ((val) == 0) {
1067 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x\n", val));
1068 663e8e51 ths
    }
1069 663e8e51 ths
    /* Clear command byte after command was accepted. */
1070 663e8e51 ths
    s->mem[SCBCmd] = 0;
1071 663e8e51 ths
}
1072 663e8e51 ths
1073 663e8e51 ths
/*****************************************************************************
1074 663e8e51 ths
 *
1075 663e8e51 ths
 * EEPROM emulation.
1076 663e8e51 ths
 *
1077 663e8e51 ths
 ****************************************************************************/
1078 663e8e51 ths
1079 663e8e51 ths
#define EEPROM_CS       0x02
1080 663e8e51 ths
#define EEPROM_SK       0x01
1081 663e8e51 ths
#define EEPROM_DI       0x04
1082 663e8e51 ths
#define EEPROM_DO       0x08
1083 663e8e51 ths
1084 663e8e51 ths
static uint16_t eepro100_read_eeprom(EEPRO100State * s)
1085 663e8e51 ths
{
1086 e5e23ab8 Stefan Weil
    uint16_t val = e100_read_reg2(s, SCBeeprom);
1087 663e8e51 ths
    if (eeprom93xx_read(s->eeprom)) {
1088 663e8e51 ths
        val |= EEPROM_DO;
1089 663e8e51 ths
    } else {
1090 663e8e51 ths
        val &= ~EEPROM_DO;
1091 663e8e51 ths
    }
1092 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("val=0x%04x\n", val));
1093 663e8e51 ths
    return val;
1094 663e8e51 ths
}
1095 663e8e51 ths
1096 c227f099 Anthony Liguori
static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val)
1097 663e8e51 ths
{
1098 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("val=0x%02x\n", val));
1099 663e8e51 ths
1100 ebabb67a Stefan Weil
    /* mask unwritable bits */
1101 e7493b25 Stefan Weil
#if 0
1102 e7493b25 Stefan Weil
    val = SET_MASKED(val, 0x31, eeprom->value);
1103 e7493b25 Stefan Weil
#endif
1104 663e8e51 ths
1105 663e8e51 ths
    int eecs = ((val & EEPROM_CS) != 0);
1106 663e8e51 ths
    int eesk = ((val & EEPROM_SK) != 0);
1107 663e8e51 ths
    int eedi = ((val & EEPROM_DI) != 0);
1108 663e8e51 ths
    eeprom93xx_write(eeprom, eecs, eesk, eedi);
1109 663e8e51 ths
}
1110 663e8e51 ths
1111 663e8e51 ths
/*****************************************************************************
1112 663e8e51 ths
 *
1113 663e8e51 ths
 * MDI emulation.
1114 663e8e51 ths
 *
1115 663e8e51 ths
 ****************************************************************************/
1116 663e8e51 ths
1117 663e8e51 ths
#if defined(DEBUG_EEPRO100)
1118 6a0b9cc9 Reimar Dรถffinger
static const char * const mdi_op_name[] = {
1119 663e8e51 ths
    "opcode 0",
1120 663e8e51 ths
    "write",
1121 663e8e51 ths
    "read",
1122 663e8e51 ths
    "opcode 3"
1123 663e8e51 ths
};
1124 663e8e51 ths
1125 6a0b9cc9 Reimar Dรถffinger
static const char * const mdi_reg_name[] = {
1126 663e8e51 ths
    "Control",
1127 663e8e51 ths
    "Status",
1128 663e8e51 ths
    "PHY Identification (Word 1)",
1129 663e8e51 ths
    "PHY Identification (Word 2)",
1130 663e8e51 ths
    "Auto-Negotiation Advertisement",
1131 663e8e51 ths
    "Auto-Negotiation Link Partner Ability",
1132 663e8e51 ths
    "Auto-Negotiation Expansion"
1133 663e8e51 ths
};
1134 aac443e6 Stefan Weil
1135 aac443e6 Stefan Weil
static const char *reg2name(uint8_t reg)
1136 aac443e6 Stefan Weil
{
1137 aac443e6 Stefan Weil
    static char buffer[10];
1138 aac443e6 Stefan Weil
    const char *p = buffer;
1139 aac443e6 Stefan Weil
    if (reg < ARRAY_SIZE(mdi_reg_name)) {
1140 aac443e6 Stefan Weil
        p = mdi_reg_name[reg];
1141 aac443e6 Stefan Weil
    } else {
1142 aac443e6 Stefan Weil
        snprintf(buffer, sizeof(buffer), "reg=0x%02x", reg);
1143 aac443e6 Stefan Weil
    }
1144 aac443e6 Stefan Weil
    return p;
1145 aac443e6 Stefan Weil
}
1146 663e8e51 ths
#endif                          /* DEBUG_EEPRO100 */
1147 663e8e51 ths
1148 663e8e51 ths
static uint32_t eepro100_read_mdi(EEPRO100State * s)
1149 663e8e51 ths
{
1150 e5e23ab8 Stefan Weil
    uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
1151 663e8e51 ths
1152 663e8e51 ths
#ifdef DEBUG_EEPRO100
1153 663e8e51 ths
    uint8_t raiseint = (val & BIT(29)) >> 29;
1154 663e8e51 ths
    uint8_t opcode = (val & BITS(27, 26)) >> 26;
1155 663e8e51 ths
    uint8_t phy = (val & BITS(25, 21)) >> 21;
1156 663e8e51 ths
    uint8_t reg = (val & BITS(20, 16)) >> 16;
1157 663e8e51 ths
    uint16_t data = (val & BITS(15, 0));
1158 663e8e51 ths
#endif
1159 663e8e51 ths
    /* Emulation takes no time to finish MDI transaction. */
1160 663e8e51 ths
    val |= BIT(28);
1161 663e8e51 ths
    TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1162 663e8e51 ths
                      val, raiseint, mdi_op_name[opcode], phy,
1163 aac443e6 Stefan Weil
                      reg2name(reg), data));
1164 663e8e51 ths
    return val;
1165 663e8e51 ths
}
1166 663e8e51 ths
1167 0113f48d Stefan Weil
static void eepro100_write_mdi(EEPRO100State *s)
1168 663e8e51 ths
{
1169 0113f48d Stefan Weil
    uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
1170 663e8e51 ths
    uint8_t raiseint = (val & BIT(29)) >> 29;
1171 663e8e51 ths
    uint8_t opcode = (val & BITS(27, 26)) >> 26;
1172 663e8e51 ths
    uint8_t phy = (val & BITS(25, 21)) >> 21;
1173 663e8e51 ths
    uint8_t reg = (val & BITS(20, 16)) >> 16;
1174 663e8e51 ths
    uint16_t data = (val & BITS(15, 0));
1175 aac443e6 Stefan Weil
    TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1176 aac443e6 Stefan Weil
          val, raiseint, mdi_op_name[opcode], phy, reg2name(reg), data));
1177 663e8e51 ths
    if (phy != 1) {
1178 663e8e51 ths
        /* Unsupported PHY address. */
1179 e7493b25 Stefan Weil
#if 0
1180 e7493b25 Stefan Weil
        logout("phy must be 1 but is %u\n", phy);
1181 e7493b25 Stefan Weil
#endif
1182 663e8e51 ths
        data = 0;
1183 663e8e51 ths
    } else if (opcode != 1 && opcode != 2) {
1184 663e8e51 ths
        /* Unsupported opcode. */
1185 663e8e51 ths
        logout("opcode must be 1 or 2 but is %u\n", opcode);
1186 663e8e51 ths
        data = 0;
1187 663e8e51 ths
    } else if (reg > 6) {
1188 663e8e51 ths
        /* Unsupported register. */
1189 663e8e51 ths
        logout("register must be 0...6 but is %u\n", reg);
1190 663e8e51 ths
        data = 0;
1191 663e8e51 ths
    } else {
1192 663e8e51 ths
        TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1193 663e8e51 ths
                          val, raiseint, mdi_op_name[opcode], phy,
1194 aac443e6 Stefan Weil
                          reg2name(reg), data));
1195 663e8e51 ths
        if (opcode == 1) {
1196 663e8e51 ths
            /* MDI write */
1197 663e8e51 ths
            switch (reg) {
1198 663e8e51 ths
            case 0:            /* Control Register */
1199 663e8e51 ths
                if (data & 0x8000) {
1200 663e8e51 ths
                    /* Reset status and control registers to default. */
1201 663e8e51 ths
                    s->mdimem[0] = eepro100_mdi_default[0];
1202 663e8e51 ths
                    s->mdimem[1] = eepro100_mdi_default[1];
1203 663e8e51 ths
                    data = s->mdimem[reg];
1204 663e8e51 ths
                } else {
1205 663e8e51 ths
                    /* Restart Auto Configuration = Normal Operation */
1206 663e8e51 ths
                    data &= ~0x0200;
1207 663e8e51 ths
                }
1208 663e8e51 ths
                break;
1209 663e8e51 ths
            case 1:            /* Status Register */
1210 663e8e51 ths
                missing("not writable");
1211 663e8e51 ths
                data = s->mdimem[reg];
1212 663e8e51 ths
                break;
1213 663e8e51 ths
            case 2:            /* PHY Identification Register (Word 1) */
1214 663e8e51 ths
            case 3:            /* PHY Identification Register (Word 2) */
1215 663e8e51 ths
                missing("not implemented");
1216 663e8e51 ths
                break;
1217 663e8e51 ths
            case 4:            /* Auto-Negotiation Advertisement Register */
1218 663e8e51 ths
            case 5:            /* Auto-Negotiation Link Partner Ability Register */
1219 663e8e51 ths
                break;
1220 663e8e51 ths
            case 6:            /* Auto-Negotiation Expansion Register */
1221 663e8e51 ths
            default:
1222 663e8e51 ths
                missing("not implemented");
1223 663e8e51 ths
            }
1224 663e8e51 ths
            s->mdimem[reg] = data;
1225 663e8e51 ths
        } else if (opcode == 2) {
1226 663e8e51 ths
            /* MDI read */
1227 663e8e51 ths
            switch (reg) {
1228 663e8e51 ths
            case 0:            /* Control Register */
1229 663e8e51 ths
                if (data & 0x8000) {
1230 663e8e51 ths
                    /* Reset status and control registers to default. */
1231 663e8e51 ths
                    s->mdimem[0] = eepro100_mdi_default[0];
1232 663e8e51 ths
                    s->mdimem[1] = eepro100_mdi_default[1];
1233 663e8e51 ths
                }
1234 663e8e51 ths
                break;
1235 663e8e51 ths
            case 1:            /* Status Register */
1236 663e8e51 ths
                s->mdimem[reg] |= 0x0020;
1237 663e8e51 ths
                break;
1238 663e8e51 ths
            case 2:            /* PHY Identification Register (Word 1) */
1239 663e8e51 ths
            case 3:            /* PHY Identification Register (Word 2) */
1240 663e8e51 ths
            case 4:            /* Auto-Negotiation Advertisement Register */
1241 663e8e51 ths
                break;
1242 663e8e51 ths
            case 5:            /* Auto-Negotiation Link Partner Ability Register */
1243 663e8e51 ths
                s->mdimem[reg] = 0x41fe;
1244 663e8e51 ths
                break;
1245 663e8e51 ths
            case 6:            /* Auto-Negotiation Expansion Register */
1246 663e8e51 ths
                s->mdimem[reg] = 0x0001;
1247 663e8e51 ths
                break;
1248 663e8e51 ths
            }
1249 663e8e51 ths
            data = s->mdimem[reg];
1250 663e8e51 ths
        }
1251 663e8e51 ths
        /* Emulation takes no time to finish MDI transaction.
1252 663e8e51 ths
         * Set MDI bit in SCB status register. */
1253 663e8e51 ths
        s->mem[SCBAck] |= 0x08;
1254 663e8e51 ths
        val |= BIT(28);
1255 663e8e51 ths
        if (raiseint) {
1256 663e8e51 ths
            eepro100_mdi_interrupt(s);
1257 663e8e51 ths
        }
1258 663e8e51 ths
    }
1259 663e8e51 ths
    val = (val & 0xffff0000) + data;
1260 e5e23ab8 Stefan Weil
    e100_write_reg4(s, SCBCtrlMDI, val);
1261 663e8e51 ths
}
1262 663e8e51 ths
1263 663e8e51 ths
/*****************************************************************************
1264 663e8e51 ths
 *
1265 663e8e51 ths
 * Port emulation.
1266 663e8e51 ths
 *
1267 663e8e51 ths
 ****************************************************************************/
1268 663e8e51 ths
1269 663e8e51 ths
#define PORT_SOFTWARE_RESET     0
1270 663e8e51 ths
#define PORT_SELFTEST           1
1271 663e8e51 ths
#define PORT_SELECTIVE_RESET    2
1272 663e8e51 ths
#define PORT_DUMP               3
1273 663e8e51 ths
#define PORT_SELECTION_MASK     3
1274 663e8e51 ths
1275 663e8e51 ths
typedef struct {
1276 663e8e51 ths
    uint32_t st_sign;           /* Self Test Signature */
1277 663e8e51 ths
    uint32_t st_result;         /* Self Test Results */
1278 c227f099 Anthony Liguori
} eepro100_selftest_t;
1279 663e8e51 ths
1280 663e8e51 ths
static uint32_t eepro100_read_port(EEPRO100State * s)
1281 663e8e51 ths
{
1282 663e8e51 ths
    return 0;
1283 663e8e51 ths
}
1284 663e8e51 ths
1285 3fd3d0b4 Stefan Weil
static void eepro100_write_port(EEPRO100State *s)
1286 663e8e51 ths
{
1287 3fd3d0b4 Stefan Weil
    uint32_t val = e100_read_reg4(s, SCBPort);
1288 663e8e51 ths
    uint32_t address = (val & ~PORT_SELECTION_MASK);
1289 663e8e51 ths
    uint8_t selection = (val & PORT_SELECTION_MASK);
1290 663e8e51 ths
    switch (selection) {
1291 663e8e51 ths
    case PORT_SOFTWARE_RESET:
1292 663e8e51 ths
        nic_reset(s);
1293 663e8e51 ths
        break;
1294 663e8e51 ths
    case PORT_SELFTEST:
1295 aac443e6 Stefan Weil
        TRACE(OTHER, logout("selftest address=0x%08x\n", address));
1296 c227f099 Anthony Liguori
        eepro100_selftest_t data;
1297 16ef60c9 Eduard - Gabriel Munteanu
        pci_dma_read(&s->dev, address, (uint8_t *) &data, sizeof(data));
1298 663e8e51 ths
        data.st_sign = 0xffffffff;
1299 663e8e51 ths
        data.st_result = 0;
1300 16ef60c9 Eduard - Gabriel Munteanu
        pci_dma_write(&s->dev, address, (uint8_t *) &data, sizeof(data));
1301 663e8e51 ths
        break;
1302 663e8e51 ths
    case PORT_SELECTIVE_RESET:
1303 aac443e6 Stefan Weil
        TRACE(OTHER, logout("selective reset, selftest address=0x%08x\n", address));
1304 663e8e51 ths
        nic_selective_reset(s);
1305 663e8e51 ths
        break;
1306 663e8e51 ths
    default:
1307 663e8e51 ths
        logout("val=0x%08x\n", val);
1308 663e8e51 ths
        missing("unknown port selection");
1309 663e8e51 ths
    }
1310 663e8e51 ths
}
1311 663e8e51 ths
1312 663e8e51 ths
/*****************************************************************************
1313 663e8e51 ths
 *
1314 663e8e51 ths
 * General hardware emulation.
1315 663e8e51 ths
 *
1316 663e8e51 ths
 ****************************************************************************/
1317 663e8e51 ths
1318 663e8e51 ths
static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
1319 663e8e51 ths
{
1320 ef476062 Blue Swirl
    uint8_t val = 0;
1321 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1322 e5e23ab8 Stefan Weil
        val = s->mem[addr];
1323 663e8e51 ths
    }
1324 663e8e51 ths
1325 663e8e51 ths
    switch (addr) {
1326 663e8e51 ths
    case SCBStatus:
1327 663e8e51 ths
    case SCBAck:
1328 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1329 663e8e51 ths
        break;
1330 663e8e51 ths
    case SCBCmd:
1331 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1332 e7493b25 Stefan Weil
#if 0
1333 e7493b25 Stefan Weil
        val = eepro100_read_command(s);
1334 e7493b25 Stefan Weil
#endif
1335 663e8e51 ths
        break;
1336 663e8e51 ths
    case SCBIntmask:
1337 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1338 663e8e51 ths
        break;
1339 663e8e51 ths
    case SCBPort + 3:
1340 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1341 663e8e51 ths
        break;
1342 663e8e51 ths
    case SCBeeprom:
1343 663e8e51 ths
        val = eepro100_read_eeprom(s);
1344 663e8e51 ths
        break;
1345 0113f48d Stefan Weil
    case SCBCtrlMDI:
1346 0113f48d Stefan Weil
    case SCBCtrlMDI + 1:
1347 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1348 0113f48d Stefan Weil
    case SCBCtrlMDI + 3:
1349 0113f48d Stefan Weil
        val = (uint8_t)(eepro100_read_mdi(s) >> (8 * (addr & 3)));
1350 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1351 0113f48d Stefan Weil
        break;
1352 0908bba1 Stefan Weil
    case SCBpmdr:       /* Power Management Driver Register */
1353 663e8e51 ths
        val = 0;
1354 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1355 663e8e51 ths
        break;
1356 a39bd017 Stefan Weil
    case SCBgctrl:      /* General Control Register */
1357 a39bd017 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1358 a39bd017 Stefan Weil
        break;
1359 0908bba1 Stefan Weil
    case SCBgstat:      /* General Status Register */
1360 663e8e51 ths
        /* 100 Mbps full duplex, valid link */
1361 663e8e51 ths
        val = 0x07;
1362 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=General Status val=%02x\n", val));
1363 663e8e51 ths
        break;
1364 663e8e51 ths
    default:
1365 663e8e51 ths
        logout("addr=%s val=0x%02x\n", regname(addr), val);
1366 663e8e51 ths
        missing("unknown byte read");
1367 663e8e51 ths
    }
1368 663e8e51 ths
    return val;
1369 663e8e51 ths
}
1370 663e8e51 ths
1371 663e8e51 ths
static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr)
1372 663e8e51 ths
{
1373 ef476062 Blue Swirl
    uint16_t val = 0;
1374 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1375 e5e23ab8 Stefan Weil
        val = e100_read_reg2(s, addr);
1376 663e8e51 ths
    }
1377 663e8e51 ths
1378 663e8e51 ths
    switch (addr) {
1379 663e8e51 ths
    case SCBStatus:
1380 dbbaaff6 =?UTF-8?q?Reimar=20D=C3=B6ffinger?=
    case SCBCmd:
1381 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1382 663e8e51 ths
        break;
1383 663e8e51 ths
    case SCBeeprom:
1384 663e8e51 ths
        val = eepro100_read_eeprom(s);
1385 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1386 663e8e51 ths
        break;
1387 0113f48d Stefan Weil
    case SCBCtrlMDI:
1388 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1389 0113f48d Stefan Weil
        val = (uint16_t)(eepro100_read_mdi(s) >> (8 * (addr & 3)));
1390 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1391 0113f48d Stefan Weil
        break;
1392 663e8e51 ths
    default:
1393 663e8e51 ths
        logout("addr=%s val=0x%04x\n", regname(addr), val);
1394 663e8e51 ths
        missing("unknown word read");
1395 663e8e51 ths
    }
1396 663e8e51 ths
    return val;
1397 663e8e51 ths
}
1398 663e8e51 ths
1399 663e8e51 ths
static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
1400 663e8e51 ths
{
1401 ef476062 Blue Swirl
    uint32_t val = 0;
1402 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1403 e5e23ab8 Stefan Weil
        val = e100_read_reg4(s, addr);
1404 663e8e51 ths
    }
1405 663e8e51 ths
1406 663e8e51 ths
    switch (addr) {
1407 663e8e51 ths
    case SCBStatus:
1408 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1409 663e8e51 ths
        break;
1410 663e8e51 ths
    case SCBPointer:
1411 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1412 663e8e51 ths
        break;
1413 663e8e51 ths
    case SCBPort:
1414 663e8e51 ths
        val = eepro100_read_port(s);
1415 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1416 663e8e51 ths
        break;
1417 072476ea Stefan Weil
    case SCBflash:
1418 072476ea Stefan Weil
        val = eepro100_read_eeprom(s);
1419 072476ea Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1420 072476ea Stefan Weil
        break;
1421 663e8e51 ths
    case SCBCtrlMDI:
1422 663e8e51 ths
        val = eepro100_read_mdi(s);
1423 663e8e51 ths
        break;
1424 663e8e51 ths
    default:
1425 663e8e51 ths
        logout("addr=%s val=0x%08x\n", regname(addr), val);
1426 663e8e51 ths
        missing("unknown longword read");
1427 663e8e51 ths
    }
1428 663e8e51 ths
    return val;
1429 663e8e51 ths
}
1430 663e8e51 ths
1431 663e8e51 ths
static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
1432 663e8e51 ths
{
1433 e74818f3 Stefan Weil
    /* SCBStatus is readonly. */
1434 e74818f3 Stefan Weil
    if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
1435 e5e23ab8 Stefan Weil
        s->mem[addr] = val;
1436 663e8e51 ths
    }
1437 663e8e51 ths
1438 663e8e51 ths
    switch (addr) {
1439 663e8e51 ths
    case SCBStatus:
1440 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1441 663e8e51 ths
        break;
1442 663e8e51 ths
    case SCBAck:
1443 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1444 663e8e51 ths
        eepro100_acknowledge(s);
1445 663e8e51 ths
        break;
1446 663e8e51 ths
    case SCBCmd:
1447 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1448 663e8e51 ths
        eepro100_write_command(s, val);
1449 663e8e51 ths
        break;
1450 663e8e51 ths
    case SCBIntmask:
1451 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1452 663e8e51 ths
        if (val & BIT(1)) {
1453 663e8e51 ths
            eepro100_swi_interrupt(s);
1454 663e8e51 ths
        }
1455 663e8e51 ths
        eepro100_interrupt(s, 0);
1456 663e8e51 ths
        break;
1457 27a05006 Stefan Weil
    case SCBPointer:
1458 27a05006 Stefan Weil
    case SCBPointer + 1:
1459 27a05006 Stefan Weil
    case SCBPointer + 2:
1460 27a05006 Stefan Weil
    case SCBPointer + 3:
1461 27a05006 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1462 27a05006 Stefan Weil
        break;
1463 3fd3d0b4 Stefan Weil
    case SCBPort:
1464 3fd3d0b4 Stefan Weil
    case SCBPort + 1:
1465 3fd3d0b4 Stefan Weil
    case SCBPort + 2:
1466 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1467 3fd3d0b4 Stefan Weil
        break;
1468 663e8e51 ths
    case SCBPort + 3:
1469 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1470 3fd3d0b4 Stefan Weil
        eepro100_write_port(s);
1471 3fd3d0b4 Stefan Weil
        break;
1472 aac443e6 Stefan Weil
    case SCBFlow:       /* does not exist on 82557 */
1473 3257d2b6 ths
    case SCBFlow + 1:
1474 3257d2b6 ths
    case SCBFlow + 2:
1475 0908bba1 Stefan Weil
    case SCBpmdr:       /* does not exist on 82557 */
1476 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1477 663e8e51 ths
        break;
1478 663e8e51 ths
    case SCBeeprom:
1479 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1480 663e8e51 ths
        eepro100_write_eeprom(s->eeprom, val);
1481 663e8e51 ths
        break;
1482 0113f48d Stefan Weil
    case SCBCtrlMDI:
1483 0113f48d Stefan Weil
    case SCBCtrlMDI + 1:
1484 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1485 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1486 0113f48d Stefan Weil
        break;
1487 0113f48d Stefan Weil
    case SCBCtrlMDI + 3:
1488 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1489 0113f48d Stefan Weil
        eepro100_write_mdi(s);
1490 0113f48d Stefan Weil
        break;
1491 663e8e51 ths
    default:
1492 663e8e51 ths
        logout("addr=%s val=0x%02x\n", regname(addr), val);
1493 663e8e51 ths
        missing("unknown byte write");
1494 663e8e51 ths
    }
1495 663e8e51 ths
}
1496 663e8e51 ths
1497 663e8e51 ths
static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
1498 663e8e51 ths
{
1499 e74818f3 Stefan Weil
    /* SCBStatus is readonly. */
1500 e74818f3 Stefan Weil
    if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
1501 e5e23ab8 Stefan Weil
        e100_write_reg2(s, addr, val);
1502 663e8e51 ths
    }
1503 663e8e51 ths
1504 663e8e51 ths
    switch (addr) {
1505 663e8e51 ths
    case SCBStatus:
1506 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1507 e74818f3 Stefan Weil
        s->mem[SCBAck] = (val >> 8);
1508 663e8e51 ths
        eepro100_acknowledge(s);
1509 663e8e51 ths
        break;
1510 663e8e51 ths
    case SCBCmd:
1511 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1512 663e8e51 ths
        eepro100_write_command(s, val);
1513 663e8e51 ths
        eepro100_write1(s, SCBIntmask, val >> 8);
1514 663e8e51 ths
        break;
1515 27a05006 Stefan Weil
    case SCBPointer:
1516 27a05006 Stefan Weil
    case SCBPointer + 2:
1517 27a05006 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1518 27a05006 Stefan Weil
        break;
1519 3fd3d0b4 Stefan Weil
    case SCBPort:
1520 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1521 3fd3d0b4 Stefan Weil
        break;
1522 3fd3d0b4 Stefan Weil
    case SCBPort + 2:
1523 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1524 3fd3d0b4 Stefan Weil
        eepro100_write_port(s);
1525 3fd3d0b4 Stefan Weil
        break;
1526 663e8e51 ths
    case SCBeeprom:
1527 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1528 663e8e51 ths
        eepro100_write_eeprom(s->eeprom, val);
1529 663e8e51 ths
        break;
1530 0113f48d Stefan Weil
    case SCBCtrlMDI:
1531 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1532 0113f48d Stefan Weil
        break;
1533 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1534 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1535 0113f48d Stefan Weil
        eepro100_write_mdi(s);
1536 0113f48d Stefan Weil
        break;
1537 663e8e51 ths
    default:
1538 663e8e51 ths
        logout("addr=%s val=0x%04x\n", regname(addr), val);
1539 663e8e51 ths
        missing("unknown word write");
1540 663e8e51 ths
    }
1541 663e8e51 ths
}
1542 663e8e51 ths
1543 663e8e51 ths
static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
1544 663e8e51 ths
{
1545 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1546 e5e23ab8 Stefan Weil
        e100_write_reg4(s, addr, val);
1547 663e8e51 ths
    }
1548 663e8e51 ths
1549 663e8e51 ths
    switch (addr) {
1550 663e8e51 ths
    case SCBPointer:
1551 27a05006 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1552 663e8e51 ths
        break;
1553 663e8e51 ths
    case SCBPort:
1554 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1555 3fd3d0b4 Stefan Weil
        eepro100_write_port(s);
1556 663e8e51 ths
        break;
1557 072476ea Stefan Weil
    case SCBflash:
1558 072476ea Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1559 072476ea Stefan Weil
        val = val >> 16;
1560 072476ea Stefan Weil
        eepro100_write_eeprom(s->eeprom, val);
1561 072476ea Stefan Weil
        break;
1562 663e8e51 ths
    case SCBCtrlMDI:
1563 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1564 0113f48d Stefan Weil
        eepro100_write_mdi(s);
1565 663e8e51 ths
        break;
1566 663e8e51 ths
    default:
1567 663e8e51 ths
        logout("addr=%s val=0x%08x\n", regname(addr), val);
1568 663e8e51 ths
        missing("unknown longword write");
1569 663e8e51 ths
    }
1570 663e8e51 ths
}
1571 663e8e51 ths
1572 5e6ffdde Avi Kivity
static uint64_t eepro100_read(void *opaque, target_phys_addr_t addr,
1573 5e6ffdde Avi Kivity
                              unsigned size)
1574 663e8e51 ths
{
1575 663e8e51 ths
    EEPRO100State *s = opaque;
1576 663e8e51 ths
1577 5e6ffdde Avi Kivity
    switch (size) {
1578 5e6ffdde Avi Kivity
    case 1: return eepro100_read1(s, addr);
1579 5e6ffdde Avi Kivity
    case 2: return eepro100_read2(s, addr);
1580 5e6ffdde Avi Kivity
    case 4: return eepro100_read4(s, addr);
1581 5e6ffdde Avi Kivity
    default: abort();
1582 5e6ffdde Avi Kivity
    }
1583 663e8e51 ths
}
1584 663e8e51 ths
1585 5e6ffdde Avi Kivity
static void eepro100_write(void *opaque, target_phys_addr_t addr,
1586 5e6ffdde Avi Kivity
                           uint64_t data, unsigned size)
1587 663e8e51 ths
{
1588 663e8e51 ths
    EEPRO100State *s = opaque;
1589 663e8e51 ths
1590 5e6ffdde Avi Kivity
    switch (size) {
1591 5e6ffdde Avi Kivity
    case 1: return eepro100_write1(s, addr, data);
1592 5e6ffdde Avi Kivity
    case 2: return eepro100_write2(s, addr, data);
1593 5e6ffdde Avi Kivity
    case 4: return eepro100_write4(s, addr, data);
1594 5e6ffdde Avi Kivity
    default: abort();
1595 5e6ffdde Avi Kivity
    }
1596 663e8e51 ths
}
1597 663e8e51 ths
1598 5e6ffdde Avi Kivity
static const MemoryRegionOps eepro100_ops = {
1599 5e6ffdde Avi Kivity
    .read = eepro100_read,
1600 5e6ffdde Avi Kivity
    .write = eepro100_write,
1601 5e6ffdde Avi Kivity
    .endianness = DEVICE_LITTLE_ENDIAN,
1602 663e8e51 ths
};
1603 663e8e51 ths
1604 e00e365e Mark McLoughlin
static int nic_can_receive(VLANClientState *nc)
1605 663e8e51 ths
{
1606 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1607 aac443e6 Stefan Weil
    TRACE(RXTX, logout("%p\n", s));
1608 663e8e51 ths
    return get_ru_state(s) == ru_ready;
1609 e7493b25 Stefan Weil
#if 0
1610 e7493b25 Stefan Weil
    return !eepro100_buffer_full(s);
1611 e7493b25 Stefan Weil
#endif
1612 663e8e51 ths
}
1613 663e8e51 ths
1614 e00e365e Mark McLoughlin
static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size)
1615 663e8e51 ths
{
1616 663e8e51 ths
    /* TODO:
1617 663e8e51 ths
     * - Magic packets should set bit 30 in power management driver register.
1618 663e8e51 ths
     * - Interesting packets should set bit 29 in power management driver register.
1619 663e8e51 ths
     */
1620 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1621 663e8e51 ths
    uint16_t rfd_status = 0xa000;
1622 792f1d63 Stefan Weil
#if defined(CONFIG_PAD_RECEIVED_FRAMES)
1623 792f1d63 Stefan Weil
    uint8_t min_buf[60];
1624 792f1d63 Stefan Weil
#endif
1625 663e8e51 ths
    static const uint8_t broadcast_macaddr[6] =
1626 663e8e51 ths
        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1627 663e8e51 ths
1628 792f1d63 Stefan Weil
#if defined(CONFIG_PAD_RECEIVED_FRAMES)
1629 792f1d63 Stefan Weil
    /* Pad to minimum Ethernet frame length */
1630 792f1d63 Stefan Weil
    if (size < sizeof(min_buf)) {
1631 792f1d63 Stefan Weil
        memcpy(min_buf, buf, size);
1632 792f1d63 Stefan Weil
        memset(&min_buf[size], 0, sizeof(min_buf) - size);
1633 792f1d63 Stefan Weil
        buf = min_buf;
1634 792f1d63 Stefan Weil
        size = sizeof(min_buf);
1635 792f1d63 Stefan Weil
    }
1636 792f1d63 Stefan Weil
#endif
1637 792f1d63 Stefan Weil
1638 663e8e51 ths
    if (s->configuration[8] & 0x80) {
1639 663e8e51 ths
        /* CSMA is disabled. */
1640 663e8e51 ths
        logout("%p received while CSMA is disabled\n", s);
1641 4f1c942b Mark McLoughlin
        return -1;
1642 792f1d63 Stefan Weil
#if !defined(CONFIG_PAD_RECEIVED_FRAMES)
1643 ced5296a Stefan Weil
    } else if (size < 64 && (s->configuration[7] & BIT(0))) {
1644 663e8e51 ths
        /* Short frame and configuration byte 7/0 (discard short receive) set:
1645 663e8e51 ths
         * Short frame is discarded */
1646 067d01de Stefan Weil
        logout("%p received short frame (%zu byte)\n", s, size);
1647 663e8e51 ths
        s->statistics.rx_short_frame_errors++;
1648 e7493b25 Stefan Weil
        return -1;
1649 e7493b25 Stefan Weil
#endif
1650 ced5296a Stefan Weil
    } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & BIT(3))) {
1651 663e8e51 ths
        /* Long frame and configuration byte 18/3 (long receive ok) not set:
1652 663e8e51 ths
         * Long frames are discarded. */
1653 067d01de Stefan Weil
        logout("%p received long frame (%zu byte), ignored\n", s, size);
1654 4f1c942b Mark McLoughlin
        return -1;
1655 e7493b25 Stefan Weil
    } else if (memcmp(buf, s->conf.macaddr.a, 6) == 0) {       /* !!! */
1656 663e8e51 ths
        /* Frame matches individual address. */
1657 663e8e51 ths
        /* TODO: check configuration byte 15/4 (ignore U/L). */
1658 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame for me, len=%zu\n", s, size));
1659 663e8e51 ths
    } else if (memcmp(buf, broadcast_macaddr, 6) == 0) {
1660 663e8e51 ths
        /* Broadcast frame. */
1661 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received broadcast, len=%zu\n", s, size));
1662 663e8e51 ths
        rfd_status |= 0x0002;
1663 7b8737de Stefan Weil
    } else if (buf[0] & 0x01) {
1664 663e8e51 ths
        /* Multicast frame. */
1665 7b8737de Stefan Weil
        TRACE(RXTX, logout("%p received multicast, len=%zu,%s\n", s, size, nic_dump(buf, size)));
1666 7f1e9d4e Kevin Wolf
        if (s->configuration[21] & BIT(3)) {
1667 7b8737de Stefan Weil
          /* Multicast all bit is set, receive all multicast frames. */
1668 7b8737de Stefan Weil
        } else {
1669 7b8737de Stefan Weil
          unsigned mcast_idx = compute_mcast_idx(buf);
1670 7b8737de Stefan Weil
          assert(mcast_idx < 64);
1671 7b8737de Stefan Weil
          if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
1672 7b8737de Stefan Weil
            /* Multicast frame is allowed in hash table. */
1673 ced5296a Stefan Weil
          } else if (s->configuration[15] & BIT(0)) {
1674 7b8737de Stefan Weil
              /* Promiscuous: receive all. */
1675 7b8737de Stefan Weil
              rfd_status |= 0x0004;
1676 7b8737de Stefan Weil
          } else {
1677 7b8737de Stefan Weil
              TRACE(RXTX, logout("%p multicast ignored\n", s));
1678 7b8737de Stefan Weil
              return -1;
1679 7b8737de Stefan Weil
          }
1680 663e8e51 ths
        }
1681 7b8737de Stefan Weil
        /* TODO: Next not for promiscuous mode? */
1682 663e8e51 ths
        rfd_status |= 0x0002;
1683 ced5296a Stefan Weil
    } else if (s->configuration[15] & BIT(0)) {
1684 663e8e51 ths
        /* Promiscuous: receive all. */
1685 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame in promiscuous mode, len=%zu\n", s, size));
1686 663e8e51 ths
        rfd_status |= 0x0004;
1687 010ec629 Stefan Weil
    } else if (s->configuration[20] & BIT(6)) {
1688 010ec629 Stefan Weil
        /* Multiple IA bit set. */
1689 010ec629 Stefan Weil
        unsigned mcast_idx = compute_mcast_idx(buf);
1690 010ec629 Stefan Weil
        assert(mcast_idx < 64);
1691 010ec629 Stefan Weil
        if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
1692 010ec629 Stefan Weil
            TRACE(RXTX, logout("%p accepted, multiple IA bit set\n", s));
1693 010ec629 Stefan Weil
        } else {
1694 010ec629 Stefan Weil
            TRACE(RXTX, logout("%p frame ignored, multiple IA bit set\n", s));
1695 010ec629 Stefan Weil
            return -1;
1696 010ec629 Stefan Weil
        }
1697 663e8e51 ths
    } else {
1698 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame, ignored, len=%zu,%s\n", s, size,
1699 aac443e6 Stefan Weil
              nic_dump(buf, size)));
1700 4f1c942b Mark McLoughlin
        return size;
1701 663e8e51 ths
    }
1702 663e8e51 ths
1703 663e8e51 ths
    if (get_ru_state(s) != ru_ready) {
1704 aac443e6 Stefan Weil
        /* No resources available. */
1705 aac443e6 Stefan Weil
        logout("no resources, state=%u\n", get_ru_state(s));
1706 e824012b Stefan Weil
        /* TODO: RNR interrupt only at first failed frame? */
1707 e824012b Stefan Weil
        eepro100_rnr_interrupt(s);
1708 663e8e51 ths
        s->statistics.rx_resource_errors++;
1709 e7493b25 Stefan Weil
#if 0
1710 e7493b25 Stefan Weil
        assert(!"no resources");
1711 e7493b25 Stefan Weil
#endif
1712 4f1c942b Mark McLoughlin
        return -1;
1713 663e8e51 ths
    }
1714 e7493b25 Stefan Weil
    /* !!! */
1715 c227f099 Anthony Liguori
    eepro100_rx_t rx;
1716 16ef60c9 Eduard - Gabriel Munteanu
    pci_dma_read(&s->dev, s->ru_base + s->ru_offset,
1717 e965d4bc David Gibson
                 &rx, sizeof(eepro100_rx_t));
1718 663e8e51 ths
    uint16_t rfd_command = le16_to_cpu(rx.command);
1719 663e8e51 ths
    uint16_t rfd_size = le16_to_cpu(rx.size);
1720 7f1e9d4e Kevin Wolf
1721 7f1e9d4e Kevin Wolf
    if (size > rfd_size) {
1722 7f1e9d4e Kevin Wolf
        logout("Receive buffer (%" PRId16 " bytes) too small for data "
1723 7f1e9d4e Kevin Wolf
            "(%zu bytes); data truncated\n", rfd_size, size);
1724 7f1e9d4e Kevin Wolf
        size = rfd_size;
1725 7f1e9d4e Kevin Wolf
    }
1726 792f1d63 Stefan Weil
#if !defined(CONFIG_PAD_RECEIVED_FRAMES)
1727 663e8e51 ths
    if (size < 64) {
1728 663e8e51 ths
        rfd_status |= 0x0080;
1729 663e8e51 ths
    }
1730 792f1d63 Stefan Weil
#endif
1731 aac443e6 Stefan Weil
    TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n",
1732 aac443e6 Stefan Weil
          rfd_command, rx.link, rx.rx_buf_addr, rfd_size));
1733 16ef60c9 Eduard - Gabriel Munteanu
    stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset +
1734 16ef60c9 Eduard - Gabriel Munteanu
                offsetof(eepro100_rx_t, status), rfd_status);
1735 16ef60c9 Eduard - Gabriel Munteanu
    stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset +
1736 16ef60c9 Eduard - Gabriel Munteanu
                offsetof(eepro100_rx_t, count), size);
1737 663e8e51 ths
    /* Early receive interrupt not supported. */
1738 e7493b25 Stefan Weil
#if 0
1739 e7493b25 Stefan Weil
    eepro100_er_interrupt(s);
1740 e7493b25 Stefan Weil
#endif
1741 663e8e51 ths
    /* Receive CRC Transfer not supported. */
1742 ced5296a Stefan Weil
    if (s->configuration[18] & BIT(2)) {
1743 7f1e9d4e Kevin Wolf
        missing("Receive CRC Transfer");
1744 7f1e9d4e Kevin Wolf
        return -1;
1745 7f1e9d4e Kevin Wolf
    }
1746 663e8e51 ths
    /* TODO: check stripping enable bit. */
1747 e7493b25 Stefan Weil
#if 0
1748 e7493b25 Stefan Weil
    assert(!(s->configuration[17] & BIT(0)));
1749 e7493b25 Stefan Weil
#endif
1750 16ef60c9 Eduard - Gabriel Munteanu
    pci_dma_write(&s->dev, s->ru_base + s->ru_offset +
1751 16ef60c9 Eduard - Gabriel Munteanu
                  sizeof(eepro100_rx_t), buf, size);
1752 663e8e51 ths
    s->statistics.rx_good_frames++;
1753 663e8e51 ths
    eepro100_fr_interrupt(s);
1754 663e8e51 ths
    s->ru_offset = le32_to_cpu(rx.link);
1755 ced5296a Stefan Weil
    if (rfd_command & COMMAND_EL) {
1756 663e8e51 ths
        /* EL bit is set, so this was the last frame. */
1757 7f1e9d4e Kevin Wolf
        logout("receive: Running out of frames\n");
1758 7f1e9d4e Kevin Wolf
        set_ru_state(s, ru_suspended);
1759 663e8e51 ths
    }
1760 ced5296a Stefan Weil
    if (rfd_command & COMMAND_S) {
1761 663e8e51 ths
        /* S bit is set. */
1762 663e8e51 ths
        set_ru_state(s, ru_suspended);
1763 663e8e51 ths
    }
1764 4f1c942b Mark McLoughlin
    return size;
1765 663e8e51 ths
}
1766 663e8e51 ths
1767 151b2986 Juan Quintela
static const VMStateDescription vmstate_eepro100 = {
1768 151b2986 Juan Quintela
    .version_id = 3,
1769 151b2986 Juan Quintela
    .minimum_version_id = 2,
1770 151b2986 Juan Quintela
    .minimum_version_id_old = 2,
1771 151b2986 Juan Quintela
    .fields      = (VMStateField []) {
1772 151b2986 Juan Quintela
        VMSTATE_PCI_DEVICE(dev, EEPRO100State),
1773 151b2986 Juan Quintela
        VMSTATE_UNUSED(32),
1774 151b2986 Juan Quintela
        VMSTATE_BUFFER(mult, EEPRO100State),
1775 151b2986 Juan Quintela
        VMSTATE_BUFFER(mem, EEPRO100State),
1776 151b2986 Juan Quintela
        /* Save all members of struct between scb_stat and mem. */
1777 151b2986 Juan Quintela
        VMSTATE_UINT8(scb_stat, EEPRO100State),
1778 151b2986 Juan Quintela
        VMSTATE_UINT8(int_stat, EEPRO100State),
1779 151b2986 Juan Quintela
        VMSTATE_UNUSED(3*4),
1780 151b2986 Juan Quintela
        VMSTATE_MACADDR(conf.macaddr, EEPRO100State),
1781 151b2986 Juan Quintela
        VMSTATE_UNUSED(19*4),
1782 151b2986 Juan Quintela
        VMSTATE_UINT16_ARRAY(mdimem, EEPRO100State, 32),
1783 151b2986 Juan Quintela
        /* The eeprom should be saved and restored by its own routines. */
1784 151b2986 Juan Quintela
        VMSTATE_UINT32(device, EEPRO100State),
1785 151b2986 Juan Quintela
        /* TODO check device. */
1786 151b2986 Juan Quintela
        VMSTATE_UINT32(cu_base, EEPRO100State),
1787 151b2986 Juan Quintela
        VMSTATE_UINT32(cu_offset, EEPRO100State),
1788 151b2986 Juan Quintela
        VMSTATE_UINT32(ru_base, EEPRO100State),
1789 151b2986 Juan Quintela
        VMSTATE_UINT32(ru_offset, EEPRO100State),
1790 151b2986 Juan Quintela
        VMSTATE_UINT32(statsaddr, EEPRO100State),
1791 ba42b646 Stefan Weil
        /* Save eepro100_stats_t statistics. */
1792 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_good_frames, EEPRO100State),
1793 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_max_collisions, EEPRO100State),
1794 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_late_collisions, EEPRO100State),
1795 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_underruns, EEPRO100State),
1796 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_lost_crs, EEPRO100State),
1797 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_deferred, EEPRO100State),
1798 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_single_collisions, EEPRO100State),
1799 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_multiple_collisions, EEPRO100State),
1800 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_total_collisions, EEPRO100State),
1801 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_good_frames, EEPRO100State),
1802 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_crc_errors, EEPRO100State),
1803 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_alignment_errors, EEPRO100State),
1804 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_resource_errors, EEPRO100State),
1805 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_overrun_errors, EEPRO100State),
1806 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_cdt_errors, EEPRO100State),
1807 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_short_frame_errors, EEPRO100State),
1808 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_xmt_pause, EEPRO100State),
1809 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_rcv_pause, EEPRO100State),
1810 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_rcv_unsupported, EEPRO100State),
1811 151b2986 Juan Quintela
        VMSTATE_UINT16(statistics.xmt_tco_frames, EEPRO100State),
1812 151b2986 Juan Quintela
        VMSTATE_UINT16(statistics.rcv_tco_frames, EEPRO100State),
1813 151b2986 Juan Quintela
        /* Configuration bytes. */
1814 151b2986 Juan Quintela
        VMSTATE_BUFFER(configuration, EEPRO100State),
1815 151b2986 Juan Quintela
        VMSTATE_END_OF_LIST()
1816 aac443e6 Stefan Weil
    }
1817 151b2986 Juan Quintela
};
1818 663e8e51 ths
1819 e00e365e Mark McLoughlin
static void nic_cleanup(VLANClientState *nc)
1820 b946a153 aliguori
{
1821 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1822 b946a153 aliguori
1823 e00e365e Mark McLoughlin
    s->nic = NULL;
1824 b946a153 aliguori
}
1825 b946a153 aliguori
1826 c4c270e2 Stefan Weil
static int pci_nic_uninit(PCIDevice *pci_dev)
1827 b946a153 aliguori
{
1828 c4c270e2 Stefan Weil
    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
1829 b946a153 aliguori
1830 5e6ffdde Avi Kivity
    memory_region_destroy(&s->mmio_bar);
1831 5e6ffdde Avi Kivity
    memory_region_destroy(&s->io_bar);
1832 5e6ffdde Avi Kivity
    memory_region_destroy(&s->flash_bar);
1833 0be71e32 Alex Williamson
    vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
1834 5fce2b3e Alex Williamson
    eeprom93xx_free(&pci_dev->qdev, s->eeprom);
1835 e00e365e Mark McLoughlin
    qemu_del_vlan_client(&s->nic->nc);
1836 b946a153 aliguori
    return 0;
1837 b946a153 aliguori
}
1838 b946a153 aliguori
1839 e00e365e Mark McLoughlin
static NetClientInfo net_eepro100_info = {
1840 e00e365e Mark McLoughlin
    .type = NET_CLIENT_TYPE_NIC,
1841 e00e365e Mark McLoughlin
    .size = sizeof(NICState),
1842 e00e365e Mark McLoughlin
    .can_receive = nic_can_receive,
1843 e00e365e Mark McLoughlin
    .receive = nic_receive,
1844 e00e365e Mark McLoughlin
    .cleanup = nic_cleanup,
1845 e00e365e Mark McLoughlin
};
1846 e00e365e Mark McLoughlin
1847 558c8634 Stefan Weil
static int e100_nic_init(PCIDevice *pci_dev)
1848 663e8e51 ths
{
1849 273a2142 Juan Quintela
    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
1850 558c8634 Stefan Weil
    E100PCIDeviceInfo *e100_device = DO_UPCAST(E100PCIDeviceInfo, pci.qdev,
1851 558c8634 Stefan Weil
                                               pci_dev->qdev.info);
1852 663e8e51 ths
1853 aac443e6 Stefan Weil
    TRACE(OTHER, logout("\n"));
1854 663e8e51 ths
1855 558c8634 Stefan Weil
    s->device = e100_device->device;
1856 663e8e51 ths
1857 558c8634 Stefan Weil
    e100_pci_reset(s, e100_device);
1858 663e8e51 ths
1859 663e8e51 ths
    /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
1860 663e8e51 ths
     * i82559 and later support 64 or 256 word EEPROM. */
1861 5fce2b3e Alex Williamson
    s->eeprom = eeprom93xx_new(&pci_dev->qdev, EEPROM_SIZE);
1862 663e8e51 ths
1863 663e8e51 ths
    /* Handler for memory-mapped I/O */
1864 5e6ffdde Avi Kivity
    memory_region_init_io(&s->mmio_bar, &eepro100_ops, s, "eepro100-mmio",
1865 5e6ffdde Avi Kivity
                          PCI_MEM_SIZE);
1866 e824b2cc Avi Kivity
    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->mmio_bar);
1867 5e6ffdde Avi Kivity
    memory_region_init_io(&s->io_bar, &eepro100_ops, s, "eepro100-io",
1868 5e6ffdde Avi Kivity
                          PCI_IO_SIZE);
1869 e824b2cc Avi Kivity
    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
1870 5e6ffdde Avi Kivity
    /* FIXME: flash aliases to mmio?! */
1871 5e6ffdde Avi Kivity
    memory_region_init_io(&s->flash_bar, &eepro100_ops, s, "eepro100-flash",
1872 5e6ffdde Avi Kivity
                          PCI_FLASH_SIZE);
1873 e824b2cc Avi Kivity
    pci_register_bar(&s->dev, 2, 0, &s->flash_bar);
1874 663e8e51 ths
1875 508ef936 Gerd Hoffmann
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
1876 ce0e58b3 Stefan Weil
    logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6));
1877 663e8e51 ths
1878 663e8e51 ths
    nic_reset(s);
1879 663e8e51 ths
1880 e00e365e Mark McLoughlin
    s->nic = qemu_new_nic(&net_eepro100_info, &s->conf,
1881 e00e365e Mark McLoughlin
                          pci_dev->qdev.info->name, pci_dev->qdev.id, s);
1882 663e8e51 ths
1883 e00e365e Mark McLoughlin
    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
1884 e00e365e Mark McLoughlin
    TRACE(OTHER, logout("%s\n", s->nic->nc.info_str));
1885 663e8e51 ths
1886 a08d4367 Jan Kiszka
    qemu_register_reset(nic_reset, s);
1887 663e8e51 ths
1888 7267c094 Anthony Liguori
    s->vmstate = g_malloc(sizeof(vmstate_eepro100));
1889 151b2986 Juan Quintela
    memcpy(s->vmstate, &vmstate_eepro100, sizeof(vmstate_eepro100));
1890 e00e365e Mark McLoughlin
    s->vmstate->name = s->nic->nc.model;
1891 0be71e32 Alex Williamson
    vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
1892 4e9df06a Stefan Weil
1893 1ca4d09a Gleb Natapov
    add_boot_device_path(s->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
1894 1ca4d09a Gleb Natapov
1895 81a322d4 Gerd Hoffmann
    return 0;
1896 663e8e51 ths
}
1897 663e8e51 ths
1898 558c8634 Stefan Weil
static E100PCIDeviceInfo e100_devices[] = {
1899 0aab0d3a Gerd Hoffmann
    {
1900 558c8634 Stefan Weil
        .pci.qdev.name = "i82550",
1901 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82550 Ethernet",
1902 558c8634 Stefan Weil
        .device = i82550,
1903 558c8634 Stefan Weil
        /* TODO: check device id. */
1904 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
1905 558c8634 Stefan Weil
        /* Revision ID: 0x0c, 0x0d, 0x0e. */
1906 ad03502b Isaku Yamahata
        .pci.revision = 0x0e,
1907 558c8634 Stefan Weil
        /* TODO: check size of statistical counters. */
1908 558c8634 Stefan Weil
        .stats_size = 80,
1909 558c8634 Stefan Weil
        /* TODO: check extended tcb support. */
1910 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1911 558c8634 Stefan Weil
        .power_management = true,
1912 0aab0d3a Gerd Hoffmann
    },{
1913 558c8634 Stefan Weil
        .pci.qdev.name = "i82551",
1914 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82551 Ethernet",
1915 558c8634 Stefan Weil
        .device = i82551,
1916 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
1917 558c8634 Stefan Weil
        /* Revision ID: 0x0f, 0x10. */
1918 ad03502b Isaku Yamahata
        .pci.revision = 0x0f,
1919 558c8634 Stefan Weil
        /* TODO: check size of statistical counters. */
1920 558c8634 Stefan Weil
        .stats_size = 80,
1921 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1922 558c8634 Stefan Weil
        .power_management = true,
1923 c4c270e2 Stefan Weil
    },{
1924 558c8634 Stefan Weil
        .pci.qdev.name = "i82557a",
1925 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82557A Ethernet",
1926 558c8634 Stefan Weil
        .device = i82557A,
1927 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1928 ad03502b Isaku Yamahata
        .pci.revision = 0x01,
1929 558c8634 Stefan Weil
        .power_management = false,
1930 0aab0d3a Gerd Hoffmann
    },{
1931 558c8634 Stefan Weil
        .pci.qdev.name = "i82557b",
1932 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82557B Ethernet",
1933 558c8634 Stefan Weil
        .device = i82557B,
1934 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1935 ad03502b Isaku Yamahata
        .pci.revision = 0x02,
1936 558c8634 Stefan Weil
        .power_management = false,
1937 c4c270e2 Stefan Weil
    },{
1938 558c8634 Stefan Weil
        .pci.qdev.name = "i82557c",
1939 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82557C Ethernet",
1940 558c8634 Stefan Weil
        .device = i82557C,
1941 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1942 ad03502b Isaku Yamahata
        .pci.revision = 0x03,
1943 558c8634 Stefan Weil
        .power_management = false,
1944 c4c270e2 Stefan Weil
    },{
1945 558c8634 Stefan Weil
        .pci.qdev.name = "i82558a",
1946 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82558A Ethernet",
1947 558c8634 Stefan Weil
        .device = i82558A,
1948 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1949 ad03502b Isaku Yamahata
        .pci.revision = 0x04,
1950 558c8634 Stefan Weil
        .stats_size = 76,
1951 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1952 558c8634 Stefan Weil
        .power_management = true,
1953 c4c270e2 Stefan Weil
    },{
1954 558c8634 Stefan Weil
        .pci.qdev.name = "i82558b",
1955 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82558B Ethernet",
1956 558c8634 Stefan Weil
        .device = i82558B,
1957 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1958 ad03502b Isaku Yamahata
        .pci.revision = 0x05,
1959 558c8634 Stefan Weil
        .stats_size = 76,
1960 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1961 558c8634 Stefan Weil
        .power_management = true,
1962 c4c270e2 Stefan Weil
    },{
1963 558c8634 Stefan Weil
        .pci.qdev.name = "i82559a",
1964 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82559A Ethernet",
1965 558c8634 Stefan Weil
        .device = i82559A,
1966 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1967 ad03502b Isaku Yamahata
        .pci.revision = 0x06,
1968 558c8634 Stefan Weil
        .stats_size = 80,
1969 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1970 558c8634 Stefan Weil
        .power_management = true,
1971 c4c270e2 Stefan Weil
    },{
1972 558c8634 Stefan Weil
        .pci.qdev.name = "i82559b",
1973 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82559B Ethernet",
1974 558c8634 Stefan Weil
        .device = i82559B,
1975 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1976 ad03502b Isaku Yamahata
        .pci.revision = 0x07,
1977 558c8634 Stefan Weil
        .stats_size = 80,
1978 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1979 558c8634 Stefan Weil
        .power_management = true,
1980 c4c270e2 Stefan Weil
    },{
1981 558c8634 Stefan Weil
        .pci.qdev.name = "i82559c",
1982 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82559C Ethernet",
1983 558c8634 Stefan Weil
        .device = i82559C,
1984 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82557,
1985 558c8634 Stefan Weil
#if 0
1986 ad03502b Isaku Yamahata
        .pci.revision = 0x08,
1987 558c8634 Stefan Weil
#endif
1988 558c8634 Stefan Weil
        /* TODO: Windows wants revision id 0x0c. */
1989 ad03502b Isaku Yamahata
        .pci.revision = 0x0c,
1990 ad03502b Isaku Yamahata
#if EEPROM_SIZE > 0
1991 ad03502b Isaku Yamahata
        .pci.subsystem_vendor_id = PCI_VENDOR_ID_INTEL,
1992 ad03502b Isaku Yamahata
        .pci.subsystem_id = 0x0040,
1993 ad03502b Isaku Yamahata
#endif
1994 558c8634 Stefan Weil
        .stats_size = 80,
1995 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1996 558c8634 Stefan Weil
        .power_management = true,
1997 0aab0d3a Gerd Hoffmann
    },{
1998 558c8634 Stefan Weil
        .pci.qdev.name = "i82559er",
1999 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82559ER Ethernet",
2000 558c8634 Stefan Weil
        .device = i82559ER,
2001 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
2002 ad03502b Isaku Yamahata
        .pci.revision = 0x09,
2003 558c8634 Stefan Weil
        .stats_size = 80,
2004 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
2005 558c8634 Stefan Weil
        .power_management = true,
2006 c4c270e2 Stefan Weil
    },{
2007 558c8634 Stefan Weil
        .pci.qdev.name = "i82562",
2008 558c8634 Stefan Weil
        .pci.qdev.desc = "Intel i82562 Ethernet",
2009 558c8634 Stefan Weil
        .device = i82562,
2010 558c8634 Stefan Weil
        /* TODO: check device id. */
2011 ad03502b Isaku Yamahata
        .pci.device_id = PCI_DEVICE_ID_INTEL_82551IT,
2012 558c8634 Stefan Weil
        /* TODO: wrong revision id. */
2013 ad03502b Isaku Yamahata
        .pci.revision = 0x0e,
2014 558c8634 Stefan Weil
        .stats_size = 80,
2015 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
2016 558c8634 Stefan Weil
        .power_management = true,
2017 db667a12 Stefan Weil
    },{
2018 db667a12 Stefan Weil
        /* Toshiba Tecra 8200. */
2019 db667a12 Stefan Weil
        .pci.qdev.name = "i82801",
2020 db667a12 Stefan Weil
        .pci.qdev.desc = "Intel i82801 Ethernet",
2021 db667a12 Stefan Weil
        .device = i82801,
2022 ad03502b Isaku Yamahata
        .pci.device_id = 0x2449,
2023 ad03502b Isaku Yamahata
        .pci.revision = 0x03,
2024 db667a12 Stefan Weil
        .stats_size = 80,
2025 db667a12 Stefan Weil
        .has_extended_tcb_support = true,
2026 db667a12 Stefan Weil
        .power_management = true,
2027 0aab0d3a Gerd Hoffmann
    }
2028 0aab0d3a Gerd Hoffmann
};
2029 0aab0d3a Gerd Hoffmann
2030 558c8634 Stefan Weil
static Property e100_properties[] = {
2031 558c8634 Stefan Weil
    DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2032 558c8634 Stefan Weil
    DEFINE_PROP_END_OF_LIST(),
2033 558c8634 Stefan Weil
};
2034 558c8634 Stefan Weil
2035 9d07d757 Paul Brook
static void eepro100_register_devices(void)
2036 663e8e51 ths
{
2037 558c8634 Stefan Weil
    size_t i;
2038 558c8634 Stefan Weil
    for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
2039 558c8634 Stefan Weil
        PCIDeviceInfo *pci_dev = &e100_devices[i].pci;
2040 0389ced4 Stefan Weil
        /* We use the same rom file for all device ids.
2041 0389ced4 Stefan Weil
           QEMU fixes the device id during rom load. */
2042 ad03502b Isaku Yamahata
        pci_dev->vendor_id = PCI_VENDOR_ID_INTEL;
2043 ad03502b Isaku Yamahata
        pci_dev->class_id = PCI_CLASS_NETWORK_ETHERNET;
2044 5ee8ad71 Alex Williamson
        pci_dev->romfile = "pxe-eepro100.rom";
2045 558c8634 Stefan Weil
        pci_dev->init = e100_nic_init;
2046 558c8634 Stefan Weil
        pci_dev->exit = pci_nic_uninit;
2047 558c8634 Stefan Weil
        pci_dev->qdev.props = e100_properties;
2048 558c8634 Stefan Weil
        pci_dev->qdev.size = sizeof(EEPRO100State);
2049 558c8634 Stefan Weil
        pci_qdev_register(pci_dev);
2050 558c8634 Stefan Weil
    }
2051 663e8e51 ths
}
2052 663e8e51 ths
2053 9d07d757 Paul Brook
device_init(eepro100_register_devices)