Statistics
| Branch: | Revision:

root / hw / eepro100.c @ ab902981

History | View | Annotate | Download (69 kB)

1 663e8e51 ths
/*
2 663e8e51 ths
 * QEMU i8255x (PRO100) emulation
3 663e8e51 ths
 *
4 1b4f97d6 Stefan Weil
 * Copyright (C) 2006-2011 Stefan Weil
5 663e8e51 ths
 *
6 663e8e51 ths
 * Portions of the code are copies from grub / etherboot eepro100.c
7 663e8e51 ths
 * and linux e100.c.
8 663e8e51 ths
 *
9 230a167c Stefan Weil
 * This program is free software: you can redistribute it and/or modify
10 663e8e51 ths
 * it under the terms of the GNU General Public License as published by
11 230a167c Stefan Weil
 * the Free Software Foundation, either version 2 of the License, or
12 230a167c Stefan Weil
 * (at your option) version 3 or any later version.
13 663e8e51 ths
 *
14 663e8e51 ths
 * This program is distributed in the hope that it will be useful,
15 663e8e51 ths
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 663e8e51 ths
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17 663e8e51 ths
 * GNU General Public License for more details.
18 663e8e51 ths
 *
19 663e8e51 ths
 * You should have received a copy of the GNU General Public License
20 230a167c Stefan Weil
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
21 663e8e51 ths
 *
22 663e8e51 ths
 * Tested features (i82559):
23 e5e23ab8 Stefan Weil
 *      PXE boot (i386 guest, i386 / mips / mipsel / ppc host) ok
24 663e8e51 ths
 *      Linux networking (i386) ok
25 663e8e51 ths
 *
26 663e8e51 ths
 * Untested:
27 663e8e51 ths
 *      Windows networking
28 663e8e51 ths
 *
29 663e8e51 ths
 * References:
30 663e8e51 ths
 *
31 663e8e51 ths
 * Intel 8255x 10/100 Mbps Ethernet Controller Family
32 663e8e51 ths
 * Open Source Software Developer Manual
33 ba19f2de Stefan Weil
 *
34 ba19f2de Stefan Weil
 * TODO:
35 ba19f2de Stefan Weil
 *      * PHY emulation should be separated from nic emulation.
36 ba19f2de Stefan Weil
 *        Most nic emulations could share the same phy code.
37 ba19f2de Stefan Weil
 *      * i82550 is untested. It is programmed like the i82559.
38 ba19f2de Stefan Weil
 *      * i82562 is untested. It is programmed like the i82559.
39 ba19f2de Stefan Weil
 *      * Power management (i82558 and later) is not implemented.
40 ba19f2de Stefan Weil
 *      * Wake-on-LAN is not implemented.
41 663e8e51 ths
 */
42 663e8e51 ths
43 663e8e51 ths
#include <stddef.h>             /* offsetof */
44 87ecb68b pbrook
#include "hw.h"
45 87ecb68b pbrook
#include "pci.h"
46 87ecb68b pbrook
#include "net.h"
47 663e8e51 ths
#include "eeprom93xx.h"
48 1ca4d09a Gleb Natapov
#include "sysemu.h"
49 16ef60c9 Eduard - Gabriel Munteanu
#include "dma.h"
50 663e8e51 ths
51 792f1d63 Stefan Weil
/* QEMU sends frames smaller than 60 bytes to ethernet nics.
52 792f1d63 Stefan Weil
 * Such frames are rejected by real nics and their emulations.
53 792f1d63 Stefan Weil
 * To avoid this behaviour, other nic emulations pad received
54 792f1d63 Stefan Weil
 * frames. The following definition enables this padding for
55 792f1d63 Stefan Weil
 * eepro100, too. We keep the define around in case it might
56 792f1d63 Stefan Weil
 * become useful the future if the core networking is ever
57 792f1d63 Stefan Weil
 * changed to pad short packets itself. */
58 792f1d63 Stefan Weil
#define CONFIG_PAD_RECEIVED_FRAMES
59 792f1d63 Stefan Weil
60 663e8e51 ths
#define KiB 1024
61 663e8e51 ths
62 aac443e6 Stefan Weil
/* Debug EEPRO100 card. */
63 ce0e58b3 Stefan Weil
#if 0
64 ce0e58b3 Stefan Weil
# define DEBUG_EEPRO100
65 ce0e58b3 Stefan Weil
#endif
66 663e8e51 ths
67 663e8e51 ths
#ifdef DEBUG_EEPRO100
68 001faf32 Blue Swirl
#define logout(fmt, ...) fprintf(stderr, "EE100\t%-24s" fmt, __func__, ## __VA_ARGS__)
69 663e8e51 ths
#else
70 001faf32 Blue Swirl
#define logout(fmt, ...) ((void)0)
71 663e8e51 ths
#endif
72 663e8e51 ths
73 663e8e51 ths
/* Set flags to 0 to disable debug output. */
74 aac443e6 Stefan Weil
#define INT     1       /* interrupt related actions */
75 aac443e6 Stefan Weil
#define MDI     1       /* mdi related actions */
76 aac443e6 Stefan Weil
#define OTHER   1
77 aac443e6 Stefan Weil
#define RXTX    1
78 aac443e6 Stefan Weil
#define EEPROM  1       /* eeprom related actions */
79 663e8e51 ths
80 663e8e51 ths
#define TRACE(flag, command) ((flag) ? (command) : (void)0)
81 663e8e51 ths
82 7f1e9d4e Kevin Wolf
#define missing(text) fprintf(stderr, "eepro100: feature is missing in this emulation: " text "\n")
83 663e8e51 ths
84 663e8e51 ths
#define MAX_ETH_FRAME_SIZE 1514
85 663e8e51 ths
86 663e8e51 ths
/* This driver supports several different devices which are declared here. */
87 c4c270e2 Stefan Weil
#define i82550          0x82550
88 663e8e51 ths
#define i82551          0x82551
89 c4c270e2 Stefan Weil
#define i82557A         0x82557a
90 663e8e51 ths
#define i82557B         0x82557b
91 663e8e51 ths
#define i82557C         0x82557c
92 c4c270e2 Stefan Weil
#define i82558A         0x82558a
93 663e8e51 ths
#define i82558B         0x82558b
94 c4c270e2 Stefan Weil
#define i82559A         0x82559a
95 c4c270e2 Stefan Weil
#define i82559B         0x82559b
96 663e8e51 ths
#define i82559C         0x82559c
97 663e8e51 ths
#define i82559ER        0x82559e
98 663e8e51 ths
#define i82562          0x82562
99 db667a12 Stefan Weil
#define i82801          0x82801
100 663e8e51 ths
101 aac443e6 Stefan Weil
/* Use 64 word EEPROM. TODO: could be a runtime option. */
102 663e8e51 ths
#define EEPROM_SIZE     64
103 663e8e51 ths
104 663e8e51 ths
#define PCI_MEM_SIZE            (4 * KiB)
105 663e8e51 ths
#define PCI_IO_SIZE             64
106 663e8e51 ths
#define PCI_FLASH_SIZE          (128 * KiB)
107 663e8e51 ths
108 663e8e51 ths
#define BIT(n) (1 << (n))
109 663e8e51 ths
#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
110 663e8e51 ths
111 663e8e51 ths
/* The SCB accepts the following controls for the Tx and Rx units: */
112 663e8e51 ths
#define  CU_NOP         0x0000  /* No operation. */
113 663e8e51 ths
#define  CU_START       0x0010  /* CU start. */
114 663e8e51 ths
#define  CU_RESUME      0x0020  /* CU resume. */
115 663e8e51 ths
#define  CU_STATSADDR   0x0040  /* Load dump counters address. */
116 663e8e51 ths
#define  CU_SHOWSTATS   0x0050  /* Dump statistical counters. */
117 663e8e51 ths
#define  CU_CMD_BASE    0x0060  /* Load CU base address. */
118 663e8e51 ths
#define  CU_DUMPSTATS   0x0070  /* Dump and reset statistical counters. */
119 663e8e51 ths
#define  CU_SRESUME     0x00a0  /* CU static resume. */
120 663e8e51 ths
121 663e8e51 ths
#define  RU_NOP         0x0000
122 663e8e51 ths
#define  RX_START       0x0001
123 663e8e51 ths
#define  RX_RESUME      0x0002
124 e824012b Stefan Weil
#define  RU_ABORT       0x0004
125 663e8e51 ths
#define  RX_ADDR_LOAD   0x0006
126 663e8e51 ths
#define  RX_RESUMENR    0x0007
127 663e8e51 ths
#define INT_MASK        0x0100
128 663e8e51 ths
#define DRVR_INT        0x0200  /* Driver generated interrupt. */
129 663e8e51 ths
130 558c8634 Stefan Weil
typedef struct {
131 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 f3a52e50 Stefan Weil
    qemu_send_packet(&s->nic->nc, 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 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (rx start)\n", val));
1040 663e8e51 ths
        break;
1041 663e8e51 ths
    case RX_RESUME:
1042 663e8e51 ths
        /* Restart RU. */
1043 663e8e51 ths
        if (get_ru_state(s) != ru_suspended) {
1044 663e8e51 ths
            logout("RU state is %u, should be %u\n", get_ru_state(s),
1045 663e8e51 ths
                   ru_suspended);
1046 e7493b25 Stefan Weil
#if 0
1047 e7493b25 Stefan Weil
            assert(!"wrong RU state");
1048 e7493b25 Stefan Weil
#endif
1049 663e8e51 ths
        }
1050 663e8e51 ths
        set_ru_state(s, ru_ready);
1051 663e8e51 ths
        break;
1052 e824012b Stefan Weil
    case RU_ABORT:
1053 e824012b Stefan Weil
        /* RU abort. */
1054 e824012b Stefan Weil
        if (get_ru_state(s) == ru_ready) {
1055 e824012b Stefan Weil
            eepro100_rnr_interrupt(s);
1056 e824012b Stefan Weil
        }
1057 e824012b Stefan Weil
        set_ru_state(s, ru_idle);
1058 e824012b Stefan Weil
        break;
1059 663e8e51 ths
    case RX_ADDR_LOAD:
1060 663e8e51 ths
        /* Load RU base. */
1061 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (RU base address)\n", val));
1062 27a05006 Stefan Weil
        s->ru_base = e100_read_reg4(s, SCBPointer);
1063 663e8e51 ths
        break;
1064 663e8e51 ths
    default:
1065 663e8e51 ths
        logout("val=0x%02x (undefined RU command)\n", val);
1066 663e8e51 ths
        missing("Undefined SU command");
1067 663e8e51 ths
    }
1068 663e8e51 ths
}
1069 663e8e51 ths
1070 663e8e51 ths
static void eepro100_write_command(EEPRO100State * s, uint8_t val)
1071 663e8e51 ths
{
1072 663e8e51 ths
    eepro100_ru_command(s, val & 0x0f);
1073 663e8e51 ths
    eepro100_cu_command(s, val & 0xf0);
1074 663e8e51 ths
    if ((val) == 0) {
1075 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x\n", val));
1076 663e8e51 ths
    }
1077 663e8e51 ths
    /* Clear command byte after command was accepted. */
1078 663e8e51 ths
    s->mem[SCBCmd] = 0;
1079 663e8e51 ths
}
1080 663e8e51 ths
1081 663e8e51 ths
/*****************************************************************************
1082 663e8e51 ths
 *
1083 663e8e51 ths
 * EEPROM emulation.
1084 663e8e51 ths
 *
1085 663e8e51 ths
 ****************************************************************************/
1086 663e8e51 ths
1087 663e8e51 ths
#define EEPROM_CS       0x02
1088 663e8e51 ths
#define EEPROM_SK       0x01
1089 663e8e51 ths
#define EEPROM_DI       0x04
1090 663e8e51 ths
#define EEPROM_DO       0x08
1091 663e8e51 ths
1092 663e8e51 ths
static uint16_t eepro100_read_eeprom(EEPRO100State * s)
1093 663e8e51 ths
{
1094 e5e23ab8 Stefan Weil
    uint16_t val = e100_read_reg2(s, SCBeeprom);
1095 663e8e51 ths
    if (eeprom93xx_read(s->eeprom)) {
1096 663e8e51 ths
        val |= EEPROM_DO;
1097 663e8e51 ths
    } else {
1098 663e8e51 ths
        val &= ~EEPROM_DO;
1099 663e8e51 ths
    }
1100 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("val=0x%04x\n", val));
1101 663e8e51 ths
    return val;
1102 663e8e51 ths
}
1103 663e8e51 ths
1104 c227f099 Anthony Liguori
static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val)
1105 663e8e51 ths
{
1106 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("val=0x%02x\n", val));
1107 663e8e51 ths
1108 ebabb67a Stefan Weil
    /* mask unwritable bits */
1109 e7493b25 Stefan Weil
#if 0
1110 e7493b25 Stefan Weil
    val = SET_MASKED(val, 0x31, eeprom->value);
1111 e7493b25 Stefan Weil
#endif
1112 663e8e51 ths
1113 663e8e51 ths
    int eecs = ((val & EEPROM_CS) != 0);
1114 663e8e51 ths
    int eesk = ((val & EEPROM_SK) != 0);
1115 663e8e51 ths
    int eedi = ((val & EEPROM_DI) != 0);
1116 663e8e51 ths
    eeprom93xx_write(eeprom, eecs, eesk, eedi);
1117 663e8e51 ths
}
1118 663e8e51 ths
1119 663e8e51 ths
/*****************************************************************************
1120 663e8e51 ths
 *
1121 663e8e51 ths
 * MDI emulation.
1122 663e8e51 ths
 *
1123 663e8e51 ths
 ****************************************************************************/
1124 663e8e51 ths
1125 663e8e51 ths
#if defined(DEBUG_EEPRO100)
1126 6a0b9cc9 Reimar Döffinger
static const char * const mdi_op_name[] = {
1127 663e8e51 ths
    "opcode 0",
1128 663e8e51 ths
    "write",
1129 663e8e51 ths
    "read",
1130 663e8e51 ths
    "opcode 3"
1131 663e8e51 ths
};
1132 663e8e51 ths
1133 6a0b9cc9 Reimar Döffinger
static const char * const mdi_reg_name[] = {
1134 663e8e51 ths
    "Control",
1135 663e8e51 ths
    "Status",
1136 663e8e51 ths
    "PHY Identification (Word 1)",
1137 663e8e51 ths
    "PHY Identification (Word 2)",
1138 663e8e51 ths
    "Auto-Negotiation Advertisement",
1139 663e8e51 ths
    "Auto-Negotiation Link Partner Ability",
1140 663e8e51 ths
    "Auto-Negotiation Expansion"
1141 663e8e51 ths
};
1142 aac443e6 Stefan Weil
1143 aac443e6 Stefan Weil
static const char *reg2name(uint8_t reg)
1144 aac443e6 Stefan Weil
{
1145 aac443e6 Stefan Weil
    static char buffer[10];
1146 aac443e6 Stefan Weil
    const char *p = buffer;
1147 aac443e6 Stefan Weil
    if (reg < ARRAY_SIZE(mdi_reg_name)) {
1148 aac443e6 Stefan Weil
        p = mdi_reg_name[reg];
1149 aac443e6 Stefan Weil
    } else {
1150 aac443e6 Stefan Weil
        snprintf(buffer, sizeof(buffer), "reg=0x%02x", reg);
1151 aac443e6 Stefan Weil
    }
1152 aac443e6 Stefan Weil
    return p;
1153 aac443e6 Stefan Weil
}
1154 663e8e51 ths
#endif                          /* DEBUG_EEPRO100 */
1155 663e8e51 ths
1156 663e8e51 ths
static uint32_t eepro100_read_mdi(EEPRO100State * s)
1157 663e8e51 ths
{
1158 e5e23ab8 Stefan Weil
    uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
1159 663e8e51 ths
1160 663e8e51 ths
#ifdef DEBUG_EEPRO100
1161 663e8e51 ths
    uint8_t raiseint = (val & BIT(29)) >> 29;
1162 663e8e51 ths
    uint8_t opcode = (val & BITS(27, 26)) >> 26;
1163 663e8e51 ths
    uint8_t phy = (val & BITS(25, 21)) >> 21;
1164 663e8e51 ths
    uint8_t reg = (val & BITS(20, 16)) >> 16;
1165 663e8e51 ths
    uint16_t data = (val & BITS(15, 0));
1166 663e8e51 ths
#endif
1167 663e8e51 ths
    /* Emulation takes no time to finish MDI transaction. */
1168 663e8e51 ths
    val |= BIT(28);
1169 663e8e51 ths
    TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1170 663e8e51 ths
                      val, raiseint, mdi_op_name[opcode], phy,
1171 aac443e6 Stefan Weil
                      reg2name(reg), data));
1172 663e8e51 ths
    return val;
1173 663e8e51 ths
}
1174 663e8e51 ths
1175 0113f48d Stefan Weil
static void eepro100_write_mdi(EEPRO100State *s)
1176 663e8e51 ths
{
1177 0113f48d Stefan Weil
    uint32_t val = e100_read_reg4(s, SCBCtrlMDI);
1178 663e8e51 ths
    uint8_t raiseint = (val & BIT(29)) >> 29;
1179 663e8e51 ths
    uint8_t opcode = (val & BITS(27, 26)) >> 26;
1180 663e8e51 ths
    uint8_t phy = (val & BITS(25, 21)) >> 21;
1181 663e8e51 ths
    uint8_t reg = (val & BITS(20, 16)) >> 16;
1182 663e8e51 ths
    uint16_t data = (val & BITS(15, 0));
1183 aac443e6 Stefan Weil
    TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1184 aac443e6 Stefan Weil
          val, raiseint, mdi_op_name[opcode], phy, reg2name(reg), data));
1185 663e8e51 ths
    if (phy != 1) {
1186 663e8e51 ths
        /* Unsupported PHY address. */
1187 e7493b25 Stefan Weil
#if 0
1188 e7493b25 Stefan Weil
        logout("phy must be 1 but is %u\n", phy);
1189 e7493b25 Stefan Weil
#endif
1190 663e8e51 ths
        data = 0;
1191 663e8e51 ths
    } else if (opcode != 1 && opcode != 2) {
1192 663e8e51 ths
        /* Unsupported opcode. */
1193 663e8e51 ths
        logout("opcode must be 1 or 2 but is %u\n", opcode);
1194 663e8e51 ths
        data = 0;
1195 663e8e51 ths
    } else if (reg > 6) {
1196 663e8e51 ths
        /* Unsupported register. */
1197 663e8e51 ths
        logout("register must be 0...6 but is %u\n", reg);
1198 663e8e51 ths
        data = 0;
1199 663e8e51 ths
    } else {
1200 663e8e51 ths
        TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1201 663e8e51 ths
                          val, raiseint, mdi_op_name[opcode], phy,
1202 aac443e6 Stefan Weil
                          reg2name(reg), data));
1203 663e8e51 ths
        if (opcode == 1) {
1204 663e8e51 ths
            /* MDI write */
1205 663e8e51 ths
            switch (reg) {
1206 663e8e51 ths
            case 0:            /* Control Register */
1207 663e8e51 ths
                if (data & 0x8000) {
1208 663e8e51 ths
                    /* Reset status and control registers to default. */
1209 663e8e51 ths
                    s->mdimem[0] = eepro100_mdi_default[0];
1210 663e8e51 ths
                    s->mdimem[1] = eepro100_mdi_default[1];
1211 663e8e51 ths
                    data = s->mdimem[reg];
1212 663e8e51 ths
                } else {
1213 663e8e51 ths
                    /* Restart Auto Configuration = Normal Operation */
1214 663e8e51 ths
                    data &= ~0x0200;
1215 663e8e51 ths
                }
1216 663e8e51 ths
                break;
1217 663e8e51 ths
            case 1:            /* Status Register */
1218 663e8e51 ths
                missing("not writable");
1219 663e8e51 ths
                data = s->mdimem[reg];
1220 663e8e51 ths
                break;
1221 663e8e51 ths
            case 2:            /* PHY Identification Register (Word 1) */
1222 663e8e51 ths
            case 3:            /* PHY Identification Register (Word 2) */
1223 663e8e51 ths
                missing("not implemented");
1224 663e8e51 ths
                break;
1225 663e8e51 ths
            case 4:            /* Auto-Negotiation Advertisement Register */
1226 663e8e51 ths
            case 5:            /* Auto-Negotiation Link Partner Ability Register */
1227 663e8e51 ths
                break;
1228 663e8e51 ths
            case 6:            /* Auto-Negotiation Expansion Register */
1229 663e8e51 ths
            default:
1230 663e8e51 ths
                missing("not implemented");
1231 663e8e51 ths
            }
1232 663e8e51 ths
            s->mdimem[reg] = data;
1233 663e8e51 ths
        } else if (opcode == 2) {
1234 663e8e51 ths
            /* MDI read */
1235 663e8e51 ths
            switch (reg) {
1236 663e8e51 ths
            case 0:            /* Control Register */
1237 663e8e51 ths
                if (data & 0x8000) {
1238 663e8e51 ths
                    /* Reset status and control registers to default. */
1239 663e8e51 ths
                    s->mdimem[0] = eepro100_mdi_default[0];
1240 663e8e51 ths
                    s->mdimem[1] = eepro100_mdi_default[1];
1241 663e8e51 ths
                }
1242 663e8e51 ths
                break;
1243 663e8e51 ths
            case 1:            /* Status Register */
1244 663e8e51 ths
                s->mdimem[reg] |= 0x0020;
1245 663e8e51 ths
                break;
1246 663e8e51 ths
            case 2:            /* PHY Identification Register (Word 1) */
1247 663e8e51 ths
            case 3:            /* PHY Identification Register (Word 2) */
1248 663e8e51 ths
            case 4:            /* Auto-Negotiation Advertisement Register */
1249 663e8e51 ths
                break;
1250 663e8e51 ths
            case 5:            /* Auto-Negotiation Link Partner Ability Register */
1251 663e8e51 ths
                s->mdimem[reg] = 0x41fe;
1252 663e8e51 ths
                break;
1253 663e8e51 ths
            case 6:            /* Auto-Negotiation Expansion Register */
1254 663e8e51 ths
                s->mdimem[reg] = 0x0001;
1255 663e8e51 ths
                break;
1256 663e8e51 ths
            }
1257 663e8e51 ths
            data = s->mdimem[reg];
1258 663e8e51 ths
        }
1259 663e8e51 ths
        /* Emulation takes no time to finish MDI transaction.
1260 663e8e51 ths
         * Set MDI bit in SCB status register. */
1261 663e8e51 ths
        s->mem[SCBAck] |= 0x08;
1262 663e8e51 ths
        val |= BIT(28);
1263 663e8e51 ths
        if (raiseint) {
1264 663e8e51 ths
            eepro100_mdi_interrupt(s);
1265 663e8e51 ths
        }
1266 663e8e51 ths
    }
1267 663e8e51 ths
    val = (val & 0xffff0000) + data;
1268 e5e23ab8 Stefan Weil
    e100_write_reg4(s, SCBCtrlMDI, val);
1269 663e8e51 ths
}
1270 663e8e51 ths
1271 663e8e51 ths
/*****************************************************************************
1272 663e8e51 ths
 *
1273 663e8e51 ths
 * Port emulation.
1274 663e8e51 ths
 *
1275 663e8e51 ths
 ****************************************************************************/
1276 663e8e51 ths
1277 663e8e51 ths
#define PORT_SOFTWARE_RESET     0
1278 663e8e51 ths
#define PORT_SELFTEST           1
1279 663e8e51 ths
#define PORT_SELECTIVE_RESET    2
1280 663e8e51 ths
#define PORT_DUMP               3
1281 663e8e51 ths
#define PORT_SELECTION_MASK     3
1282 663e8e51 ths
1283 663e8e51 ths
typedef struct {
1284 663e8e51 ths
    uint32_t st_sign;           /* Self Test Signature */
1285 663e8e51 ths
    uint32_t st_result;         /* Self Test Results */
1286 c227f099 Anthony Liguori
} eepro100_selftest_t;
1287 663e8e51 ths
1288 663e8e51 ths
static uint32_t eepro100_read_port(EEPRO100State * s)
1289 663e8e51 ths
{
1290 663e8e51 ths
    return 0;
1291 663e8e51 ths
}
1292 663e8e51 ths
1293 3fd3d0b4 Stefan Weil
static void eepro100_write_port(EEPRO100State *s)
1294 663e8e51 ths
{
1295 3fd3d0b4 Stefan Weil
    uint32_t val = e100_read_reg4(s, SCBPort);
1296 663e8e51 ths
    uint32_t address = (val & ~PORT_SELECTION_MASK);
1297 663e8e51 ths
    uint8_t selection = (val & PORT_SELECTION_MASK);
1298 663e8e51 ths
    switch (selection) {
1299 663e8e51 ths
    case PORT_SOFTWARE_RESET:
1300 663e8e51 ths
        nic_reset(s);
1301 663e8e51 ths
        break;
1302 663e8e51 ths
    case PORT_SELFTEST:
1303 aac443e6 Stefan Weil
        TRACE(OTHER, logout("selftest address=0x%08x\n", address));
1304 c227f099 Anthony Liguori
        eepro100_selftest_t data;
1305 16ef60c9 Eduard - Gabriel Munteanu
        pci_dma_read(&s->dev, address, (uint8_t *) &data, sizeof(data));
1306 663e8e51 ths
        data.st_sign = 0xffffffff;
1307 663e8e51 ths
        data.st_result = 0;
1308 16ef60c9 Eduard - Gabriel Munteanu
        pci_dma_write(&s->dev, address, (uint8_t *) &data, sizeof(data));
1309 663e8e51 ths
        break;
1310 663e8e51 ths
    case PORT_SELECTIVE_RESET:
1311 aac443e6 Stefan Weil
        TRACE(OTHER, logout("selective reset, selftest address=0x%08x\n", address));
1312 663e8e51 ths
        nic_selective_reset(s);
1313 663e8e51 ths
        break;
1314 663e8e51 ths
    default:
1315 663e8e51 ths
        logout("val=0x%08x\n", val);
1316 663e8e51 ths
        missing("unknown port selection");
1317 663e8e51 ths
    }
1318 663e8e51 ths
}
1319 663e8e51 ths
1320 663e8e51 ths
/*****************************************************************************
1321 663e8e51 ths
 *
1322 663e8e51 ths
 * General hardware emulation.
1323 663e8e51 ths
 *
1324 663e8e51 ths
 ****************************************************************************/
1325 663e8e51 ths
1326 663e8e51 ths
static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
1327 663e8e51 ths
{
1328 ef476062 Blue Swirl
    uint8_t val = 0;
1329 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1330 e5e23ab8 Stefan Weil
        val = s->mem[addr];
1331 663e8e51 ths
    }
1332 663e8e51 ths
1333 663e8e51 ths
    switch (addr) {
1334 663e8e51 ths
    case SCBStatus:
1335 663e8e51 ths
    case SCBAck:
1336 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1337 663e8e51 ths
        break;
1338 663e8e51 ths
    case SCBCmd:
1339 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1340 e7493b25 Stefan Weil
#if 0
1341 e7493b25 Stefan Weil
        val = eepro100_read_command(s);
1342 e7493b25 Stefan Weil
#endif
1343 663e8e51 ths
        break;
1344 663e8e51 ths
    case SCBIntmask:
1345 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1346 663e8e51 ths
        break;
1347 663e8e51 ths
    case SCBPort + 3:
1348 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1349 663e8e51 ths
        break;
1350 663e8e51 ths
    case SCBeeprom:
1351 663e8e51 ths
        val = eepro100_read_eeprom(s);
1352 663e8e51 ths
        break;
1353 0113f48d Stefan Weil
    case SCBCtrlMDI:
1354 0113f48d Stefan Weil
    case SCBCtrlMDI + 1:
1355 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1356 0113f48d Stefan Weil
    case SCBCtrlMDI + 3:
1357 0113f48d Stefan Weil
        val = (uint8_t)(eepro100_read_mdi(s) >> (8 * (addr & 3)));
1358 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1359 0113f48d Stefan Weil
        break;
1360 0908bba1 Stefan Weil
    case SCBpmdr:       /* Power Management Driver Register */
1361 663e8e51 ths
        val = 0;
1362 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1363 663e8e51 ths
        break;
1364 a39bd017 Stefan Weil
    case SCBgctrl:      /* General Control Register */
1365 a39bd017 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1366 a39bd017 Stefan Weil
        break;
1367 0908bba1 Stefan Weil
    case SCBgstat:      /* General Status Register */
1368 663e8e51 ths
        /* 100 Mbps full duplex, valid link */
1369 663e8e51 ths
        val = 0x07;
1370 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=General Status val=%02x\n", val));
1371 663e8e51 ths
        break;
1372 663e8e51 ths
    default:
1373 663e8e51 ths
        logout("addr=%s val=0x%02x\n", regname(addr), val);
1374 663e8e51 ths
        missing("unknown byte read");
1375 663e8e51 ths
    }
1376 663e8e51 ths
    return val;
1377 663e8e51 ths
}
1378 663e8e51 ths
1379 663e8e51 ths
static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr)
1380 663e8e51 ths
{
1381 ef476062 Blue Swirl
    uint16_t val = 0;
1382 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1383 e5e23ab8 Stefan Weil
        val = e100_read_reg2(s, addr);
1384 663e8e51 ths
    }
1385 663e8e51 ths
1386 663e8e51 ths
    switch (addr) {
1387 663e8e51 ths
    case SCBStatus:
1388 dbbaaff6 =?UTF-8?q?Reimar=20D=C3=B6ffinger?=
    case SCBCmd:
1389 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1390 663e8e51 ths
        break;
1391 663e8e51 ths
    case SCBeeprom:
1392 663e8e51 ths
        val = eepro100_read_eeprom(s);
1393 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1394 663e8e51 ths
        break;
1395 0113f48d Stefan Weil
    case SCBCtrlMDI:
1396 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1397 0113f48d Stefan Weil
        val = (uint16_t)(eepro100_read_mdi(s) >> (8 * (addr & 3)));
1398 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1399 0113f48d Stefan Weil
        break;
1400 663e8e51 ths
    default:
1401 663e8e51 ths
        logout("addr=%s val=0x%04x\n", regname(addr), val);
1402 663e8e51 ths
        missing("unknown word read");
1403 663e8e51 ths
    }
1404 663e8e51 ths
    return val;
1405 663e8e51 ths
}
1406 663e8e51 ths
1407 663e8e51 ths
static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
1408 663e8e51 ths
{
1409 ef476062 Blue Swirl
    uint32_t val = 0;
1410 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1411 e5e23ab8 Stefan Weil
        val = e100_read_reg4(s, addr);
1412 663e8e51 ths
    }
1413 663e8e51 ths
1414 663e8e51 ths
    switch (addr) {
1415 663e8e51 ths
    case SCBStatus:
1416 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1417 663e8e51 ths
        break;
1418 663e8e51 ths
    case SCBPointer:
1419 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1420 663e8e51 ths
        break;
1421 663e8e51 ths
    case SCBPort:
1422 663e8e51 ths
        val = eepro100_read_port(s);
1423 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1424 663e8e51 ths
        break;
1425 072476ea Stefan Weil
    case SCBflash:
1426 072476ea Stefan Weil
        val = eepro100_read_eeprom(s);
1427 072476ea Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1428 072476ea Stefan Weil
        break;
1429 663e8e51 ths
    case SCBCtrlMDI:
1430 663e8e51 ths
        val = eepro100_read_mdi(s);
1431 663e8e51 ths
        break;
1432 663e8e51 ths
    default:
1433 663e8e51 ths
        logout("addr=%s val=0x%08x\n", regname(addr), val);
1434 663e8e51 ths
        missing("unknown longword read");
1435 663e8e51 ths
    }
1436 663e8e51 ths
    return val;
1437 663e8e51 ths
}
1438 663e8e51 ths
1439 663e8e51 ths
static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
1440 663e8e51 ths
{
1441 e74818f3 Stefan Weil
    /* SCBStatus is readonly. */
1442 e74818f3 Stefan Weil
    if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
1443 e5e23ab8 Stefan Weil
        s->mem[addr] = val;
1444 663e8e51 ths
    }
1445 663e8e51 ths
1446 663e8e51 ths
    switch (addr) {
1447 663e8e51 ths
    case SCBStatus:
1448 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1449 663e8e51 ths
        break;
1450 663e8e51 ths
    case SCBAck:
1451 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1452 663e8e51 ths
        eepro100_acknowledge(s);
1453 663e8e51 ths
        break;
1454 663e8e51 ths
    case SCBCmd:
1455 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1456 663e8e51 ths
        eepro100_write_command(s, val);
1457 663e8e51 ths
        break;
1458 663e8e51 ths
    case SCBIntmask:
1459 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1460 663e8e51 ths
        if (val & BIT(1)) {
1461 663e8e51 ths
            eepro100_swi_interrupt(s);
1462 663e8e51 ths
        }
1463 663e8e51 ths
        eepro100_interrupt(s, 0);
1464 663e8e51 ths
        break;
1465 27a05006 Stefan Weil
    case SCBPointer:
1466 27a05006 Stefan Weil
    case SCBPointer + 1:
1467 27a05006 Stefan Weil
    case SCBPointer + 2:
1468 27a05006 Stefan Weil
    case SCBPointer + 3:
1469 27a05006 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1470 27a05006 Stefan Weil
        break;
1471 3fd3d0b4 Stefan Weil
    case SCBPort:
1472 3fd3d0b4 Stefan Weil
    case SCBPort + 1:
1473 3fd3d0b4 Stefan Weil
    case SCBPort + 2:
1474 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1475 3fd3d0b4 Stefan Weil
        break;
1476 663e8e51 ths
    case SCBPort + 3:
1477 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1478 3fd3d0b4 Stefan Weil
        eepro100_write_port(s);
1479 3fd3d0b4 Stefan Weil
        break;
1480 aac443e6 Stefan Weil
    case SCBFlow:       /* does not exist on 82557 */
1481 3257d2b6 ths
    case SCBFlow + 1:
1482 3257d2b6 ths
    case SCBFlow + 2:
1483 0908bba1 Stefan Weil
    case SCBpmdr:       /* does not exist on 82557 */
1484 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1485 663e8e51 ths
        break;
1486 663e8e51 ths
    case SCBeeprom:
1487 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1488 663e8e51 ths
        eepro100_write_eeprom(s->eeprom, val);
1489 663e8e51 ths
        break;
1490 0113f48d Stefan Weil
    case SCBCtrlMDI:
1491 0113f48d Stefan Weil
    case SCBCtrlMDI + 1:
1492 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1493 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1494 0113f48d Stefan Weil
        break;
1495 0113f48d Stefan Weil
    case SCBCtrlMDI + 3:
1496 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1497 0113f48d Stefan Weil
        eepro100_write_mdi(s);
1498 0113f48d Stefan Weil
        break;
1499 663e8e51 ths
    default:
1500 663e8e51 ths
        logout("addr=%s val=0x%02x\n", regname(addr), val);
1501 663e8e51 ths
        missing("unknown byte write");
1502 663e8e51 ths
    }
1503 663e8e51 ths
}
1504 663e8e51 ths
1505 663e8e51 ths
static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
1506 663e8e51 ths
{
1507 e74818f3 Stefan Weil
    /* SCBStatus is readonly. */
1508 e74818f3 Stefan Weil
    if (addr > SCBStatus && addr <= sizeof(s->mem) - sizeof(val)) {
1509 e5e23ab8 Stefan Weil
        e100_write_reg2(s, addr, val);
1510 663e8e51 ths
    }
1511 663e8e51 ths
1512 663e8e51 ths
    switch (addr) {
1513 663e8e51 ths
    case SCBStatus:
1514 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1515 e74818f3 Stefan Weil
        s->mem[SCBAck] = (val >> 8);
1516 663e8e51 ths
        eepro100_acknowledge(s);
1517 663e8e51 ths
        break;
1518 663e8e51 ths
    case SCBCmd:
1519 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1520 663e8e51 ths
        eepro100_write_command(s, val);
1521 663e8e51 ths
        eepro100_write1(s, SCBIntmask, val >> 8);
1522 663e8e51 ths
        break;
1523 27a05006 Stefan Weil
    case SCBPointer:
1524 27a05006 Stefan Weil
    case SCBPointer + 2:
1525 27a05006 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1526 27a05006 Stefan Weil
        break;
1527 3fd3d0b4 Stefan Weil
    case SCBPort:
1528 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1529 3fd3d0b4 Stefan Weil
        break;
1530 3fd3d0b4 Stefan Weil
    case SCBPort + 2:
1531 3fd3d0b4 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1532 3fd3d0b4 Stefan Weil
        eepro100_write_port(s);
1533 3fd3d0b4 Stefan Weil
        break;
1534 663e8e51 ths
    case SCBeeprom:
1535 1b4f97d6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1536 663e8e51 ths
        eepro100_write_eeprom(s->eeprom, val);
1537 663e8e51 ths
        break;
1538 0113f48d Stefan Weil
    case SCBCtrlMDI:
1539 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1540 0113f48d Stefan Weil
        break;
1541 0113f48d Stefan Weil
    case SCBCtrlMDI + 2:
1542 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1543 0113f48d Stefan Weil
        eepro100_write_mdi(s);
1544 0113f48d Stefan Weil
        break;
1545 663e8e51 ths
    default:
1546 663e8e51 ths
        logout("addr=%s val=0x%04x\n", regname(addr), val);
1547 663e8e51 ths
        missing("unknown word write");
1548 663e8e51 ths
    }
1549 663e8e51 ths
}
1550 663e8e51 ths
1551 663e8e51 ths
static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
1552 663e8e51 ths
{
1553 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1554 e5e23ab8 Stefan Weil
        e100_write_reg4(s, addr, val);
1555 663e8e51 ths
    }
1556 663e8e51 ths
1557 663e8e51 ths
    switch (addr) {
1558 663e8e51 ths
    case SCBPointer:
1559 27a05006 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1560 663e8e51 ths
        break;
1561 663e8e51 ths
    case SCBPort:
1562 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1563 3fd3d0b4 Stefan Weil
        eepro100_write_port(s);
1564 663e8e51 ths
        break;
1565 072476ea Stefan Weil
    case SCBflash:
1566 072476ea Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1567 072476ea Stefan Weil
        val = val >> 16;
1568 072476ea Stefan Weil
        eepro100_write_eeprom(s->eeprom, val);
1569 072476ea Stefan Weil
        break;
1570 663e8e51 ths
    case SCBCtrlMDI:
1571 0113f48d Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1572 0113f48d Stefan Weil
        eepro100_write_mdi(s);
1573 663e8e51 ths
        break;
1574 663e8e51 ths
    default:
1575 663e8e51 ths
        logout("addr=%s val=0x%08x\n", regname(addr), val);
1576 663e8e51 ths
        missing("unknown longword write");
1577 663e8e51 ths
    }
1578 663e8e51 ths
}
1579 663e8e51 ths
1580 5e6ffdde Avi Kivity
static uint64_t eepro100_read(void *opaque, target_phys_addr_t addr,
1581 5e6ffdde Avi Kivity
                              unsigned size)
1582 663e8e51 ths
{
1583 663e8e51 ths
    EEPRO100State *s = opaque;
1584 663e8e51 ths
1585 5e6ffdde Avi Kivity
    switch (size) {
1586 5e6ffdde Avi Kivity
    case 1: return eepro100_read1(s, addr);
1587 5e6ffdde Avi Kivity
    case 2: return eepro100_read2(s, addr);
1588 5e6ffdde Avi Kivity
    case 4: return eepro100_read4(s, addr);
1589 5e6ffdde Avi Kivity
    default: abort();
1590 5e6ffdde Avi Kivity
    }
1591 663e8e51 ths
}
1592 663e8e51 ths
1593 5e6ffdde Avi Kivity
static void eepro100_write(void *opaque, target_phys_addr_t addr,
1594 5e6ffdde Avi Kivity
                           uint64_t data, unsigned size)
1595 663e8e51 ths
{
1596 663e8e51 ths
    EEPRO100State *s = opaque;
1597 663e8e51 ths
1598 5e6ffdde Avi Kivity
    switch (size) {
1599 0ed8b6f6 Blue Swirl
    case 1:
1600 0ed8b6f6 Blue Swirl
        eepro100_write1(s, addr, data);
1601 0ed8b6f6 Blue Swirl
        break;
1602 0ed8b6f6 Blue Swirl
    case 2:
1603 0ed8b6f6 Blue Swirl
        eepro100_write2(s, addr, data);
1604 0ed8b6f6 Blue Swirl
        break;
1605 0ed8b6f6 Blue Swirl
    case 4:
1606 0ed8b6f6 Blue Swirl
        eepro100_write4(s, addr, data);
1607 0ed8b6f6 Blue Swirl
        break;
1608 0ed8b6f6 Blue Swirl
    default:
1609 0ed8b6f6 Blue Swirl
        abort();
1610 5e6ffdde Avi Kivity
    }
1611 663e8e51 ths
}
1612 663e8e51 ths
1613 5e6ffdde Avi Kivity
static const MemoryRegionOps eepro100_ops = {
1614 5e6ffdde Avi Kivity
    .read = eepro100_read,
1615 5e6ffdde Avi Kivity
    .write = eepro100_write,
1616 5e6ffdde Avi Kivity
    .endianness = DEVICE_LITTLE_ENDIAN,
1617 663e8e51 ths
};
1618 663e8e51 ths
1619 4e68f7a0 Stefan Hajnoczi
static int nic_can_receive(NetClientState *nc)
1620 663e8e51 ths
{
1621 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1622 aac443e6 Stefan Weil
    TRACE(RXTX, logout("%p\n", s));
1623 663e8e51 ths
    return get_ru_state(s) == ru_ready;
1624 e7493b25 Stefan Weil
#if 0
1625 e7493b25 Stefan Weil
    return !eepro100_buffer_full(s);
1626 e7493b25 Stefan Weil
#endif
1627 663e8e51 ths
}
1628 663e8e51 ths
1629 4e68f7a0 Stefan Hajnoczi
static ssize_t nic_receive(NetClientState *nc, const uint8_t * buf, size_t size)
1630 663e8e51 ths
{
1631 663e8e51 ths
    /* TODO:
1632 663e8e51 ths
     * - Magic packets should set bit 30 in power management driver register.
1633 663e8e51 ths
     * - Interesting packets should set bit 29 in power management driver register.
1634 663e8e51 ths
     */
1635 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1636 663e8e51 ths
    uint16_t rfd_status = 0xa000;
1637 792f1d63 Stefan Weil
#if defined(CONFIG_PAD_RECEIVED_FRAMES)
1638 792f1d63 Stefan Weil
    uint8_t min_buf[60];
1639 792f1d63 Stefan Weil
#endif
1640 663e8e51 ths
    static const uint8_t broadcast_macaddr[6] =
1641 663e8e51 ths
        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1642 663e8e51 ths
1643 792f1d63 Stefan Weil
#if defined(CONFIG_PAD_RECEIVED_FRAMES)
1644 792f1d63 Stefan Weil
    /* Pad to minimum Ethernet frame length */
1645 792f1d63 Stefan Weil
    if (size < sizeof(min_buf)) {
1646 792f1d63 Stefan Weil
        memcpy(min_buf, buf, size);
1647 792f1d63 Stefan Weil
        memset(&min_buf[size], 0, sizeof(min_buf) - size);
1648 792f1d63 Stefan Weil
        buf = min_buf;
1649 792f1d63 Stefan Weil
        size = sizeof(min_buf);
1650 792f1d63 Stefan Weil
    }
1651 792f1d63 Stefan Weil
#endif
1652 792f1d63 Stefan Weil
1653 663e8e51 ths
    if (s->configuration[8] & 0x80) {
1654 663e8e51 ths
        /* CSMA is disabled. */
1655 663e8e51 ths
        logout("%p received while CSMA is disabled\n", s);
1656 4f1c942b Mark McLoughlin
        return -1;
1657 792f1d63 Stefan Weil
#if !defined(CONFIG_PAD_RECEIVED_FRAMES)
1658 ced5296a Stefan Weil
    } else if (size < 64 && (s->configuration[7] & BIT(0))) {
1659 663e8e51 ths
        /* Short frame and configuration byte 7/0 (discard short receive) set:
1660 663e8e51 ths
         * Short frame is discarded */
1661 067d01de Stefan Weil
        logout("%p received short frame (%zu byte)\n", s, size);
1662 663e8e51 ths
        s->statistics.rx_short_frame_errors++;
1663 e7493b25 Stefan Weil
        return -1;
1664 e7493b25 Stefan Weil
#endif
1665 ced5296a Stefan Weil
    } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & BIT(3))) {
1666 663e8e51 ths
        /* Long frame and configuration byte 18/3 (long receive ok) not set:
1667 663e8e51 ths
         * Long frames are discarded. */
1668 067d01de Stefan Weil
        logout("%p received long frame (%zu byte), ignored\n", s, size);
1669 4f1c942b Mark McLoughlin
        return -1;
1670 e7493b25 Stefan Weil
    } else if (memcmp(buf, s->conf.macaddr.a, 6) == 0) {       /* !!! */
1671 663e8e51 ths
        /* Frame matches individual address. */
1672 663e8e51 ths
        /* TODO: check configuration byte 15/4 (ignore U/L). */
1673 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame for me, len=%zu\n", s, size));
1674 663e8e51 ths
    } else if (memcmp(buf, broadcast_macaddr, 6) == 0) {
1675 663e8e51 ths
        /* Broadcast frame. */
1676 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received broadcast, len=%zu\n", s, size));
1677 663e8e51 ths
        rfd_status |= 0x0002;
1678 7b8737de Stefan Weil
    } else if (buf[0] & 0x01) {
1679 663e8e51 ths
        /* Multicast frame. */
1680 7b8737de Stefan Weil
        TRACE(RXTX, logout("%p received multicast, len=%zu,%s\n", s, size, nic_dump(buf, size)));
1681 7f1e9d4e Kevin Wolf
        if (s->configuration[21] & BIT(3)) {
1682 7b8737de Stefan Weil
          /* Multicast all bit is set, receive all multicast frames. */
1683 7b8737de Stefan Weil
        } else {
1684 69f3ce78 Stefan Weil
          unsigned mcast_idx = e100_compute_mcast_idx(buf);
1685 7b8737de Stefan Weil
          assert(mcast_idx < 64);
1686 7b8737de Stefan Weil
          if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
1687 7b8737de Stefan Weil
            /* Multicast frame is allowed in hash table. */
1688 ced5296a Stefan Weil
          } else if (s->configuration[15] & BIT(0)) {
1689 7b8737de Stefan Weil
              /* Promiscuous: receive all. */
1690 7b8737de Stefan Weil
              rfd_status |= 0x0004;
1691 7b8737de Stefan Weil
          } else {
1692 7b8737de Stefan Weil
              TRACE(RXTX, logout("%p multicast ignored\n", s));
1693 7b8737de Stefan Weil
              return -1;
1694 7b8737de Stefan Weil
          }
1695 663e8e51 ths
        }
1696 7b8737de Stefan Weil
        /* TODO: Next not for promiscuous mode? */
1697 663e8e51 ths
        rfd_status |= 0x0002;
1698 ced5296a Stefan Weil
    } else if (s->configuration[15] & BIT(0)) {
1699 663e8e51 ths
        /* Promiscuous: receive all. */
1700 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame in promiscuous mode, len=%zu\n", s, size));
1701 663e8e51 ths
        rfd_status |= 0x0004;
1702 010ec629 Stefan Weil
    } else if (s->configuration[20] & BIT(6)) {
1703 010ec629 Stefan Weil
        /* Multiple IA bit set. */
1704 010ec629 Stefan Weil
        unsigned mcast_idx = compute_mcast_idx(buf);
1705 010ec629 Stefan Weil
        assert(mcast_idx < 64);
1706 010ec629 Stefan Weil
        if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
1707 010ec629 Stefan Weil
            TRACE(RXTX, logout("%p accepted, multiple IA bit set\n", s));
1708 010ec629 Stefan Weil
        } else {
1709 010ec629 Stefan Weil
            TRACE(RXTX, logout("%p frame ignored, multiple IA bit set\n", s));
1710 010ec629 Stefan Weil
            return -1;
1711 010ec629 Stefan Weil
        }
1712 663e8e51 ths
    } else {
1713 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame, ignored, len=%zu,%s\n", s, size,
1714 aac443e6 Stefan Weil
              nic_dump(buf, size)));
1715 4f1c942b Mark McLoughlin
        return size;
1716 663e8e51 ths
    }
1717 663e8e51 ths
1718 663e8e51 ths
    if (get_ru_state(s) != ru_ready) {
1719 aac443e6 Stefan Weil
        /* No resources available. */
1720 aac443e6 Stefan Weil
        logout("no resources, state=%u\n", get_ru_state(s));
1721 e824012b Stefan Weil
        /* TODO: RNR interrupt only at first failed frame? */
1722 e824012b Stefan Weil
        eepro100_rnr_interrupt(s);
1723 663e8e51 ths
        s->statistics.rx_resource_errors++;
1724 e7493b25 Stefan Weil
#if 0
1725 e7493b25 Stefan Weil
        assert(!"no resources");
1726 e7493b25 Stefan Weil
#endif
1727 4f1c942b Mark McLoughlin
        return -1;
1728 663e8e51 ths
    }
1729 e7493b25 Stefan Weil
    /* !!! */
1730 c227f099 Anthony Liguori
    eepro100_rx_t rx;
1731 16ef60c9 Eduard - Gabriel Munteanu
    pci_dma_read(&s->dev, s->ru_base + s->ru_offset,
1732 e965d4bc David Gibson
                 &rx, sizeof(eepro100_rx_t));
1733 663e8e51 ths
    uint16_t rfd_command = le16_to_cpu(rx.command);
1734 663e8e51 ths
    uint16_t rfd_size = le16_to_cpu(rx.size);
1735 7f1e9d4e Kevin Wolf
1736 7f1e9d4e Kevin Wolf
    if (size > rfd_size) {
1737 7f1e9d4e Kevin Wolf
        logout("Receive buffer (%" PRId16 " bytes) too small for data "
1738 7f1e9d4e Kevin Wolf
            "(%zu bytes); data truncated\n", rfd_size, size);
1739 7f1e9d4e Kevin Wolf
        size = rfd_size;
1740 7f1e9d4e Kevin Wolf
    }
1741 792f1d63 Stefan Weil
#if !defined(CONFIG_PAD_RECEIVED_FRAMES)
1742 663e8e51 ths
    if (size < 64) {
1743 663e8e51 ths
        rfd_status |= 0x0080;
1744 663e8e51 ths
    }
1745 792f1d63 Stefan Weil
#endif
1746 aac443e6 Stefan Weil
    TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n",
1747 aac443e6 Stefan Weil
          rfd_command, rx.link, rx.rx_buf_addr, rfd_size));
1748 16ef60c9 Eduard - Gabriel Munteanu
    stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset +
1749 16ef60c9 Eduard - Gabriel Munteanu
                offsetof(eepro100_rx_t, status), rfd_status);
1750 16ef60c9 Eduard - Gabriel Munteanu
    stw_le_pci_dma(&s->dev, s->ru_base + s->ru_offset +
1751 16ef60c9 Eduard - Gabriel Munteanu
                offsetof(eepro100_rx_t, count), size);
1752 663e8e51 ths
    /* Early receive interrupt not supported. */
1753 e7493b25 Stefan Weil
#if 0
1754 e7493b25 Stefan Weil
    eepro100_er_interrupt(s);
1755 e7493b25 Stefan Weil
#endif
1756 663e8e51 ths
    /* Receive CRC Transfer not supported. */
1757 ced5296a Stefan Weil
    if (s->configuration[18] & BIT(2)) {
1758 7f1e9d4e Kevin Wolf
        missing("Receive CRC Transfer");
1759 7f1e9d4e Kevin Wolf
        return -1;
1760 7f1e9d4e Kevin Wolf
    }
1761 663e8e51 ths
    /* TODO: check stripping enable bit. */
1762 e7493b25 Stefan Weil
#if 0
1763 e7493b25 Stefan Weil
    assert(!(s->configuration[17] & BIT(0)));
1764 e7493b25 Stefan Weil
#endif
1765 16ef60c9 Eduard - Gabriel Munteanu
    pci_dma_write(&s->dev, s->ru_base + s->ru_offset +
1766 16ef60c9 Eduard - Gabriel Munteanu
                  sizeof(eepro100_rx_t), buf, size);
1767 663e8e51 ths
    s->statistics.rx_good_frames++;
1768 663e8e51 ths
    eepro100_fr_interrupt(s);
1769 663e8e51 ths
    s->ru_offset = le32_to_cpu(rx.link);
1770 ced5296a Stefan Weil
    if (rfd_command & COMMAND_EL) {
1771 663e8e51 ths
        /* EL bit is set, so this was the last frame. */
1772 7f1e9d4e Kevin Wolf
        logout("receive: Running out of frames\n");
1773 7f1e9d4e Kevin Wolf
        set_ru_state(s, ru_suspended);
1774 663e8e51 ths
    }
1775 ced5296a Stefan Weil
    if (rfd_command & COMMAND_S) {
1776 663e8e51 ths
        /* S bit is set. */
1777 663e8e51 ths
        set_ru_state(s, ru_suspended);
1778 663e8e51 ths
    }
1779 4f1c942b Mark McLoughlin
    return size;
1780 663e8e51 ths
}
1781 663e8e51 ths
1782 151b2986 Juan Quintela
static const VMStateDescription vmstate_eepro100 = {
1783 151b2986 Juan Quintela
    .version_id = 3,
1784 151b2986 Juan Quintela
    .minimum_version_id = 2,
1785 151b2986 Juan Quintela
    .minimum_version_id_old = 2,
1786 151b2986 Juan Quintela
    .fields      = (VMStateField []) {
1787 151b2986 Juan Quintela
        VMSTATE_PCI_DEVICE(dev, EEPRO100State),
1788 151b2986 Juan Quintela
        VMSTATE_UNUSED(32),
1789 151b2986 Juan Quintela
        VMSTATE_BUFFER(mult, EEPRO100State),
1790 151b2986 Juan Quintela
        VMSTATE_BUFFER(mem, EEPRO100State),
1791 151b2986 Juan Quintela
        /* Save all members of struct between scb_stat and mem. */
1792 151b2986 Juan Quintela
        VMSTATE_UINT8(scb_stat, EEPRO100State),
1793 151b2986 Juan Quintela
        VMSTATE_UINT8(int_stat, EEPRO100State),
1794 151b2986 Juan Quintela
        VMSTATE_UNUSED(3*4),
1795 151b2986 Juan Quintela
        VMSTATE_MACADDR(conf.macaddr, EEPRO100State),
1796 151b2986 Juan Quintela
        VMSTATE_UNUSED(19*4),
1797 151b2986 Juan Quintela
        VMSTATE_UINT16_ARRAY(mdimem, EEPRO100State, 32),
1798 151b2986 Juan Quintela
        /* The eeprom should be saved and restored by its own routines. */
1799 151b2986 Juan Quintela
        VMSTATE_UINT32(device, EEPRO100State),
1800 151b2986 Juan Quintela
        /* TODO check device. */
1801 151b2986 Juan Quintela
        VMSTATE_UINT32(cu_base, EEPRO100State),
1802 151b2986 Juan Quintela
        VMSTATE_UINT32(cu_offset, EEPRO100State),
1803 151b2986 Juan Quintela
        VMSTATE_UINT32(ru_base, EEPRO100State),
1804 151b2986 Juan Quintela
        VMSTATE_UINT32(ru_offset, EEPRO100State),
1805 151b2986 Juan Quintela
        VMSTATE_UINT32(statsaddr, EEPRO100State),
1806 ba42b646 Stefan Weil
        /* Save eepro100_stats_t statistics. */
1807 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_good_frames, EEPRO100State),
1808 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_max_collisions, EEPRO100State),
1809 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_late_collisions, EEPRO100State),
1810 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_underruns, EEPRO100State),
1811 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_lost_crs, EEPRO100State),
1812 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_deferred, EEPRO100State),
1813 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_single_collisions, EEPRO100State),
1814 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_multiple_collisions, EEPRO100State),
1815 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_total_collisions, EEPRO100State),
1816 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_good_frames, EEPRO100State),
1817 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_crc_errors, EEPRO100State),
1818 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_alignment_errors, EEPRO100State),
1819 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_resource_errors, EEPRO100State),
1820 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_overrun_errors, EEPRO100State),
1821 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_cdt_errors, EEPRO100State),
1822 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_short_frame_errors, EEPRO100State),
1823 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_xmt_pause, EEPRO100State),
1824 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_rcv_pause, EEPRO100State),
1825 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_rcv_unsupported, EEPRO100State),
1826 151b2986 Juan Quintela
        VMSTATE_UINT16(statistics.xmt_tco_frames, EEPRO100State),
1827 151b2986 Juan Quintela
        VMSTATE_UINT16(statistics.rcv_tco_frames, EEPRO100State),
1828 151b2986 Juan Quintela
        /* Configuration bytes. */
1829 151b2986 Juan Quintela
        VMSTATE_BUFFER(configuration, EEPRO100State),
1830 151b2986 Juan Quintela
        VMSTATE_END_OF_LIST()
1831 aac443e6 Stefan Weil
    }
1832 151b2986 Juan Quintela
};
1833 663e8e51 ths
1834 4e68f7a0 Stefan Hajnoczi
static void nic_cleanup(NetClientState *nc)
1835 b946a153 aliguori
{
1836 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1837 b946a153 aliguori
1838 e00e365e Mark McLoughlin
    s->nic = NULL;
1839 b946a153 aliguori
}
1840 b946a153 aliguori
1841 f90c2bcd Alex Williamson
static void pci_nic_uninit(PCIDevice *pci_dev)
1842 b946a153 aliguori
{
1843 c4c270e2 Stefan Weil
    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
1844 b946a153 aliguori
1845 5e6ffdde Avi Kivity
    memory_region_destroy(&s->mmio_bar);
1846 5e6ffdde Avi Kivity
    memory_region_destroy(&s->io_bar);
1847 5e6ffdde Avi Kivity
    memory_region_destroy(&s->flash_bar);
1848 0be71e32 Alex Williamson
    vmstate_unregister(&pci_dev->qdev, s->vmstate, s);
1849 5fce2b3e Alex Williamson
    eeprom93xx_free(&pci_dev->qdev, s->eeprom);
1850 b20c6b9e Stefan Hajnoczi
    qemu_del_net_client(&s->nic->nc);
1851 b946a153 aliguori
}
1852 b946a153 aliguori
1853 e00e365e Mark McLoughlin
static NetClientInfo net_eepro100_info = {
1854 2be64a68 Laszlo Ersek
    .type = NET_CLIENT_OPTIONS_KIND_NIC,
1855 e00e365e Mark McLoughlin
    .size = sizeof(NICState),
1856 e00e365e Mark McLoughlin
    .can_receive = nic_can_receive,
1857 e00e365e Mark McLoughlin
    .receive = nic_receive,
1858 e00e365e Mark McLoughlin
    .cleanup = nic_cleanup,
1859 e00e365e Mark McLoughlin
};
1860 e00e365e Mark McLoughlin
1861 558c8634 Stefan Weil
static int e100_nic_init(PCIDevice *pci_dev)
1862 663e8e51 ths
{
1863 273a2142 Juan Quintela
    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
1864 40021f08 Anthony Liguori
    E100PCIDeviceInfo *info = eepro100_get_class(s);
1865 663e8e51 ths
1866 aac443e6 Stefan Weil
    TRACE(OTHER, logout("\n"));
1867 663e8e51 ths
1868 40021f08 Anthony Liguori
    s->device = info->device;
1869 663e8e51 ths
1870 40021f08 Anthony Liguori
    e100_pci_reset(s);
1871 663e8e51 ths
1872 663e8e51 ths
    /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
1873 663e8e51 ths
     * i82559 and later support 64 or 256 word EEPROM. */
1874 5fce2b3e Alex Williamson
    s->eeprom = eeprom93xx_new(&pci_dev->qdev, EEPROM_SIZE);
1875 663e8e51 ths
1876 663e8e51 ths
    /* Handler for memory-mapped I/O */
1877 5e6ffdde Avi Kivity
    memory_region_init_io(&s->mmio_bar, &eepro100_ops, s, "eepro100-mmio",
1878 5e6ffdde Avi Kivity
                          PCI_MEM_SIZE);
1879 e824b2cc Avi Kivity
    pci_register_bar(&s->dev, 0, PCI_BASE_ADDRESS_MEM_PREFETCH, &s->mmio_bar);
1880 5e6ffdde Avi Kivity
    memory_region_init_io(&s->io_bar, &eepro100_ops, s, "eepro100-io",
1881 5e6ffdde Avi Kivity
                          PCI_IO_SIZE);
1882 e824b2cc Avi Kivity
    pci_register_bar(&s->dev, 1, PCI_BASE_ADDRESS_SPACE_IO, &s->io_bar);
1883 5e6ffdde Avi Kivity
    /* FIXME: flash aliases to mmio?! */
1884 5e6ffdde Avi Kivity
    memory_region_init_io(&s->flash_bar, &eepro100_ops, s, "eepro100-flash",
1885 5e6ffdde Avi Kivity
                          PCI_FLASH_SIZE);
1886 e824b2cc Avi Kivity
    pci_register_bar(&s->dev, 2, 0, &s->flash_bar);
1887 663e8e51 ths
1888 508ef936 Gerd Hoffmann
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
1889 ce0e58b3 Stefan Weil
    logout("macaddr: %s\n", nic_dump(&s->conf.macaddr.a[0], 6));
1890 663e8e51 ths
1891 663e8e51 ths
    nic_reset(s);
1892 663e8e51 ths
1893 e00e365e Mark McLoughlin
    s->nic = qemu_new_nic(&net_eepro100_info, &s->conf,
1894 f79f2bfc Anthony Liguori
                          object_get_typename(OBJECT(pci_dev)), pci_dev->qdev.id, s);
1895 663e8e51 ths
1896 e00e365e Mark McLoughlin
    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
1897 e00e365e Mark McLoughlin
    TRACE(OTHER, logout("%s\n", s->nic->nc.info_str));
1898 663e8e51 ths
1899 a08d4367 Jan Kiszka
    qemu_register_reset(nic_reset, s);
1900 663e8e51 ths
1901 7267c094 Anthony Liguori
    s->vmstate = g_malloc(sizeof(vmstate_eepro100));
1902 151b2986 Juan Quintela
    memcpy(s->vmstate, &vmstate_eepro100, sizeof(vmstate_eepro100));
1903 e00e365e Mark McLoughlin
    s->vmstate->name = s->nic->nc.model;
1904 0be71e32 Alex Williamson
    vmstate_register(&pci_dev->qdev, -1, s->vmstate, s);
1905 4e9df06a Stefan Weil
1906 1ca4d09a Gleb Natapov
    add_boot_device_path(s->conf.bootindex, &pci_dev->qdev, "/ethernet-phy@0");
1907 1ca4d09a Gleb Natapov
1908 81a322d4 Gerd Hoffmann
    return 0;
1909 663e8e51 ths
}
1910 663e8e51 ths
1911 558c8634 Stefan Weil
static E100PCIDeviceInfo e100_devices[] = {
1912 0aab0d3a Gerd Hoffmann
    {
1913 39bffca2 Anthony Liguori
        .name = "i82550",
1914 39bffca2 Anthony Liguori
        .desc = "Intel i82550 Ethernet",
1915 558c8634 Stefan Weil
        .device = i82550,
1916 558c8634 Stefan Weil
        /* TODO: check device id. */
1917 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82551IT,
1918 558c8634 Stefan Weil
        /* Revision ID: 0x0c, 0x0d, 0x0e. */
1919 40021f08 Anthony Liguori
        .revision = 0x0e,
1920 558c8634 Stefan Weil
        /* TODO: check size of statistical counters. */
1921 558c8634 Stefan Weil
        .stats_size = 80,
1922 558c8634 Stefan Weil
        /* TODO: check extended tcb support. */
1923 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1924 558c8634 Stefan Weil
        .power_management = true,
1925 0aab0d3a Gerd Hoffmann
    },{
1926 39bffca2 Anthony Liguori
        .name = "i82551",
1927 39bffca2 Anthony Liguori
        .desc = "Intel i82551 Ethernet",
1928 558c8634 Stefan Weil
        .device = i82551,
1929 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82551IT,
1930 558c8634 Stefan Weil
        /* Revision ID: 0x0f, 0x10. */
1931 40021f08 Anthony Liguori
        .revision = 0x0f,
1932 558c8634 Stefan Weil
        /* TODO: check size of statistical counters. */
1933 558c8634 Stefan Weil
        .stats_size = 80,
1934 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1935 558c8634 Stefan Weil
        .power_management = true,
1936 c4c270e2 Stefan Weil
    },{
1937 39bffca2 Anthony Liguori
        .name = "i82557a",
1938 39bffca2 Anthony Liguori
        .desc = "Intel i82557A Ethernet",
1939 558c8634 Stefan Weil
        .device = i82557A,
1940 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82557,
1941 40021f08 Anthony Liguori
        .revision = 0x01,
1942 558c8634 Stefan Weil
        .power_management = false,
1943 0aab0d3a Gerd Hoffmann
    },{
1944 39bffca2 Anthony Liguori
        .name = "i82557b",
1945 39bffca2 Anthony Liguori
        .desc = "Intel i82557B Ethernet",
1946 558c8634 Stefan Weil
        .device = i82557B,
1947 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82557,
1948 40021f08 Anthony Liguori
        .revision = 0x02,
1949 558c8634 Stefan Weil
        .power_management = false,
1950 c4c270e2 Stefan Weil
    },{
1951 39bffca2 Anthony Liguori
        .name = "i82557c",
1952 39bffca2 Anthony Liguori
        .desc = "Intel i82557C Ethernet",
1953 558c8634 Stefan Weil
        .device = i82557C,
1954 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82557,
1955 40021f08 Anthony Liguori
        .revision = 0x03,
1956 558c8634 Stefan Weil
        .power_management = false,
1957 c4c270e2 Stefan Weil
    },{
1958 39bffca2 Anthony Liguori
        .name = "i82558a",
1959 39bffca2 Anthony Liguori
        .desc = "Intel i82558A Ethernet",
1960 558c8634 Stefan Weil
        .device = i82558A,
1961 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82557,
1962 40021f08 Anthony Liguori
        .revision = 0x04,
1963 558c8634 Stefan Weil
        .stats_size = 76,
1964 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1965 558c8634 Stefan Weil
        .power_management = true,
1966 c4c270e2 Stefan Weil
    },{
1967 39bffca2 Anthony Liguori
        .name = "i82558b",
1968 39bffca2 Anthony Liguori
        .desc = "Intel i82558B Ethernet",
1969 558c8634 Stefan Weil
        .device = i82558B,
1970 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82557,
1971 40021f08 Anthony Liguori
        .revision = 0x05,
1972 558c8634 Stefan Weil
        .stats_size = 76,
1973 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1974 558c8634 Stefan Weil
        .power_management = true,
1975 c4c270e2 Stefan Weil
    },{
1976 39bffca2 Anthony Liguori
        .name = "i82559a",
1977 39bffca2 Anthony Liguori
        .desc = "Intel i82559A Ethernet",
1978 558c8634 Stefan Weil
        .device = i82559A,
1979 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82557,
1980 40021f08 Anthony Liguori
        .revision = 0x06,
1981 558c8634 Stefan Weil
        .stats_size = 80,
1982 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1983 558c8634 Stefan Weil
        .power_management = true,
1984 c4c270e2 Stefan Weil
    },{
1985 39bffca2 Anthony Liguori
        .name = "i82559b",
1986 39bffca2 Anthony Liguori
        .desc = "Intel i82559B Ethernet",
1987 558c8634 Stefan Weil
        .device = i82559B,
1988 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82557,
1989 40021f08 Anthony Liguori
        .revision = 0x07,
1990 558c8634 Stefan Weil
        .stats_size = 80,
1991 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
1992 558c8634 Stefan Weil
        .power_management = true,
1993 c4c270e2 Stefan Weil
    },{
1994 39bffca2 Anthony Liguori
        .name = "i82559c",
1995 39bffca2 Anthony Liguori
        .desc = "Intel i82559C Ethernet",
1996 558c8634 Stefan Weil
        .device = i82559C,
1997 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82557,
1998 558c8634 Stefan Weil
#if 0
1999 40021f08 Anthony Liguori
        .revision = 0x08,
2000 558c8634 Stefan Weil
#endif
2001 558c8634 Stefan Weil
        /* TODO: Windows wants revision id 0x0c. */
2002 40021f08 Anthony Liguori
        .revision = 0x0c,
2003 ad03502b Isaku Yamahata
#if EEPROM_SIZE > 0
2004 40021f08 Anthony Liguori
        .subsystem_vendor_id = PCI_VENDOR_ID_INTEL,
2005 40021f08 Anthony Liguori
        .subsystem_id = 0x0040,
2006 ad03502b Isaku Yamahata
#endif
2007 558c8634 Stefan Weil
        .stats_size = 80,
2008 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
2009 558c8634 Stefan Weil
        .power_management = true,
2010 0aab0d3a Gerd Hoffmann
    },{
2011 39bffca2 Anthony Liguori
        .name = "i82559er",
2012 39bffca2 Anthony Liguori
        .desc = "Intel i82559ER Ethernet",
2013 558c8634 Stefan Weil
        .device = i82559ER,
2014 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82551IT,
2015 40021f08 Anthony Liguori
        .revision = 0x09,
2016 558c8634 Stefan Weil
        .stats_size = 80,
2017 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
2018 558c8634 Stefan Weil
        .power_management = true,
2019 c4c270e2 Stefan Weil
    },{
2020 39bffca2 Anthony Liguori
        .name = "i82562",
2021 39bffca2 Anthony Liguori
        .desc = "Intel i82562 Ethernet",
2022 558c8634 Stefan Weil
        .device = i82562,
2023 558c8634 Stefan Weil
        /* TODO: check device id. */
2024 40021f08 Anthony Liguori
        .device_id = PCI_DEVICE_ID_INTEL_82551IT,
2025 558c8634 Stefan Weil
        /* TODO: wrong revision id. */
2026 40021f08 Anthony Liguori
        .revision = 0x0e,
2027 558c8634 Stefan Weil
        .stats_size = 80,
2028 558c8634 Stefan Weil
        .has_extended_tcb_support = true,
2029 558c8634 Stefan Weil
        .power_management = true,
2030 db667a12 Stefan Weil
    },{
2031 db667a12 Stefan Weil
        /* Toshiba Tecra 8200. */
2032 39bffca2 Anthony Liguori
        .name = "i82801",
2033 39bffca2 Anthony Liguori
        .desc = "Intel i82801 Ethernet",
2034 db667a12 Stefan Weil
        .device = i82801,
2035 40021f08 Anthony Liguori
        .device_id = 0x2449,
2036 40021f08 Anthony Liguori
        .revision = 0x03,
2037 db667a12 Stefan Weil
        .stats_size = 80,
2038 db667a12 Stefan Weil
        .has_extended_tcb_support = true,
2039 db667a12 Stefan Weil
        .power_management = true,
2040 0aab0d3a Gerd Hoffmann
    }
2041 0aab0d3a Gerd Hoffmann
};
2042 0aab0d3a Gerd Hoffmann
2043 40021f08 Anthony Liguori
static E100PCIDeviceInfo *eepro100_get_class_by_name(const char *typename)
2044 40021f08 Anthony Liguori
{
2045 40021f08 Anthony Liguori
    E100PCIDeviceInfo *info = NULL;
2046 40021f08 Anthony Liguori
    int i;
2047 40021f08 Anthony Liguori
2048 40021f08 Anthony Liguori
    /* This is admittedly awkward but also temporary.  QOM allows for
2049 40021f08 Anthony Liguori
     * parameterized typing and for subclassing both of which would suitable
2050 40021f08 Anthony Liguori
     * handle what's going on here.  But class_data is already being used as
2051 40021f08 Anthony Liguori
     * a stop-gap hack to allow incremental qdev conversion so we cannot use it
2052 40021f08 Anthony Liguori
     * right now.  Once we merge the final QOM series, we can come back here and
2053 40021f08 Anthony Liguori
     * do this in a much more elegant fashion.
2054 40021f08 Anthony Liguori
     */
2055 40021f08 Anthony Liguori
    for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
2056 39bffca2 Anthony Liguori
        if (strcmp(e100_devices[i].name, typename) == 0) {
2057 40021f08 Anthony Liguori
            info = &e100_devices[i];
2058 40021f08 Anthony Liguori
            break;
2059 40021f08 Anthony Liguori
        }
2060 40021f08 Anthony Liguori
    }
2061 40021f08 Anthony Liguori
    assert(info != NULL);
2062 40021f08 Anthony Liguori
2063 40021f08 Anthony Liguori
    return info;
2064 40021f08 Anthony Liguori
}
2065 40021f08 Anthony Liguori
2066 40021f08 Anthony Liguori
static E100PCIDeviceInfo *eepro100_get_class(EEPRO100State *s)
2067 40021f08 Anthony Liguori
{
2068 40021f08 Anthony Liguori
    return eepro100_get_class_by_name(object_get_typename(OBJECT(s)));
2069 40021f08 Anthony Liguori
}
2070 40021f08 Anthony Liguori
2071 39bffca2 Anthony Liguori
static Property e100_properties[] = {
2072 39bffca2 Anthony Liguori
    DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2073 39bffca2 Anthony Liguori
    DEFINE_PROP_END_OF_LIST(),
2074 39bffca2 Anthony Liguori
};
2075 39bffca2 Anthony Liguori
2076 40021f08 Anthony Liguori
static void eepro100_class_init(ObjectClass *klass, void *data)
2077 40021f08 Anthony Liguori
{
2078 39bffca2 Anthony Liguori
    DeviceClass *dc = DEVICE_CLASS(klass);
2079 40021f08 Anthony Liguori
    PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
2080 40021f08 Anthony Liguori
    E100PCIDeviceInfo *info;
2081 40021f08 Anthony Liguori
2082 40021f08 Anthony Liguori
    info = eepro100_get_class_by_name(object_class_get_name(klass));
2083 40021f08 Anthony Liguori
2084 39bffca2 Anthony Liguori
    dc->props = e100_properties;
2085 39bffca2 Anthony Liguori
    dc->desc = info->desc;
2086 40021f08 Anthony Liguori
    k->vendor_id = PCI_VENDOR_ID_INTEL;
2087 40021f08 Anthony Liguori
    k->class_id = PCI_CLASS_NETWORK_ETHERNET;
2088 40021f08 Anthony Liguori
    k->romfile = "pxe-eepro100.rom";
2089 40021f08 Anthony Liguori
    k->init = e100_nic_init;
2090 40021f08 Anthony Liguori
    k->exit = pci_nic_uninit;
2091 40021f08 Anthony Liguori
    k->device_id = info->device_id;
2092 40021f08 Anthony Liguori
    k->revision = info->revision;
2093 40021f08 Anthony Liguori
    k->subsystem_vendor_id = info->subsystem_vendor_id;
2094 40021f08 Anthony Liguori
    k->subsystem_id = info->subsystem_id;
2095 40021f08 Anthony Liguori
}
2096 40021f08 Anthony Liguori
2097 83f7d43a Andreas Färber
static void eepro100_register_types(void)
2098 663e8e51 ths
{
2099 558c8634 Stefan Weil
    size_t i;
2100 558c8634 Stefan Weil
    for (i = 0; i < ARRAY_SIZE(e100_devices); i++) {
2101 39bffca2 Anthony Liguori
        TypeInfo type_info = {};
2102 39bffca2 Anthony Liguori
        E100PCIDeviceInfo *info = &e100_devices[i];
2103 40021f08 Anthony Liguori
2104 39bffca2 Anthony Liguori
        type_info.name = info->name;
2105 39bffca2 Anthony Liguori
        type_info.parent = TYPE_PCI_DEVICE;
2106 39bffca2 Anthony Liguori
        type_info.class_init = eepro100_class_init;
2107 39bffca2 Anthony Liguori
        type_info.instance_size = sizeof(EEPRO100State);
2108 40021f08 Anthony Liguori
        
2109 39bffca2 Anthony Liguori
        type_register(&type_info);
2110 558c8634 Stefan Weil
    }
2111 663e8e51 ths
}
2112 663e8e51 ths
2113 83f7d43a Andreas Färber
type_init(eepro100_register_types)