Statistics
| Branch: | Revision:

root / hw / eepro100.c @ c557e889

History | View | Annotate | Download (70.9 kB)

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