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