Statistics
| Branch: | Revision:

root / hw / eepro100.c @ bc20ba98

History | View | Annotate | Download (65.7 kB)

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