Statistics
| Branch: | Revision:

root / hw / eepro100.c @ e824012b

History | View | Annotate | Download (70.2 kB)

1 663e8e51 ths
/*
2 663e8e51 ths
 * QEMU i8255x (PRO100) emulation
3 663e8e51 ths
 *
4 230a167c Stefan Weil
 * Copyright (C) 2006-2010 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 6cded3a4 Stefan Weil
 *      PXE boot (i386) ok
24 663e8e51 ths
 *      Linux networking (i386) ok
25 663e8e51 ths
 *
26 663e8e51 ths
 * Untested:
27 663e8e51 ths
 *      non-i386 platforms
28 663e8e51 ths
 *      Windows networking
29 663e8e51 ths
 *
30 663e8e51 ths
 * References:
31 663e8e51 ths
 *
32 663e8e51 ths
 * Intel 8255x 10/100 Mbps Ethernet Controller Family
33 663e8e51 ths
 * Open Source Software Developer Manual
34 ba19f2de Stefan Weil
 *
35 ba19f2de Stefan Weil
 * TODO:
36 ba19f2de Stefan Weil
 *      * PHY emulation should be separated from nic emulation.
37 ba19f2de Stefan Weil
 *        Most nic emulations could share the same phy code.
38 ba19f2de Stefan Weil
 *      * i82550 is untested. It is programmed like the i82559.
39 ba19f2de Stefan Weil
 *      * i82562 is untested. It is programmed like the i82559.
40 ba19f2de Stefan Weil
 *      * Power management (i82558 and later) is not implemented.
41 ba19f2de Stefan Weil
 *      * Wake-on-LAN is not implemented.
42 663e8e51 ths
 */
43 663e8e51 ths
44 663e8e51 ths
#include <stddef.h>             /* offsetof */
45 b84a5c6f Amit Shah
#include <stdbool.h>
46 87ecb68b pbrook
#include "hw.h"
47 87ecb68b pbrook
#include "pci.h"
48 87ecb68b pbrook
#include "net.h"
49 663e8e51 ths
#include "eeprom93xx.h"
50 663e8e51 ths
51 663e8e51 ths
/* Common declarations for all PCI devices. */
52 663e8e51 ths
53 663e8e51 ths
#define PCI_CONFIG_8(offset, value) \
54 663e8e51 ths
    (pci_conf[offset] = (value))
55 663e8e51 ths
#define PCI_CONFIG_16(offset, value) \
56 663e8e51 ths
    (*(uint16_t *)&pci_conf[offset] = cpu_to_le16(value))
57 663e8e51 ths
#define PCI_CONFIG_32(offset, value) \
58 663e8e51 ths
    (*(uint32_t *)&pci_conf[offset] = cpu_to_le32(value))
59 663e8e51 ths
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 663e8e51 ths
100 aac443e6 Stefan Weil
/* Use 64 word EEPROM. TODO: could be a runtime option. */
101 663e8e51 ths
#define EEPROM_SIZE     64
102 663e8e51 ths
103 663e8e51 ths
#define PCI_MEM_SIZE            (4 * KiB)
104 663e8e51 ths
#define PCI_IO_SIZE             64
105 663e8e51 ths
#define PCI_FLASH_SIZE          (128 * KiB)
106 663e8e51 ths
107 663e8e51 ths
#define BIT(n) (1 << (n))
108 663e8e51 ths
#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
109 663e8e51 ths
110 663e8e51 ths
/* The SCB accepts the following controls for the Tx and Rx units: */
111 663e8e51 ths
#define  CU_NOP         0x0000  /* No operation. */
112 663e8e51 ths
#define  CU_START       0x0010  /* CU start. */
113 663e8e51 ths
#define  CU_RESUME      0x0020  /* CU resume. */
114 663e8e51 ths
#define  CU_STATSADDR   0x0040  /* Load dump counters address. */
115 663e8e51 ths
#define  CU_SHOWSTATS   0x0050  /* Dump statistical counters. */
116 663e8e51 ths
#define  CU_CMD_BASE    0x0060  /* Load CU base address. */
117 663e8e51 ths
#define  CU_DUMPSTATS   0x0070  /* Dump and reset statistical counters. */
118 663e8e51 ths
#define  CU_SRESUME     0x00a0  /* CU static resume. */
119 663e8e51 ths
120 663e8e51 ths
#define  RU_NOP         0x0000
121 663e8e51 ths
#define  RX_START       0x0001
122 663e8e51 ths
#define  RX_RESUME      0x0002
123 e824012b Stefan Weil
#define  RU_ABORT       0x0004
124 663e8e51 ths
#define  RX_ADDR_LOAD   0x0006
125 663e8e51 ths
#define  RX_RESUMENR    0x0007
126 663e8e51 ths
#define INT_MASK        0x0100
127 663e8e51 ths
#define DRVR_INT        0x0200  /* Driver generated interrupt. */
128 663e8e51 ths
129 663e8e51 ths
/* Offsets to the various registers.
130 663e8e51 ths
   All accesses need not be longword aligned. */
131 663e8e51 ths
enum speedo_offsets {
132 0908bba1 Stefan Weil
    SCBStatus = 0,              /* Status Word. */
133 663e8e51 ths
    SCBAck = 1,
134 663e8e51 ths
    SCBCmd = 2,                 /* Rx/Command Unit command and status. */
135 663e8e51 ths
    SCBIntmask = 3,
136 663e8e51 ths
    SCBPointer = 4,             /* General purpose pointer. */
137 663e8e51 ths
    SCBPort = 8,                /* Misc. commands and operands.  */
138 0908bba1 Stefan Weil
    SCBflash = 12,              /* Flash memory control. */
139 0908bba1 Stefan Weil
    SCBeeprom = 14,             /* EEPROM control. */
140 663e8e51 ths
    SCBCtrlMDI = 16,            /* MDI interface control. */
141 663e8e51 ths
    SCBEarlyRx = 20,            /* Early receive byte count. */
142 0908bba1 Stefan Weil
    SCBFlow = 24,               /* Flow Control. */
143 0908bba1 Stefan Weil
    SCBpmdr = 27,               /* Power Management Driver. */
144 0908bba1 Stefan Weil
    SCBgctrl = 28,              /* General Control. */
145 0908bba1 Stefan Weil
    SCBgstat = 29,              /* General Status. */
146 663e8e51 ths
};
147 663e8e51 ths
148 663e8e51 ths
/* A speedo3 transmit buffer descriptor with two buffers... */
149 663e8e51 ths
typedef struct {
150 663e8e51 ths
    uint16_t status;
151 663e8e51 ths
    uint16_t command;
152 663e8e51 ths
    uint32_t link;              /* void * */
153 7b8737de Stefan Weil
    uint32_t tbd_array_addr;    /* transmit buffer descriptor array address. */
154 663e8e51 ths
    uint16_t tcb_bytes;         /* transmit command block byte count (in lower 14 bits */
155 663e8e51 ths
    uint8_t tx_threshold;       /* transmit threshold */
156 663e8e51 ths
    uint8_t tbd_count;          /* TBD number */
157 663e8e51 ths
    //~ /* This constitutes two "TBD" entries: hdr and data */
158 663e8e51 ths
    //~ uint32_t tx_buf_addr0;  /* void *, header of frame to be transmitted.  */
159 663e8e51 ths
    //~ int32_t  tx_buf_size0;  /* Length of Tx hdr. */
160 663e8e51 ths
    //~ uint32_t tx_buf_addr1;  /* void *, data to be transmitted.  */
161 663e8e51 ths
    //~ int32_t  tx_buf_size1;  /* Length of Tx data. */
162 c227f099 Anthony Liguori
} eepro100_tx_t;
163 663e8e51 ths
164 663e8e51 ths
/* Receive frame descriptor. */
165 663e8e51 ths
typedef struct {
166 663e8e51 ths
    int16_t status;
167 663e8e51 ths
    uint16_t command;
168 663e8e51 ths
    uint32_t link;              /* struct RxFD * */
169 663e8e51 ths
    uint32_t rx_buf_addr;       /* void * */
170 663e8e51 ths
    uint16_t count;
171 663e8e51 ths
    uint16_t size;
172 663e8e51 ths
    char packet[MAX_ETH_FRAME_SIZE + 4];
173 c227f099 Anthony Liguori
} eepro100_rx_t;
174 663e8e51 ths
175 ced5296a Stefan Weil
typedef enum {
176 ced5296a Stefan Weil
    COMMAND_EL = BIT(15),
177 ced5296a Stefan Weil
    COMMAND_S = BIT(14),
178 ced5296a Stefan Weil
    COMMAND_I = BIT(13),
179 ced5296a Stefan Weil
    COMMAND_NC = BIT(4),
180 ced5296a Stefan Weil
    COMMAND_SF = BIT(3),
181 ced5296a Stefan Weil
    COMMAND_CMD = BITS(2, 0),
182 ced5296a Stefan Weil
} scb_command_bit;
183 ced5296a Stefan Weil
184 ced5296a Stefan Weil
typedef enum {
185 ced5296a Stefan Weil
    STATUS_C = BIT(15),
186 ced5296a Stefan Weil
    STATUS_OK = BIT(13),
187 ced5296a Stefan Weil
} scb_status_bit;
188 ced5296a Stefan Weil
189 663e8e51 ths
typedef struct {
190 663e8e51 ths
    uint32_t tx_good_frames, tx_max_collisions, tx_late_collisions,
191 663e8e51 ths
        tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
192 663e8e51 ths
        tx_multiple_collisions, tx_total_collisions;
193 663e8e51 ths
    uint32_t rx_good_frames, rx_crc_errors, rx_alignment_errors,
194 663e8e51 ths
        rx_resource_errors, rx_overrun_errors, rx_cdt_errors,
195 663e8e51 ths
        rx_short_frame_errors;
196 663e8e51 ths
    uint32_t fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
197 663e8e51 ths
    uint16_t xmt_tco_frames, rcv_tco_frames;
198 ba42b646 Stefan Weil
    /* TODO: i82559 has six reserved statistics but a total of 24 dwords. */
199 ba42b646 Stefan Weil
    uint32_t reserved[4];
200 c227f099 Anthony Liguori
} eepro100_stats_t;
201 663e8e51 ths
202 663e8e51 ths
typedef enum {
203 663e8e51 ths
    cu_idle = 0,
204 663e8e51 ths
    cu_suspended = 1,
205 663e8e51 ths
    cu_active = 2,
206 663e8e51 ths
    cu_lpq_active = 2,
207 663e8e51 ths
    cu_hqp_active = 3
208 c227f099 Anthony Liguori
} cu_state_t;
209 663e8e51 ths
210 663e8e51 ths
typedef enum {
211 663e8e51 ths
    ru_idle = 0,
212 663e8e51 ths
    ru_suspended = 1,
213 663e8e51 ths
    ru_no_resources = 2,
214 663e8e51 ths
    ru_ready = 4
215 c227f099 Anthony Liguori
} ru_state_t;
216 663e8e51 ths
217 663e8e51 ths
typedef struct {
218 273a2142 Juan Quintela
    PCIDevice dev;
219 663e8e51 ths
    uint8_t mult[8];            /* multicast mask array */
220 663e8e51 ths
    int mmio_index;
221 e00e365e Mark McLoughlin
    NICState *nic;
222 508ef936 Gerd Hoffmann
    NICConf conf;
223 663e8e51 ths
    uint8_t scb_stat;           /* SCB stat/ack byte */
224 663e8e51 ths
    uint8_t int_stat;           /* PCI interrupt status */
225 3706c43f Stefan Weil
    /* region must not be saved by nic_save. */
226 663e8e51 ths
    uint32_t region[3];         /* PCI region addresses */
227 663e8e51 ths
    uint16_t mdimem[32];
228 c227f099 Anthony Liguori
    eeprom_t *eeprom;
229 663e8e51 ths
    uint32_t device;            /* device variant */
230 663e8e51 ths
    uint32_t pointer;
231 663e8e51 ths
    /* (cu_base + cu_offset) address the next command block in the command block list. */
232 663e8e51 ths
    uint32_t cu_base;           /* CU base address */
233 663e8e51 ths
    uint32_t cu_offset;         /* CU address offset */
234 663e8e51 ths
    /* (ru_base + ru_offset) address the RFD in the Receive Frame Area. */
235 663e8e51 ths
    uint32_t ru_base;           /* RU base address */
236 663e8e51 ths
    uint32_t ru_offset;         /* RU address offset */
237 c227f099 Anthony Liguori
    uint32_t statsaddr;         /* pointer to eepro100_stats_t */
238 ba42b646 Stefan Weil
239 f3a52e50 Stefan Weil
    /* Temporary status information (no need to save these values),
240 f3a52e50 Stefan Weil
     * used while processing CU commands. */
241 f3a52e50 Stefan Weil
    eepro100_tx_t tx;           /* transmit buffer descriptor */
242 f3a52e50 Stefan Weil
    uint32_t cb_address;        /* = cu_base + cu_offset */
243 f3a52e50 Stefan Weil
244 ba42b646 Stefan Weil
    /* Statistical counters. Also used for wake-up packet (i82559). */
245 ba42b646 Stefan Weil
    eepro100_stats_t statistics;
246 ba42b646 Stefan Weil
247 663e8e51 ths
#if 0
248 663e8e51 ths
    uint16_t status;
249 663e8e51 ths
#endif
250 663e8e51 ths
251 663e8e51 ths
    /* Configuration bytes. */
252 663e8e51 ths
    uint8_t configuration[22];
253 663e8e51 ths
254 663e8e51 ths
    /* Data in mem is always in the byte order of the controller (le). */
255 663e8e51 ths
    uint8_t mem[PCI_MEM_SIZE];
256 151b2986 Juan Quintela
    /* vmstate for each particular nic */
257 151b2986 Juan Quintela
    VMStateDescription *vmstate;
258 ba42b646 Stefan Weil
259 ba42b646 Stefan Weil
    /* Quasi static device properties (no need to save them). */
260 ba42b646 Stefan Weil
    uint16_t stats_size;
261 ba42b646 Stefan Weil
    bool has_extended_tcb_support;
262 663e8e51 ths
} EEPRO100State;
263 663e8e51 ths
264 6cded3a4 Stefan Weil
/* Word indices in EEPROM. */
265 6cded3a4 Stefan Weil
typedef enum {
266 6cded3a4 Stefan Weil
    EEPROM_CNFG_MDIX  = 0x03,
267 6cded3a4 Stefan Weil
    EEPROM_ID         = 0x05,
268 6cded3a4 Stefan Weil
    EEPROM_PHY_ID     = 0x06,
269 6cded3a4 Stefan Weil
    EEPROM_VENDOR_ID  = 0x0c,
270 6cded3a4 Stefan Weil
    EEPROM_CONFIG_ASF = 0x0d,
271 6cded3a4 Stefan Weil
    EEPROM_DEVICE_ID  = 0x23,
272 6cded3a4 Stefan Weil
    EEPROM_SMBUS_ADDR = 0x90,
273 6cded3a4 Stefan Weil
} EEPROMOffset;
274 6cded3a4 Stefan Weil
275 b1e87018 Stefan Weil
/* Bit values for EEPROM ID word. */
276 b1e87018 Stefan Weil
typedef enum {
277 b1e87018 Stefan Weil
    EEPROM_ID_MDM = BIT(0),     /* Modem */
278 b1e87018 Stefan Weil
    EEPROM_ID_STB = BIT(1),     /* Standby Enable */
279 b1e87018 Stefan Weil
    EEPROM_ID_WMR = BIT(2),     /* ??? */
280 b1e87018 Stefan Weil
    EEPROM_ID_WOL = BIT(5),     /* Wake on LAN */
281 b1e87018 Stefan Weil
    EEPROM_ID_DPD = BIT(6),     /* Deep Power Down */
282 b1e87018 Stefan Weil
    EEPROM_ID_ALT = BIT(7),     /* */
283 b1e87018 Stefan Weil
    /* BITS(10, 8) device revision */
284 b1e87018 Stefan Weil
    EEPROM_ID_BD = BIT(11),     /* boot disable */
285 b1e87018 Stefan Weil
    EEPROM_ID_ID = BIT(13),     /* id bit */
286 b1e87018 Stefan Weil
    /* BITS(15, 14) signature */
287 b1e87018 Stefan Weil
    EEPROM_ID_VALID = BIT(14),  /* signature for valid eeprom */
288 b1e87018 Stefan Weil
} eeprom_id_bit;
289 b1e87018 Stefan Weil
290 663e8e51 ths
/* Default values for MDI (PHY) registers */
291 663e8e51 ths
static const uint16_t eepro100_mdi_default[] = {
292 663e8e51 ths
    /* MDI Registers 0 - 6, 7 */
293 663e8e51 ths
    0x3000, 0x780d, 0x02a8, 0x0154, 0x05e1, 0x0000, 0x0000, 0x0000,
294 663e8e51 ths
    /* MDI Registers 8 - 15 */
295 663e8e51 ths
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
296 663e8e51 ths
    /* MDI Registers 16 - 31 */
297 663e8e51 ths
    0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
298 663e8e51 ths
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
299 663e8e51 ths
};
300 663e8e51 ths
301 663e8e51 ths
/* Readonly mask for MDI (PHY) registers */
302 663e8e51 ths
static const uint16_t eepro100_mdi_mask[] = {
303 663e8e51 ths
    0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000,
304 663e8e51 ths
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
305 663e8e51 ths
    0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
306 663e8e51 ths
    0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
307 663e8e51 ths
};
308 663e8e51 ths
309 ba42b646 Stefan Weil
/* XXX: optimize */
310 ba42b646 Stefan Weil
static void stl_le_phys(target_phys_addr_t addr, uint32_t val)
311 ba42b646 Stefan Weil
{
312 ba42b646 Stefan Weil
    val = cpu_to_le32(val);
313 ba42b646 Stefan Weil
    cpu_physical_memory_write(addr, (const uint8_t *)&val, sizeof(val));
314 ba42b646 Stefan Weil
}
315 ba42b646 Stefan Weil
316 663e8e51 ths
#define POLYNOMIAL 0x04c11db6
317 663e8e51 ths
318 663e8e51 ths
/* From FreeBSD */
319 663e8e51 ths
/* XXX: optimize */
320 7b8737de Stefan Weil
static unsigned compute_mcast_idx(const uint8_t * ep)
321 663e8e51 ths
{
322 663e8e51 ths
    uint32_t crc;
323 663e8e51 ths
    int carry, i, j;
324 663e8e51 ths
    uint8_t b;
325 663e8e51 ths
326 663e8e51 ths
    crc = 0xffffffff;
327 663e8e51 ths
    for (i = 0; i < 6; i++) {
328 663e8e51 ths
        b = *ep++;
329 663e8e51 ths
        for (j = 0; j < 8; j++) {
330 663e8e51 ths
            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
331 663e8e51 ths
            crc <<= 1;
332 663e8e51 ths
            b >>= 1;
333 aac443e6 Stefan Weil
            if (carry) {
334 663e8e51 ths
                crc = ((crc ^ POLYNOMIAL) | carry);
335 aac443e6 Stefan Weil
            }
336 663e8e51 ths
        }
337 663e8e51 ths
    }
338 7b8737de Stefan Weil
    return (crc & BITS(7, 2)) >> 2;
339 663e8e51 ths
}
340 663e8e51 ths
341 663e8e51 ths
#if defined(DEBUG_EEPRO100)
342 663e8e51 ths
static const char *nic_dump(const uint8_t * buf, unsigned size)
343 663e8e51 ths
{
344 663e8e51 ths
    static char dump[3 * 16 + 1];
345 663e8e51 ths
    char *p = &dump[0];
346 aac443e6 Stefan Weil
    if (size > 16) {
347 663e8e51 ths
        size = 16;
348 aac443e6 Stefan Weil
    }
349 663e8e51 ths
    while (size-- > 0) {
350 663e8e51 ths
        p += sprintf(p, " %02x", *buf++);
351 663e8e51 ths
    }
352 663e8e51 ths
    return dump;
353 663e8e51 ths
}
354 663e8e51 ths
#endif                          /* DEBUG_EEPRO100 */
355 663e8e51 ths
356 663e8e51 ths
enum scb_stat_ack {
357 663e8e51 ths
    stat_ack_not_ours = 0x00,
358 663e8e51 ths
    stat_ack_sw_gen = 0x04,
359 663e8e51 ths
    stat_ack_rnr = 0x10,
360 663e8e51 ths
    stat_ack_cu_idle = 0x20,
361 663e8e51 ths
    stat_ack_frame_rx = 0x40,
362 663e8e51 ths
    stat_ack_cu_cmd_done = 0x80,
363 663e8e51 ths
    stat_ack_not_present = 0xFF,
364 663e8e51 ths
    stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx),
365 663e8e51 ths
    stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done),
366 663e8e51 ths
};
367 663e8e51 ths
368 663e8e51 ths
static void disable_interrupt(EEPRO100State * s)
369 663e8e51 ths
{
370 663e8e51 ths
    if (s->int_stat) {
371 aac443e6 Stefan Weil
        TRACE(INT, logout("interrupt disabled\n"));
372 273a2142 Juan Quintela
        qemu_irq_lower(s->dev.irq[0]);
373 663e8e51 ths
        s->int_stat = 0;
374 663e8e51 ths
    }
375 663e8e51 ths
}
376 663e8e51 ths
377 663e8e51 ths
static void enable_interrupt(EEPRO100State * s)
378 663e8e51 ths
{
379 663e8e51 ths
    if (!s->int_stat) {
380 aac443e6 Stefan Weil
        TRACE(INT, logout("interrupt enabled\n"));
381 273a2142 Juan Quintela
        qemu_irq_raise(s->dev.irq[0]);
382 663e8e51 ths
        s->int_stat = 1;
383 663e8e51 ths
    }
384 663e8e51 ths
}
385 663e8e51 ths
386 663e8e51 ths
static void eepro100_acknowledge(EEPRO100State * s)
387 663e8e51 ths
{
388 663e8e51 ths
    s->scb_stat &= ~s->mem[SCBAck];
389 663e8e51 ths
    s->mem[SCBAck] = s->scb_stat;
390 663e8e51 ths
    if (s->scb_stat == 0) {
391 663e8e51 ths
        disable_interrupt(s);
392 663e8e51 ths
    }
393 663e8e51 ths
}
394 663e8e51 ths
395 e715c8e8 Stefan Weil
static void eepro100_interrupt(EEPRO100State * s, uint8_t status)
396 663e8e51 ths
{
397 663e8e51 ths
    uint8_t mask = ~s->mem[SCBIntmask];
398 e715c8e8 Stefan Weil
    s->mem[SCBAck] |= status;
399 e715c8e8 Stefan Weil
    status = s->scb_stat = s->mem[SCBAck];
400 e715c8e8 Stefan Weil
    status &= (mask | 0x0f);
401 e715c8e8 Stefan Weil
    //~ status &= (~s->mem[SCBIntmask] | 0x0xf);
402 e715c8e8 Stefan Weil
    if (status && (mask & 0x01)) {
403 663e8e51 ths
        /* SCB mask and SCB Bit M do not disable interrupt. */
404 663e8e51 ths
        enable_interrupt(s);
405 663e8e51 ths
    } else if (s->int_stat) {
406 663e8e51 ths
        disable_interrupt(s);
407 663e8e51 ths
    }
408 663e8e51 ths
}
409 663e8e51 ths
410 663e8e51 ths
static void eepro100_cx_interrupt(EEPRO100State * s)
411 663e8e51 ths
{
412 663e8e51 ths
    /* CU completed action command. */
413 663e8e51 ths
    /* Transmit not ok (82557 only, not in emulation). */
414 663e8e51 ths
    eepro100_interrupt(s, 0x80);
415 663e8e51 ths
}
416 663e8e51 ths
417 663e8e51 ths
static void eepro100_cna_interrupt(EEPRO100State * s)
418 663e8e51 ths
{
419 663e8e51 ths
    /* CU left the active state. */
420 663e8e51 ths
    eepro100_interrupt(s, 0x20);
421 663e8e51 ths
}
422 663e8e51 ths
423 663e8e51 ths
static void eepro100_fr_interrupt(EEPRO100State * s)
424 663e8e51 ths
{
425 663e8e51 ths
    /* RU received a complete frame. */
426 663e8e51 ths
    eepro100_interrupt(s, 0x40);
427 663e8e51 ths
}
428 663e8e51 ths
429 663e8e51 ths
static void eepro100_rnr_interrupt(EEPRO100State * s)
430 663e8e51 ths
{
431 663e8e51 ths
    /* RU is not ready. */
432 663e8e51 ths
    eepro100_interrupt(s, 0x10);
433 663e8e51 ths
}
434 663e8e51 ths
435 663e8e51 ths
static void eepro100_mdi_interrupt(EEPRO100State * s)
436 663e8e51 ths
{
437 663e8e51 ths
    /* MDI completed read or write cycle. */
438 663e8e51 ths
    eepro100_interrupt(s, 0x08);
439 663e8e51 ths
}
440 663e8e51 ths
441 663e8e51 ths
static void eepro100_swi_interrupt(EEPRO100State * s)
442 663e8e51 ths
{
443 663e8e51 ths
    /* Software has requested an interrupt. */
444 663e8e51 ths
    eepro100_interrupt(s, 0x04);
445 663e8e51 ths
}
446 663e8e51 ths
447 663e8e51 ths
#if 0
448 663e8e51 ths
static void eepro100_fcp_interrupt(EEPRO100State * s)
449 663e8e51 ths
{
450 663e8e51 ths
    /* Flow control pause interrupt (82558 and later). */
451 663e8e51 ths
    eepro100_interrupt(s, 0x01);
452 663e8e51 ths
}
453 663e8e51 ths
#endif
454 663e8e51 ths
455 663e8e51 ths
static void pci_reset(EEPRO100State * s)
456 663e8e51 ths
{
457 663e8e51 ths
    uint32_t device = s->device;
458 273a2142 Juan Quintela
    uint8_t *pci_conf = s->dev.config;
459 ba42b646 Stefan Weil
    bool power_management = 1;
460 663e8e51 ths
461 aac443e6 Stefan Weil
    TRACE(OTHER, logout("%p\n", s));
462 663e8e51 ths
463 663e8e51 ths
    /* PCI Vendor ID */
464 deb54399 aliguori
    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
465 d6fd1e66 Stefan Weil
    /* PCI Device ID depends on device and is set below. */
466 663e8e51 ths
    /* PCI Command */
467 508cc6b4 Michael S. Tsirkin
    /* TODO: this is the default, do not override. */
468 663e8e51 ths
    PCI_CONFIG_16(PCI_COMMAND, 0x0000);
469 663e8e51 ths
    /* PCI Status */
470 508cc6b4 Michael S. Tsirkin
    /* TODO: Value at RST# should be 0. */
471 61702408 Stefan Weil
    PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_FAST_BACK);
472 663e8e51 ths
    /* PCI Revision ID */
473 663e8e51 ths
    PCI_CONFIG_8(PCI_REVISION_ID, 0x08);
474 508cc6b4 Michael S. Tsirkin
    /* TODO: this is the default, do not override. */
475 663e8e51 ths
    /* PCI Class Code */
476 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_CLASS_PROG, 0x00);
477 173a543b blueswir1
    pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
478 663e8e51 ths
    /* PCI Cache Line Size */
479 663e8e51 ths
    /* check cache line size!!! */
480 663e8e51 ths
    //~ PCI_CONFIG_8(0x0c, 0x00);
481 663e8e51 ths
    /* PCI Latency Timer */
482 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_LATENCY_TIMER, 0x20);   // latency timer = 32 clocks
483 663e8e51 ths
    /* PCI Header Type */
484 663e8e51 ths
    /* BIST (built-in self test) */
485 663e8e51 ths
    /* Expansion ROM Base Address (depends on boot disable!!!) */
486 508cc6b4 Michael S. Tsirkin
    /* TODO: not needed, set when BAR is registered */
487 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_32(PCI_ROM_ADDRESS, PCI_BASE_ADDRESS_SPACE_MEMORY);
488 663e8e51 ths
    /* Capability Pointer */
489 508cc6b4 Michael S. Tsirkin
    /* TODO: revisions with power_management 1 use this but
490 508cc6b4 Michael S. Tsirkin
     * do not set new capability list bit in status register. */
491 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_CAPABILITY_LIST, 0xdc);
492 aac443e6 Stefan Weil
    /* Interrupt Line */
493 663e8e51 ths
    /* Interrupt Pin */
494 508cc6b4 Michael S. Tsirkin
    /* TODO: RST# value should be 0 */
495 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_INTERRUPT_PIN, 1);      // interrupt pin 0
496 663e8e51 ths
    /* Minimum Grant */
497 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_MIN_GNT, 0x08);
498 663e8e51 ths
    /* Maximum Latency */
499 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_MAX_LAT, 0x18);
500 663e8e51 ths
501 663e8e51 ths
    switch (device) {
502 ba42b646 Stefan Weil
    case i82550:
503 ba42b646 Stefan Weil
        // TODO: check device id.
504 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82551IT);
505 ba42b646 Stefan Weil
        /* Revision ID: 0x0c, 0x0d, 0x0e. */
506 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x0e);
507 ba42b646 Stefan Weil
        // TODO: check size of statistical counters.
508 ba42b646 Stefan Weil
        s->stats_size = 80;
509 ba42b646 Stefan Weil
        // TODO: check extended tcb support.
510 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
511 ba42b646 Stefan Weil
        break;
512 663e8e51 ths
    case i82551:
513 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82551IT);
514 ba42b646 Stefan Weil
        /* Revision ID: 0x0f, 0x10. */
515 663e8e51 ths
        PCI_CONFIG_8(PCI_REVISION_ID, 0x0f);
516 ba42b646 Stefan Weil
        // TODO: check size of statistical counters.
517 ba42b646 Stefan Weil
        s->stats_size = 80;
518 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
519 ba42b646 Stefan Weil
        break;
520 ba42b646 Stefan Weil
    case i82557A:
521 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
522 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x01);
523 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_8(PCI_CAPABILITY_LIST, 0x00);
524 ba42b646 Stefan Weil
        power_management = 0;
525 663e8e51 ths
        break;
526 663e8e51 ths
    case i82557B:
527 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
528 663e8e51 ths
        PCI_CONFIG_8(PCI_REVISION_ID, 0x02);
529 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_8(PCI_CAPABILITY_LIST, 0x00);
530 ba42b646 Stefan Weil
        power_management = 0;
531 663e8e51 ths
        break;
532 663e8e51 ths
    case i82557C:
533 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
534 663e8e51 ths
        PCI_CONFIG_8(PCI_REVISION_ID, 0x03);
535 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_8(PCI_CAPABILITY_LIST, 0x00);
536 ba42b646 Stefan Weil
        power_management = 0;
537 ba42b646 Stefan Weil
        break;
538 ba42b646 Stefan Weil
    case i82558A:
539 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
540 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
541 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
542 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x04);
543 ba42b646 Stefan Weil
        s->stats_size = 76;
544 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
545 663e8e51 ths
        break;
546 663e8e51 ths
    case i82558B:
547 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
548 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
549 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
550 663e8e51 ths
        PCI_CONFIG_8(PCI_REVISION_ID, 0x05);
551 ba42b646 Stefan Weil
        s->stats_size = 76;
552 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
553 ba42b646 Stefan Weil
        break;
554 ba42b646 Stefan Weil
    case i82559A:
555 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
556 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
557 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
558 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x06);
559 ba42b646 Stefan Weil
        s->stats_size = 80;
560 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
561 ba42b646 Stefan Weil
        break;
562 ba42b646 Stefan Weil
    case i82559B:
563 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
564 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
565 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
566 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x07);
567 ba42b646 Stefan Weil
        s->stats_size = 80;
568 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
569 663e8e51 ths
        break;
570 663e8e51 ths
    case i82559C:
571 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
572 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
573 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
574 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x08);
575 ba42b646 Stefan Weil
        // TODO: Windows wants revision id 0x0c.
576 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x0c);
577 ba42b646 Stefan Weil
#if EEPROM_SIZE > 0
578 ba42b646 Stefan Weil
        PCI_CONFIG_16(PCI_SUBSYSTEM_VENDOR_ID, 0x8086);
579 ba42b646 Stefan Weil
        PCI_CONFIG_16(PCI_SUBSYSTEM_ID, 0x0040);
580 ba42b646 Stefan Weil
#endif
581 ba42b646 Stefan Weil
        s->stats_size = 80;
582 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
583 663e8e51 ths
        break;
584 663e8e51 ths
    case i82559ER:
585 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82551IT);
586 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
587 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
588 663e8e51 ths
        PCI_CONFIG_8(PCI_REVISION_ID, 0x09);
589 ba42b646 Stefan Weil
        s->stats_size = 80;
590 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
591 ba42b646 Stefan Weil
        break;
592 ba42b646 Stefan Weil
    case i82562:
593 ba42b646 Stefan Weil
        // TODO: check device id.
594 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82551IT);
595 ba42b646 Stefan Weil
        /* TODO: wrong revision id. */
596 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x0e);
597 ba42b646 Stefan Weil
        s->stats_size = 80;
598 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
599 663e8e51 ths
        break;
600 663e8e51 ths
    default:
601 663e8e51 ths
        logout("Device %X is undefined!\n", device);
602 663e8e51 ths
    }
603 663e8e51 ths
604 ba42b646 Stefan Weil
    s->configuration[6] |= BIT(5);
605 ba42b646 Stefan Weil
606 ba42b646 Stefan Weil
    if (s->stats_size == 80) {
607 ba42b646 Stefan Weil
        /* TODO: check TCO Statistical Counters bit. Documentation not clear. */
608 ba42b646 Stefan Weil
        if (s->configuration[6] & BIT(2)) {
609 ba42b646 Stefan Weil
            /* TCO statistical counters. */
610 ba42b646 Stefan Weil
            assert(s->configuration[6] & BIT(5));
611 ba42b646 Stefan Weil
        } else {
612 ba42b646 Stefan Weil
            if (s->configuration[6] & BIT(5)) {
613 ba42b646 Stefan Weil
                /* No extended statistical counters, i82557 compatible. */
614 ba42b646 Stefan Weil
                s->stats_size = 64;
615 ba42b646 Stefan Weil
            } else {
616 ba42b646 Stefan Weil
                /* i82558 compatible. */
617 ba42b646 Stefan Weil
                s->stats_size = 76;
618 ba42b646 Stefan Weil
            }
619 ba42b646 Stefan Weil
        }
620 ba42b646 Stefan Weil
    } else {
621 ba42b646 Stefan Weil
        if (s->configuration[6] & BIT(5)) {
622 ba42b646 Stefan Weil
            /* No extended statistical counters. */
623 ba42b646 Stefan Weil
            s->stats_size = 64;
624 ba42b646 Stefan Weil
        }
625 ba42b646 Stefan Weil
    }
626 ba42b646 Stefan Weil
    assert(s->stats_size > 0 && s->stats_size <= sizeof(s->statistics));
627 ba42b646 Stefan Weil
628 ba42b646 Stefan Weil
    if (power_management) {
629 ba42b646 Stefan Weil
        /* Power Management Capabilities */
630 ba42b646 Stefan Weil
        PCI_CONFIG_8(0xdc, 0x01);
631 ba42b646 Stefan Weil
        /* Next Item Pointer */
632 ba42b646 Stefan Weil
        /* Capability ID */
633 ba42b646 Stefan Weil
        PCI_CONFIG_16(0xde, 0x7e21);
634 ba42b646 Stefan Weil
        /* TODO: Power Management Control / Status. */
635 ba42b646 Stefan Weil
        /* TODO: Ethernet Power Consumption Registers (i82559 and later). */
636 ba42b646 Stefan Weil
    }
637 ba42b646 Stefan Weil
638 ba42b646 Stefan Weil
#if EEPROM_SIZE > 0
639 663e8e51 ths
    if (device == i82557C || device == i82558B || device == i82559C) {
640 ba42b646 Stefan Weil
        // TODO: get vendor id from EEPROM for i82557C or later.
641 ba42b646 Stefan Weil
        // TODO: get device id from EEPROM for i82557C or later.
642 ba42b646 Stefan Weil
        // TODO: status bit 4 can be disabled by EEPROM for i82558, i82559.
643 ba42b646 Stefan Weil
        // TODO: header type is determined by EEPROM for i82559.
644 ba42b646 Stefan Weil
        // TODO: get subsystem id from EEPROM for i82557C or later.
645 ba42b646 Stefan Weil
        // TODO: get subsystem vendor id from EEPROM for i82557C or later.
646 ba42b646 Stefan Weil
        // TODO: exp. rom baddr depends on a bit in EEPROM for i82558 or later.
647 ba42b646 Stefan Weil
        // TODO: capability pointer depends on EEPROM for i82558.
648 663e8e51 ths
        logout("Get device id and revision from EEPROM!!!\n");
649 663e8e51 ths
    }
650 ba42b646 Stefan Weil
#endif /* EEPROM_SIZE > 0 */
651 663e8e51 ths
}
652 663e8e51 ths
653 663e8e51 ths
static void nic_selective_reset(EEPRO100State * s)
654 663e8e51 ths
{
655 663e8e51 ths
    size_t i;
656 663e8e51 ths
    uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom);
657 663e8e51 ths
    //~ eeprom93xx_reset(s->eeprom);
658 508ef936 Gerd Hoffmann
    memcpy(eeprom_contents, s->conf.macaddr.a, 6);
659 b1e87018 Stefan Weil
    eeprom_contents[EEPROM_ID] = EEPROM_ID_VALID;
660 f4e94dfe =?UTF-8?q?Reimar=20D=C3=B6ffinger?=
    if (s->device == i82557B || s->device == i82557C)
661 f4e94dfe =?UTF-8?q?Reimar=20D=C3=B6ffinger?=
        eeprom_contents[5] = 0x0100;
662 6cded3a4 Stefan Weil
    eeprom_contents[EEPROM_PHY_ID] = 1;
663 663e8e51 ths
    uint16_t sum = 0;
664 663e8e51 ths
    for (i = 0; i < EEPROM_SIZE - 1; i++) {
665 663e8e51 ths
        sum += eeprom_contents[i];
666 663e8e51 ths
    }
667 663e8e51 ths
    eeprom_contents[EEPROM_SIZE - 1] = 0xbaba - sum;
668 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("checksum=0x%04x\n", eeprom_contents[EEPROM_SIZE - 1]));
669 663e8e51 ths
670 663e8e51 ths
    memset(s->mem, 0, sizeof(s->mem));
671 663e8e51 ths
    uint32_t val = BIT(21);
672 663e8e51 ths
    memcpy(&s->mem[SCBCtrlMDI], &val, sizeof(val));
673 663e8e51 ths
674 663e8e51 ths
    assert(sizeof(s->mdimem) == sizeof(eepro100_mdi_default));
675 663e8e51 ths
    memcpy(&s->mdimem[0], &eepro100_mdi_default[0], sizeof(s->mdimem));
676 663e8e51 ths
}
677 663e8e51 ths
678 663e8e51 ths
static void nic_reset(void *opaque)
679 663e8e51 ths
{
680 769cf7a5 Juan Quintela
    EEPRO100State *s = opaque;
681 aac443e6 Stefan Weil
    TRACE(OTHER, logout("%p\n", s));
682 7b8737de Stefan Weil
    /* TODO: Clearing of multicast table for selective reset, too? */
683 7b8737de Stefan Weil
    memset(&s->mult[0], 0, sizeof(s->mult));
684 663e8e51 ths
    nic_selective_reset(s);
685 663e8e51 ths
}
686 663e8e51 ths
687 663e8e51 ths
#if defined(DEBUG_EEPRO100)
688 b8f6ba0d Stefan Weil
static const char * const e100_reg[PCI_IO_SIZE / 4] = {
689 663e8e51 ths
    "Command/Status",
690 663e8e51 ths
    "General Pointer",
691 663e8e51 ths
    "Port",
692 663e8e51 ths
    "EEPROM/Flash Control",
693 663e8e51 ths
    "MDI Control",
694 663e8e51 ths
    "Receive DMA Byte Count",
695 b8f6ba0d Stefan Weil
    "Flow Control",
696 663e8e51 ths
    "General Status/Control"
697 663e8e51 ths
};
698 663e8e51 ths
699 663e8e51 ths
static char *regname(uint32_t addr)
700 663e8e51 ths
{
701 ec169288 David Benjamin
    static char buf[32];
702 663e8e51 ths
    if (addr < PCI_IO_SIZE) {
703 b8f6ba0d Stefan Weil
        const char *r = e100_reg[addr / 4];
704 663e8e51 ths
        if (r != 0) {
705 41cbc23c Stefan Weil
            snprintf(buf, sizeof(buf), "%s+%u", r, addr % 4);
706 663e8e51 ths
        } else {
707 41cbc23c Stefan Weil
            snprintf(buf, sizeof(buf), "0x%02x", addr);
708 663e8e51 ths
        }
709 663e8e51 ths
    } else {
710 41cbc23c Stefan Weil
        snprintf(buf, sizeof(buf), "??? 0x%08x", addr);
711 663e8e51 ths
    }
712 663e8e51 ths
    return buf;
713 663e8e51 ths
}
714 663e8e51 ths
#endif                          /* DEBUG_EEPRO100 */
715 663e8e51 ths
716 663e8e51 ths
#if 0
717 663e8e51 ths
static uint16_t eepro100_read_status(EEPRO100State * s)
718 663e8e51 ths
{
719 663e8e51 ths
    uint16_t val = s->status;
720 aac443e6 Stefan Weil
    TRACE(OTHER, logout("val=0x%04x\n", val));
721 663e8e51 ths
    return val;
722 663e8e51 ths
}
723 663e8e51 ths

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