Statistics
| Branch: | Revision:

root / hw / eepro100.c @ 0f921197

History | View | Annotate | Download (67.6 kB)

1 663e8e51 ths
/*
2 663e8e51 ths
 * QEMU i8255x (PRO100) emulation
3 663e8e51 ths
 *
4 663e8e51 ths
 * Copyright (c) 2006-2007 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 663e8e51 ths
 * 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 663e8e51 ths
 * the Free Software Foundation; either version 2 of the License, or
12 663e8e51 ths
 * (at your option) 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 8167ee88 Blue Swirl
 * along with this program; if not, see <http://www.gnu.org/licenses/>.
21 663e8e51 ths
 *
22 663e8e51 ths
 * Tested features (i82559):
23 663e8e51 ths
 *      PXE boot (i386) no valid link
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 663e8e51 ths
 */
35 663e8e51 ths
36 663e8e51 ths
#if defined(TARGET_I386)
37 663e8e51 ths
# warning "PXE boot still not working!"
38 663e8e51 ths
#endif
39 663e8e51 ths
40 663e8e51 ths
#include <stddef.h>             /* offsetof */
41 b84a5c6f Amit Shah
#include <stdbool.h>
42 87ecb68b pbrook
#include "hw.h"
43 87ecb68b pbrook
#include "pci.h"
44 87ecb68b pbrook
#include "net.h"
45 663e8e51 ths
#include "eeprom93xx.h"
46 663e8e51 ths
47 663e8e51 ths
/* Common declarations for all PCI devices. */
48 663e8e51 ths
49 663e8e51 ths
#define PCI_CONFIG_8(offset, value) \
50 663e8e51 ths
    (pci_conf[offset] = (value))
51 663e8e51 ths
#define PCI_CONFIG_16(offset, value) \
52 663e8e51 ths
    (*(uint16_t *)&pci_conf[offset] = cpu_to_le16(value))
53 663e8e51 ths
#define PCI_CONFIG_32(offset, value) \
54 663e8e51 ths
    (*(uint32_t *)&pci_conf[offset] = cpu_to_le32(value))
55 663e8e51 ths
56 663e8e51 ths
#define KiB 1024
57 663e8e51 ths
58 aac443e6 Stefan Weil
/* Debug EEPRO100 card. */
59 663e8e51 ths
//~ #define DEBUG_EEPRO100
60 663e8e51 ths
61 663e8e51 ths
#ifdef DEBUG_EEPRO100
62 001faf32 Blue Swirl
#define logout(fmt, ...) fprintf(stderr, "EE100\t%-24s" fmt, __func__, ## __VA_ARGS__)
63 663e8e51 ths
#else
64 001faf32 Blue Swirl
#define logout(fmt, ...) ((void)0)
65 663e8e51 ths
#endif
66 663e8e51 ths
67 663e8e51 ths
/* Set flags to 0 to disable debug output. */
68 aac443e6 Stefan Weil
#define INT     1       /* interrupt related actions */
69 aac443e6 Stefan Weil
#define MDI     1       /* mdi related actions */
70 aac443e6 Stefan Weil
#define OTHER   1
71 aac443e6 Stefan Weil
#define RXTX    1
72 aac443e6 Stefan Weil
#define EEPROM  1       /* eeprom related actions */
73 663e8e51 ths
74 663e8e51 ths
#define TRACE(flag, command) ((flag) ? (command) : (void)0)
75 663e8e51 ths
76 7f1e9d4e Kevin Wolf
#define missing(text) fprintf(stderr, "eepro100: feature is missing in this emulation: " text "\n")
77 663e8e51 ths
78 663e8e51 ths
#define MAX_ETH_FRAME_SIZE 1514
79 663e8e51 ths
80 663e8e51 ths
/* This driver supports several different devices which are declared here. */
81 c4c270e2 Stefan Weil
#define i82550          0x82550
82 663e8e51 ths
#define i82551          0x82551
83 c4c270e2 Stefan Weil
#define i82557A         0x82557a
84 663e8e51 ths
#define i82557B         0x82557b
85 663e8e51 ths
#define i82557C         0x82557c
86 c4c270e2 Stefan Weil
#define i82558A         0x82558a
87 663e8e51 ths
#define i82558B         0x82558b
88 c4c270e2 Stefan Weil
#define i82559A         0x82559a
89 c4c270e2 Stefan Weil
#define i82559B         0x82559b
90 663e8e51 ths
#define i82559C         0x82559c
91 663e8e51 ths
#define i82559ER        0x82559e
92 663e8e51 ths
#define i82562          0x82562
93 663e8e51 ths
94 aac443e6 Stefan Weil
/* Use 64 word EEPROM. TODO: could be a runtime option. */
95 663e8e51 ths
#define EEPROM_SIZE     64
96 663e8e51 ths
97 663e8e51 ths
#define PCI_MEM_SIZE            (4 * KiB)
98 663e8e51 ths
#define PCI_IO_SIZE             64
99 663e8e51 ths
#define PCI_FLASH_SIZE          (128 * KiB)
100 663e8e51 ths
101 663e8e51 ths
#define BIT(n) (1 << (n))
102 663e8e51 ths
#define BITS(n, m) (((0xffffffffU << (31 - n)) >> (31 - n + m)) << m)
103 663e8e51 ths
104 663e8e51 ths
/* The SCB accepts the following controls for the Tx and Rx units: */
105 663e8e51 ths
#define  CU_NOP         0x0000  /* No operation. */
106 663e8e51 ths
#define  CU_START       0x0010  /* CU start. */
107 663e8e51 ths
#define  CU_RESUME      0x0020  /* CU resume. */
108 663e8e51 ths
#define  CU_STATSADDR   0x0040  /* Load dump counters address. */
109 663e8e51 ths
#define  CU_SHOWSTATS   0x0050  /* Dump statistical counters. */
110 663e8e51 ths
#define  CU_CMD_BASE    0x0060  /* Load CU base address. */
111 663e8e51 ths
#define  CU_DUMPSTATS   0x0070  /* Dump and reset statistical counters. */
112 663e8e51 ths
#define  CU_SRESUME     0x00a0  /* CU static resume. */
113 663e8e51 ths
114 663e8e51 ths
#define  RU_NOP         0x0000
115 663e8e51 ths
#define  RX_START       0x0001
116 663e8e51 ths
#define  RX_RESUME      0x0002
117 663e8e51 ths
#define  RX_ABORT       0x0004
118 663e8e51 ths
#define  RX_ADDR_LOAD   0x0006
119 663e8e51 ths
#define  RX_RESUMENR    0x0007
120 663e8e51 ths
#define INT_MASK        0x0100
121 663e8e51 ths
#define DRVR_INT        0x0200  /* Driver generated interrupt. */
122 663e8e51 ths
123 663e8e51 ths
/* Offsets to the various registers.
124 663e8e51 ths
   All accesses need not be longword aligned. */
125 663e8e51 ths
enum speedo_offsets {
126 663e8e51 ths
    SCBStatus = 0,
127 663e8e51 ths
    SCBAck = 1,
128 663e8e51 ths
    SCBCmd = 2,                 /* Rx/Command Unit command and status. */
129 663e8e51 ths
    SCBIntmask = 3,
130 663e8e51 ths
    SCBPointer = 4,             /* General purpose pointer. */
131 663e8e51 ths
    SCBPort = 8,                /* Misc. commands and operands.  */
132 663e8e51 ths
    SCBflash = 12, SCBeeprom = 14,      /* EEPROM and flash memory control. */
133 663e8e51 ths
    SCBCtrlMDI = 16,            /* MDI interface control. */
134 663e8e51 ths
    SCBEarlyRx = 20,            /* Early receive byte count. */
135 3257d2b6 ths
    SCBFlow = 24,
136 663e8e51 ths
};
137 663e8e51 ths
138 663e8e51 ths
/* A speedo3 transmit buffer descriptor with two buffers... */
139 663e8e51 ths
typedef struct {
140 663e8e51 ths
    uint16_t status;
141 663e8e51 ths
    uint16_t command;
142 663e8e51 ths
    uint32_t link;              /* void * */
143 7b8737de Stefan Weil
    uint32_t tbd_array_addr;    /* transmit buffer descriptor array address. */
144 663e8e51 ths
    uint16_t tcb_bytes;         /* transmit command block byte count (in lower 14 bits */
145 663e8e51 ths
    uint8_t tx_threshold;       /* transmit threshold */
146 663e8e51 ths
    uint8_t tbd_count;          /* TBD number */
147 663e8e51 ths
    //~ /* This constitutes two "TBD" entries: hdr and data */
148 663e8e51 ths
    //~ uint32_t tx_buf_addr0;  /* void *, header of frame to be transmitted.  */
149 663e8e51 ths
    //~ int32_t  tx_buf_size0;  /* Length of Tx hdr. */
150 663e8e51 ths
    //~ uint32_t tx_buf_addr1;  /* void *, data to be transmitted.  */
151 663e8e51 ths
    //~ int32_t  tx_buf_size1;  /* Length of Tx data. */
152 c227f099 Anthony Liguori
} eepro100_tx_t;
153 663e8e51 ths
154 663e8e51 ths
/* Receive frame descriptor. */
155 663e8e51 ths
typedef struct {
156 663e8e51 ths
    int16_t status;
157 663e8e51 ths
    uint16_t command;
158 663e8e51 ths
    uint32_t link;              /* struct RxFD * */
159 663e8e51 ths
    uint32_t rx_buf_addr;       /* void * */
160 663e8e51 ths
    uint16_t count;
161 663e8e51 ths
    uint16_t size;
162 663e8e51 ths
    char packet[MAX_ETH_FRAME_SIZE + 4];
163 c227f099 Anthony Liguori
} eepro100_rx_t;
164 663e8e51 ths
165 663e8e51 ths
typedef struct {
166 663e8e51 ths
    uint32_t tx_good_frames, tx_max_collisions, tx_late_collisions,
167 663e8e51 ths
        tx_underruns, tx_lost_crs, tx_deferred, tx_single_collisions,
168 663e8e51 ths
        tx_multiple_collisions, tx_total_collisions;
169 663e8e51 ths
    uint32_t rx_good_frames, rx_crc_errors, rx_alignment_errors,
170 663e8e51 ths
        rx_resource_errors, rx_overrun_errors, rx_cdt_errors,
171 663e8e51 ths
        rx_short_frame_errors;
172 663e8e51 ths
    uint32_t fc_xmt_pause, fc_rcv_pause, fc_rcv_unsupported;
173 663e8e51 ths
    uint16_t xmt_tco_frames, rcv_tco_frames;
174 ba42b646 Stefan Weil
    /* TODO: i82559 has six reserved statistics but a total of 24 dwords. */
175 ba42b646 Stefan Weil
    uint32_t reserved[4];
176 c227f099 Anthony Liguori
} eepro100_stats_t;
177 663e8e51 ths
178 663e8e51 ths
typedef enum {
179 663e8e51 ths
    cu_idle = 0,
180 663e8e51 ths
    cu_suspended = 1,
181 663e8e51 ths
    cu_active = 2,
182 663e8e51 ths
    cu_lpq_active = 2,
183 663e8e51 ths
    cu_hqp_active = 3
184 c227f099 Anthony Liguori
} cu_state_t;
185 663e8e51 ths
186 663e8e51 ths
typedef enum {
187 663e8e51 ths
    ru_idle = 0,
188 663e8e51 ths
    ru_suspended = 1,
189 663e8e51 ths
    ru_no_resources = 2,
190 663e8e51 ths
    ru_ready = 4
191 c227f099 Anthony Liguori
} ru_state_t;
192 663e8e51 ths
193 663e8e51 ths
typedef struct {
194 273a2142 Juan Quintela
    PCIDevice dev;
195 663e8e51 ths
    uint8_t mult[8];            /* multicast mask array */
196 663e8e51 ths
    int mmio_index;
197 e00e365e Mark McLoughlin
    NICState *nic;
198 508ef936 Gerd Hoffmann
    NICConf conf;
199 663e8e51 ths
    uint8_t scb_stat;           /* SCB stat/ack byte */
200 663e8e51 ths
    uint8_t int_stat;           /* PCI interrupt status */
201 3706c43f Stefan Weil
    /* region must not be saved by nic_save. */
202 663e8e51 ths
    uint32_t region[3];         /* PCI region addresses */
203 663e8e51 ths
    uint16_t mdimem[32];
204 c227f099 Anthony Liguori
    eeprom_t *eeprom;
205 663e8e51 ths
    uint32_t device;            /* device variant */
206 663e8e51 ths
    uint32_t pointer;
207 663e8e51 ths
    /* (cu_base + cu_offset) address the next command block in the command block list. */
208 663e8e51 ths
    uint32_t cu_base;           /* CU base address */
209 663e8e51 ths
    uint32_t cu_offset;         /* CU address offset */
210 663e8e51 ths
    /* (ru_base + ru_offset) address the RFD in the Receive Frame Area. */
211 663e8e51 ths
    uint32_t ru_base;           /* RU base address */
212 663e8e51 ths
    uint32_t ru_offset;         /* RU address offset */
213 c227f099 Anthony Liguori
    uint32_t statsaddr;         /* pointer to eepro100_stats_t */
214 ba42b646 Stefan Weil
215 f3a52e50 Stefan Weil
    /* Temporary status information (no need to save these values),
216 f3a52e50 Stefan Weil
     * used while processing CU commands. */
217 f3a52e50 Stefan Weil
    eepro100_tx_t tx;           /* transmit buffer descriptor */
218 f3a52e50 Stefan Weil
    uint32_t cb_address;        /* = cu_base + cu_offset */
219 f3a52e50 Stefan Weil
220 ba42b646 Stefan Weil
    /* Statistical counters. Also used for wake-up packet (i82559). */
221 ba42b646 Stefan Weil
    eepro100_stats_t statistics;
222 ba42b646 Stefan Weil
223 663e8e51 ths
#if 0
224 663e8e51 ths
    uint16_t status;
225 663e8e51 ths
#endif
226 663e8e51 ths
227 663e8e51 ths
    /* Configuration bytes. */
228 663e8e51 ths
    uint8_t configuration[22];
229 663e8e51 ths
230 663e8e51 ths
    /* Data in mem is always in the byte order of the controller (le). */
231 663e8e51 ths
    uint8_t mem[PCI_MEM_SIZE];
232 151b2986 Juan Quintela
    /* vmstate for each particular nic */
233 151b2986 Juan Quintela
    VMStateDescription *vmstate;
234 ba42b646 Stefan Weil
235 ba42b646 Stefan Weil
    /* Quasi static device properties (no need to save them). */
236 ba42b646 Stefan Weil
    uint16_t stats_size;
237 ba42b646 Stefan Weil
    bool has_extended_tcb_support;
238 663e8e51 ths
} EEPRO100State;
239 663e8e51 ths
240 663e8e51 ths
/* Default values for MDI (PHY) registers */
241 663e8e51 ths
static const uint16_t eepro100_mdi_default[] = {
242 663e8e51 ths
    /* MDI Registers 0 - 6, 7 */
243 663e8e51 ths
    0x3000, 0x780d, 0x02a8, 0x0154, 0x05e1, 0x0000, 0x0000, 0x0000,
244 663e8e51 ths
    /* MDI Registers 8 - 15 */
245 663e8e51 ths
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
246 663e8e51 ths
    /* MDI Registers 16 - 31 */
247 663e8e51 ths
    0x0003, 0x0000, 0x0001, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
248 663e8e51 ths
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
249 663e8e51 ths
};
250 663e8e51 ths
251 663e8e51 ths
/* Readonly mask for MDI (PHY) registers */
252 663e8e51 ths
static const uint16_t eepro100_mdi_mask[] = {
253 663e8e51 ths
    0x0000, 0xffff, 0xffff, 0xffff, 0xc01f, 0xffff, 0xffff, 0x0000,
254 663e8e51 ths
    0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
255 663e8e51 ths
    0x0fff, 0x0000, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff, 0xffff,
256 663e8e51 ths
    0xffff, 0xffff, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000, 0x0000,
257 663e8e51 ths
};
258 663e8e51 ths
259 ba42b646 Stefan Weil
/* XXX: optimize */
260 ba42b646 Stefan Weil
static void stl_le_phys(target_phys_addr_t addr, uint32_t val)
261 ba42b646 Stefan Weil
{
262 ba42b646 Stefan Weil
    val = cpu_to_le32(val);
263 ba42b646 Stefan Weil
    cpu_physical_memory_write(addr, (const uint8_t *)&val, sizeof(val));
264 ba42b646 Stefan Weil
}
265 ba42b646 Stefan Weil
266 663e8e51 ths
#define POLYNOMIAL 0x04c11db6
267 663e8e51 ths
268 663e8e51 ths
/* From FreeBSD */
269 663e8e51 ths
/* XXX: optimize */
270 7b8737de Stefan Weil
static unsigned compute_mcast_idx(const uint8_t * ep)
271 663e8e51 ths
{
272 663e8e51 ths
    uint32_t crc;
273 663e8e51 ths
    int carry, i, j;
274 663e8e51 ths
    uint8_t b;
275 663e8e51 ths
276 663e8e51 ths
    crc = 0xffffffff;
277 663e8e51 ths
    for (i = 0; i < 6; i++) {
278 663e8e51 ths
        b = *ep++;
279 663e8e51 ths
        for (j = 0; j < 8; j++) {
280 663e8e51 ths
            carry = ((crc & 0x80000000L) ? 1 : 0) ^ (b & 0x01);
281 663e8e51 ths
            crc <<= 1;
282 663e8e51 ths
            b >>= 1;
283 aac443e6 Stefan Weil
            if (carry) {
284 663e8e51 ths
                crc = ((crc ^ POLYNOMIAL) | carry);
285 aac443e6 Stefan Weil
            }
286 663e8e51 ths
        }
287 663e8e51 ths
    }
288 7b8737de Stefan Weil
    return (crc & BITS(7, 2)) >> 2;
289 663e8e51 ths
}
290 663e8e51 ths
291 663e8e51 ths
#if defined(DEBUG_EEPRO100)
292 663e8e51 ths
static const char *nic_dump(const uint8_t * buf, unsigned size)
293 663e8e51 ths
{
294 663e8e51 ths
    static char dump[3 * 16 + 1];
295 663e8e51 ths
    char *p = &dump[0];
296 aac443e6 Stefan Weil
    if (size > 16) {
297 663e8e51 ths
        size = 16;
298 aac443e6 Stefan Weil
    }
299 663e8e51 ths
    while (size-- > 0) {
300 663e8e51 ths
        p += sprintf(p, " %02x", *buf++);
301 663e8e51 ths
    }
302 663e8e51 ths
    return dump;
303 663e8e51 ths
}
304 663e8e51 ths
#endif                          /* DEBUG_EEPRO100 */
305 663e8e51 ths
306 663e8e51 ths
enum scb_stat_ack {
307 663e8e51 ths
    stat_ack_not_ours = 0x00,
308 663e8e51 ths
    stat_ack_sw_gen = 0x04,
309 663e8e51 ths
    stat_ack_rnr = 0x10,
310 663e8e51 ths
    stat_ack_cu_idle = 0x20,
311 663e8e51 ths
    stat_ack_frame_rx = 0x40,
312 663e8e51 ths
    stat_ack_cu_cmd_done = 0x80,
313 663e8e51 ths
    stat_ack_not_present = 0xFF,
314 663e8e51 ths
    stat_ack_rx = (stat_ack_sw_gen | stat_ack_rnr | stat_ack_frame_rx),
315 663e8e51 ths
    stat_ack_tx = (stat_ack_cu_idle | stat_ack_cu_cmd_done),
316 663e8e51 ths
};
317 663e8e51 ths
318 663e8e51 ths
static void disable_interrupt(EEPRO100State * s)
319 663e8e51 ths
{
320 663e8e51 ths
    if (s->int_stat) {
321 aac443e6 Stefan Weil
        TRACE(INT, logout("interrupt disabled\n"));
322 273a2142 Juan Quintela
        qemu_irq_lower(s->dev.irq[0]);
323 663e8e51 ths
        s->int_stat = 0;
324 663e8e51 ths
    }
325 663e8e51 ths
}
326 663e8e51 ths
327 663e8e51 ths
static void enable_interrupt(EEPRO100State * s)
328 663e8e51 ths
{
329 663e8e51 ths
    if (!s->int_stat) {
330 aac443e6 Stefan Weil
        TRACE(INT, logout("interrupt enabled\n"));
331 273a2142 Juan Quintela
        qemu_irq_raise(s->dev.irq[0]);
332 663e8e51 ths
        s->int_stat = 1;
333 663e8e51 ths
    }
334 663e8e51 ths
}
335 663e8e51 ths
336 663e8e51 ths
static void eepro100_acknowledge(EEPRO100State * s)
337 663e8e51 ths
{
338 663e8e51 ths
    s->scb_stat &= ~s->mem[SCBAck];
339 663e8e51 ths
    s->mem[SCBAck] = s->scb_stat;
340 663e8e51 ths
    if (s->scb_stat == 0) {
341 663e8e51 ths
        disable_interrupt(s);
342 663e8e51 ths
    }
343 663e8e51 ths
}
344 663e8e51 ths
345 663e8e51 ths
static void eepro100_interrupt(EEPRO100State * s, uint8_t stat)
346 663e8e51 ths
{
347 663e8e51 ths
    uint8_t mask = ~s->mem[SCBIntmask];
348 663e8e51 ths
    s->mem[SCBAck] |= stat;
349 663e8e51 ths
    stat = s->scb_stat = s->mem[SCBAck];
350 663e8e51 ths
    stat &= (mask | 0x0f);
351 663e8e51 ths
    //~ stat &= (~s->mem[SCBIntmask] | 0x0xf);
352 663e8e51 ths
    if (stat && (mask & 0x01)) {
353 663e8e51 ths
        /* SCB mask and SCB Bit M do not disable interrupt. */
354 663e8e51 ths
        enable_interrupt(s);
355 663e8e51 ths
    } else if (s->int_stat) {
356 663e8e51 ths
        disable_interrupt(s);
357 663e8e51 ths
    }
358 663e8e51 ths
}
359 663e8e51 ths
360 663e8e51 ths
static void eepro100_cx_interrupt(EEPRO100State * s)
361 663e8e51 ths
{
362 663e8e51 ths
    /* CU completed action command. */
363 663e8e51 ths
    /* Transmit not ok (82557 only, not in emulation). */
364 663e8e51 ths
    eepro100_interrupt(s, 0x80);
365 663e8e51 ths
}
366 663e8e51 ths
367 663e8e51 ths
static void eepro100_cna_interrupt(EEPRO100State * s)
368 663e8e51 ths
{
369 663e8e51 ths
    /* CU left the active state. */
370 663e8e51 ths
    eepro100_interrupt(s, 0x20);
371 663e8e51 ths
}
372 663e8e51 ths
373 663e8e51 ths
static void eepro100_fr_interrupt(EEPRO100State * s)
374 663e8e51 ths
{
375 663e8e51 ths
    /* RU received a complete frame. */
376 663e8e51 ths
    eepro100_interrupt(s, 0x40);
377 663e8e51 ths
}
378 663e8e51 ths
379 663e8e51 ths
#if 0
380 663e8e51 ths
static void eepro100_rnr_interrupt(EEPRO100State * s)
381 663e8e51 ths
{
382 663e8e51 ths
    /* RU is not ready. */
383 663e8e51 ths
    eepro100_interrupt(s, 0x10);
384 663e8e51 ths
}
385 663e8e51 ths
#endif
386 663e8e51 ths
387 663e8e51 ths
static void eepro100_mdi_interrupt(EEPRO100State * s)
388 663e8e51 ths
{
389 663e8e51 ths
    /* MDI completed read or write cycle. */
390 663e8e51 ths
    eepro100_interrupt(s, 0x08);
391 663e8e51 ths
}
392 663e8e51 ths
393 663e8e51 ths
static void eepro100_swi_interrupt(EEPRO100State * s)
394 663e8e51 ths
{
395 663e8e51 ths
    /* Software has requested an interrupt. */
396 663e8e51 ths
    eepro100_interrupt(s, 0x04);
397 663e8e51 ths
}
398 663e8e51 ths
399 663e8e51 ths
#if 0
400 663e8e51 ths
static void eepro100_fcp_interrupt(EEPRO100State * s)
401 663e8e51 ths
{
402 663e8e51 ths
    /* Flow control pause interrupt (82558 and later). */
403 663e8e51 ths
    eepro100_interrupt(s, 0x01);
404 663e8e51 ths
}
405 663e8e51 ths
#endif
406 663e8e51 ths
407 663e8e51 ths
static void pci_reset(EEPRO100State * s)
408 663e8e51 ths
{
409 663e8e51 ths
    uint32_t device = s->device;
410 273a2142 Juan Quintela
    uint8_t *pci_conf = s->dev.config;
411 ba42b646 Stefan Weil
    bool power_management = 1;
412 663e8e51 ths
413 aac443e6 Stefan Weil
    TRACE(OTHER, logout("%p\n", s));
414 663e8e51 ths
415 663e8e51 ths
    /* PCI Vendor ID */
416 deb54399 aliguori
    pci_config_set_vendor_id(pci_conf, PCI_VENDOR_ID_INTEL);
417 d6fd1e66 Stefan Weil
    /* PCI Device ID depends on device and is set below. */
418 663e8e51 ths
    /* PCI Command */
419 508cc6b4 Michael S. Tsirkin
    /* TODO: this is the default, do not override. */
420 663e8e51 ths
    PCI_CONFIG_16(PCI_COMMAND, 0x0000);
421 663e8e51 ths
    /* PCI Status */
422 508cc6b4 Michael S. Tsirkin
    /* TODO: Value at RST# should be 0. */
423 61702408 Stefan Weil
    PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM | PCI_STATUS_FAST_BACK);
424 663e8e51 ths
    /* PCI Revision ID */
425 663e8e51 ths
    PCI_CONFIG_8(PCI_REVISION_ID, 0x08);
426 508cc6b4 Michael S. Tsirkin
    /* TODO: this is the default, do not override. */
427 663e8e51 ths
    /* PCI Class Code */
428 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_CLASS_PROG, 0x00);
429 173a543b blueswir1
    pci_config_set_class(pci_conf, PCI_CLASS_NETWORK_ETHERNET);
430 663e8e51 ths
    /* PCI Cache Line Size */
431 663e8e51 ths
    /* check cache line size!!! */
432 663e8e51 ths
    //~ PCI_CONFIG_8(0x0c, 0x00);
433 663e8e51 ths
    /* PCI Latency Timer */
434 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_LATENCY_TIMER, 0x20);   // latency timer = 32 clocks
435 663e8e51 ths
    /* PCI Header Type */
436 663e8e51 ths
    /* BIST (built-in self test) */
437 663e8e51 ths
#if defined(TARGET_I386)
438 663e8e51 ths
// !!! workaround for buggy bios
439 0392a017 Isaku Yamahata
//~ #define PCI_BASE_ADDRESS_MEM_PREFETCH 0
440 663e8e51 ths
#endif
441 663e8e51 ths
#if 0
442 663e8e51 ths
    /* PCI Base Address Registers */
443 663e8e51 ths
    /* CSR Memory Mapped Base Address */
444 663e8e51 ths
    PCI_CONFIG_32(PCI_BASE_ADDRESS_0,
445 0392a017 Isaku Yamahata
                  PCI_BASE_ADDRESS_SPACE_MEMORY |
446 0392a017 Isaku Yamahata
                  PCI_BASE_ADDRESS_MEM_PREFETCH);
447 663e8e51 ths
    /* CSR I/O Mapped Base Address */
448 0392a017 Isaku Yamahata
    PCI_CONFIG_32(PCI_BASE_ADDRESS_1, PCI_BASE_ADDRESS_SPACE_IO);
449 663e8e51 ths
#if 0
450 663e8e51 ths
    /* Flash Memory Mapped Base Address */
451 0392a017 Isaku Yamahata
    PCI_CONFIG_32(PCI_BASE_ADDRESS_2,
452 0392a017 Isaku Yamahata
                  0xfffe0000 | PCI_BASE_ADDRESS_SPACE_MEMORY);
453 663e8e51 ths
#endif
454 663e8e51 ths
#endif
455 663e8e51 ths
    /* Expansion ROM Base Address (depends on boot disable!!!) */
456 508cc6b4 Michael S. Tsirkin
    /* TODO: not needed, set when BAR is registered */
457 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_32(PCI_ROM_ADDRESS, PCI_BASE_ADDRESS_SPACE_MEMORY);
458 663e8e51 ths
    /* Capability Pointer */
459 508cc6b4 Michael S. Tsirkin
    /* TODO: revisions with power_management 1 use this but
460 508cc6b4 Michael S. Tsirkin
     * do not set new capability list bit in status register. */
461 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_CAPABILITY_LIST, 0xdc);
462 aac443e6 Stefan Weil
    /* Interrupt Line */
463 663e8e51 ths
    /* Interrupt Pin */
464 508cc6b4 Michael S. Tsirkin
    /* TODO: RST# value should be 0 */
465 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_INTERRUPT_PIN, 1);      // interrupt pin 0
466 663e8e51 ths
    /* Minimum Grant */
467 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_MIN_GNT, 0x08);
468 663e8e51 ths
    /* Maximum Latency */
469 508cc6b4 Michael S. Tsirkin
    PCI_CONFIG_8(PCI_MAX_LAT, 0x18);
470 663e8e51 ths
471 663e8e51 ths
    switch (device) {
472 ba42b646 Stefan Weil
    case i82550:
473 ba42b646 Stefan Weil
        // TODO: check device id.
474 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82551IT);
475 ba42b646 Stefan Weil
        /* Revision ID: 0x0c, 0x0d, 0x0e. */
476 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x0e);
477 ba42b646 Stefan Weil
        // TODO: check size of statistical counters.
478 ba42b646 Stefan Weil
        s->stats_size = 80;
479 ba42b646 Stefan Weil
        // TODO: check extended tcb support.
480 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
481 ba42b646 Stefan Weil
        break;
482 663e8e51 ths
    case i82551:
483 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82551IT);
484 ba42b646 Stefan Weil
        /* Revision ID: 0x0f, 0x10. */
485 663e8e51 ths
        PCI_CONFIG_8(PCI_REVISION_ID, 0x0f);
486 ba42b646 Stefan Weil
        // TODO: check size of statistical counters.
487 ba42b646 Stefan Weil
        s->stats_size = 80;
488 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
489 ba42b646 Stefan Weil
        break;
490 ba42b646 Stefan Weil
    case i82557A:
491 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
492 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x01);
493 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_8(PCI_CAPABILITY_LIST, 0x00);
494 ba42b646 Stefan Weil
        power_management = 0;
495 663e8e51 ths
        break;
496 663e8e51 ths
    case i82557B:
497 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
498 663e8e51 ths
        PCI_CONFIG_8(PCI_REVISION_ID, 0x02);
499 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_8(PCI_CAPABILITY_LIST, 0x00);
500 ba42b646 Stefan Weil
        power_management = 0;
501 663e8e51 ths
        break;
502 663e8e51 ths
    case i82557C:
503 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
504 663e8e51 ths
        PCI_CONFIG_8(PCI_REVISION_ID, 0x03);
505 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_8(PCI_CAPABILITY_LIST, 0x00);
506 ba42b646 Stefan Weil
        power_management = 0;
507 ba42b646 Stefan Weil
        break;
508 ba42b646 Stefan Weil
    case i82558A:
509 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
510 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
511 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
512 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x04);
513 ba42b646 Stefan Weil
        s->stats_size = 76;
514 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
515 663e8e51 ths
        break;
516 663e8e51 ths
    case i82558B:
517 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
518 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
519 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
520 663e8e51 ths
        PCI_CONFIG_8(PCI_REVISION_ID, 0x05);
521 ba42b646 Stefan Weil
        s->stats_size = 76;
522 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
523 ba42b646 Stefan Weil
        break;
524 ba42b646 Stefan Weil
    case i82559A:
525 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
526 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
527 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
528 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x06);
529 ba42b646 Stefan Weil
        s->stats_size = 80;
530 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
531 ba42b646 Stefan Weil
        break;
532 ba42b646 Stefan Weil
    case i82559B:
533 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
534 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
535 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
536 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x07);
537 ba42b646 Stefan Weil
        s->stats_size = 80;
538 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
539 663e8e51 ths
        break;
540 663e8e51 ths
    case i82559C:
541 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82557);
542 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
543 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
544 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x08);
545 ba42b646 Stefan Weil
        // TODO: Windows wants revision id 0x0c.
546 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x0c);
547 ba42b646 Stefan Weil
#if EEPROM_SIZE > 0
548 ba42b646 Stefan Weil
        PCI_CONFIG_16(PCI_SUBSYSTEM_VENDOR_ID, 0x8086);
549 ba42b646 Stefan Weil
        PCI_CONFIG_16(PCI_SUBSYSTEM_ID, 0x0040);
550 ba42b646 Stefan Weil
#endif
551 ba42b646 Stefan Weil
        s->stats_size = 80;
552 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
553 663e8e51 ths
        break;
554 663e8e51 ths
    case i82559ER:
555 d6fd1e66 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82551IT);
556 508cc6b4 Michael S. Tsirkin
        PCI_CONFIG_16(PCI_STATUS, PCI_STATUS_DEVSEL_MEDIUM |
557 508cc6b4 Michael S. Tsirkin
                                  PCI_STATUS_FAST_BACK | PCI_STATUS_CAP_LIST);
558 663e8e51 ths
        PCI_CONFIG_8(PCI_REVISION_ID, 0x09);
559 ba42b646 Stefan Weil
        s->stats_size = 80;
560 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
561 ba42b646 Stefan Weil
        break;
562 ba42b646 Stefan Weil
    case i82562:
563 ba42b646 Stefan Weil
        // TODO: check device id.
564 ba42b646 Stefan Weil
        pci_config_set_device_id(pci_conf, PCI_DEVICE_ID_INTEL_82551IT);
565 ba42b646 Stefan Weil
        /* TODO: wrong revision id. */
566 ba42b646 Stefan Weil
        PCI_CONFIG_8(PCI_REVISION_ID, 0x0e);
567 ba42b646 Stefan Weil
        s->stats_size = 80;
568 ba42b646 Stefan Weil
        s->has_extended_tcb_support = 1;
569 663e8e51 ths
        break;
570 663e8e51 ths
    default:
571 663e8e51 ths
        logout("Device %X is undefined!\n", device);
572 663e8e51 ths
    }
573 663e8e51 ths
574 ba42b646 Stefan Weil
    s->configuration[6] |= BIT(5);
575 ba42b646 Stefan Weil
576 ba42b646 Stefan Weil
    if (s->stats_size == 80) {
577 ba42b646 Stefan Weil
        /* TODO: check TCO Statistical Counters bit. Documentation not clear. */
578 ba42b646 Stefan Weil
        if (s->configuration[6] & BIT(2)) {
579 ba42b646 Stefan Weil
            /* TCO statistical counters. */
580 ba42b646 Stefan Weil
            assert(s->configuration[6] & BIT(5));
581 ba42b646 Stefan Weil
        } else {
582 ba42b646 Stefan Weil
            if (s->configuration[6] & BIT(5)) {
583 ba42b646 Stefan Weil
                /* No extended statistical counters, i82557 compatible. */
584 ba42b646 Stefan Weil
                s->stats_size = 64;
585 ba42b646 Stefan Weil
            } else {
586 ba42b646 Stefan Weil
                /* i82558 compatible. */
587 ba42b646 Stefan Weil
                s->stats_size = 76;
588 ba42b646 Stefan Weil
            }
589 ba42b646 Stefan Weil
        }
590 ba42b646 Stefan Weil
    } else {
591 ba42b646 Stefan Weil
        if (s->configuration[6] & BIT(5)) {
592 ba42b646 Stefan Weil
            /* No extended statistical counters. */
593 ba42b646 Stefan Weil
            s->stats_size = 64;
594 ba42b646 Stefan Weil
        }
595 ba42b646 Stefan Weil
    }
596 ba42b646 Stefan Weil
    assert(s->stats_size > 0 && s->stats_size <= sizeof(s->statistics));
597 ba42b646 Stefan Weil
598 ba42b646 Stefan Weil
    if (power_management) {
599 ba42b646 Stefan Weil
        /* Power Management Capabilities */
600 ba42b646 Stefan Weil
        PCI_CONFIG_8(0xdc, 0x01);
601 ba42b646 Stefan Weil
        /* Next Item Pointer */
602 ba42b646 Stefan Weil
        /* Capability ID */
603 ba42b646 Stefan Weil
        PCI_CONFIG_16(0xde, 0x7e21);
604 ba42b646 Stefan Weil
        /* TODO: Power Management Control / Status. */
605 ba42b646 Stefan Weil
        /* TODO: Ethernet Power Consumption Registers (i82559 and later). */
606 ba42b646 Stefan Weil
    }
607 ba42b646 Stefan Weil
608 ba42b646 Stefan Weil
#if EEPROM_SIZE > 0
609 663e8e51 ths
    if (device == i82557C || device == i82558B || device == i82559C) {
610 ba42b646 Stefan Weil
        // TODO: get vendor id from EEPROM for i82557C or later.
611 ba42b646 Stefan Weil
        // TODO: get device id from EEPROM for i82557C or later.
612 ba42b646 Stefan Weil
        // TODO: status bit 4 can be disabled by EEPROM for i82558, i82559.
613 ba42b646 Stefan Weil
        // TODO: header type is determined by EEPROM for i82559.
614 ba42b646 Stefan Weil
        // TODO: get subsystem id from EEPROM for i82557C or later.
615 ba42b646 Stefan Weil
        // TODO: get subsystem vendor id from EEPROM for i82557C or later.
616 ba42b646 Stefan Weil
        // TODO: exp. rom baddr depends on a bit in EEPROM for i82558 or later.
617 ba42b646 Stefan Weil
        // TODO: capability pointer depends on EEPROM for i82558.
618 663e8e51 ths
        logout("Get device id and revision from EEPROM!!!\n");
619 663e8e51 ths
    }
620 ba42b646 Stefan Weil
#endif /* EEPROM_SIZE > 0 */
621 663e8e51 ths
}
622 663e8e51 ths
623 663e8e51 ths
static void nic_selective_reset(EEPRO100State * s)
624 663e8e51 ths
{
625 663e8e51 ths
    size_t i;
626 663e8e51 ths
    uint16_t *eeprom_contents = eeprom93xx_data(s->eeprom);
627 663e8e51 ths
    //~ eeprom93xx_reset(s->eeprom);
628 508ef936 Gerd Hoffmann
    memcpy(eeprom_contents, s->conf.macaddr.a, 6);
629 663e8e51 ths
    eeprom_contents[0xa] = 0x4000;
630 f4e94dfe =?UTF-8?q?Reimar=20D=C3=B6ffinger?=
    if (s->device == i82557B || s->device == i82557C)
631 f4e94dfe =?UTF-8?q?Reimar=20D=C3=B6ffinger?=
        eeprom_contents[5] = 0x0100;
632 663e8e51 ths
    uint16_t sum = 0;
633 663e8e51 ths
    for (i = 0; i < EEPROM_SIZE - 1; i++) {
634 663e8e51 ths
        sum += eeprom_contents[i];
635 663e8e51 ths
    }
636 663e8e51 ths
    eeprom_contents[EEPROM_SIZE - 1] = 0xbaba - sum;
637 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("checksum=0x%04x\n", eeprom_contents[EEPROM_SIZE - 1]));
638 663e8e51 ths
639 663e8e51 ths
    memset(s->mem, 0, sizeof(s->mem));
640 663e8e51 ths
    uint32_t val = BIT(21);
641 663e8e51 ths
    memcpy(&s->mem[SCBCtrlMDI], &val, sizeof(val));
642 663e8e51 ths
643 663e8e51 ths
    assert(sizeof(s->mdimem) == sizeof(eepro100_mdi_default));
644 663e8e51 ths
    memcpy(&s->mdimem[0], &eepro100_mdi_default[0], sizeof(s->mdimem));
645 663e8e51 ths
}
646 663e8e51 ths
647 663e8e51 ths
static void nic_reset(void *opaque)
648 663e8e51 ths
{
649 769cf7a5 Juan Quintela
    EEPRO100State *s = opaque;
650 aac443e6 Stefan Weil
    TRACE(OTHER, logout("%p\n", s));
651 7b8737de Stefan Weil
    /* TODO: Clearing of multicast table for selective reset, too? */
652 7b8737de Stefan Weil
    memset(&s->mult[0], 0, sizeof(s->mult));
653 663e8e51 ths
    nic_selective_reset(s);
654 663e8e51 ths
}
655 663e8e51 ths
656 663e8e51 ths
#if defined(DEBUG_EEPRO100)
657 b8f6ba0d Stefan Weil
static const char * const e100_reg[PCI_IO_SIZE / 4] = {
658 663e8e51 ths
    "Command/Status",
659 663e8e51 ths
    "General Pointer",
660 663e8e51 ths
    "Port",
661 663e8e51 ths
    "EEPROM/Flash Control",
662 663e8e51 ths
    "MDI Control",
663 663e8e51 ths
    "Receive DMA Byte Count",
664 b8f6ba0d Stefan Weil
    "Flow Control",
665 663e8e51 ths
    "General Status/Control"
666 663e8e51 ths
};
667 663e8e51 ths
668 663e8e51 ths
static char *regname(uint32_t addr)
669 663e8e51 ths
{
670 ec169288 David Benjamin
    static char buf[32];
671 663e8e51 ths
    if (addr < PCI_IO_SIZE) {
672 b8f6ba0d Stefan Weil
        const char *r = e100_reg[addr / 4];
673 663e8e51 ths
        if (r != 0) {
674 41cbc23c Stefan Weil
            snprintf(buf, sizeof(buf), "%s+%u", r, addr % 4);
675 663e8e51 ths
        } else {
676 41cbc23c Stefan Weil
            snprintf(buf, sizeof(buf), "0x%02x", addr);
677 663e8e51 ths
        }
678 663e8e51 ths
    } else {
679 41cbc23c Stefan Weil
        snprintf(buf, sizeof(buf), "??? 0x%08x", addr);
680 663e8e51 ths
    }
681 663e8e51 ths
    return buf;
682 663e8e51 ths
}
683 663e8e51 ths
#endif                          /* DEBUG_EEPRO100 */
684 663e8e51 ths
685 663e8e51 ths
#if 0
686 663e8e51 ths
static uint16_t eepro100_read_status(EEPRO100State * s)
687 663e8e51 ths
{
688 663e8e51 ths
    uint16_t val = s->status;
689 aac443e6 Stefan Weil
    TRACE(OTHER, logout("val=0x%04x\n", val));
690 663e8e51 ths
    return val;
691 663e8e51 ths
}
692 663e8e51 ths

693 663e8e51 ths
static void eepro100_write_status(EEPRO100State * s, uint16_t val)
694 663e8e51 ths
{
695 aac443e6 Stefan Weil
    TRACE(OTHER, logout("val=0x%04x\n", val));
696 663e8e51 ths
    s->status = val;
697 663e8e51 ths
}
698 663e8e51 ths
#endif
699 663e8e51 ths
700 663e8e51 ths
/*****************************************************************************
701 663e8e51 ths
 *
702 663e8e51 ths
 * Command emulation.
703 663e8e51 ths
 *
704 663e8e51 ths
 ****************************************************************************/
705 663e8e51 ths
706 663e8e51 ths
#if 0
707 663e8e51 ths
static uint16_t eepro100_read_command(EEPRO100State * s)
708 663e8e51 ths
{
709 663e8e51 ths
    uint16_t val = 0xffff;
710 aac443e6 Stefan Weil
    //~ TRACE(OTHER, logout("val=0x%04x\n", val));
711 663e8e51 ths
    return val;
712 663e8e51 ths
}
713 663e8e51 ths
#endif
714 663e8e51 ths
715 663e8e51 ths
/* Commands that can be put in a command list entry. */
716 663e8e51 ths
enum commands {
717 663e8e51 ths
    CmdNOp = 0,
718 663e8e51 ths
    CmdIASetup = 1,
719 663e8e51 ths
    CmdConfigure = 2,
720 663e8e51 ths
    CmdMulticastList = 3,
721 663e8e51 ths
    CmdTx = 4,
722 663e8e51 ths
    CmdTDR = 5,                 /* load microcode */
723 663e8e51 ths
    CmdDump = 6,
724 663e8e51 ths
    CmdDiagnose = 7,
725 663e8e51 ths
726 663e8e51 ths
    /* And some extra flags: */
727 663e8e51 ths
    CmdSuspend = 0x4000,        /* Suspend after completion. */
728 663e8e51 ths
    CmdIntr = 0x2000,           /* Interrupt after completion. */
729 663e8e51 ths
    CmdTxFlex = 0x0008,         /* Use "Flexible mode" for CmdTx command. */
730 663e8e51 ths
};
731 663e8e51 ths
732 c227f099 Anthony Liguori
static cu_state_t get_cu_state(EEPRO100State * s)
733 663e8e51 ths
{
734 663e8e51 ths
    return ((s->mem[SCBStatus] >> 6) & 0x03);
735 663e8e51 ths
}
736 663e8e51 ths
737 c227f099 Anthony Liguori
static void set_cu_state(EEPRO100State * s, cu_state_t state)
738 663e8e51 ths
{
739 663e8e51 ths
    s->mem[SCBStatus] = (s->mem[SCBStatus] & 0x3f) + (state << 6);
740 663e8e51 ths
}
741 663e8e51 ths
742 c227f099 Anthony Liguori
static ru_state_t get_ru_state(EEPRO100State * s)
743 663e8e51 ths
{
744 663e8e51 ths
    return ((s->mem[SCBStatus] >> 2) & 0x0f);
745 663e8e51 ths
}
746 663e8e51 ths
747 c227f099 Anthony Liguori
static void set_ru_state(EEPRO100State * s, ru_state_t state)
748 663e8e51 ths
{
749 663e8e51 ths
    s->mem[SCBStatus] = (s->mem[SCBStatus] & 0xc3) + (state << 2);
750 663e8e51 ths
}
751 663e8e51 ths
752 663e8e51 ths
static void dump_statistics(EEPRO100State * s)
753 663e8e51 ths
{
754 663e8e51 ths
    /* Dump statistical data. Most data is never changed by the emulation
755 663e8e51 ths
     * and always 0, so we first just copy the whole block and then those
756 663e8e51 ths
     * values which really matter.
757 663e8e51 ths
     * Number of data should check configuration!!!
758 663e8e51 ths
     */
759 ba42b646 Stefan Weil
    cpu_physical_memory_write(s->statsaddr,
760 ba42b646 Stefan Weil
                              (uint8_t *) & s->statistics, s->stats_size);
761 ba42b646 Stefan Weil
    stl_le_phys(s->statsaddr + 0, s->statistics.tx_good_frames);
762 ba42b646 Stefan Weil
    stl_le_phys(s->statsaddr + 36, s->statistics.rx_good_frames);
763 ba42b646 Stefan Weil
    stl_le_phys(s->statsaddr + 48, s->statistics.rx_resource_errors);
764 ba42b646 Stefan Weil
    stl_le_phys(s->statsaddr + 60, s->statistics.rx_short_frame_errors);
765 ba42b646 Stefan Weil
    //~ stw_le_phys(s->statsaddr + 76, s->statistics.xmt_tco_frames);
766 ba42b646 Stefan Weil
    //~ stw_le_phys(s->statsaddr + 78, s->statistics.rcv_tco_frames);
767 663e8e51 ths
    //~ missing("CU dump statistical counters");
768 663e8e51 ths
}
769 663e8e51 ths
770 f3a52e50 Stefan Weil
static void tx_command(EEPRO100State *s)
771 f3a52e50 Stefan Weil
{
772 7b8737de Stefan Weil
    uint32_t tbd_array = le32_to_cpu(s->tx.tbd_array_addr);
773 f3a52e50 Stefan Weil
    uint16_t tcb_bytes = (le16_to_cpu(s->tx.tcb_bytes) & 0x3fff);
774 f3a52e50 Stefan Weil
    /* Sends larger than MAX_ETH_FRAME_SIZE are allowed, up to 2600 bytes. */
775 f3a52e50 Stefan Weil
    uint8_t buf[2600];
776 f3a52e50 Stefan Weil
    uint16_t size = 0;
777 f3a52e50 Stefan Weil
    uint32_t tbd_address = s->cb_address + 0x10;
778 f3a52e50 Stefan Weil
    TRACE(RXTX, logout
779 f3a52e50 Stefan Weil
        ("transmit, TBD array address 0x%08x, TCB byte count 0x%04x, TBD count %u\n",
780 f3a52e50 Stefan Weil
         tbd_array, tcb_bytes, s->tx.tbd_count));
781 f3a52e50 Stefan Weil
782 f3a52e50 Stefan Weil
    if (tcb_bytes > 2600) {
783 f3a52e50 Stefan Weil
        logout("TCB byte count too large, using 2600\n");
784 f3a52e50 Stefan Weil
        tcb_bytes = 2600;
785 f3a52e50 Stefan Weil
    }
786 f3a52e50 Stefan Weil
    if (!((tcb_bytes > 0) || (tbd_array != 0xffffffff))) {
787 f3a52e50 Stefan Weil
        logout
788 f3a52e50 Stefan Weil
            ("illegal values of TBD array address and TCB byte count!\n");
789 f3a52e50 Stefan Weil
    }
790 f3a52e50 Stefan Weil
    assert(tcb_bytes <= sizeof(buf));
791 f3a52e50 Stefan Weil
    while (size < tcb_bytes) {
792 f3a52e50 Stefan Weil
        uint32_t tx_buffer_address = ldl_phys(tbd_address);
793 f3a52e50 Stefan Weil
        uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
794 f3a52e50 Stefan Weil
        //~ uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
795 f3a52e50 Stefan Weil
        tbd_address += 8;
796 f3a52e50 Stefan Weil
        TRACE(RXTX, logout
797 f3a52e50 Stefan Weil
            ("TBD (simplified mode): buffer address 0x%08x, size 0x%04x\n",
798 f3a52e50 Stefan Weil
             tx_buffer_address, tx_buffer_size));
799 f3a52e50 Stefan Weil
        tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
800 f3a52e50 Stefan Weil
        cpu_physical_memory_read(tx_buffer_address, &buf[size],
801 f3a52e50 Stefan Weil
                                 tx_buffer_size);
802 f3a52e50 Stefan Weil
        size += tx_buffer_size;
803 f3a52e50 Stefan Weil
    }
804 f3a52e50 Stefan Weil
    if (tbd_array == 0xffffffff) {
805 f3a52e50 Stefan Weil
        /* Simplified mode. Was already handled by code above. */
806 f3a52e50 Stefan Weil
    } else {
807 f3a52e50 Stefan Weil
        /* Flexible mode. */
808 f3a52e50 Stefan Weil
        uint8_t tbd_count = 0;
809 f3a52e50 Stefan Weil
        if (s->has_extended_tcb_support && !(s->configuration[6] & BIT(4))) {
810 f3a52e50 Stefan Weil
            /* Extended Flexible TCB. */
811 f3a52e50 Stefan Weil
            for (; tbd_count < 2; tbd_count++) {
812 f3a52e50 Stefan Weil
                uint32_t tx_buffer_address = ldl_phys(tbd_address);
813 f3a52e50 Stefan Weil
                uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
814 f3a52e50 Stefan Weil
                uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
815 f3a52e50 Stefan Weil
                tbd_address += 8;
816 f3a52e50 Stefan Weil
                TRACE(RXTX, logout
817 f3a52e50 Stefan Weil
                    ("TBD (extended flexible mode): buffer address 0x%08x, size 0x%04x\n",
818 f3a52e50 Stefan Weil
                     tx_buffer_address, tx_buffer_size));
819 f3a52e50 Stefan Weil
                tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
820 f3a52e50 Stefan Weil
                cpu_physical_memory_read(tx_buffer_address, &buf[size],
821 f3a52e50 Stefan Weil
                                         tx_buffer_size);
822 f3a52e50 Stefan Weil
                size += tx_buffer_size;
823 f3a52e50 Stefan Weil
                if (tx_buffer_el & 1) {
824 f3a52e50 Stefan Weil
                    break;
825 f3a52e50 Stefan Weil
                }
826 f3a52e50 Stefan Weil
            }
827 f3a52e50 Stefan Weil
        }
828 f3a52e50 Stefan Weil
        tbd_address = tbd_array;
829 f3a52e50 Stefan Weil
        for (; tbd_count < s->tx.tbd_count; tbd_count++) {
830 f3a52e50 Stefan Weil
            uint32_t tx_buffer_address = ldl_phys(tbd_address);
831 f3a52e50 Stefan Weil
            uint16_t tx_buffer_size = lduw_phys(tbd_address + 4);
832 f3a52e50 Stefan Weil
            uint16_t tx_buffer_el = lduw_phys(tbd_address + 6);
833 f3a52e50 Stefan Weil
            tbd_address += 8;
834 f3a52e50 Stefan Weil
            TRACE(RXTX, logout
835 f3a52e50 Stefan Weil
                ("TBD (flexible mode): buffer address 0x%08x, size 0x%04x\n",
836 f3a52e50 Stefan Weil
                 tx_buffer_address, tx_buffer_size));
837 f3a52e50 Stefan Weil
            tx_buffer_size = MIN(tx_buffer_size, sizeof(buf) - size);
838 f3a52e50 Stefan Weil
            cpu_physical_memory_read(tx_buffer_address, &buf[size],
839 f3a52e50 Stefan Weil
                                     tx_buffer_size);
840 f3a52e50 Stefan Weil
            size += tx_buffer_size;
841 f3a52e50 Stefan Weil
            if (tx_buffer_el & 1) {
842 f3a52e50 Stefan Weil
                break;
843 f3a52e50 Stefan Weil
            }
844 f3a52e50 Stefan Weil
        }
845 f3a52e50 Stefan Weil
    }
846 f3a52e50 Stefan Weil
    TRACE(RXTX, logout("%p sending frame, len=%d,%s\n", s, size, nic_dump(buf, size)));
847 f3a52e50 Stefan Weil
    qemu_send_packet(&s->nic->nc, buf, size);
848 f3a52e50 Stefan Weil
    s->statistics.tx_good_frames++;
849 f3a52e50 Stefan Weil
    /* Transmit with bad status would raise an CX/TNO interrupt.
850 f3a52e50 Stefan Weil
     * (82557 only). Emulation never has bad status. */
851 f3a52e50 Stefan Weil
    //~ eepro100_cx_interrupt(s);
852 f3a52e50 Stefan Weil
}
853 f3a52e50 Stefan Weil
854 7b8737de Stefan Weil
static void set_multicast_list(EEPRO100State *s)
855 7b8737de Stefan Weil
{
856 7b8737de Stefan Weil
    uint16_t multicast_count = s->tx.tbd_array_addr & BITS(13, 0);
857 7b8737de Stefan Weil
    uint16_t i;
858 7b8737de Stefan Weil
    memset(&s->mult[0], 0, sizeof(s->mult));
859 7b8737de Stefan Weil
    TRACE(OTHER, logout("multicast list, multicast count = %u\n", multicast_count));
860 7b8737de Stefan Weil
    for (i = 0; i < multicast_count; i += 6) {
861 7b8737de Stefan Weil
        uint8_t multicast_addr[6];
862 7b8737de Stefan Weil
        cpu_physical_memory_read(s->cb_address + 10 + i, multicast_addr, 6);
863 7b8737de Stefan Weil
        TRACE(OTHER, logout("multicast entry %s\n", nic_dump(multicast_addr, 6)));
864 7b8737de Stefan Weil
        unsigned mcast_idx = compute_mcast_idx(multicast_addr);
865 7b8737de Stefan Weil
        assert(mcast_idx < 64);
866 7b8737de Stefan Weil
        s->mult[mcast_idx >> 3] |= (1 << (mcast_idx & 7));
867 7b8737de Stefan Weil
    }
868 7b8737de Stefan Weil
}
869 7b8737de Stefan Weil
870 5fa9a0ae Stefan Weil
static void action_command(EEPRO100State *s)
871 663e8e51 ths
{
872 5fa9a0ae Stefan Weil
    for (;;) {
873 f3a52e50 Stefan Weil
        s->cb_address = s->cu_base + s->cu_offset;
874 f3a52e50 Stefan Weil
        cpu_physical_memory_read(s->cb_address, (uint8_t *)&s->tx, sizeof(s->tx));
875 f3a52e50 Stefan Weil
        uint16_t status = le16_to_cpu(s->tx.status);
876 f3a52e50 Stefan Weil
        uint16_t command = le16_to_cpu(s->tx.command);
877 663e8e51 ths
        logout
878 663e8e51 ths
            ("val=0x%02x (cu start), status=0x%04x, command=0x%04x, link=0x%08x\n",
879 f3a52e50 Stefan Weil
             val, status, command, s->tx.link);
880 663e8e51 ths
        bool bit_el = ((command & 0x8000) != 0);
881 663e8e51 ths
        bool bit_s = ((command & 0x4000) != 0);
882 663e8e51 ths
        bool bit_i = ((command & 0x2000) != 0);
883 663e8e51 ths
        bool bit_nc = ((command & 0x0010) != 0);
884 7f1e9d4e Kevin Wolf
        bool success = true;
885 663e8e51 ths
        //~ bool bit_sf = ((command & 0x0008) != 0);
886 663e8e51 ths
        uint16_t cmd = command & 0x0007;
887 f3a52e50 Stefan Weil
        s->cu_offset = le32_to_cpu(s->tx.link);
888 663e8e51 ths
        switch (cmd) {
889 663e8e51 ths
        case CmdNOp:
890 663e8e51 ths
            /* Do nothing. */
891 663e8e51 ths
            break;
892 663e8e51 ths
        case CmdIASetup:
893 f3a52e50 Stefan Weil
            cpu_physical_memory_read(s->cb_address + 8, &s->conf.macaddr.a[0], 6);
894 aac443e6 Stefan Weil
            TRACE(OTHER, logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6)));
895 663e8e51 ths
            break;
896 663e8e51 ths
        case CmdConfigure:
897 f3a52e50 Stefan Weil
            cpu_physical_memory_read(s->cb_address + 8, &s->configuration[0],
898 663e8e51 ths
                                     sizeof(s->configuration));
899 aac443e6 Stefan Weil
            TRACE(OTHER, logout("configuration: %s\n", nic_dump(&s->configuration[0], 16)));
900 663e8e51 ths
            break;
901 663e8e51 ths
        case CmdMulticastList:
902 7b8737de Stefan Weil
            set_multicast_list(s);
903 663e8e51 ths
            break;
904 663e8e51 ths
        case CmdTx:
905 7f1e9d4e Kevin Wolf
            if (bit_nc) {
906 7f1e9d4e Kevin Wolf
                missing("CmdTx: NC = 0");
907 7f1e9d4e Kevin Wolf
                success = false;
908 7f1e9d4e Kevin Wolf
                break;
909 7f1e9d4e Kevin Wolf
            }
910 f3a52e50 Stefan Weil
            tx_command(s);
911 663e8e51 ths
            break;
912 663e8e51 ths
        case CmdTDR:
913 aac443e6 Stefan Weil
            TRACE(OTHER, logout("load microcode\n"));
914 663e8e51 ths
            /* Starting with offset 8, the command contains
915 663e8e51 ths
             * 64 dwords microcode which we just ignore here. */
916 663e8e51 ths
            break;
917 663e8e51 ths
        default:
918 663e8e51 ths
            missing("undefined command");
919 7f1e9d4e Kevin Wolf
            success = false;
920 7f1e9d4e Kevin Wolf
            break;
921 663e8e51 ths
        }
922 7f1e9d4e Kevin Wolf
        /* Write new status. */
923 f3a52e50 Stefan Weil
        stw_phys(s->cb_address, status | 0x8000 | (success ? 0x2000 : 0));
924 663e8e51 ths
        if (bit_i) {
925 663e8e51 ths
            /* CU completed action. */
926 663e8e51 ths
            eepro100_cx_interrupt(s);
927 663e8e51 ths
        }
928 663e8e51 ths
        if (bit_el) {
929 aac443e6 Stefan Weil
            /* CU becomes idle. Terminate command loop. */
930 663e8e51 ths
            set_cu_state(s, cu_idle);
931 663e8e51 ths
            eepro100_cna_interrupt(s);
932 5fa9a0ae Stefan Weil
            break;
933 663e8e51 ths
        } else if (bit_s) {
934 5fa9a0ae Stefan Weil
            /* CU becomes suspended. Terminate command loop. */
935 663e8e51 ths
            set_cu_state(s, cu_suspended);
936 663e8e51 ths
            eepro100_cna_interrupt(s);
937 5fa9a0ae Stefan Weil
            break;
938 663e8e51 ths
        } else {
939 663e8e51 ths
            /* More entries in list. */
940 aac443e6 Stefan Weil
            TRACE(OTHER, logout("CU list with at least one more entry\n"));
941 663e8e51 ths
        }
942 5fa9a0ae Stefan Weil
    }
943 5fa9a0ae Stefan Weil
    TRACE(OTHER, logout("CU list empty\n"));
944 5fa9a0ae Stefan Weil
    /* List is empty. Now CU is idle or suspended. */
945 5fa9a0ae Stefan Weil
}
946 5fa9a0ae Stefan Weil
947 5fa9a0ae Stefan Weil
static void eepro100_cu_command(EEPRO100State * s, uint8_t val)
948 5fa9a0ae Stefan Weil
{
949 5fa9a0ae Stefan Weil
    switch (val) {
950 5fa9a0ae Stefan Weil
    case CU_NOP:
951 5fa9a0ae Stefan Weil
        /* No operation. */
952 5fa9a0ae Stefan Weil
        break;
953 5fa9a0ae Stefan Weil
    case CU_START:
954 5fa9a0ae Stefan Weil
        if (get_cu_state(s) != cu_idle) {
955 5fa9a0ae Stefan Weil
            /* Intel documentation says that CU must be idle for the CU
956 5fa9a0ae Stefan Weil
             * start command. Intel driver for Linux also starts the CU
957 5fa9a0ae Stefan Weil
             * from suspended state. */
958 5fa9a0ae Stefan Weil
            logout("CU state is %u, should be %u\n", get_cu_state(s), cu_idle);
959 5fa9a0ae Stefan Weil
            //~ assert(!"wrong CU state");
960 5fa9a0ae Stefan Weil
        }
961 5fa9a0ae Stefan Weil
        set_cu_state(s, cu_active);
962 5fa9a0ae Stefan Weil
        s->cu_offset = s->pointer;
963 5fa9a0ae Stefan Weil
        action_command(s);
964 663e8e51 ths
        break;
965 663e8e51 ths
    case CU_RESUME:
966 663e8e51 ths
        if (get_cu_state(s) != cu_suspended) {
967 663e8e51 ths
            logout("bad CU resume from CU state %u\n", get_cu_state(s));
968 663e8e51 ths
            /* Workaround for bad Linux eepro100 driver which resumes
969 663e8e51 ths
             * from idle state. */
970 663e8e51 ths
            //~ missing("cu resume");
971 663e8e51 ths
            set_cu_state(s, cu_suspended);
972 663e8e51 ths
        }
973 663e8e51 ths
        if (get_cu_state(s) == cu_suspended) {
974 aac443e6 Stefan Weil
            TRACE(OTHER, logout("CU resuming\n"));
975 663e8e51 ths
            set_cu_state(s, cu_active);
976 5fa9a0ae Stefan Weil
            action_command(s);
977 663e8e51 ths
        }
978 663e8e51 ths
        break;
979 663e8e51 ths
    case CU_STATSADDR:
980 663e8e51 ths
        /* Load dump counters address. */
981 663e8e51 ths
        s->statsaddr = s->pointer;
982 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (status address)\n", val));
983 663e8e51 ths
        break;
984 663e8e51 ths
    case CU_SHOWSTATS:
985 663e8e51 ths
        /* Dump statistical counters. */
986 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (dump stats)\n", val));
987 663e8e51 ths
        dump_statistics(s);
988 ba42b646 Stefan Weil
        stl_le_phys(s->statsaddr + s->stats_size, 0xa005);
989 663e8e51 ths
        break;
990 663e8e51 ths
    case CU_CMD_BASE:
991 663e8e51 ths
        /* Load CU base. */
992 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (CU base address)\n", val));
993 663e8e51 ths
        s->cu_base = s->pointer;
994 663e8e51 ths
        break;
995 663e8e51 ths
    case CU_DUMPSTATS:
996 663e8e51 ths
        /* Dump and reset statistical counters. */
997 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (dump stats and reset)\n", val));
998 663e8e51 ths
        dump_statistics(s);
999 ba42b646 Stefan Weil
        stl_le_phys(s->statsaddr + s->stats_size, 0xa007);
1000 663e8e51 ths
        memset(&s->statistics, 0, sizeof(s->statistics));
1001 663e8e51 ths
        break;
1002 663e8e51 ths
    case CU_SRESUME:
1003 663e8e51 ths
        /* CU static resume. */
1004 663e8e51 ths
        missing("CU static resume");
1005 663e8e51 ths
        break;
1006 663e8e51 ths
    default:
1007 663e8e51 ths
        missing("Undefined CU command");
1008 663e8e51 ths
    }
1009 663e8e51 ths
}
1010 663e8e51 ths
1011 663e8e51 ths
static void eepro100_ru_command(EEPRO100State * s, uint8_t val)
1012 663e8e51 ths
{
1013 663e8e51 ths
    switch (val) {
1014 663e8e51 ths
    case RU_NOP:
1015 663e8e51 ths
        /* No operation. */
1016 663e8e51 ths
        break;
1017 663e8e51 ths
    case RX_START:
1018 663e8e51 ths
        /* RU start. */
1019 663e8e51 ths
        if (get_ru_state(s) != ru_idle) {
1020 663e8e51 ths
            logout("RU state is %u, should be %u\n", get_ru_state(s), ru_idle);
1021 663e8e51 ths
            //~ assert(!"wrong RU state");
1022 663e8e51 ths
        }
1023 663e8e51 ths
        set_ru_state(s, ru_ready);
1024 663e8e51 ths
        s->ru_offset = s->pointer;
1025 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (rx start)\n", val));
1026 663e8e51 ths
        break;
1027 663e8e51 ths
    case RX_RESUME:
1028 663e8e51 ths
        /* Restart RU. */
1029 663e8e51 ths
        if (get_ru_state(s) != ru_suspended) {
1030 663e8e51 ths
            logout("RU state is %u, should be %u\n", get_ru_state(s),
1031 663e8e51 ths
                   ru_suspended);
1032 663e8e51 ths
            //~ assert(!"wrong RU state");
1033 663e8e51 ths
        }
1034 663e8e51 ths
        set_ru_state(s, ru_ready);
1035 663e8e51 ths
        break;
1036 663e8e51 ths
    case RX_ADDR_LOAD:
1037 663e8e51 ths
        /* Load RU base. */
1038 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x (RU base address)\n", val));
1039 663e8e51 ths
        s->ru_base = s->pointer;
1040 663e8e51 ths
        break;
1041 663e8e51 ths
    default:
1042 663e8e51 ths
        logout("val=0x%02x (undefined RU command)\n", val);
1043 663e8e51 ths
        missing("Undefined SU command");
1044 663e8e51 ths
    }
1045 663e8e51 ths
}
1046 663e8e51 ths
1047 663e8e51 ths
static void eepro100_write_command(EEPRO100State * s, uint8_t val)
1048 663e8e51 ths
{
1049 663e8e51 ths
    eepro100_ru_command(s, val & 0x0f);
1050 663e8e51 ths
    eepro100_cu_command(s, val & 0xf0);
1051 663e8e51 ths
    if ((val) == 0) {
1052 aac443e6 Stefan Weil
        TRACE(OTHER, logout("val=0x%02x\n", val));
1053 663e8e51 ths
    }
1054 663e8e51 ths
    /* Clear command byte after command was accepted. */
1055 663e8e51 ths
    s->mem[SCBCmd] = 0;
1056 663e8e51 ths
}
1057 663e8e51 ths
1058 663e8e51 ths
/*****************************************************************************
1059 663e8e51 ths
 *
1060 663e8e51 ths
 * EEPROM emulation.
1061 663e8e51 ths
 *
1062 663e8e51 ths
 ****************************************************************************/
1063 663e8e51 ths
1064 663e8e51 ths
#define EEPROM_CS       0x02
1065 663e8e51 ths
#define EEPROM_SK       0x01
1066 663e8e51 ths
#define EEPROM_DI       0x04
1067 663e8e51 ths
#define EEPROM_DO       0x08
1068 663e8e51 ths
1069 663e8e51 ths
static uint16_t eepro100_read_eeprom(EEPRO100State * s)
1070 663e8e51 ths
{
1071 663e8e51 ths
    uint16_t val;
1072 663e8e51 ths
    memcpy(&val, &s->mem[SCBeeprom], sizeof(val));
1073 663e8e51 ths
    if (eeprom93xx_read(s->eeprom)) {
1074 663e8e51 ths
        val |= EEPROM_DO;
1075 663e8e51 ths
    } else {
1076 663e8e51 ths
        val &= ~EEPROM_DO;
1077 663e8e51 ths
    }
1078 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("val=0x%04x\n", val));
1079 663e8e51 ths
    return val;
1080 663e8e51 ths
}
1081 663e8e51 ths
1082 c227f099 Anthony Liguori
static void eepro100_write_eeprom(eeprom_t * eeprom, uint8_t val)
1083 663e8e51 ths
{
1084 aac443e6 Stefan Weil
    TRACE(EEPROM, logout("val=0x%02x\n", val));
1085 663e8e51 ths
1086 663e8e51 ths
    /* mask unwriteable bits */
1087 663e8e51 ths
    //~ val = SET_MASKED(val, 0x31, eeprom->value);
1088 663e8e51 ths
1089 663e8e51 ths
    int eecs = ((val & EEPROM_CS) != 0);
1090 663e8e51 ths
    int eesk = ((val & EEPROM_SK) != 0);
1091 663e8e51 ths
    int eedi = ((val & EEPROM_DI) != 0);
1092 663e8e51 ths
    eeprom93xx_write(eeprom, eecs, eesk, eedi);
1093 663e8e51 ths
}
1094 663e8e51 ths
1095 663e8e51 ths
static void eepro100_write_pointer(EEPRO100State * s, uint32_t val)
1096 663e8e51 ths
{
1097 663e8e51 ths
    s->pointer = le32_to_cpu(val);
1098 aac443e6 Stefan Weil
    TRACE(OTHER, logout("val=0x%08x\n", val));
1099 663e8e51 ths
}
1100 663e8e51 ths
1101 663e8e51 ths
/*****************************************************************************
1102 663e8e51 ths
 *
1103 663e8e51 ths
 * MDI emulation.
1104 663e8e51 ths
 *
1105 663e8e51 ths
 ****************************************************************************/
1106 663e8e51 ths
1107 663e8e51 ths
#if defined(DEBUG_EEPRO100)
1108 6a0b9cc9 Reimar Dรถffinger
static const char * const mdi_op_name[] = {
1109 663e8e51 ths
    "opcode 0",
1110 663e8e51 ths
    "write",
1111 663e8e51 ths
    "read",
1112 663e8e51 ths
    "opcode 3"
1113 663e8e51 ths
};
1114 663e8e51 ths
1115 6a0b9cc9 Reimar Dรถffinger
static const char * const mdi_reg_name[] = {
1116 663e8e51 ths
    "Control",
1117 663e8e51 ths
    "Status",
1118 663e8e51 ths
    "PHY Identification (Word 1)",
1119 663e8e51 ths
    "PHY Identification (Word 2)",
1120 663e8e51 ths
    "Auto-Negotiation Advertisement",
1121 663e8e51 ths
    "Auto-Negotiation Link Partner Ability",
1122 663e8e51 ths
    "Auto-Negotiation Expansion"
1123 663e8e51 ths
};
1124 aac443e6 Stefan Weil
1125 aac443e6 Stefan Weil
static const char *reg2name(uint8_t reg)
1126 aac443e6 Stefan Weil
{
1127 aac443e6 Stefan Weil
    static char buffer[10];
1128 aac443e6 Stefan Weil
    const char *p = buffer;
1129 aac443e6 Stefan Weil
    if (reg < ARRAY_SIZE(mdi_reg_name)) {
1130 aac443e6 Stefan Weil
        p = mdi_reg_name[reg];
1131 aac443e6 Stefan Weil
    } else {
1132 aac443e6 Stefan Weil
        snprintf(buffer, sizeof(buffer), "reg=0x%02x", reg);
1133 aac443e6 Stefan Weil
    }
1134 aac443e6 Stefan Weil
    return p;
1135 aac443e6 Stefan Weil
}
1136 663e8e51 ths
#endif                          /* DEBUG_EEPRO100 */
1137 663e8e51 ths
1138 663e8e51 ths
static uint32_t eepro100_read_mdi(EEPRO100State * s)
1139 663e8e51 ths
{
1140 663e8e51 ths
    uint32_t val;
1141 663e8e51 ths
    memcpy(&val, &s->mem[0x10], sizeof(val));
1142 663e8e51 ths
1143 663e8e51 ths
#ifdef DEBUG_EEPRO100
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 663e8e51 ths
#endif
1150 663e8e51 ths
    /* Emulation takes no time to finish MDI transaction. */
1151 663e8e51 ths
    val |= BIT(28);
1152 663e8e51 ths
    TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1153 663e8e51 ths
                      val, raiseint, mdi_op_name[opcode], phy,
1154 aac443e6 Stefan Weil
                      reg2name(reg), data));
1155 663e8e51 ths
    return val;
1156 663e8e51 ths
}
1157 663e8e51 ths
1158 663e8e51 ths
static void eepro100_write_mdi(EEPRO100State * s, uint32_t val)
1159 663e8e51 ths
{
1160 663e8e51 ths
    uint8_t raiseint = (val & BIT(29)) >> 29;
1161 663e8e51 ths
    uint8_t opcode = (val & BITS(27, 26)) >> 26;
1162 663e8e51 ths
    uint8_t phy = (val & BITS(25, 21)) >> 21;
1163 663e8e51 ths
    uint8_t reg = (val & BITS(20, 16)) >> 16;
1164 663e8e51 ths
    uint16_t data = (val & BITS(15, 0));
1165 aac443e6 Stefan Weil
    TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1166 aac443e6 Stefan Weil
          val, raiseint, mdi_op_name[opcode], phy, reg2name(reg), data));
1167 663e8e51 ths
    if (phy != 1) {
1168 663e8e51 ths
        /* Unsupported PHY address. */
1169 663e8e51 ths
        //~ logout("phy must be 1 but is %u\n", phy);
1170 663e8e51 ths
        data = 0;
1171 663e8e51 ths
    } else if (opcode != 1 && opcode != 2) {
1172 663e8e51 ths
        /* Unsupported opcode. */
1173 663e8e51 ths
        logout("opcode must be 1 or 2 but is %u\n", opcode);
1174 663e8e51 ths
        data = 0;
1175 663e8e51 ths
    } else if (reg > 6) {
1176 663e8e51 ths
        /* Unsupported register. */
1177 663e8e51 ths
        logout("register must be 0...6 but is %u\n", reg);
1178 663e8e51 ths
        data = 0;
1179 663e8e51 ths
    } else {
1180 663e8e51 ths
        TRACE(MDI, logout("val=0x%08x (int=%u, %s, phy=%u, %s, data=0x%04x\n",
1181 663e8e51 ths
                          val, raiseint, mdi_op_name[opcode], phy,
1182 aac443e6 Stefan Weil
                          reg2name(reg), data));
1183 663e8e51 ths
        if (opcode == 1) {
1184 663e8e51 ths
            /* MDI write */
1185 663e8e51 ths
            switch (reg) {
1186 663e8e51 ths
            case 0:            /* Control Register */
1187 663e8e51 ths
                if (data & 0x8000) {
1188 663e8e51 ths
                    /* Reset status and control registers to default. */
1189 663e8e51 ths
                    s->mdimem[0] = eepro100_mdi_default[0];
1190 663e8e51 ths
                    s->mdimem[1] = eepro100_mdi_default[1];
1191 663e8e51 ths
                    data = s->mdimem[reg];
1192 663e8e51 ths
                } else {
1193 663e8e51 ths
                    /* Restart Auto Configuration = Normal Operation */
1194 663e8e51 ths
                    data &= ~0x0200;
1195 663e8e51 ths
                }
1196 663e8e51 ths
                break;
1197 663e8e51 ths
            case 1:            /* Status Register */
1198 663e8e51 ths
                missing("not writable");
1199 663e8e51 ths
                data = s->mdimem[reg];
1200 663e8e51 ths
                break;
1201 663e8e51 ths
            case 2:            /* PHY Identification Register (Word 1) */
1202 663e8e51 ths
            case 3:            /* PHY Identification Register (Word 2) */
1203 663e8e51 ths
                missing("not implemented");
1204 663e8e51 ths
                break;
1205 663e8e51 ths
            case 4:            /* Auto-Negotiation Advertisement Register */
1206 663e8e51 ths
            case 5:            /* Auto-Negotiation Link Partner Ability Register */
1207 663e8e51 ths
                break;
1208 663e8e51 ths
            case 6:            /* Auto-Negotiation Expansion Register */
1209 663e8e51 ths
            default:
1210 663e8e51 ths
                missing("not implemented");
1211 663e8e51 ths
            }
1212 663e8e51 ths
            s->mdimem[reg] = data;
1213 663e8e51 ths
        } else if (opcode == 2) {
1214 663e8e51 ths
            /* MDI read */
1215 663e8e51 ths
            switch (reg) {
1216 663e8e51 ths
            case 0:            /* Control Register */
1217 663e8e51 ths
                if (data & 0x8000) {
1218 663e8e51 ths
                    /* Reset status and control registers to default. */
1219 663e8e51 ths
                    s->mdimem[0] = eepro100_mdi_default[0];
1220 663e8e51 ths
                    s->mdimem[1] = eepro100_mdi_default[1];
1221 663e8e51 ths
                }
1222 663e8e51 ths
                break;
1223 663e8e51 ths
            case 1:            /* Status Register */
1224 663e8e51 ths
                s->mdimem[reg] |= 0x0020;
1225 663e8e51 ths
                break;
1226 663e8e51 ths
            case 2:            /* PHY Identification Register (Word 1) */
1227 663e8e51 ths
            case 3:            /* PHY Identification Register (Word 2) */
1228 663e8e51 ths
            case 4:            /* Auto-Negotiation Advertisement Register */
1229 663e8e51 ths
                break;
1230 663e8e51 ths
            case 5:            /* Auto-Negotiation Link Partner Ability Register */
1231 663e8e51 ths
                s->mdimem[reg] = 0x41fe;
1232 663e8e51 ths
                break;
1233 663e8e51 ths
            case 6:            /* Auto-Negotiation Expansion Register */
1234 663e8e51 ths
                s->mdimem[reg] = 0x0001;
1235 663e8e51 ths
                break;
1236 663e8e51 ths
            }
1237 663e8e51 ths
            data = s->mdimem[reg];
1238 663e8e51 ths
        }
1239 663e8e51 ths
        /* Emulation takes no time to finish MDI transaction.
1240 663e8e51 ths
         * Set MDI bit in SCB status register. */
1241 663e8e51 ths
        s->mem[SCBAck] |= 0x08;
1242 663e8e51 ths
        val |= BIT(28);
1243 663e8e51 ths
        if (raiseint) {
1244 663e8e51 ths
            eepro100_mdi_interrupt(s);
1245 663e8e51 ths
        }
1246 663e8e51 ths
    }
1247 663e8e51 ths
    val = (val & 0xffff0000) + data;
1248 663e8e51 ths
    memcpy(&s->mem[0x10], &val, sizeof(val));
1249 663e8e51 ths
}
1250 663e8e51 ths
1251 663e8e51 ths
/*****************************************************************************
1252 663e8e51 ths
 *
1253 663e8e51 ths
 * Port emulation.
1254 663e8e51 ths
 *
1255 663e8e51 ths
 ****************************************************************************/
1256 663e8e51 ths
1257 663e8e51 ths
#define PORT_SOFTWARE_RESET     0
1258 663e8e51 ths
#define PORT_SELFTEST           1
1259 663e8e51 ths
#define PORT_SELECTIVE_RESET    2
1260 663e8e51 ths
#define PORT_DUMP               3
1261 663e8e51 ths
#define PORT_SELECTION_MASK     3
1262 663e8e51 ths
1263 663e8e51 ths
typedef struct {
1264 663e8e51 ths
    uint32_t st_sign;           /* Self Test Signature */
1265 663e8e51 ths
    uint32_t st_result;         /* Self Test Results */
1266 c227f099 Anthony Liguori
} eepro100_selftest_t;
1267 663e8e51 ths
1268 663e8e51 ths
static uint32_t eepro100_read_port(EEPRO100State * s)
1269 663e8e51 ths
{
1270 663e8e51 ths
    return 0;
1271 663e8e51 ths
}
1272 663e8e51 ths
1273 663e8e51 ths
static void eepro100_write_port(EEPRO100State * s, uint32_t val)
1274 663e8e51 ths
{
1275 663e8e51 ths
    val = le32_to_cpu(val);
1276 663e8e51 ths
    uint32_t address = (val & ~PORT_SELECTION_MASK);
1277 663e8e51 ths
    uint8_t selection = (val & PORT_SELECTION_MASK);
1278 663e8e51 ths
    switch (selection) {
1279 663e8e51 ths
    case PORT_SOFTWARE_RESET:
1280 663e8e51 ths
        nic_reset(s);
1281 663e8e51 ths
        break;
1282 663e8e51 ths
    case PORT_SELFTEST:
1283 aac443e6 Stefan Weil
        TRACE(OTHER, logout("selftest address=0x%08x\n", address));
1284 c227f099 Anthony Liguori
        eepro100_selftest_t data;
1285 663e8e51 ths
        cpu_physical_memory_read(address, (uint8_t *) & data, sizeof(data));
1286 663e8e51 ths
        data.st_sign = 0xffffffff;
1287 663e8e51 ths
        data.st_result = 0;
1288 663e8e51 ths
        cpu_physical_memory_write(address, (uint8_t *) & data, sizeof(data));
1289 663e8e51 ths
        break;
1290 663e8e51 ths
    case PORT_SELECTIVE_RESET:
1291 aac443e6 Stefan Weil
        TRACE(OTHER, logout("selective reset, selftest address=0x%08x\n", address));
1292 663e8e51 ths
        nic_selective_reset(s);
1293 663e8e51 ths
        break;
1294 663e8e51 ths
    default:
1295 663e8e51 ths
        logout("val=0x%08x\n", val);
1296 663e8e51 ths
        missing("unknown port selection");
1297 663e8e51 ths
    }
1298 663e8e51 ths
}
1299 663e8e51 ths
1300 663e8e51 ths
/*****************************************************************************
1301 663e8e51 ths
 *
1302 663e8e51 ths
 * General hardware emulation.
1303 663e8e51 ths
 *
1304 663e8e51 ths
 ****************************************************************************/
1305 663e8e51 ths
1306 663e8e51 ths
static uint8_t eepro100_read1(EEPRO100State * s, uint32_t addr)
1307 663e8e51 ths
{
1308 663e8e51 ths
    uint8_t val;
1309 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1310 663e8e51 ths
        memcpy(&val, &s->mem[addr], sizeof(val));
1311 663e8e51 ths
    }
1312 663e8e51 ths
1313 663e8e51 ths
    switch (addr) {
1314 663e8e51 ths
    case SCBStatus:
1315 663e8e51 ths
        //~ val = eepro100_read_status(s);
1316 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1317 663e8e51 ths
        break;
1318 663e8e51 ths
    case SCBAck:
1319 663e8e51 ths
        //~ val = eepro100_read_status(s);
1320 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1321 663e8e51 ths
        break;
1322 663e8e51 ths
    case SCBCmd:
1323 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1324 663e8e51 ths
        //~ val = eepro100_read_command(s);
1325 663e8e51 ths
        break;
1326 663e8e51 ths
    case SCBIntmask:
1327 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1328 663e8e51 ths
        break;
1329 663e8e51 ths
    case SCBPort + 3:
1330 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1331 663e8e51 ths
        break;
1332 663e8e51 ths
    case SCBeeprom:
1333 663e8e51 ths
        val = eepro100_read_eeprom(s);
1334 663e8e51 ths
        break;
1335 663e8e51 ths
    case 0x1b:                 /* PMDR (power management driver register) */
1336 663e8e51 ths
        val = 0;
1337 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1338 663e8e51 ths
        break;
1339 663e8e51 ths
    case 0x1d:                 /* general status register */
1340 663e8e51 ths
        /* 100 Mbps full duplex, valid link */
1341 663e8e51 ths
        val = 0x07;
1342 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=General Status val=%02x\n", val));
1343 663e8e51 ths
        break;
1344 663e8e51 ths
    default:
1345 663e8e51 ths
        logout("addr=%s val=0x%02x\n", regname(addr), val);
1346 663e8e51 ths
        missing("unknown byte read");
1347 663e8e51 ths
    }
1348 663e8e51 ths
    return val;
1349 663e8e51 ths
}
1350 663e8e51 ths
1351 663e8e51 ths
static uint16_t eepro100_read2(EEPRO100State * s, uint32_t addr)
1352 663e8e51 ths
{
1353 663e8e51 ths
    uint16_t val;
1354 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1355 663e8e51 ths
        memcpy(&val, &s->mem[addr], sizeof(val));
1356 663e8e51 ths
    }
1357 663e8e51 ths
1358 663e8e51 ths
    switch (addr) {
1359 663e8e51 ths
    case SCBStatus:
1360 663e8e51 ths
        //~ val = eepro100_read_status(s);
1361 dbbaaff6 =?UTF-8?q?Reimar=20D=C3=B6ffinger?=
    case SCBCmd:
1362 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1363 663e8e51 ths
        break;
1364 663e8e51 ths
    case SCBeeprom:
1365 663e8e51 ths
        val = eepro100_read_eeprom(s);
1366 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1367 663e8e51 ths
        break;
1368 663e8e51 ths
    default:
1369 663e8e51 ths
        logout("addr=%s val=0x%04x\n", regname(addr), val);
1370 663e8e51 ths
        missing("unknown word read");
1371 663e8e51 ths
    }
1372 663e8e51 ths
    return val;
1373 663e8e51 ths
}
1374 663e8e51 ths
1375 663e8e51 ths
static uint32_t eepro100_read4(EEPRO100State * s, uint32_t addr)
1376 663e8e51 ths
{
1377 663e8e51 ths
    uint32_t val;
1378 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1379 663e8e51 ths
        memcpy(&val, &s->mem[addr], sizeof(val));
1380 663e8e51 ths
    }
1381 663e8e51 ths
1382 663e8e51 ths
    switch (addr) {
1383 663e8e51 ths
    case SCBStatus:
1384 663e8e51 ths
        //~ val = eepro100_read_status(s);
1385 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1386 663e8e51 ths
        break;
1387 663e8e51 ths
    case SCBPointer:
1388 663e8e51 ths
        //~ val = eepro100_read_pointer(s);
1389 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1390 663e8e51 ths
        break;
1391 663e8e51 ths
    case SCBPort:
1392 663e8e51 ths
        val = eepro100_read_port(s);
1393 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1394 663e8e51 ths
        break;
1395 663e8e51 ths
    case SCBCtrlMDI:
1396 663e8e51 ths
        val = eepro100_read_mdi(s);
1397 663e8e51 ths
        break;
1398 663e8e51 ths
    default:
1399 663e8e51 ths
        logout("addr=%s val=0x%08x\n", regname(addr), val);
1400 663e8e51 ths
        missing("unknown longword read");
1401 663e8e51 ths
    }
1402 663e8e51 ths
    return val;
1403 663e8e51 ths
}
1404 663e8e51 ths
1405 663e8e51 ths
static void eepro100_write1(EEPRO100State * s, uint32_t addr, uint8_t val)
1406 663e8e51 ths
{
1407 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1408 663e8e51 ths
        memcpy(&s->mem[addr], &val, sizeof(val));
1409 663e8e51 ths
    }
1410 663e8e51 ths
1411 aac443e6 Stefan Weil
    TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1412 663e8e51 ths
1413 663e8e51 ths
    switch (addr) {
1414 663e8e51 ths
    case SCBStatus:
1415 663e8e51 ths
        //~ eepro100_write_status(s, val);
1416 663e8e51 ths
        break;
1417 663e8e51 ths
    case SCBAck:
1418 663e8e51 ths
        eepro100_acknowledge(s);
1419 663e8e51 ths
        break;
1420 663e8e51 ths
    case SCBCmd:
1421 663e8e51 ths
        eepro100_write_command(s, val);
1422 663e8e51 ths
        break;
1423 663e8e51 ths
    case SCBIntmask:
1424 663e8e51 ths
        if (val & BIT(1)) {
1425 663e8e51 ths
            eepro100_swi_interrupt(s);
1426 663e8e51 ths
        }
1427 663e8e51 ths
        eepro100_interrupt(s, 0);
1428 663e8e51 ths
        break;
1429 663e8e51 ths
    case SCBPort + 3:
1430 aac443e6 Stefan Weil
    case SCBFlow:       /* does not exist on 82557 */
1431 3257d2b6 ths
    case SCBFlow + 1:
1432 3257d2b6 ths
    case SCBFlow + 2:
1433 3257d2b6 ths
    case SCBFlow + 3:
1434 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%02x\n", regname(addr), val));
1435 663e8e51 ths
        break;
1436 663e8e51 ths
    case SCBeeprom:
1437 663e8e51 ths
        eepro100_write_eeprom(s->eeprom, val);
1438 663e8e51 ths
        break;
1439 663e8e51 ths
    default:
1440 663e8e51 ths
        logout("addr=%s val=0x%02x\n", regname(addr), val);
1441 663e8e51 ths
        missing("unknown byte write");
1442 663e8e51 ths
    }
1443 663e8e51 ths
}
1444 663e8e51 ths
1445 663e8e51 ths
static void eepro100_write2(EEPRO100State * s, uint32_t addr, uint16_t val)
1446 663e8e51 ths
{
1447 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1448 663e8e51 ths
        memcpy(&s->mem[addr], &val, sizeof(val));
1449 663e8e51 ths
    }
1450 663e8e51 ths
1451 aac443e6 Stefan Weil
    TRACE(OTHER, logout("addr=%s val=0x%04x\n", regname(addr), val));
1452 663e8e51 ths
1453 663e8e51 ths
    switch (addr) {
1454 663e8e51 ths
    case SCBStatus:
1455 663e8e51 ths
        //~ eepro100_write_status(s, val);
1456 663e8e51 ths
        eepro100_acknowledge(s);
1457 663e8e51 ths
        break;
1458 663e8e51 ths
    case SCBCmd:
1459 663e8e51 ths
        eepro100_write_command(s, val);
1460 663e8e51 ths
        eepro100_write1(s, SCBIntmask, val >> 8);
1461 663e8e51 ths
        break;
1462 663e8e51 ths
    case SCBeeprom:
1463 663e8e51 ths
        eepro100_write_eeprom(s->eeprom, val);
1464 663e8e51 ths
        break;
1465 663e8e51 ths
    default:
1466 663e8e51 ths
        logout("addr=%s val=0x%04x\n", regname(addr), val);
1467 663e8e51 ths
        missing("unknown word write");
1468 663e8e51 ths
    }
1469 663e8e51 ths
}
1470 663e8e51 ths
1471 663e8e51 ths
static void eepro100_write4(EEPRO100State * s, uint32_t addr, uint32_t val)
1472 663e8e51 ths
{
1473 663e8e51 ths
    if (addr <= sizeof(s->mem) - sizeof(val)) {
1474 663e8e51 ths
        memcpy(&s->mem[addr], &val, sizeof(val));
1475 663e8e51 ths
    }
1476 663e8e51 ths
1477 663e8e51 ths
    switch (addr) {
1478 663e8e51 ths
    case SCBPointer:
1479 663e8e51 ths
        eepro100_write_pointer(s, val);
1480 663e8e51 ths
        break;
1481 663e8e51 ths
    case SCBPort:
1482 aac443e6 Stefan Weil
        TRACE(OTHER, logout("addr=%s val=0x%08x\n", regname(addr), val));
1483 663e8e51 ths
        eepro100_write_port(s, val);
1484 663e8e51 ths
        break;
1485 663e8e51 ths
    case SCBCtrlMDI:
1486 663e8e51 ths
        eepro100_write_mdi(s, val);
1487 663e8e51 ths
        break;
1488 663e8e51 ths
    default:
1489 663e8e51 ths
        logout("addr=%s val=0x%08x\n", regname(addr), val);
1490 663e8e51 ths
        missing("unknown longword write");
1491 663e8e51 ths
    }
1492 663e8e51 ths
}
1493 663e8e51 ths
1494 aac443e6 Stefan Weil
/*****************************************************************************
1495 aac443e6 Stefan Weil
 *
1496 aac443e6 Stefan Weil
 * Port mapped I/O.
1497 aac443e6 Stefan Weil
 *
1498 aac443e6 Stefan Weil
 ****************************************************************************/
1499 aac443e6 Stefan Weil
1500 663e8e51 ths
static uint32_t ioport_read1(void *opaque, uint32_t addr)
1501 663e8e51 ths
{
1502 663e8e51 ths
    EEPRO100State *s = opaque;
1503 663e8e51 ths
    //~ logout("addr=%s\n", regname(addr));
1504 663e8e51 ths
    return eepro100_read1(s, addr - s->region[1]);
1505 663e8e51 ths
}
1506 663e8e51 ths
1507 663e8e51 ths
static uint32_t ioport_read2(void *opaque, uint32_t addr)
1508 663e8e51 ths
{
1509 663e8e51 ths
    EEPRO100State *s = opaque;
1510 663e8e51 ths
    return eepro100_read2(s, addr - s->region[1]);
1511 663e8e51 ths
}
1512 663e8e51 ths
1513 663e8e51 ths
static uint32_t ioport_read4(void *opaque, uint32_t addr)
1514 663e8e51 ths
{
1515 663e8e51 ths
    EEPRO100State *s = opaque;
1516 663e8e51 ths
    return eepro100_read4(s, addr - s->region[1]);
1517 663e8e51 ths
}
1518 663e8e51 ths
1519 663e8e51 ths
static void ioport_write1(void *opaque, uint32_t addr, uint32_t val)
1520 663e8e51 ths
{
1521 663e8e51 ths
    EEPRO100State *s = opaque;
1522 663e8e51 ths
    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
1523 663e8e51 ths
    eepro100_write1(s, addr - s->region[1], val);
1524 663e8e51 ths
}
1525 663e8e51 ths
1526 663e8e51 ths
static void ioport_write2(void *opaque, uint32_t addr, uint32_t val)
1527 663e8e51 ths
{
1528 663e8e51 ths
    EEPRO100State *s = opaque;
1529 663e8e51 ths
    eepro100_write2(s, addr - s->region[1], val);
1530 663e8e51 ths
}
1531 663e8e51 ths
1532 663e8e51 ths
static void ioport_write4(void *opaque, uint32_t addr, uint32_t val)
1533 663e8e51 ths
{
1534 663e8e51 ths
    EEPRO100State *s = opaque;
1535 663e8e51 ths
    eepro100_write4(s, addr - s->region[1], val);
1536 663e8e51 ths
}
1537 663e8e51 ths
1538 663e8e51 ths
/***********************************************************/
1539 663e8e51 ths
/* PCI EEPRO100 definitions */
1540 663e8e51 ths
1541 663e8e51 ths
static void pci_map(PCIDevice * pci_dev, int region_num,
1542 6e355d90 Isaku Yamahata
                    pcibus_t addr, pcibus_t size, int type)
1543 663e8e51 ths
{
1544 273a2142 Juan Quintela
    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
1545 663e8e51 ths
1546 89e8b13c Isaku Yamahata
    TRACE(OTHER, logout("region %d, addr=0x%08"FMT_PCIBUS", "
1547 89e8b13c Isaku Yamahata
          "size=0x%08"FMT_PCIBUS", type=%d\n",
1548 aac443e6 Stefan Weil
          region_num, addr, size, type));
1549 663e8e51 ths
1550 663e8e51 ths
    assert(region_num == 1);
1551 663e8e51 ths
    register_ioport_write(addr, size, 1, ioport_write1, s);
1552 663e8e51 ths
    register_ioport_read(addr, size, 1, ioport_read1, s);
1553 663e8e51 ths
    register_ioport_write(addr, size, 2, ioport_write2, s);
1554 663e8e51 ths
    register_ioport_read(addr, size, 2, ioport_read2, s);
1555 663e8e51 ths
    register_ioport_write(addr, size, 4, ioport_write4, s);
1556 663e8e51 ths
    register_ioport_read(addr, size, 4, ioport_read4, s);
1557 663e8e51 ths
1558 663e8e51 ths
    s->region[region_num] = addr;
1559 663e8e51 ths
}
1560 663e8e51 ths
1561 aac443e6 Stefan Weil
/*****************************************************************************
1562 aac443e6 Stefan Weil
 *
1563 aac443e6 Stefan Weil
 * Memory mapped I/O.
1564 aac443e6 Stefan Weil
 *
1565 aac443e6 Stefan Weil
 ****************************************************************************/
1566 aac443e6 Stefan Weil
1567 c227f099 Anthony Liguori
static void pci_mmio_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1568 663e8e51 ths
{
1569 663e8e51 ths
    EEPRO100State *s = opaque;
1570 663e8e51 ths
    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
1571 663e8e51 ths
    eepro100_write1(s, addr, val);
1572 663e8e51 ths
}
1573 663e8e51 ths
1574 c227f099 Anthony Liguori
static void pci_mmio_writew(void *opaque, target_phys_addr_t addr, uint32_t val)
1575 663e8e51 ths
{
1576 663e8e51 ths
    EEPRO100State *s = opaque;
1577 663e8e51 ths
    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
1578 663e8e51 ths
    eepro100_write2(s, addr, val);
1579 663e8e51 ths
}
1580 663e8e51 ths
1581 c227f099 Anthony Liguori
static void pci_mmio_writel(void *opaque, target_phys_addr_t addr, uint32_t val)
1582 663e8e51 ths
{
1583 663e8e51 ths
    EEPRO100State *s = opaque;
1584 663e8e51 ths
    //~ logout("addr=%s val=0x%02x\n", regname(addr), val);
1585 663e8e51 ths
    eepro100_write4(s, addr, val);
1586 663e8e51 ths
}
1587 663e8e51 ths
1588 c227f099 Anthony Liguori
static uint32_t pci_mmio_readb(void *opaque, target_phys_addr_t addr)
1589 663e8e51 ths
{
1590 663e8e51 ths
    EEPRO100State *s = opaque;
1591 663e8e51 ths
    //~ logout("addr=%s\n", regname(addr));
1592 663e8e51 ths
    return eepro100_read1(s, addr);
1593 663e8e51 ths
}
1594 663e8e51 ths
1595 c227f099 Anthony Liguori
static uint32_t pci_mmio_readw(void *opaque, target_phys_addr_t addr)
1596 663e8e51 ths
{
1597 663e8e51 ths
    EEPRO100State *s = opaque;
1598 663e8e51 ths
    //~ logout("addr=%s\n", regname(addr));
1599 663e8e51 ths
    return eepro100_read2(s, addr);
1600 663e8e51 ths
}
1601 663e8e51 ths
1602 c227f099 Anthony Liguori
static uint32_t pci_mmio_readl(void *opaque, target_phys_addr_t addr)
1603 663e8e51 ths
{
1604 663e8e51 ths
    EEPRO100State *s = opaque;
1605 663e8e51 ths
    //~ logout("addr=%s\n", regname(addr));
1606 663e8e51 ths
    return eepro100_read4(s, addr);
1607 663e8e51 ths
}
1608 663e8e51 ths
1609 d60efc6b Blue Swirl
static CPUWriteMemoryFunc * const pci_mmio_write[] = {
1610 663e8e51 ths
    pci_mmio_writeb,
1611 663e8e51 ths
    pci_mmio_writew,
1612 663e8e51 ths
    pci_mmio_writel
1613 663e8e51 ths
};
1614 663e8e51 ths
1615 d60efc6b Blue Swirl
static CPUReadMemoryFunc * const pci_mmio_read[] = {
1616 663e8e51 ths
    pci_mmio_readb,
1617 663e8e51 ths
    pci_mmio_readw,
1618 663e8e51 ths
    pci_mmio_readl
1619 663e8e51 ths
};
1620 663e8e51 ths
1621 663e8e51 ths
static void pci_mmio_map(PCIDevice * pci_dev, int region_num,
1622 6e355d90 Isaku Yamahata
                         pcibus_t addr, pcibus_t size, int type)
1623 663e8e51 ths
{
1624 273a2142 Juan Quintela
    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
1625 663e8e51 ths
1626 89e8b13c Isaku Yamahata
    TRACE(OTHER, logout("region %d, addr=0x%08"FMT_PCIBUS", "
1627 89e8b13c Isaku Yamahata
          "size=0x%08"FMT_PCIBUS", type=%d\n",
1628 aac443e6 Stefan Weil
          region_num, addr, size, type));
1629 663e8e51 ths
1630 663e8e51 ths
    if (region_num == 0) {
1631 663e8e51 ths
        /* Map control / status registers. */
1632 273a2142 Juan Quintela
        cpu_register_physical_memory(addr, size, s->mmio_index);
1633 273a2142 Juan Quintela
        s->region[region_num] = addr;
1634 663e8e51 ths
    }
1635 663e8e51 ths
}
1636 663e8e51 ths
1637 e00e365e Mark McLoughlin
static int nic_can_receive(VLANClientState *nc)
1638 663e8e51 ths
{
1639 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1640 aac443e6 Stefan Weil
    TRACE(RXTX, logout("%p\n", s));
1641 663e8e51 ths
    return get_ru_state(s) == ru_ready;
1642 663e8e51 ths
    //~ return !eepro100_buffer_full(s);
1643 663e8e51 ths
}
1644 663e8e51 ths
1645 e00e365e Mark McLoughlin
static ssize_t nic_receive(VLANClientState *nc, const uint8_t * buf, size_t size)
1646 663e8e51 ths
{
1647 663e8e51 ths
    /* TODO:
1648 663e8e51 ths
     * - Magic packets should set bit 30 in power management driver register.
1649 663e8e51 ths
     * - Interesting packets should set bit 29 in power management driver register.
1650 663e8e51 ths
     */
1651 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1652 663e8e51 ths
    uint16_t rfd_status = 0xa000;
1653 663e8e51 ths
    static const uint8_t broadcast_macaddr[6] =
1654 663e8e51 ths
        { 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
1655 663e8e51 ths
1656 663e8e51 ths
    /* TODO: check multiple IA bit. */
1657 7f1e9d4e Kevin Wolf
    if (s->configuration[20] & BIT(6)) {
1658 7f1e9d4e Kevin Wolf
        missing("Multiple IA bit");
1659 7f1e9d4e Kevin Wolf
        return -1;
1660 7f1e9d4e Kevin Wolf
    }
1661 663e8e51 ths
1662 663e8e51 ths
    if (s->configuration[8] & 0x80) {
1663 663e8e51 ths
        /* CSMA is disabled. */
1664 663e8e51 ths
        logout("%p received while CSMA is disabled\n", s);
1665 4f1c942b Mark McLoughlin
        return -1;
1666 663e8e51 ths
    } else if (size < 64 && (s->configuration[7] & 1)) {
1667 663e8e51 ths
        /* Short frame and configuration byte 7/0 (discard short receive) set:
1668 663e8e51 ths
         * Short frame is discarded */
1669 067d01de Stefan Weil
        logout("%p received short frame (%zu byte)\n", s, size);
1670 663e8e51 ths
        s->statistics.rx_short_frame_errors++;
1671 4f1c942b Mark McLoughlin
        //~ return -1;
1672 663e8e51 ths
    } else if ((size > MAX_ETH_FRAME_SIZE + 4) && !(s->configuration[18] & 8)) {
1673 663e8e51 ths
        /* Long frame and configuration byte 18/3 (long receive ok) not set:
1674 663e8e51 ths
         * Long frames are discarded. */
1675 067d01de Stefan Weil
        logout("%p received long frame (%zu byte), ignored\n", s, size);
1676 4f1c942b Mark McLoughlin
        return -1;
1677 508ef936 Gerd Hoffmann
    } else if (memcmp(buf, s->conf.macaddr.a, 6) == 0) {       // !!!
1678 663e8e51 ths
        /* Frame matches individual address. */
1679 663e8e51 ths
        /* TODO: check configuration byte 15/4 (ignore U/L). */
1680 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame for me, len=%zu\n", s, size));
1681 663e8e51 ths
    } else if (memcmp(buf, broadcast_macaddr, 6) == 0) {
1682 663e8e51 ths
        /* Broadcast frame. */
1683 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received broadcast, len=%zu\n", s, size));
1684 663e8e51 ths
        rfd_status |= 0x0002;
1685 7b8737de Stefan Weil
    } else if (buf[0] & 0x01) {
1686 663e8e51 ths
        /* Multicast frame. */
1687 7b8737de Stefan Weil
        TRACE(RXTX, logout("%p received multicast, len=%zu,%s\n", s, size, nic_dump(buf, size)));
1688 7f1e9d4e Kevin Wolf
        if (s->configuration[21] & BIT(3)) {
1689 7b8737de Stefan Weil
          /* Multicast all bit is set, receive all multicast frames. */
1690 7b8737de Stefan Weil
        } else {
1691 7b8737de Stefan Weil
          unsigned mcast_idx = compute_mcast_idx(buf);
1692 7b8737de Stefan Weil
          assert(mcast_idx < 64);
1693 7b8737de Stefan Weil
          if (s->mult[mcast_idx >> 3] & (1 << (mcast_idx & 7))) {
1694 7b8737de Stefan Weil
            /* Multicast frame is allowed in hash table. */
1695 7b8737de Stefan Weil
          } else if (s->configuration[15] & 1) {
1696 7b8737de Stefan Weil
              /* Promiscuous: receive all. */
1697 7b8737de Stefan Weil
              rfd_status |= 0x0004;
1698 7b8737de Stefan Weil
          } else {
1699 7b8737de Stefan Weil
              TRACE(RXTX, logout("%p multicast ignored\n", s));
1700 7b8737de Stefan Weil
              return -1;
1701 7b8737de Stefan Weil
          }
1702 663e8e51 ths
        }
1703 7b8737de Stefan Weil
        /* TODO: Next not for promiscuous mode? */
1704 663e8e51 ths
        rfd_status |= 0x0002;
1705 663e8e51 ths
    } else if (s->configuration[15] & 1) {
1706 663e8e51 ths
        /* Promiscuous: receive all. */
1707 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame in promiscuous mode, len=%zu\n", s, size));
1708 663e8e51 ths
        rfd_status |= 0x0004;
1709 663e8e51 ths
    } else {
1710 067d01de Stefan Weil
        TRACE(RXTX, logout("%p received frame, ignored, len=%zu,%s\n", s, size,
1711 aac443e6 Stefan Weil
              nic_dump(buf, size)));
1712 4f1c942b Mark McLoughlin
        return size;
1713 663e8e51 ths
    }
1714 663e8e51 ths
1715 663e8e51 ths
    if (get_ru_state(s) != ru_ready) {
1716 aac443e6 Stefan Weil
        /* No resources available. */
1717 aac443e6 Stefan Weil
        logout("no resources, state=%u\n", get_ru_state(s));
1718 663e8e51 ths
        s->statistics.rx_resource_errors++;
1719 aac443e6 Stefan Weil
        //~ assert(!"no resources");
1720 4f1c942b Mark McLoughlin
        return -1;
1721 663e8e51 ths
    }
1722 663e8e51 ths
    //~ !!!
1723 663e8e51 ths
//~ $3 = {status = 0x0, command = 0xc000, link = 0x2d220, rx_buf_addr = 0x207dc, count = 0x0, size = 0x5f8, packet = {0x0 <repeats 1518 times>}}
1724 c227f099 Anthony Liguori
    eepro100_rx_t rx;
1725 663e8e51 ths
    cpu_physical_memory_read(s->ru_base + s->ru_offset, (uint8_t *) & rx,
1726 c227f099 Anthony Liguori
                             offsetof(eepro100_rx_t, packet));
1727 663e8e51 ths
    uint16_t rfd_command = le16_to_cpu(rx.command);
1728 663e8e51 ths
    uint16_t rfd_size = le16_to_cpu(rx.size);
1729 7f1e9d4e Kevin Wolf
1730 7f1e9d4e Kevin Wolf
    if (size > rfd_size) {
1731 7f1e9d4e Kevin Wolf
        logout("Receive buffer (%" PRId16 " bytes) too small for data "
1732 7f1e9d4e Kevin Wolf
            "(%zu bytes); data truncated\n", rfd_size, size);
1733 7f1e9d4e Kevin Wolf
        size = rfd_size;
1734 7f1e9d4e Kevin Wolf
    }
1735 663e8e51 ths
    if (size < 64) {
1736 663e8e51 ths
        rfd_status |= 0x0080;
1737 663e8e51 ths
    }
1738 aac443e6 Stefan Weil
    TRACE(OTHER, logout("command 0x%04x, link 0x%08x, addr 0x%08x, size %u\n",
1739 aac443e6 Stefan Weil
          rfd_command, rx.link, rx.rx_buf_addr, rfd_size));
1740 c227f099 Anthony Liguori
    stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, status),
1741 663e8e51 ths
             rfd_status);
1742 c227f099 Anthony Liguori
    stw_phys(s->ru_base + s->ru_offset + offsetof(eepro100_rx_t, count), size);
1743 663e8e51 ths
    /* Early receive interrupt not supported. */
1744 663e8e51 ths
    //~ eepro100_er_interrupt(s);
1745 663e8e51 ths
    /* Receive CRC Transfer not supported. */
1746 7f1e9d4e Kevin Wolf
    if (s->configuration[18] & 4) {
1747 7f1e9d4e Kevin Wolf
        missing("Receive CRC Transfer");
1748 7f1e9d4e Kevin Wolf
        return -1;
1749 7f1e9d4e Kevin Wolf
    }
1750 663e8e51 ths
    /* TODO: check stripping enable bit. */
1751 663e8e51 ths
    //~ assert(!(s->configuration[17] & 1));
1752 663e8e51 ths
    cpu_physical_memory_write(s->ru_base + s->ru_offset +
1753 c227f099 Anthony Liguori
                              offsetof(eepro100_rx_t, packet), buf, size);
1754 663e8e51 ths
    s->statistics.rx_good_frames++;
1755 663e8e51 ths
    eepro100_fr_interrupt(s);
1756 663e8e51 ths
    s->ru_offset = le32_to_cpu(rx.link);
1757 663e8e51 ths
    if (rfd_command & 0x8000) {
1758 663e8e51 ths
        /* EL bit is set, so this was the last frame. */
1759 7f1e9d4e Kevin Wolf
        logout("receive: Running out of frames\n");
1760 7f1e9d4e Kevin Wolf
        set_ru_state(s, ru_suspended);
1761 663e8e51 ths
    }
1762 663e8e51 ths
    if (rfd_command & 0x4000) {
1763 663e8e51 ths
        /* S bit is set. */
1764 663e8e51 ths
        set_ru_state(s, ru_suspended);
1765 663e8e51 ths
    }
1766 4f1c942b Mark McLoughlin
    return size;
1767 663e8e51 ths
}
1768 663e8e51 ths
1769 151b2986 Juan Quintela
static const VMStateDescription vmstate_eepro100 = {
1770 151b2986 Juan Quintela
    .version_id = 3,
1771 151b2986 Juan Quintela
    .minimum_version_id = 2,
1772 151b2986 Juan Quintela
    .minimum_version_id_old = 2,
1773 151b2986 Juan Quintela
    .fields      = (VMStateField []) {
1774 151b2986 Juan Quintela
        VMSTATE_PCI_DEVICE(dev, EEPRO100State),
1775 151b2986 Juan Quintela
        VMSTATE_UNUSED(32),
1776 151b2986 Juan Quintela
        VMSTATE_BUFFER(mult, EEPRO100State),
1777 151b2986 Juan Quintela
        VMSTATE_BUFFER(mem, EEPRO100State),
1778 151b2986 Juan Quintela
        /* Save all members of struct between scb_stat and mem. */
1779 151b2986 Juan Quintela
        VMSTATE_UINT8(scb_stat, EEPRO100State),
1780 151b2986 Juan Quintela
        VMSTATE_UINT8(int_stat, EEPRO100State),
1781 151b2986 Juan Quintela
        VMSTATE_UNUSED(3*4),
1782 151b2986 Juan Quintela
        VMSTATE_MACADDR(conf.macaddr, EEPRO100State),
1783 151b2986 Juan Quintela
        VMSTATE_UNUSED(19*4),
1784 151b2986 Juan Quintela
        VMSTATE_UINT16_ARRAY(mdimem, EEPRO100State, 32),
1785 151b2986 Juan Quintela
        /* The eeprom should be saved and restored by its own routines. */
1786 151b2986 Juan Quintela
        VMSTATE_UINT32(device, EEPRO100State),
1787 151b2986 Juan Quintela
        /* TODO check device. */
1788 151b2986 Juan Quintela
        VMSTATE_UINT32(pointer, EEPRO100State),
1789 151b2986 Juan Quintela
        VMSTATE_UINT32(cu_base, EEPRO100State),
1790 151b2986 Juan Quintela
        VMSTATE_UINT32(cu_offset, EEPRO100State),
1791 151b2986 Juan Quintela
        VMSTATE_UINT32(ru_base, EEPRO100State),
1792 151b2986 Juan Quintela
        VMSTATE_UINT32(ru_offset, EEPRO100State),
1793 151b2986 Juan Quintela
        VMSTATE_UINT32(statsaddr, EEPRO100State),
1794 ba42b646 Stefan Weil
        /* Save eepro100_stats_t statistics. */
1795 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_good_frames, EEPRO100State),
1796 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_max_collisions, EEPRO100State),
1797 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_late_collisions, EEPRO100State),
1798 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_underruns, EEPRO100State),
1799 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_lost_crs, EEPRO100State),
1800 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_deferred, EEPRO100State),
1801 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_single_collisions, EEPRO100State),
1802 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_multiple_collisions, EEPRO100State),
1803 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.tx_total_collisions, EEPRO100State),
1804 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_good_frames, EEPRO100State),
1805 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_crc_errors, EEPRO100State),
1806 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_alignment_errors, EEPRO100State),
1807 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_resource_errors, EEPRO100State),
1808 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_overrun_errors, EEPRO100State),
1809 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_cdt_errors, EEPRO100State),
1810 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.rx_short_frame_errors, EEPRO100State),
1811 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_xmt_pause, EEPRO100State),
1812 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_rcv_pause, EEPRO100State),
1813 151b2986 Juan Quintela
        VMSTATE_UINT32(statistics.fc_rcv_unsupported, EEPRO100State),
1814 151b2986 Juan Quintela
        VMSTATE_UINT16(statistics.xmt_tco_frames, EEPRO100State),
1815 151b2986 Juan Quintela
        VMSTATE_UINT16(statistics.rcv_tco_frames, EEPRO100State),
1816 2657c663 balrog
#if 0
1817 151b2986 Juan Quintela
        VMSTATE_UINT16(status, EEPRO100State),
1818 2657c663 balrog
#endif
1819 151b2986 Juan Quintela
        /* Configuration bytes. */
1820 151b2986 Juan Quintela
        VMSTATE_BUFFER(configuration, EEPRO100State),
1821 151b2986 Juan Quintela
        VMSTATE_END_OF_LIST()
1822 aac443e6 Stefan Weil
    }
1823 151b2986 Juan Quintela
};
1824 663e8e51 ths
1825 e00e365e Mark McLoughlin
static void nic_cleanup(VLANClientState *nc)
1826 b946a153 aliguori
{
1827 e00e365e Mark McLoughlin
    EEPRO100State *s = DO_UPCAST(NICState, nc, nc)->opaque;
1828 b946a153 aliguori
1829 e00e365e Mark McLoughlin
    s->nic = NULL;
1830 b946a153 aliguori
}
1831 b946a153 aliguori
1832 c4c270e2 Stefan Weil
static int pci_nic_uninit(PCIDevice *pci_dev)
1833 b946a153 aliguori
{
1834 c4c270e2 Stefan Weil
    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
1835 b946a153 aliguori
1836 b946a153 aliguori
    cpu_unregister_io_memory(s->mmio_index);
1837 151b2986 Juan Quintela
    vmstate_unregister(s->vmstate, s);
1838 508ef936 Gerd Hoffmann
    eeprom93xx_free(s->eeprom);
1839 e00e365e Mark McLoughlin
    qemu_del_vlan_client(&s->nic->nc);
1840 b946a153 aliguori
    return 0;
1841 b946a153 aliguori
}
1842 b946a153 aliguori
1843 e00e365e Mark McLoughlin
static NetClientInfo net_eepro100_info = {
1844 e00e365e Mark McLoughlin
    .type = NET_CLIENT_TYPE_NIC,
1845 e00e365e Mark McLoughlin
    .size = sizeof(NICState),
1846 e00e365e Mark McLoughlin
    .can_receive = nic_can_receive,
1847 e00e365e Mark McLoughlin
    .receive = nic_receive,
1848 e00e365e Mark McLoughlin
    .cleanup = nic_cleanup,
1849 e00e365e Mark McLoughlin
};
1850 e00e365e Mark McLoughlin
1851 81a322d4 Gerd Hoffmann
static int nic_init(PCIDevice *pci_dev, uint32_t device)
1852 663e8e51 ths
{
1853 273a2142 Juan Quintela
    EEPRO100State *s = DO_UPCAST(EEPRO100State, dev, pci_dev);
1854 663e8e51 ths
1855 aac443e6 Stefan Weil
    TRACE(OTHER, logout("\n"));
1856 663e8e51 ths
1857 663e8e51 ths
    s->device = device;
1858 663e8e51 ths
1859 663e8e51 ths
    pci_reset(s);
1860 663e8e51 ths
1861 663e8e51 ths
    /* Add 64 * 2 EEPROM. i82557 and i82558 support a 64 word EEPROM,
1862 663e8e51 ths
     * i82559 and later support 64 or 256 word EEPROM. */
1863 663e8e51 ths
    s->eeprom = eeprom93xx_new(EEPROM_SIZE);
1864 663e8e51 ths
1865 663e8e51 ths
    /* Handler for memory-mapped I/O */
1866 273a2142 Juan Quintela
    s->mmio_index =
1867 1eed09cb Avi Kivity
        cpu_register_io_memory(pci_mmio_read, pci_mmio_write, s);
1868 663e8e51 ths
1869 273a2142 Juan Quintela
    pci_register_bar(&s->dev, 0, PCI_MEM_SIZE,
1870 0392a017 Isaku Yamahata
                           PCI_BASE_ADDRESS_SPACE_MEMORY |
1871 0392a017 Isaku Yamahata
                           PCI_BASE_ADDRESS_MEM_PREFETCH, pci_mmio_map);
1872 0392a017 Isaku Yamahata
    pci_register_bar(&s->dev, 1, PCI_IO_SIZE, PCI_BASE_ADDRESS_SPACE_IO,
1873 663e8e51 ths
                           pci_map);
1874 0392a017 Isaku Yamahata
    pci_register_bar(&s->dev, 2, PCI_FLASH_SIZE, PCI_BASE_ADDRESS_SPACE_MEMORY,
1875 663e8e51 ths
                           pci_mmio_map);
1876 663e8e51 ths
1877 508ef936 Gerd Hoffmann
    qemu_macaddr_default_if_unset(&s->conf.macaddr);
1878 663e8e51 ths
    logout("macaddr: %s\n", nic_dump(&s->macaddr[0], 6));
1879 663e8e51 ths
    assert(s->region[1] == 0);
1880 663e8e51 ths
1881 663e8e51 ths
    nic_reset(s);
1882 663e8e51 ths
1883 e00e365e Mark McLoughlin
    s->nic = qemu_new_nic(&net_eepro100_info, &s->conf,
1884 e00e365e Mark McLoughlin
                          pci_dev->qdev.info->name, pci_dev->qdev.id, s);
1885 663e8e51 ths
1886 e00e365e Mark McLoughlin
    qemu_format_nic_info_str(&s->nic->nc, s->conf.macaddr.a);
1887 e00e365e Mark McLoughlin
    TRACE(OTHER, logout("%s\n", s->nic->nc.info_str));
1888 663e8e51 ths
1889 a08d4367 Jan Kiszka
    qemu_register_reset(nic_reset, s);
1890 663e8e51 ths
1891 151b2986 Juan Quintela
    s->vmstate = qemu_malloc(sizeof(vmstate_eepro100));
1892 151b2986 Juan Quintela
    memcpy(s->vmstate, &vmstate_eepro100, sizeof(vmstate_eepro100));
1893 e00e365e Mark McLoughlin
    s->vmstate->name = s->nic->nc.model;
1894 151b2986 Juan Quintela
    vmstate_register(-1, s->vmstate, s);
1895 4e9df06a Stefan Weil
1896 81a322d4 Gerd Hoffmann
    return 0;
1897 663e8e51 ths
}
1898 663e8e51 ths
1899 c4c270e2 Stefan Weil
static int pci_i82550_init(PCIDevice *pci_dev)
1900 c4c270e2 Stefan Weil
{
1901 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82550);
1902 c4c270e2 Stefan Weil
}
1903 c4c270e2 Stefan Weil
1904 c4c270e2 Stefan Weil
static int pci_i82551_init(PCIDevice *pci_dev)
1905 c4c270e2 Stefan Weil
{
1906 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82551);
1907 c4c270e2 Stefan Weil
}
1908 c4c270e2 Stefan Weil
1909 c4c270e2 Stefan Weil
static int pci_i82557a_init(PCIDevice *pci_dev)
1910 c4c270e2 Stefan Weil
{
1911 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82557A);
1912 c4c270e2 Stefan Weil
}
1913 c4c270e2 Stefan Weil
1914 c4c270e2 Stefan Weil
static int pci_i82557b_init(PCIDevice *pci_dev)
1915 c4c270e2 Stefan Weil
{
1916 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82557B);
1917 c4c270e2 Stefan Weil
}
1918 c4c270e2 Stefan Weil
1919 c4c270e2 Stefan Weil
static int pci_i82557c_init(PCIDevice *pci_dev)
1920 c4c270e2 Stefan Weil
{
1921 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82557C);
1922 c4c270e2 Stefan Weil
}
1923 c4c270e2 Stefan Weil
1924 c4c270e2 Stefan Weil
static int pci_i82558a_init(PCIDevice *pci_dev)
1925 c4c270e2 Stefan Weil
{
1926 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82558A);
1927 c4c270e2 Stefan Weil
}
1928 c4c270e2 Stefan Weil
1929 c4c270e2 Stefan Weil
static int pci_i82558b_init(PCIDevice *pci_dev)
1930 c4c270e2 Stefan Weil
{
1931 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82558B);
1932 c4c270e2 Stefan Weil
}
1933 c4c270e2 Stefan Weil
1934 c4c270e2 Stefan Weil
static int pci_i82559a_init(PCIDevice *pci_dev)
1935 c4c270e2 Stefan Weil
{
1936 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82559A);
1937 c4c270e2 Stefan Weil
}
1938 c4c270e2 Stefan Weil
1939 c4c270e2 Stefan Weil
static int pci_i82559b_init(PCIDevice *pci_dev)
1940 c4c270e2 Stefan Weil
{
1941 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82559B);
1942 c4c270e2 Stefan Weil
}
1943 c4c270e2 Stefan Weil
1944 c4c270e2 Stefan Weil
static int pci_i82559c_init(PCIDevice *pci_dev)
1945 9d07d757 Paul Brook
{
1946 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82559C);
1947 9d07d757 Paul Brook
}
1948 9d07d757 Paul Brook
1949 c4c270e2 Stefan Weil
static int pci_i82559er_init(PCIDevice *pci_dev)
1950 663e8e51 ths
{
1951 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82559ER);
1952 663e8e51 ths
}
1953 663e8e51 ths
1954 c4c270e2 Stefan Weil
static int pci_i82562_init(PCIDevice *pci_dev)
1955 663e8e51 ths
{
1956 c4c270e2 Stefan Weil
    return nic_init(pci_dev, i82562);
1957 663e8e51 ths
}
1958 663e8e51 ths
1959 0aab0d3a Gerd Hoffmann
static PCIDeviceInfo eepro100_info[] = {
1960 0aab0d3a Gerd Hoffmann
    {
1961 c4c270e2 Stefan Weil
        .qdev.name = "i82550",
1962 c4c270e2 Stefan Weil
        .qdev.size = sizeof(EEPRO100State),
1963 c4c270e2 Stefan Weil
        .init      = pci_i82550_init,
1964 6a90e308 Stefan Weil
        .exit      = pci_nic_uninit,
1965 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
1966 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
1967 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
1968 508ef936 Gerd Hoffmann
        },
1969 c4c270e2 Stefan Weil
    },{
1970 0aab0d3a Gerd Hoffmann
        .qdev.name = "i82551",
1971 273a2142 Juan Quintela
        .qdev.size = sizeof(EEPRO100State),
1972 0aab0d3a Gerd Hoffmann
        .init      = pci_i82551_init,
1973 e3936fa5 Gerd Hoffmann
        .exit      = pci_nic_uninit,
1974 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
1975 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
1976 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
1977 508ef936 Gerd Hoffmann
        },
1978 0aab0d3a Gerd Hoffmann
    },{
1979 c4c270e2 Stefan Weil
        .qdev.name = "i82557a",
1980 c4c270e2 Stefan Weil
        .qdev.size = sizeof(EEPRO100State),
1981 c4c270e2 Stefan Weil
        .init      = pci_i82557a_init,
1982 6a90e308 Stefan Weil
        .exit      = pci_nic_uninit,
1983 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
1984 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
1985 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
1986 508ef936 Gerd Hoffmann
        },
1987 c4c270e2 Stefan Weil
    },{
1988 0aab0d3a Gerd Hoffmann
        .qdev.name = "i82557b",
1989 273a2142 Juan Quintela
        .qdev.size = sizeof(EEPRO100State),
1990 0aab0d3a Gerd Hoffmann
        .init      = pci_i82557b_init,
1991 e3936fa5 Gerd Hoffmann
        .exit      = pci_nic_uninit,
1992 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
1993 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
1994 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
1995 508ef936 Gerd Hoffmann
        },
1996 0aab0d3a Gerd Hoffmann
    },{
1997 c4c270e2 Stefan Weil
        .qdev.name = "i82557c",
1998 c4c270e2 Stefan Weil
        .qdev.size = sizeof(EEPRO100State),
1999 c4c270e2 Stefan Weil
        .init      = pci_i82557c_init,
2000 6a90e308 Stefan Weil
        .exit      = pci_nic_uninit,
2001 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
2002 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2003 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
2004 508ef936 Gerd Hoffmann
        },
2005 c4c270e2 Stefan Weil
    },{
2006 c4c270e2 Stefan Weil
        .qdev.name = "i82558a",
2007 c4c270e2 Stefan Weil
        .qdev.size = sizeof(EEPRO100State),
2008 c4c270e2 Stefan Weil
        .init      = pci_i82558a_init,
2009 6a90e308 Stefan Weil
        .exit      = pci_nic_uninit,
2010 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
2011 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2012 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
2013 508ef936 Gerd Hoffmann
        },
2014 c4c270e2 Stefan Weil
    },{
2015 c4c270e2 Stefan Weil
        .qdev.name = "i82558b",
2016 c4c270e2 Stefan Weil
        .qdev.size = sizeof(EEPRO100State),
2017 c4c270e2 Stefan Weil
        .init      = pci_i82558b_init,
2018 6a90e308 Stefan Weil
        .exit      = pci_nic_uninit,
2019 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
2020 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2021 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
2022 508ef936 Gerd Hoffmann
        },
2023 c4c270e2 Stefan Weil
    },{
2024 c4c270e2 Stefan Weil
        .qdev.name = "i82559a",
2025 c4c270e2 Stefan Weil
        .qdev.size = sizeof(EEPRO100State),
2026 c4c270e2 Stefan Weil
        .init      = pci_i82559a_init,
2027 6a90e308 Stefan Weil
        .exit      = pci_nic_uninit,
2028 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
2029 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2030 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
2031 508ef936 Gerd Hoffmann
        },
2032 c4c270e2 Stefan Weil
    },{
2033 c4c270e2 Stefan Weil
        .qdev.name = "i82559b",
2034 c4c270e2 Stefan Weil
        .qdev.size = sizeof(EEPRO100State),
2035 c4c270e2 Stefan Weil
        .init      = pci_i82559b_init,
2036 6a90e308 Stefan Weil
        .exit      = pci_nic_uninit,
2037 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
2038 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2039 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
2040 508ef936 Gerd Hoffmann
        },
2041 c4c270e2 Stefan Weil
    },{
2042 c4c270e2 Stefan Weil
        .qdev.name = "i82559c",
2043 c4c270e2 Stefan Weil
        .qdev.size = sizeof(EEPRO100State),
2044 c4c270e2 Stefan Weil
        .init      = pci_i82559c_init,
2045 6a90e308 Stefan Weil
        .exit      = pci_nic_uninit,
2046 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
2047 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2048 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
2049 508ef936 Gerd Hoffmann
        },
2050 c4c270e2 Stefan Weil
    },{
2051 0aab0d3a Gerd Hoffmann
        .qdev.name = "i82559er",
2052 273a2142 Juan Quintela
        .qdev.size = sizeof(EEPRO100State),
2053 0aab0d3a Gerd Hoffmann
        .init      = pci_i82559er_init,
2054 e3936fa5 Gerd Hoffmann
        .exit      = pci_nic_uninit,
2055 938a6324 Stefan Weil
        .romfile   = "pxe-i82559er.bin",
2056 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
2057 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2058 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
2059 508ef936 Gerd Hoffmann
        },
2060 0aab0d3a Gerd Hoffmann
    },{
2061 c4c270e2 Stefan Weil
        .qdev.name = "i82562",
2062 c4c270e2 Stefan Weil
        .qdev.size = sizeof(EEPRO100State),
2063 c4c270e2 Stefan Weil
        .init      = pci_i82562_init,
2064 6a90e308 Stefan Weil
        .exit      = pci_nic_uninit,
2065 508ef936 Gerd Hoffmann
        .qdev.props = (Property[]) {
2066 508ef936 Gerd Hoffmann
            DEFINE_NIC_PROPERTIES(EEPRO100State, conf),
2067 508ef936 Gerd Hoffmann
            DEFINE_PROP_END_OF_LIST(),
2068 508ef936 Gerd Hoffmann
        },
2069 c4c270e2 Stefan Weil
    },{
2070 0aab0d3a Gerd Hoffmann
        /* end of list */
2071 0aab0d3a Gerd Hoffmann
    }
2072 0aab0d3a Gerd Hoffmann
};
2073 0aab0d3a Gerd Hoffmann
2074 9d07d757 Paul Brook
static void eepro100_register_devices(void)
2075 663e8e51 ths
{
2076 0aab0d3a Gerd Hoffmann
    pci_qdev_register_many(eepro100_info);
2077 663e8e51 ths
}
2078 663e8e51 ths
2079 9d07d757 Paul Brook
device_init(eepro100_register_devices)