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