Statistics
| Branch: | Revision:

root / hw / eepro100.c @ e74818f3

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