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