1
2
3
4
5
6
7
8
9
10#include "hw/sysbus.h"
11#include "net/net.h"
12#include "hw/devices.h"
13
14#include <zlib.h>
15
16
17#define NUM_PACKETS 4
18
19#define TYPE_SMC91C111 "smc91c111"
20#define SMC91C111(obj) OBJECT_CHECK(smc91c111_state, (obj), TYPE_SMC91C111)
21
22typedef struct {
23 SysBusDevice parent_obj;
24
25 NICState *nic;
26 NICConf conf;
27 uint16_t tcr;
28 uint16_t rcr;
29 uint16_t cr;
30 uint16_t ctr;
31 uint16_t gpr;
32 uint16_t ptr;
33 uint16_t ercv;
34 qemu_irq irq;
35 int bank;
36 int packet_num;
37 int tx_alloc;
38
39 int allocated;
40 int tx_fifo_len;
41 int tx_fifo[NUM_PACKETS];
42 int rx_fifo_len;
43 int rx_fifo[NUM_PACKETS];
44 int tx_fifo_done_len;
45 int tx_fifo_done[NUM_PACKETS];
46
47 uint8_t data[NUM_PACKETS][2048];
48 uint8_t int_level;
49 uint8_t int_mask;
50 MemoryRegion mmio;
51} smc91c111_state;
52
53static const VMStateDescription vmstate_smc91c111 = {
54 .name = "smc91c111",
55 .version_id = 1,
56 .minimum_version_id = 1,
57 .fields = (VMStateField[]) {
58 VMSTATE_UINT16(tcr, smc91c111_state),
59 VMSTATE_UINT16(rcr, smc91c111_state),
60 VMSTATE_UINT16(cr, smc91c111_state),
61 VMSTATE_UINT16(ctr, smc91c111_state),
62 VMSTATE_UINT16(gpr, smc91c111_state),
63 VMSTATE_UINT16(ptr, smc91c111_state),
64 VMSTATE_UINT16(ercv, smc91c111_state),
65 VMSTATE_INT32(bank, smc91c111_state),
66 VMSTATE_INT32(packet_num, smc91c111_state),
67 VMSTATE_INT32(tx_alloc, smc91c111_state),
68 VMSTATE_INT32(allocated, smc91c111_state),
69 VMSTATE_INT32(tx_fifo_len, smc91c111_state),
70 VMSTATE_INT32_ARRAY(tx_fifo, smc91c111_state, NUM_PACKETS),
71 VMSTATE_INT32(rx_fifo_len, smc91c111_state),
72 VMSTATE_INT32_ARRAY(rx_fifo, smc91c111_state, NUM_PACKETS),
73 VMSTATE_INT32(tx_fifo_done_len, smc91c111_state),
74 VMSTATE_INT32_ARRAY(tx_fifo_done, smc91c111_state, NUM_PACKETS),
75 VMSTATE_BUFFER_UNSAFE(data, smc91c111_state, 0, NUM_PACKETS * 2048),
76 VMSTATE_UINT8(int_level, smc91c111_state),
77 VMSTATE_UINT8(int_mask, smc91c111_state),
78 VMSTATE_END_OF_LIST()
79 }
80};
81
82#define RCR_SOFT_RST 0x8000
83#define RCR_STRIP_CRC 0x0200
84#define RCR_RXEN 0x0100
85
86#define TCR_EPH_LOOP 0x2000
87#define TCR_NOCRC 0x0100
88#define TCR_PAD_EN 0x0080
89#define TCR_FORCOL 0x0004
90#define TCR_LOOP 0x0002
91#define TCR_TXEN 0x0001
92
93#define INT_MD 0x80
94#define INT_ERCV 0x40
95#define INT_EPH 0x20
96#define INT_RX_OVRN 0x10
97#define INT_ALLOC 0x08
98#define INT_TX_EMPTY 0x04
99#define INT_TX 0x02
100#define INT_RCV 0x01
101
102#define CTR_AUTO_RELEASE 0x0800
103#define CTR_RELOAD 0x0002
104#define CTR_STORE 0x0001
105
106#define RS_ALGNERR 0x8000
107#define RS_BRODCAST 0x4000
108#define RS_BADCRC 0x2000
109#define RS_ODDFRAME 0x1000
110#define RS_TOOLONG 0x0800
111#define RS_TOOSHORT 0x0400
112#define RS_MULTICAST 0x0001
113
114
115static void smc91c111_update(smc91c111_state *s)
116{
117 int level;
118
119 if (s->tx_fifo_len == 0)
120 s->int_level |= INT_TX_EMPTY;
121 if (s->tx_fifo_done_len != 0)
122 s->int_level |= INT_TX;
123 level = (s->int_level & s->int_mask) != 0;
124 qemu_set_irq(s->irq, level);
125}
126
127static int smc91c111_can_receive(smc91c111_state *s)
128{
129 if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST)) {
130 return 1;
131 }
132 if (s->allocated == (1 << NUM_PACKETS) - 1 ||
133 s->rx_fifo_len == NUM_PACKETS) {
134 return 0;
135 }
136 return 1;
137}
138
139static inline void smc91c111_flush_queued_packets(smc91c111_state *s)
140{
141 if (smc91c111_can_receive(s)) {
142 qemu_flush_queued_packets(qemu_get_queue(s->nic));
143 }
144}
145
146
147static int smc91c111_allocate_packet(smc91c111_state *s)
148{
149 int i;
150 if (s->allocated == (1 << NUM_PACKETS) - 1) {
151 return 0x80;
152 }
153
154 for (i = 0; i < NUM_PACKETS; i++) {
155 if ((s->allocated & (1 << i)) == 0)
156 break;
157 }
158 s->allocated |= 1 << i;
159 return i;
160}
161
162
163
164static void smc91c111_tx_alloc(smc91c111_state *s)
165{
166 s->tx_alloc = smc91c111_allocate_packet(s);
167 if (s->tx_alloc == 0x80)
168 return;
169 s->int_level |= INT_ALLOC;
170 smc91c111_update(s);
171}
172
173
174static void smc91c111_pop_rx_fifo(smc91c111_state *s)
175{
176 int i;
177
178 s->rx_fifo_len--;
179 if (s->rx_fifo_len) {
180 for (i = 0; i < s->rx_fifo_len; i++)
181 s->rx_fifo[i] = s->rx_fifo[i + 1];
182 s->int_level |= INT_RCV;
183 } else {
184 s->int_level &= ~INT_RCV;
185 }
186 smc91c111_flush_queued_packets(s);
187 smc91c111_update(s);
188}
189
190
191static void smc91c111_pop_tx_fifo_done(smc91c111_state *s)
192{
193 int i;
194
195 if (s->tx_fifo_done_len == 0)
196 return;
197 s->tx_fifo_done_len--;
198 for (i = 0; i < s->tx_fifo_done_len; i++)
199 s->tx_fifo_done[i] = s->tx_fifo_done[i + 1];
200}
201
202
203static void smc91c111_release_packet(smc91c111_state *s, int packet)
204{
205 s->allocated &= ~(1 << packet);
206 if (s->tx_alloc == 0x80)
207 smc91c111_tx_alloc(s);
208 smc91c111_flush_queued_packets(s);
209}
210
211
212static void smc91c111_do_tx(smc91c111_state *s)
213{
214 int i;
215 int len;
216 int control;
217 int packetnum;
218 uint8_t *p;
219
220 if ((s->tcr & TCR_TXEN) == 0)
221 return;
222 if (s->tx_fifo_len == 0)
223 return;
224 for (i = 0; i < s->tx_fifo_len; i++) {
225 packetnum = s->tx_fifo[i];
226 p = &s->data[packetnum][0];
227
228 *(p++) = 0x01;
229 *(p++) = 0x40;
230 len = *(p++);
231 len |= ((int)*(p++)) << 8;
232 len -= 6;
233 control = p[len + 1];
234 if (control & 0x20)
235 len++;
236
237
238 if (len < 64 && (s->tcr & TCR_PAD_EN)) {
239 memset(p + len, 0, 64 - len);
240 len = 64;
241 }
242#if 0
243 {
244 int add_crc;
245
246
247
248
249
250 add_crc = (control & 0x10) || (s->tcr & TCR_NOCRC) == 0;
251 if (add_crc) {
252 uint32_t crc;
253
254 crc = crc32(~0, p, len);
255 memcpy(p + len, &crc, 4);
256 len += 4;
257 }
258 }
259#endif
260 if (s->ctr & CTR_AUTO_RELEASE)
261
262 smc91c111_release_packet(s, packetnum);
263 else if (s->tx_fifo_done_len < NUM_PACKETS)
264 s->tx_fifo_done[s->tx_fifo_done_len++] = packetnum;
265 qemu_send_packet(qemu_get_queue(s->nic), p, len);
266 }
267 s->tx_fifo_len = 0;
268 smc91c111_update(s);
269}
270
271
272static void smc91c111_queue_tx(smc91c111_state *s, int packet)
273{
274 if (s->tx_fifo_len == NUM_PACKETS)
275 return;
276 s->tx_fifo[s->tx_fifo_len++] = packet;
277 smc91c111_do_tx(s);
278}
279
280static void smc91c111_reset(DeviceState *dev)
281{
282 smc91c111_state *s = SMC91C111(dev);
283
284 s->bank = 0;
285 s->tx_fifo_len = 0;
286 s->tx_fifo_done_len = 0;
287 s->rx_fifo_len = 0;
288 s->allocated = 0;
289 s->packet_num = 0;
290 s->tx_alloc = 0;
291 s->tcr = 0;
292 s->rcr = 0;
293 s->cr = 0xa0b1;
294 s->ctr = 0x1210;
295 s->ptr = 0;
296 s->ercv = 0x1f;
297 s->int_level = INT_TX_EMPTY;
298 s->int_mask = 0;
299 smc91c111_update(s);
300}
301
302#define SET_LOW(name, val) s->name = (s->name & 0xff00) | val
303#define SET_HIGH(name, val) s->name = (s->name & 0xff) | (val << 8)
304
305static void smc91c111_writeb(void *opaque, hwaddr offset,
306 uint32_t value)
307{
308 smc91c111_state *s = (smc91c111_state *)opaque;
309
310 offset = offset & 0xf;
311 if (offset == 14) {
312 s->bank = value;
313 return;
314 }
315 if (offset == 15)
316 return;
317 switch (s->bank) {
318 case 0:
319 switch (offset) {
320 case 0:
321 SET_LOW(tcr, value);
322 return;
323 case 1:
324 SET_HIGH(tcr, value);
325 return;
326 case 4:
327 SET_LOW(rcr, value);
328 return;
329 case 5:
330 SET_HIGH(rcr, value);
331 if (s->rcr & RCR_SOFT_RST) {
332 smc91c111_reset(DEVICE(s));
333 }
334 smc91c111_flush_queued_packets(s);
335 return;
336 case 10: case 11:
337
338 return;
339 case 12: case 13:
340 return;
341 }
342 break;
343
344 case 1:
345 switch (offset) {
346 case 0:
347 SET_LOW(cr, value);
348 return;
349 case 1:
350 SET_HIGH(cr,value);
351 return;
352 case 2: case 3:
353 case 4: case 5: case 6: case 7: case 8: case 9:
354
355 return;
356 case 10:
357 SET_LOW(gpr, value);
358 return;
359 case 11:
360 SET_HIGH(gpr, value);
361 return;
362 case 12:
363 if (value & 1)
364 fprintf(stderr, "smc91c111:EEPROM store not implemented\n");
365 if (value & 2)
366 fprintf(stderr, "smc91c111:EEPROM reload not implemented\n");
367 value &= ~3;
368 SET_LOW(ctr, value);
369 return;
370 case 13:
371 SET_HIGH(ctr, value);
372 return;
373 }
374 break;
375
376 case 2:
377 switch (offset) {
378 case 0:
379 switch (value >> 5) {
380 case 0:
381 break;
382 case 1:
383 s->tx_alloc = 0x80;
384 s->int_level &= ~INT_ALLOC;
385 smc91c111_update(s);
386 smc91c111_tx_alloc(s);
387 break;
388 case 2:
389 s->allocated = 0;
390 s->tx_fifo_len = 0;
391 s->tx_fifo_done_len = 0;
392 s->rx_fifo_len = 0;
393 s->tx_alloc = 0;
394 break;
395 case 3:
396 smc91c111_pop_rx_fifo(s);
397 break;
398 case 4:
399 if (s->rx_fifo_len > 0) {
400 smc91c111_release_packet(s, s->rx_fifo[0]);
401 }
402 smc91c111_pop_rx_fifo(s);
403 break;
404 case 5:
405 smc91c111_release_packet(s, s->packet_num);
406 break;
407 case 6:
408 smc91c111_queue_tx(s, s->packet_num);
409 break;
410 case 7:
411 s->tx_fifo_len = 0;
412 s->tx_fifo_done_len = 0;
413 break;
414 }
415 return;
416 case 1:
417
418 return;
419 case 2:
420 s->packet_num = value;
421 return;
422 case 3: case 4: case 5:
423
424 return;
425 case 6:
426 SET_LOW(ptr, value);
427 return;
428 case 7:
429 SET_HIGH(ptr, value);
430 return;
431 case 8: case 9: case 10: case 11:
432 {
433 int p;
434 int n;
435
436 if (s->ptr & 0x8000)
437 n = s->rx_fifo[0];
438 else
439 n = s->packet_num;
440 p = s->ptr & 0x07ff;
441 if (s->ptr & 0x4000) {
442 s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x7ff);
443 } else {
444 p += (offset & 3);
445 }
446 s->data[n][p] = value;
447 }
448 return;
449 case 12:
450 s->int_level &= ~(value & 0xd6);
451 if (value & INT_TX)
452 smc91c111_pop_tx_fifo_done(s);
453 smc91c111_update(s);
454 return;
455 case 13:
456 s->int_mask = value;
457 smc91c111_update(s);
458 return;
459 }
460 break;
461
462 case 3:
463 switch (offset) {
464 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
465
466
467 return;
468 case 8: case 9:
469
470 return;
471 case 12:
472 s->ercv = value & 0x1f;
473 return;
474 case 13:
475
476 return;
477 }
478 break;
479 }
480 hw_error("smc91c111_write: Bad reg %d:%x\n", s->bank, (int)offset);
481}
482
483static uint32_t smc91c111_readb(void *opaque, hwaddr offset)
484{
485 smc91c111_state *s = (smc91c111_state *)opaque;
486
487 offset = offset & 0xf;
488 if (offset == 14) {
489 return s->bank;
490 }
491 if (offset == 15)
492 return 0x33;
493 switch (s->bank) {
494 case 0:
495 switch (offset) {
496 case 0:
497 return s->tcr & 0xff;
498 case 1:
499 return s->tcr >> 8;
500 case 2:
501 return 0;
502 case 3:
503 return 0x40;
504 case 4:
505 return s->rcr & 0xff;
506 case 5:
507 return s->rcr >> 8;
508 case 6:
509 case 7:
510
511 return 0;
512 case 8:
513 return NUM_PACKETS;
514 case 9:
515 {
516 int i;
517 int n;
518 n = 0;
519 for (i = 0; i < NUM_PACKETS; i++) {
520 if (s->allocated & (1 << i))
521 n++;
522 }
523 return n;
524 }
525 case 10: case 11:
526
527 return 0;
528 case 12: case 13:
529 return 0;
530 }
531 break;
532
533 case 1:
534 switch (offset) {
535 case 0:
536 return s->cr & 0xff;
537 case 1:
538 return s->cr >> 8;
539 case 2: case 3:
540
541 return 0;
542 case 4: case 5: case 6: case 7: case 8: case 9:
543 return s->conf.macaddr.a[offset - 4];
544 case 10:
545 return s->gpr & 0xff;
546 case 11:
547 return s->gpr >> 8;
548 case 12:
549 return s->ctr & 0xff;
550 case 13:
551 return s->ctr >> 8;
552 }
553 break;
554
555 case 2:
556 switch (offset) {
557 case 0: case 1:
558 return 0;
559 case 2:
560 return s->packet_num;
561 case 3:
562 return s->tx_alloc;
563 case 4:
564 if (s->tx_fifo_done_len == 0)
565 return 0x80;
566 else
567 return s->tx_fifo_done[0];
568 case 5:
569 if (s->rx_fifo_len == 0)
570 return 0x80;
571 else
572 return s->rx_fifo[0];
573 case 6:
574 return s->ptr & 0xff;
575 case 7:
576 return (s->ptr >> 8) & 0xf7;
577 case 8: case 9: case 10: case 11:
578 {
579 int p;
580 int n;
581
582 if (s->ptr & 0x8000)
583 n = s->rx_fifo[0];
584 else
585 n = s->packet_num;
586 p = s->ptr & 0x07ff;
587 if (s->ptr & 0x4000) {
588 s->ptr = (s->ptr & 0xf800) | ((s->ptr + 1) & 0x07ff);
589 } else {
590 p += (offset & 3);
591 }
592 return s->data[n][p];
593 }
594 case 12:
595 return s->int_level;
596 case 13:
597 return s->int_mask;
598 }
599 break;
600
601 case 3:
602 switch (offset) {
603 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
604
605
606 return 0;
607 case 8:
608
609 return 0x30;
610 case 9:
611 return 0x33;
612 case 10:
613 return 0x91;
614 case 11:
615 return 0x33;
616 case 12:
617 return s->ercv;
618 case 13:
619 return 0;
620 }
621 break;
622 }
623 hw_error("smc91c111_read: Bad reg %d:%x\n", s->bank, (int)offset);
624 return 0;
625}
626
627static void smc91c111_writew(void *opaque, hwaddr offset,
628 uint32_t value)
629{
630 smc91c111_writeb(opaque, offset, value & 0xff);
631 smc91c111_writeb(opaque, offset + 1, value >> 8);
632}
633
634static void smc91c111_writel(void *opaque, hwaddr offset,
635 uint32_t value)
636{
637
638
639 if (offset != 0xc)
640 smc91c111_writew(opaque, offset, value & 0xffff);
641 smc91c111_writew(opaque, offset + 2, value >> 16);
642}
643
644static uint32_t smc91c111_readw(void *opaque, hwaddr offset)
645{
646 uint32_t val;
647 val = smc91c111_readb(opaque, offset);
648 val |= smc91c111_readb(opaque, offset + 1) << 8;
649 return val;
650}
651
652static uint32_t smc91c111_readl(void *opaque, hwaddr offset)
653{
654 uint32_t val;
655 val = smc91c111_readw(opaque, offset);
656 val |= smc91c111_readw(opaque, offset + 2) << 16;
657 return val;
658}
659
660static int smc91c111_can_receive_nc(NetClientState *nc)
661{
662 smc91c111_state *s = qemu_get_nic_opaque(nc);
663
664 return smc91c111_can_receive(s);
665}
666
667static ssize_t smc91c111_receive(NetClientState *nc, const uint8_t *buf, size_t size)
668{
669 smc91c111_state *s = qemu_get_nic_opaque(nc);
670 int status;
671 int packetsize;
672 uint32_t crc;
673 int packetnum;
674 uint8_t *p;
675
676 if ((s->rcr & RCR_RXEN) == 0 || (s->rcr & RCR_SOFT_RST))
677 return -1;
678
679
680 if (size < 64)
681 packetsize = 64;
682 else
683 packetsize = (size & ~1);
684 packetsize += 6;
685 crc = (s->rcr & RCR_STRIP_CRC) == 0;
686 if (crc)
687 packetsize += 4;
688
689 if (packetsize > 2048)
690 return -1;
691 packetnum = smc91c111_allocate_packet(s);
692 if (packetnum == 0x80)
693 return -1;
694 s->rx_fifo[s->rx_fifo_len++] = packetnum;
695
696 p = &s->data[packetnum][0];
697
698 status = 0;
699 if (size > 1518)
700 status |= RS_TOOLONG;
701 if (size & 1)
702 status |= RS_ODDFRAME;
703 *(p++) = status & 0xff;
704 *(p++) = status >> 8;
705 *(p++) = packetsize & 0xff;
706 *(p++) = packetsize >> 8;
707 memcpy(p, buf, size & ~1);
708 p += (size & ~1);
709
710 if (size < 64) {
711 int pad;
712
713 if (size & 1)
714 *(p++) = buf[size - 1];
715 pad = 64 - size;
716 memset(p, 0, pad);
717 p += pad;
718 size = 64;
719 }
720
721
722
723
724 if (crc) {
725 crc = crc32(~0, buf, size);
726 *(p++) = crc & 0xff; crc >>= 8;
727 *(p++) = crc & 0xff; crc >>= 8;
728 *(p++) = crc & 0xff; crc >>= 8;
729 *(p++) = crc & 0xff;
730 }
731 if (size & 1) {
732 *(p++) = buf[size - 1];
733 *p = 0x60;
734 } else {
735 *(p++) = 0;
736 *p = 0x40;
737 }
738
739 s->int_level |= INT_RCV;
740 smc91c111_update(s);
741
742 return size;
743}
744
745static const MemoryRegionOps smc91c111_mem_ops = {
746
747
748
749 .old_mmio = {
750 .read = { smc91c111_readb, smc91c111_readw, smc91c111_readl, },
751 .write = { smc91c111_writeb, smc91c111_writew, smc91c111_writel, },
752 },
753 .endianness = DEVICE_NATIVE_ENDIAN,
754};
755
756static NetClientInfo net_smc91c111_info = {
757 .type = NET_CLIENT_OPTIONS_KIND_NIC,
758 .size = sizeof(NICState),
759 .can_receive = smc91c111_can_receive_nc,
760 .receive = smc91c111_receive,
761};
762
763static int smc91c111_init1(SysBusDevice *sbd)
764{
765 DeviceState *dev = DEVICE(sbd);
766 smc91c111_state *s = SMC91C111(dev);
767
768 memory_region_init_io(&s->mmio, OBJECT(s), &smc91c111_mem_ops, s,
769 "smc91c111-mmio", 16);
770 sysbus_init_mmio(sbd, &s->mmio);
771 sysbus_init_irq(sbd, &s->irq);
772 qemu_macaddr_default_if_unset(&s->conf.macaddr);
773 s->nic = qemu_new_nic(&net_smc91c111_info, &s->conf,
774 object_get_typename(OBJECT(dev)), dev->id, s);
775 qemu_format_nic_info_str(qemu_get_queue(s->nic), s->conf.macaddr.a);
776
777 return 0;
778}
779
780static Property smc91c111_properties[] = {
781 DEFINE_NIC_PROPERTIES(smc91c111_state, conf),
782 DEFINE_PROP_END_OF_LIST(),
783};
784
785static void smc91c111_class_init(ObjectClass *klass, void *data)
786{
787 DeviceClass *dc = DEVICE_CLASS(klass);
788 SysBusDeviceClass *k = SYS_BUS_DEVICE_CLASS(klass);
789
790 k->init = smc91c111_init1;
791 dc->reset = smc91c111_reset;
792 dc->vmsd = &vmstate_smc91c111;
793 dc->props = smc91c111_properties;
794}
795
796static const TypeInfo smc91c111_info = {
797 .name = TYPE_SMC91C111,
798 .parent = TYPE_SYS_BUS_DEVICE,
799 .instance_size = sizeof(smc91c111_state),
800 .class_init = smc91c111_class_init,
801};
802
803static void smc91c111_register_types(void)
804{
805 type_register_static(&smc91c111_info);
806}
807
808
809
810void smc91c111_init(NICInfo *nd, uint32_t base, qemu_irq irq)
811{
812 DeviceState *dev;
813 SysBusDevice *s;
814
815 qemu_check_nic_model(nd, "smc91c111");
816 dev = qdev_create(NULL, TYPE_SMC91C111);
817 qdev_set_nic_properties(dev, nd);
818 qdev_init_nofail(dev);
819 s = SYS_BUS_DEVICE(dev);
820 sysbus_mmio_map(s, 0, base);
821 sysbus_connect_irq(s, 0, irq);
822}
823
824type_init(smc91c111_register_types)
825