Statistics
| Branch: | Revision:

root / hw / eepro100.c @ 3fd3d0b4

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