Statistics
| Branch: | Revision:

root / hw / eepro100.c @ 3b4b86aa

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

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