Statistics
| Branch: | Revision:

root / hw / eepro100.c @ 5ee8ad71

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