Statistics
| Branch: | Revision:

root / hw / eepro100.c @ 81b1008d

History | View | Annotate | Download (68.1 kB)

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