0b35495f99eebd6ec9104a67251f153bbdd630cf
[qemu] / hw / ne2000.c
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 }