Statistics
| Branch: | Revision:

root / hw / eepro100.c @ ad03502b

History | View | Annotate | Download (70.7 kB)

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