Remove most uses of phys_ram_base (initial patch by Ian Jackson)
[qemu] / hw / smc91c111.c
1 /*
2  * SMSC 91C111 Ethernet interface emulation
3  *
4  * Copyright (c) 2005 CodeSourcery, LLC.
5  * Written by Paul Brook
6  *
7  * This code is licenced under the GPL
8  */
9
10 #include "hw.h"
11 #include "net.h"
12 #include "devices.h"
13 /* For crc32 */
14 #include <zlib.h>
15
16 /* Number of 2k memory pages available.  */
17 #define NUM_PACKETS 4
18
19 typedef struct {
20     uint32_t base;
21     VLANClientState *vc;
22     uint16_t tcr;
23     uint16_t rcr;
24     uint16_t cr;
25     uint16_t ctr;
26     uint16_t gpr;
27     uint16_t ptr;
28     uint16_t ercv;
29     qemu_irq irq;
30     int bank;
31     int packet_num;
32     int tx_alloc;
33     /* Bitmask of allocated packets.  */
34     int allocated;
35     int tx_fifo_len;
36     int tx_fifo[NUM_PACKETS];
37     int rx_fifo_len;
38     int rx_fifo[NUM_PACKETS];
39     int tx_fifo_done_len;
40     int tx_fifo_done[NUM_PACKETS];
41     /* Packet buffer memory.  */
42     uint8_t data[NUM_PACKETS][2048];
43     uint8_t int_level;
44     uint8_t int_mask;
45     uint8_t macaddr[6];
46 } smc91c111_state;
47
48 #define RCR_SOFT_RST  0x8000
49 #define RCR_STRIP_CRC 0x0200
50 #define RCR_RXEN      0x0100
51
52 #define TCR_EPH_LOOP  0x2000
53 #define TCR_NOCRC     0x0100
54 #define TCR_PAD_EN    0x0080
55 #define TCR_FORCOL    0x0004
56 #define TCR_LOOP      0x0002
57 #define TCR_TXEN      0x0001
58
59 #define INT_MD        0x80
60 #define INT_ERCV      0x40
61 #define INT_EPH       0x20
62 #define INT_RX_OVRN   0x10
63 #define INT_ALLOC     0x08
64 #define INT_TX_EMPTY  0x04
65 #define INT_TX        0x02
66 #define INT_RCV       0x01
67
68 #define CTR_AUTO_RELEASE  0x0800
69 #define CTR_RELOAD        0x0002
70 #define CTR_STORE         0x0001
71
72 #define RS_ALGNERR      0x8000
73 #define RS_BRODCAST     0x4000
74 #define RS_BADCRC       0x2000
75 #define RS_ODDFRAME     0x1000
76 #define RS_TOOLONG      0x0800
77 #define RS_TOOSHORT     0x0400
78 #define RS_MULTICAST    0x0001
79
80 /* Update interrupt status.  */
81 static void smc91c111_update(smc91c111_state *s)
82 {
83     int level;
84
85     if (s->tx_fifo_len == 0)
86         s->int_level |= INT_TX_EMPTY;
87     if (s->tx_fifo_done_len != 0)
88         s->int_level |= INT_TX;
89     level = (s->int_level & s->int_mask) != 0;
90     qemu_set_irq(s->irq, level);
91 }
92
93 /* Try to allocate a packet.  Returns 0x80 on failure.  */
94 static int smc91c111_allocate_packet(smc91c111_state *s)
95 {
96     int i;
97     if (s->allocated == (1 << NUM_PACKETS) - 1) {
98         return 0x80;
99     }
100
101     for (i = 0; i < NUM_PACKETS; i++) {
102         if ((s->allocated & (1 << i)) == 0)
103             break;
104     }
105     s->allocated |= 1 << i;
106     return i;
107 }
108
109
110 /* Process a pending TX allocate.  */
111 static void smc91c111_tx_alloc(smc91c111_state *s)
112 {
113     s->tx_alloc = smc91c111_allocate_packet(s);
114     if (s->tx_alloc == 0x80)
115         return;
116     s->int_level |= INT_ALLOC;
117     smc91c111_update(s);
118 }
119
120 /* Remove and item from the RX FIFO.  */
121 static void smc91c111_pop_rx_fifo(smc91c111_state *s)
122 {
123     int i;
124
125     s->rx_fifo_len--;
126     if (s->rx_fifo_len) {
127         for (i = 0; i < s->rx_fifo_len; i++)
128             s->rx_fifo[i] = s->rx_fifo[i + 1];
129         s->int_level |= INT_RCV;
130     } else {
131         s->int_level &= ~INT_RCV;
132     }
133     smc91c111_update(s);
134 }
135
136 /* Remove an item from the TX completion FIFO.  */
137 static void smc91c111_pop_tx_fifo_done(smc91c111_state *s)
138 {
139     int i;
140
141     if (s->tx_fifo_done_len == 0)
142         return;
143     s->tx_fifo_done_len--;
144     for (i = 0; i < s->tx_fifo_done_len; i++)
145         s->tx_fifo_done[i] = s->tx_fifo_done[i + 1];
146 }
147
148 /* Release the memory allocated to a packet.  */
149 static void smc91c111_release_packet(smc91c111_state *s, int packet)
150 {
151     s->allocated &= ~(1 << packet);
152     if (s->tx_alloc == 0x80)
153         smc91c111_tx_alloc(s);
154 }
155
156 /* Flush the TX FIFO.  */
157 static void smc91c111_do_tx(smc91c111_state *s)
158 {
159     int i;
160     int len;
161     int control;
162     int add_crc;
163     int packetnum;
164     uint8_t *p;
165
166     if ((s->tcr & TCR_TXEN) == 0)
167         return;
168     if (s->tx_fifo_len == 0)
169         return;
170     for (i = 0; i < s->tx_fifo_len; i++) {
171         packetnum = s->tx_fifo[i];
172         p = &s->data[packetnum][0];
173         /* Set status word.  */
174         *(p++) = 0x01;
175         *(p++) = 0x40;
176         len = *(p++);
177         len |= ((int)*(p++)) << 8;
178         len -= 6;
179         control = p[len + 1];
180         if (control & 0x20)
181             len++;
182         /* ??? This overwrites the data following the buffer.
183            Don't know what real hardware does.  */
184         if (len < 64 && (s->tcr & TCR_PAD_EN)) {
185             memset(p + len, 0, 64 - len);
186             len = 64;
187         }
188 #if 0
189         /* The card is supposed to append the CRC to the frame.  However
190            none of the other network traffic has the CRC appended.
191            Suspect this is low level ethernet detail we don't need to worry
192            about.  */
193         add_crc = (control & 0x10) || (s->tcr & TCR_NOCRC) == 0;
194         if (add_crc) {
195             uint32_t crc;
196
197             crc = crc32(~0, p, len);
198             memcpy(p + len, &crc, 4);
199             len += 4;
200         }
201 #else
202         add_crc = 0;
203 #endif
204         if (s->ctr & CTR_AUTO_RELEASE)
205             /* Race?  */
206             smc91c111_release_packet(s, packetnum);
207         else if (s->tx_fifo_done_len < NUM_PACKETS)
208             s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
209         qemu_send_packet(s->vc, p, len);
210     }
211     s->tx_fifo_len = 0;
212     smc91c111_update(s);
213 }
214
215 /* Add a packet to the TX FIFO.  */
216 static void smc91c111_queue_tx(smc91c111_state *s, int packet)
217 {
218     if (s->tx_fifo_len == NUM_PACKETS)
219         return;
220     s->tx_fifo[s->tx_fifo_len++] = packet;
221     smc91c111_do_tx(s);
222 }
223
224 static void smc91c111_reset(smc91c111_state *s)
225 {
226     s->bank = 0;
227     s->tx_fifo_len = 0;
228     s->tx_fifo_done_len = 0;
229     s->rx_fifo_len = 0;
230     s->allocated = 0;
231     s->packet_num = 0;
232     s->tx_alloc = 0;
233     s->tcr = 0;
234     s->rcr = 0;
235     s->cr = 0xa0b1;
236     s->ctr = 0x1210;
237     s->ptr = 0;
238     s->ercv = 0x1f;
239     s->int_level = INT_TX_EMPTY;
240     s->int_mask = 0;
241     smc91c111_update(s);
242 }
243
244 #define SET_LOW(name, val) s->name = (s->name & 0xff00) | val
245 #define SET_HIGH(name, val) s->name = (s->name & 0xff) | (val << 8)
246
247 static void smc91c111_writeb(void *opaque, target_phys_addr_t offset,
248                              uint32_t value)
249 {
250     smc91c111_state *s = (smc91c111_state *)opaque;
251
252     offset -= s->base;
253     if (offset == 14) {
254         s->bank = value;
255         return;
256     }
257     if (offset == 15)
258         return;
259     switch (s->bank) {
260     case 0:
261         switch (offset) {
262         case 0: /* TCR */
263             SET_LOW(tcr, value);
264             return;
265         case 1:
266             SET_HIGH(tcr, value);
267             return;
268         case 4: /* RCR */
269             SET_LOW(rcr, value);
270             return;
271         case 5:
272             SET_HIGH(rcr, value);
273             if (s->rcr & RCR_SOFT_RST)
274                 smc91c111_reset(s);
275             return;
276         case 10: case 11: /* RPCR */
277             /* Ignored */
278             return;
279         }
280         break;
281
282     case 1:
283         switch (offset) {
284         case 0: /* CONFIG */
285             SET_LOW(cr, value);
286             return;
287         case 1:
288             SET_HIGH(cr,value);
289             return;
290         case 2: case 3: /* BASE */
291         case 4: case 5: case 6: case 7: case 8: case 9: /* IA */
292             /* Not implemented.  */
293             return;
294         case 10: /* Genral Purpose */
295             SET_LOW(gpr, value);
296             return;
297         case 11:
298             SET_HIGH(gpr, value);
299             return;
300         case 12: /* Control */
301             if (value & 1)
302                 fprintf(stderr, "smc91c111:EEPROM store not implemented\n");
303             if (value & 2)
304                 fprintf(stderr, "smc91c111:EEPROM reload not implemented\n");
305             value &= ~3;
306             SET_LOW(ctr, value);
307             return;
308         case 13:
309             SET_HIGH(ctr, value);
310             return;
311         }
312         break;
313
314     case 2:
315         switch (offset) {
316         case 0: /* MMU Command */
317             switch (value >> 5) {
318             case 0: /* no-op */
319                 break;
320             case 1: /* Allocate for TX.  */
321                 s->tx_alloc = 0x80;
322                 s->int_level &= ~INT_ALLOC;
323                 smc91c111_update(s);
324                 smc91c111_tx_alloc(s);
325                 break;
326             case 2: /* Reset MMU.  */
327                 s->allocated = 0;
328                 s->tx_fifo_len = 0;
329                 s->tx_fifo_done_len = 0;
330                 s->rx_fifo_len = 0;
331                 s->tx_alloc = 0;
332                 break;
333             case 3: /* Remove from RX FIFO.  */
334                 smc91c111_pop_rx_fifo(s);
335                 break;
336             case 4: /* Remove from RX FIFO and release.  */
337                 if (s->rx_fifo_len > 0) {
338                     smc91c111_release_packet(s, s->rx_fifo[0]);
339                 }
340                 smc91c111_pop_rx_fifo(s);
341                 break;
342             case 5: /* Release.  */
343                 smc91c111_release_packet(s, s->packet_num);
344                 break;
345             case 6: /* Add to TX FIFO.  */
346                 smc91c111_queue_tx(s, s->packet_num);
347                 break;
348             case 7: /* Reset TX FIFO.  */
349                 s->tx_fifo_len = 0;
350                 s->tx_fifo_done_len = 0;
351                 break;
352             }
353             return;
354         case 1:
355             /* Ignore.  */
356             return;
357         case 2: /* Packet Number Register */
358             s->packet_num = value;
359             return;
360         case 3: case 4: case 5:
361             /* Should be readonly, but linux writes to them anyway. Ignore.  */
362             return;
363         case 6: /* Pointer */
364             SET_LOW(ptr, value);
365             return;
366         case 7:
367             SET_HIGH(ptr, value);
368             return;
369         case 8: case 9: case 10: case 11: /* Data */
370             {
371                 int p;
372                 int n;
373
374                 if (s->ptr & 0x8000)
375                     n = s->rx_fifo[0];
376                 else
377                     n = s->packet_num;
378                 p = s->ptr & 0x07ff;
379                 if (s->ptr & 0x4000) {
380                     s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff);
381                 } else {
382                     p += (offset & 3);
383                 }
384                 s->data[n][p] = value;
385             }
386             return;
387         case 12: /* Interrupt ACK.  */
388             s->int_level &= ~(value & 0xd6);
389             if (value & INT_TX)
390                 smc91c111_pop_tx_fifo_done(s);
391             smc91c111_update(s);
392             return;
393         case 13: /* Interrupt mask.  */
394             s->int_mask = value;
395             smc91c111_update(s);
396             return;
397         }
398         break;;
399
400     case 3:
401         switch (offset) {
402         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
403             /* Multicast table.  */
404             /* Not implemented.  */
405             return;
406         case 8: case 9: /* Management Interface.  */
407             /* Not implemented.  */
408             return;
409         case 12: /* Early receive.  */
410             s->ercv = value & 0x1f;
411         case 13:
412             /* Ignore.  */
413             return;
414         }
415         break;
416     }
417     cpu_abort (cpu_single_env, "smc91c111_write: Bad reg %d:%x\n",
418                s->bank, (int)offset);
419 }
420
421 static uint32_t smc91c111_readb(void *opaque, target_phys_addr_t offset)
422 {
423     smc91c111_state *s = (smc91c111_state *)opaque;
424
425     offset -= s->base;
426     if (offset == 14) {
427         return s->bank;
428     }
429     if (offset == 15)
430         return 0x33;
431     switch (s->bank) {
432     case 0:
433         switch (offset) {
434         case 0: /* TCR */
435             return s->tcr & 0xff;
436         case 1:
437             return s->tcr >> 8;
438         case 2: /* EPH Status */
439             return 0;
440         case 3:
441             return 0x40;
442         case 4: /* RCR */
443             return s->rcr & 0xff;
444         case 5:
445             return s->rcr >> 8;
446         case 6: /* Counter */
447         case 7:
448             /* Not implemented.  */
449             return 0;
450         case 8: /* Memory size.  */
451             return NUM_PACKETS;
452         case 9: /* Free memory available.  */
453             {
454                 int i;
455                 int n;
456                 n = 0;
457                 for (i = 0; i < NUM_PACKETS; i++) {
458                     if (s->allocated & (1 << i))
459                         n++;
460                 }
461                 return n;
462             }
463         case 10: case 11: /* RPCR */
464             /* Not implemented.  */
465             return 0;
466         }
467         break;
468
469     case 1:
470         switch (offset) {
471         case 0: /* CONFIG */
472             return s->cr & 0xff;
473         case 1:
474             return s->cr >> 8;
475         case 2: case 3: /* BASE */
476             /* Not implemented.  */
477             return 0;
478         case 4: case 5: case 6: case 7: case 8: case 9: /* IA */
479             return s->macaddr[offset - 4];
480         case 10: /* General Purpose */
481             return s->gpr & 0xff;
482         case 11:
483             return s->gpr >> 8;
484         case 12: /* Control */
485             return s->ctr & 0xff;
486         case 13:
487             return s->ctr >> 8;
488         }
489         break;
490
491     case 2:
492         switch (offset) {
493         case 0: case 1: /* MMUCR Busy bit.  */
494             return 0;
495         case 2: /* Packet Number.  */
496             return s->packet_num;
497         case 3: /* Allocation Result.  */
498             return s->tx_alloc;
499         case 4: /* TX FIFO */
500             if (s->tx_fifo_done_len == 0)
501                 return 0x80;
502             else
503                 return s->tx_fifo_done[0];
504         case 5: /* RX FIFO */
505             if (s->rx_fifo_len == 0)
506                 return 0x80;
507             else
508                 return s->rx_fifo[0];
509         case 6: /* Pointer */
510             return s->ptr & 0xff;
511         case 7:
512             return (s->ptr >> 8) & 0xf7;
513         case 8: case 9: case 10: case 11: /* Data */
514             {
515                 int p;
516                 int n;
517
518                 if (s->ptr & 0x8000)
519                     n = s->rx_fifo[0];
520                 else
521                     n = s->packet_num;
522                 p = s->ptr & 0x07ff;
523                 if (s->ptr & 0x4000) {
524                     s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x07ff);
525                 } else {
526                     p += (offset & 3);
527                 }
528                 return s->data[n][p];
529             }
530         case 12: /* Interrupt status.  */
531             return s->int_level;
532         case 13: /* Interrupt mask.  */
533             return s->int_mask;
534         }
535         break;
536
537     case 3:
538         switch (offset) {
539         case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
540             /* Multicast table.  */
541             /* Not implemented.  */
542             return 0;
543         case 8: /* Management Interface.  */
544             /* Not implemented.  */
545             return 0x30;
546         case 9:
547             return 0x33;
548         case 10: /* Revision.  */
549             return 0x91;
550         case 11:
551             return 0x33;
552         case 12:
553             return s->ercv;
554         case 13:
555             return 0;
556         }
557         break;
558     }
559     cpu_abort (cpu_single_env, "smc91c111_read: Bad reg %d:%x\n",
560                s->bank, (int)offset);
561     return 0;
562 }
563
564 static void smc91c111_writew(void *opaque, target_phys_addr_t offset,
565                              uint32_t value)
566 {
567     smc91c111_writeb(opaque, offset, value & 0xff);
568     smc91c111_writeb(opaque, offset + 1, value >> 8);
569 }
570
571 static void smc91c111_writel(void *opaque, target_phys_addr_t offset,
572                              uint32_t value)
573 {
574     smc91c111_state *s = (smc91c111_state *)opaque;
575     /* 32-bit writes to offset 0xc only actually write to the bank select
576        register (offset 0xe)  */
577     if (offset != s->base + 0xc)
578         smc91c111_writew(opaque, offset, value & 0xffff);
579     smc91c111_writew(opaque, offset + 2, value >> 16);
580 }
581
582 static uint32_t smc91c111_readw(void *opaque, target_phys_addr_t offset)
583 {
584     uint32_t val;
585     val = smc91c111_readb(opaque, offset);
586     val |= smc91c111_readb(opaque, offset + 1) << 8;
587     return val;
588 }
589
590 static uint32_t smc91c111_readl(void *opaque, target_phys_addr_t offset)
591 {
592     uint32_t val;
593     val = smc91c111_readw(opaque, offset);
594     val |= smc91c111_readw(opaque, offset + 2) << 16;
595     return val;
596 }
597
598 static int smc91c111_can_receive(void *opaque)
599 {
600     smc91c111_state *s = (smc91c111_state *)opaque;
601
602     if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST))
603         return 1;
604     if (s->allocated == (1 << NUM_PACKETS) - 1)
605         return 0;
606     return 1;
607 }
608
609 static void smc91c111_receive(void *opaque, const uint8_t *buf, int size)
610 {
611     smc91c111_state *s = (smc91c111_state *)opaque;
612     int status;
613     int packetsize;
614     uint32_t crc;
615     int packetnum;
616     uint8_t *p;
617
618     if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST))
619         return;
620     /* Short packets are padded with zeros.  Receiving a packet
621        < 64 bytes long is considered an error condition.  */
622     if (size < 64)
623         packetsize = 64;
624     else
625         packetsize = (size & ~1);
626     packetsize += 6;
627     crc = (s->rcr & RCR_STRIP_CRC) == 0;
628     if (crc)
629         packetsize += 4;
630     /* TODO: Flag overrun and receive errors.  */
631     if (packetsize > 2048)
632         return;
633     packetnum = smc91c111_allocate_packet(s);
634     if (packetnum == 0x80)
635         return;
636     s->rx_fifo[s->rx_fifo_len++] = packetnum;
637
638     p = &s->data[packetnum][0];
639     /* ??? Multicast packets?  */
640     status = 0;
641     if (size > 1518)
642         status |= RS_TOOLONG;
643     if (size & 1)
644         status |= RS_ODDFRAME;
645     *(p++) = status & 0xff;
646     *(p++) = status >> 8;
647     *(p++) = packetsize & 0xff;
648     *(p++) = packetsize >> 8;
649     memcpy(p, buf, size & ~1);
650     p += (size & ~1);
651     /* Pad short packets.  */
652     if (size < 64) {
653         int pad;
654
655         if (size & 1)
656             *(p++) = buf[size - 1];
657         pad = 64 - size;
658         memset(p, 0, pad);
659         p += pad;
660         size = 64;
661     }
662     /* It's not clear if the CRC should go before or after the last byte in
663        odd sized packets.  Linux disables the CRC, so that's no help.
664        The pictures in the documentation show the CRC aligned on a 16-bit
665        boundary before the last odd byte, so that's what we do.  */
666     if (crc) {
667         crc = crc32(~0, buf, size);
668         *(p++) = crc & 0xff; crc >>= 8;
669         *(p++) = crc & 0xff; crc >>= 8;
670         *(p++) = crc & 0xff; crc >>= 8;
671         *(p++) = crc & 0xff; crc >>= 8;
672     }
673     if (size & 1) {
674         *(p++) = buf[size - 1];
675         *(p++) = 0x60;
676     } else {
677         *(p++) = 0;
678         *(p++) = 0x40;
679     }
680     /* TODO: Raise early RX interrupt?  */
681     s->int_level |= INT_RCV;
682     smc91c111_update(s);
683 }
684
685 static CPUReadMemoryFunc *smc91c111_readfn[] = {
686     smc91c111_readb,
687     smc91c111_readw,
688     smc91c111_readl
689 };
690
691 static CPUWriteMemoryFunc *smc91c111_writefn[] = {
692     smc91c111_writeb,
693     smc91c111_writew,
694     smc91c111_writel
695 };
696
697 void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
698 {
699     smc91c111_state *s;
700     int iomemtype;
701
702     s = (smc91c111_state *)qemu_mallocz(sizeof(smc91c111_state));
703     iomemtype = cpu_register_io_memory(0, smc91c111_readfn,
704                                        smc91c111_writefn, s);
705     cpu_register_physical_memory(base, 16, iomemtype);
706     s->base = base;
707     s->irq = irq;
708     memcpy(s->macaddr, nd->macaddr, 6);
709
710     smc91c111_reset(s);
711
712     s->vc = qemu_new_vlan_client(nd->vlan, smc91c111_receive,
713                                  smc91c111_can_receive, s);
714     /* ??? Save/restore.  */
715 }