Statistics
| Branch: | Revision:

root / hw / eepro100.c @ 9a6ee9fd

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