Statistics
| Branch: | Revision:

root / hw / eepro100.c @ 9c9efb6b

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

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