Statistics
| Branch: | Revision:

root / hw / ne2000.c @ 80cabfad

History | View | Annotate | Download (13.6 kB)

1
/*
2
 * QEMU NE2000 emulation
3
 * 
4
 * Copyright (c) 2003-2004 Fabrice Bellard
5
 * 
6
 * Permission is hereby granted, free of charge, to any person obtaining a copy
7
 * of this software and associated documentation files (the "Software"), to deal
8
 * in the Software without restriction, including without limitation the rights
9
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10
 * copies of the Software, and to permit persons to whom the Software is
11
 * furnished to do so, subject to the following conditions:
12
 *
13
 * The above copyright notice and this permission notice shall be included in
14
 * all copies or substantial portions of the Software.
15
 *
16
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
19
 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
22
 * THE SOFTWARE.
23
 */
24
#include <stdlib.h>
25
#include <stdio.h>
26
#include <stdarg.h>
27
#include <string.h>
28
#include <getopt.h>
29
#include <inttypes.h>
30
#include <unistd.h>
31
#include <sys/mman.h>
32
#include <fcntl.h>
33
#include <signal.h>
34
#include <time.h>
35
#include <sys/time.h>
36
#include <malloc.h>
37
#include <termios.h>
38
#include <sys/poll.h>
39
#include <errno.h>
40
#include <sys/wait.h>
41
#include <netinet/in.h>
42

    
43
#include "cpu.h"
44
#include "vl.h"
45

    
46
/* debug NE2000 card */
47
//#define DEBUG_NE2000
48

    
49
/***********************************************************/
50
/* ne2000 emulation */
51

    
52
#define E8390_CMD        0x00  /* The command register (for all pages) */
53
/* Page 0 register offsets. */
54
#define EN0_CLDALO        0x01        /* Low byte of current local dma addr  RD */
55
#define EN0_STARTPG        0x01        /* Starting page of ring bfr WR */
56
#define EN0_CLDAHI        0x02        /* High byte of current local dma addr  RD */
57
#define EN0_STOPPG        0x02        /* Ending page +1 of ring bfr WR */
58
#define EN0_BOUNDARY        0x03        /* Boundary page of ring bfr RD WR */
59
#define EN0_TSR                0x04        /* Transmit status reg RD */
60
#define EN0_TPSR        0x04        /* Transmit starting page WR */
61
#define EN0_NCR                0x05        /* Number of collision reg RD */
62
#define EN0_TCNTLO        0x05        /* Low  byte of tx byte count WR */
63
#define EN0_FIFO        0x06        /* FIFO RD */
64
#define EN0_TCNTHI        0x06        /* High byte of tx byte count WR */
65
#define EN0_ISR                0x07        /* Interrupt status reg RD WR */
66
#define EN0_CRDALO        0x08        /* low byte of current remote dma address RD */
67
#define EN0_RSARLO        0x08        /* Remote start address reg 0 */
68
#define EN0_CRDAHI        0x09        /* high byte, current remote dma address RD */
69
#define EN0_RSARHI        0x09        /* Remote start address reg 1 */
70
#define EN0_RCNTLO        0x0a        /* Remote byte count reg WR */
71
#define EN0_RCNTHI        0x0b        /* Remote byte count reg WR */
72
#define EN0_RSR                0x0c        /* rx status reg RD */
73
#define EN0_RXCR        0x0c        /* RX configuration reg WR */
74
#define EN0_TXCR        0x0d        /* TX configuration reg WR */
75
#define EN0_COUNTER0        0x0d        /* Rcv alignment error counter RD */
76
#define EN0_DCFG        0x0e        /* Data configuration reg WR */
77
#define EN0_COUNTER1        0x0e        /* Rcv CRC error counter RD */
78
#define EN0_IMR                0x0f        /* Interrupt mask reg WR */
79
#define EN0_COUNTER2        0x0f        /* Rcv missed frame error counter RD */
80

    
81
#define EN1_PHYS        0x11
82
#define EN1_CURPAG      0x17
83
#define EN1_MULT        0x18
84

    
85
/*  Register accessed at EN_CMD, the 8390 base addr.  */
86
#define E8390_STOP        0x01        /* Stop and reset the chip */
87
#define E8390_START        0x02        /* Start the chip, clear reset */
88
#define E8390_TRANS        0x04        /* Transmit a frame */
89
#define E8390_RREAD        0x08        /* Remote read */
90
#define E8390_RWRITE        0x10        /* Remote write  */
91
#define E8390_NODMA        0x20        /* Remote DMA */
92
#define E8390_PAGE0        0x00        /* Select page chip registers */
93
#define E8390_PAGE1        0x40        /* using the two high-order bits */
94
#define E8390_PAGE2        0x80        /* Page 3 is invalid. */
95

    
96
/* Bits in EN0_ISR - Interrupt status register */
97
#define ENISR_RX        0x01        /* Receiver, no error */
98
#define ENISR_TX        0x02        /* Transmitter, no error */
99
#define ENISR_RX_ERR        0x04        /* Receiver, with error */
100
#define ENISR_TX_ERR        0x08        /* Transmitter, with error */
101
#define ENISR_OVER        0x10        /* Receiver overwrote the ring */
102
#define ENISR_COUNTERS        0x20        /* Counters need emptying */
103
#define ENISR_RDC        0x40        /* remote dma complete */
104
#define ENISR_RESET        0x80        /* Reset completed */
105
#define ENISR_ALL        0x3f        /* Interrupts we will enable */
106

    
107
/* Bits in received packet status byte and EN0_RSR*/
108
#define ENRSR_RXOK        0x01        /* Received a good packet */
109
#define ENRSR_CRC        0x02        /* CRC error */
110
#define ENRSR_FAE        0x04        /* frame alignment error */
111
#define ENRSR_FO        0x08        /* FIFO overrun */
112
#define ENRSR_MPA        0x10        /* missed pkt */
113
#define ENRSR_PHY        0x20        /* physical/multicast address */
114
#define ENRSR_DIS        0x40        /* receiver disable. set in monitor mode */
115
#define ENRSR_DEF        0x80        /* deferring */
116

    
117
/* Transmitted packet status, EN0_TSR. */
118
#define ENTSR_PTX 0x01        /* Packet transmitted without error */
119
#define ENTSR_ND  0x02        /* The transmit wasn't deferred. */
120
#define ENTSR_COL 0x04        /* The transmit collided at least once. */
121
#define ENTSR_ABT 0x08  /* The transmit collided 16 times, and was deferred. */
122
#define ENTSR_CRS 0x10        /* The carrier sense was lost. */
123
#define ENTSR_FU  0x20  /* A "FIFO underrun" occurred during transmit. */
124
#define ENTSR_CDH 0x40        /* The collision detect "heartbeat" signal was lost. */
125
#define ENTSR_OWC 0x80  /* There was an out-of-window collision. */
126

    
127
#define NE2000_MEM_SIZE 32768
128

    
129
typedef struct NE2000State {
130
    uint8_t cmd;
131
    uint32_t start;
132
    uint32_t stop;
133
    uint8_t boundary;
134
    uint8_t tsr;
135
    uint8_t tpsr;
136
    uint16_t tcnt;
137
    uint16_t rcnt;
138
    uint32_t rsar;
139
    uint8_t isr;
140
    uint8_t dcfg;
141
    uint8_t imr;
142
    uint8_t phys[6]; /* mac address */
143
    uint8_t curpag;
144
    uint8_t mult[8]; /* multicast mask array */
145
    int irq;
146
    uint8_t mem[NE2000_MEM_SIZE];
147
} NE2000State;
148

    
149
static NE2000State ne2000_state;
150
int net_fd = -1;
151

    
152
static void ne2000_reset(NE2000State *s)
153
{
154
    int i;
155

    
156
    s->isr = ENISR_RESET;
157
    s->mem[0] = 0x52;
158
    s->mem[1] = 0x54;
159
    s->mem[2] = 0x00;
160
    s->mem[3] = 0x12;
161
    s->mem[4] = 0x34;
162
    s->mem[5] = 0x56;
163
    s->mem[14] = 0x57;
164
    s->mem[15] = 0x57;
165

    
166
    /* duplicate prom data */
167
    for(i = 15;i >= 0; i--) {
168
        s->mem[2 * i] = s->mem[i];
169
        s->mem[2 * i + 1] = s->mem[i];
170
    }
171
}
172

    
173
static void ne2000_update_irq(NE2000State *s)
174
{
175
    int isr;
176
    isr = s->isr & s->imr;
177
    if (isr)
178
        pic_set_irq(s->irq, 1);
179
    else
180
        pic_set_irq(s->irq, 0);
181
}
182

    
183
/* return true if the NE2000 can receive more data */
184
int ne2000_can_receive(void)
185
{
186
    NE2000State *s = &ne2000_state;
187
    int avail, index, boundary;
188
    
189
    if (s->cmd & E8390_STOP)
190
        return 0;
191
    index = s->curpag << 8;
192
    boundary = s->boundary << 8;
193
    if (index < boundary)
194
        avail = boundary - index;
195
    else
196
        avail = (s->stop - s->start) - (index - boundary);
197
    if (avail < (MAX_ETH_FRAME_SIZE + 4))
198
        return 0;
199
    return 1;
200
}
201

    
202
void ne2000_receive(uint8_t *buf, int size)
203
{
204
    NE2000State *s = &ne2000_state;
205
    uint8_t *p;
206
    int total_len, next, avail, len, index;
207

    
208
#if defined(DEBUG_NE2000)
209
    printf("NE2000: received len=%d\n", size);
210
#endif
211

    
212
    index = s->curpag << 8;
213
    /* 4 bytes for header */
214
    total_len = size + 4;
215
    /* address for next packet (4 bytes for CRC) */
216
    next = index + ((total_len + 4 + 255) & ~0xff);
217
    if (next >= s->stop)
218
        next -= (s->stop - s->start);
219
    /* prepare packet header */
220
    p = s->mem + index;
221
    p[0] = ENRSR_RXOK; /* receive status */
222
    p[1] = next >> 8;
223
    p[2] = total_len;
224
    p[3] = total_len >> 8;
225
    index += 4;
226

    
227
    /* write packet data */
228
    while (size > 0) {
229
        avail = s->stop - index;
230
        len = size;
231
        if (len > avail)
232
            len = avail;
233
        memcpy(s->mem + index, buf, len);
234
        buf += len;
235
        index += len;
236
        if (index == s->stop)
237
            index = s->start;
238
        size -= len;
239
    }
240
    s->curpag = next >> 8;
241
    
242
    /* now we can signal we have receive something */
243
    s->isr |= ENISR_RX;
244
    ne2000_update_irq(s);
245
}
246

    
247
static void ne2000_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
248
{
249
    NE2000State *s = &ne2000_state;
250
    int offset, page;
251

    
252
    addr &= 0xf;
253
#ifdef DEBUG_NE2000
254
    printf("NE2000: write addr=0x%x val=0x%02x\n", addr, val);
255
#endif
256
    if (addr == E8390_CMD) {
257
        /* control register */
258
        s->cmd = val;
259
        if (val & E8390_START) {
260
            /* test specific case: zero length transfert */
261
            if ((val & (E8390_RREAD | E8390_RWRITE)) &&
262
                s->rcnt == 0) {
263
                s->isr |= ENISR_RDC;
264
                ne2000_update_irq(s);
265
            }
266
            if (val & E8390_TRANS) {
267
                net_send_packet(net_fd, s->mem + (s->tpsr << 8), s->tcnt);
268
                /* signal end of transfert */
269
                s->tsr = ENTSR_PTX;
270
                s->isr |= ENISR_TX;
271
                ne2000_update_irq(s);
272
            }
273
        }
274
    } else {
275
        page = s->cmd >> 6;
276
        offset = addr | (page << 4);
277
        switch(offset) {
278
        case EN0_STARTPG:
279
            s->start = val << 8;
280
            break;
281
        case EN0_STOPPG:
282
            s->stop = val << 8;
283
            break;
284
        case EN0_BOUNDARY:
285
            s->boundary = val;
286
            break;
287
        case EN0_IMR:
288
            s->imr = val;
289
            ne2000_update_irq(s);
290
            break;
291
        case EN0_TPSR:
292
            s->tpsr = val;
293
            break;
294
        case EN0_TCNTLO:
295
            s->tcnt = (s->tcnt & 0xff00) | val;
296
            break;
297
        case EN0_TCNTHI:
298
            s->tcnt = (s->tcnt & 0x00ff) | (val << 8);
299
            break;
300
        case EN0_RSARLO:
301
            s->rsar = (s->rsar & 0xff00) | val;
302
            break;
303
        case EN0_RSARHI:
304
            s->rsar = (s->rsar & 0x00ff) | (val << 8);
305
            break;
306
        case EN0_RCNTLO:
307
            s->rcnt = (s->rcnt & 0xff00) | val;
308
            break;
309
        case EN0_RCNTHI:
310
            s->rcnt = (s->rcnt & 0x00ff) | (val << 8);
311
            break;
312
        case EN0_DCFG:
313
            s->dcfg = val;
314
            break;
315
        case EN0_ISR:
316
            s->isr &= ~val;
317
            ne2000_update_irq(s);
318
            break;
319
        case EN1_PHYS ... EN1_PHYS + 5:
320
            s->phys[offset - EN1_PHYS] = val;
321
            break;
322
        case EN1_CURPAG:
323
            s->curpag = val;
324
            break;
325
        case EN1_MULT ... EN1_MULT + 7:
326
            s->mult[offset - EN1_MULT] = val;
327
            break;
328
        }
329
    }
330
}
331

    
332
static uint32_t ne2000_ioport_read(CPUState *env, uint32_t addr)
333
{
334
    NE2000State *s = &ne2000_state;
335
    int offset, page, ret;
336

    
337
    addr &= 0xf;
338
    if (addr == E8390_CMD) {
339
        ret = s->cmd;
340
    } else {
341
        page = s->cmd >> 6;
342
        offset = addr | (page << 4);
343
        switch(offset) {
344
        case EN0_TSR:
345
            ret = s->tsr;
346
            break;
347
        case EN0_BOUNDARY:
348
            ret = s->boundary;
349
            break;
350
        case EN0_ISR:
351
            ret = s->isr;
352
            break;
353
        case EN1_PHYS ... EN1_PHYS + 5:
354
            ret = s->phys[offset - EN1_PHYS];
355
            break;
356
        case EN1_CURPAG:
357
            ret = s->curpag;
358
            break;
359
        case EN1_MULT ... EN1_MULT + 7:
360
            ret = s->mult[offset - EN1_MULT];
361
            break;
362
        default:
363
            ret = 0x00;
364
            break;
365
        }
366
    }
367
#ifdef DEBUG_NE2000
368
    printf("NE2000: read addr=0x%x val=%02x\n", addr, ret);
369
#endif
370
    return ret;
371
}
372

    
373
static void ne2000_asic_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
374
{
375
    NE2000State *s = &ne2000_state;
376
    uint8_t *p;
377

    
378
#ifdef DEBUG_NE2000
379
    printf("NE2000: asic write val=0x%04x\n", val);
380
#endif
381
    p = s->mem + s->rsar;
382
    if (s->dcfg & 0x01) {
383
        /* 16 bit access */
384
        p[0] = val;
385
        p[1] = val >> 8;
386
        s->rsar += 2;
387
        s->rcnt -= 2;
388
    } else {
389
        /* 8 bit access */
390
        p[0] = val;
391
        s->rsar++;
392
        s->rcnt--;
393
    }
394
    /* wrap */
395
    if (s->rsar == s->stop)
396
        s->rsar = s->start;
397
    if (s->rcnt == 0) {
398
        /* signal end of transfert */
399
        s->isr |= ENISR_RDC;
400
        ne2000_update_irq(s);
401
    }
402
}
403

    
404
static uint32_t ne2000_asic_ioport_read(CPUState *env, uint32_t addr)
405
{
406
    NE2000State *s = &ne2000_state;
407
    uint8_t *p;
408
    int ret;
409

    
410
    p = s->mem + s->rsar;
411
    if (s->dcfg & 0x01) {
412
        /* 16 bit access */
413
        ret = p[0] | (p[1] << 8);
414
        s->rsar += 2;
415
        s->rcnt -= 2;
416
    } else {
417
        /* 8 bit access */
418
        ret = p[0];
419
        s->rsar++;
420
        s->rcnt--;
421
    }
422
    /* wrap */
423
    if (s->rsar == s->stop)
424
        s->rsar = s->start;
425
    if (s->rcnt == 0) {
426
        /* signal end of transfert */
427
        s->isr |= ENISR_RDC;
428
        ne2000_update_irq(s);
429
    }
430
#ifdef DEBUG_NE2000
431
    printf("NE2000: asic read val=0x%04x\n", ret);
432
#endif
433
    return ret;
434
}
435

    
436
static void ne2000_reset_ioport_write(CPUState *env, uint32_t addr, uint32_t val)
437
{
438
    /* nothing to do (end of reset pulse) */
439
}
440

    
441
static uint32_t ne2000_reset_ioport_read(CPUState *env, uint32_t addr)
442
{
443
    NE2000State *s = &ne2000_state;
444
    ne2000_reset(s);
445
    return 0;
446
}
447

    
448
void ne2000_init(int base, int irq)
449
{
450
    NE2000State *s = &ne2000_state;
451

    
452
    register_ioport_write(base, 16, ne2000_ioport_write, 1);
453
    register_ioport_read(base, 16, ne2000_ioport_read, 1);
454

    
455
    register_ioport_write(base + 0x10, 1, ne2000_asic_ioport_write, 1);
456
    register_ioport_read(base + 0x10, 1, ne2000_asic_ioport_read, 1);
457
    register_ioport_write(base + 0x10, 2, ne2000_asic_ioport_write, 2);
458
    register_ioport_read(base + 0x10, 2, ne2000_asic_ioport_read, 2);
459

    
460
    register_ioport_write(base + 0x1f, 1, ne2000_reset_ioport_write, 1);
461
    register_ioport_read(base + 0x1f, 1, ne2000_reset_ioport_read, 1);
462
    s->irq = irq;
463

    
464
    ne2000_reset(s);
465
}