2 * SMSC 91C111 Ethernet interface emulation
4 * Copyright (c) 2005 CodeSourcery, LLC.
5 * Written by Paul Brook
7 * This code is licensed under the GPL
10 #include "qemu/osdep.h"
11 #include "hw/sysbus.h"
12 #include "migration/vmstate.h"
15 #include "hw/net/smc91c111.h"
16 #include "hw/qdev-properties.h"
17 #include "qapi/error.h"
19 #include "qemu/module.h"
20 #include <zlib.h> /* for crc32 */
21 #include "qom/object.h"
23 /* Number of 2k memory pages available. */
26 #define TYPE_SMC91C111 "smc91c111"
27 OBJECT_DECLARE_SIMPLE_TYPE(smc91c111_state
, SMC91C111
)
29 struct smc91c111_state
{
30 SysBusDevice parent_obj
;
45 /* Bitmask of allocated packets. */
48 int tx_fifo
[NUM_PACKETS
];
50 int rx_fifo
[NUM_PACKETS
];
52 int tx_fifo_done
[NUM_PACKETS
];
53 /* Packet buffer memory. */
54 uint8_t data
[NUM_PACKETS
][2048];
60 static const VMStateDescription vmstate_smc91c111
= {
63 .minimum_version_id
= 1,
64 .fields
= (const VMStateField
[]) {
65 VMSTATE_UINT16(tcr
, smc91c111_state
),
66 VMSTATE_UINT16(rcr
, smc91c111_state
),
67 VMSTATE_UINT16(cr
, smc91c111_state
),
68 VMSTATE_UINT16(ctr
, smc91c111_state
),
69 VMSTATE_UINT16(gpr
, smc91c111_state
),
70 VMSTATE_UINT16(ptr
, smc91c111_state
),
71 VMSTATE_UINT16(ercv
, smc91c111_state
),
72 VMSTATE_INT32(bank
, smc91c111_state
),
73 VMSTATE_INT32(packet_num
, smc91c111_state
),
74 VMSTATE_INT32(tx_alloc
, smc91c111_state
),
75 VMSTATE_INT32(allocated
, smc91c111_state
),
76 VMSTATE_INT32(tx_fifo_len
, smc91c111_state
),
77 VMSTATE_INT32_ARRAY(tx_fifo
, smc91c111_state
, NUM_PACKETS
),
78 VMSTATE_INT32(rx_fifo_len
, smc91c111_state
),
79 VMSTATE_INT32_ARRAY(rx_fifo
, smc91c111_state
, NUM_PACKETS
),
80 VMSTATE_INT32(tx_fifo_done_len
, smc91c111_state
),
81 VMSTATE_INT32_ARRAY(tx_fifo_done
, smc91c111_state
, NUM_PACKETS
),
82 VMSTATE_BUFFER_UNSAFE(data
, smc91c111_state
, 0, NUM_PACKETS
* 2048),
83 VMSTATE_UINT8(int_level
, smc91c111_state
),
84 VMSTATE_UINT8(int_mask
, smc91c111_state
),
89 #define RCR_SOFT_RST 0x8000
90 #define RCR_STRIP_CRC 0x0200
91 #define RCR_RXEN 0x0100
93 #define TCR_EPH_LOOP 0x2000
94 #define TCR_NOCRC 0x0100
95 #define TCR_PAD_EN 0x0080
96 #define TCR_FORCOL 0x0004
97 #define TCR_LOOP 0x0002
98 #define TCR_TXEN 0x0001
101 #define INT_ERCV 0x40
103 #define INT_RX_OVRN 0x10
104 #define INT_ALLOC 0x08
105 #define INT_TX_EMPTY 0x04
109 #define CTR_AUTO_RELEASE 0x0800
110 #define CTR_RELOAD 0x0002
111 #define CTR_STORE 0x0001
113 #define RS_ALGNERR 0x8000
114 #define RS_BRODCAST 0x4000
115 #define RS_BADCRC 0x2000
116 #define RS_ODDFRAME 0x1000
117 #define RS_TOOLONG 0x0800
118 #define RS_TOOSHORT 0x0400
119 #define RS_MULTICAST 0x0001
121 /* Update interrupt status. */
122 static void smc91c111_update(smc91c111_state
*s
)
126 if (s
->tx_fifo_len
== 0)
127 s
->int_level
|= INT_TX_EMPTY
;
128 if (s
->tx_fifo_done_len
!= 0)
129 s
->int_level
|= INT_TX
;
130 level
= (s
->int_level
& s
->int_mask
) != 0;
131 qemu_set_irq(s
->irq
, level
);
134 static bool smc91c111_can_receive(smc91c111_state
*s
)
136 if ((s
->rcr
& RCR_RXEN
) == 0 || (s
->rcr
& RCR_SOFT_RST
)) {
139 if (s
->allocated
== (1 << NUM_PACKETS
) - 1 ||
140 s
->rx_fifo_len
== NUM_PACKETS
) {
146 static inline void smc91c111_flush_queued_packets(smc91c111_state
*s
)
148 if (smc91c111_can_receive(s
)) {
149 qemu_flush_queued_packets(qemu_get_queue(s
->nic
));
153 /* Try to allocate a packet. Returns 0x80 on failure. */
154 static int smc91c111_allocate_packet(smc91c111_state
*s
)
157 if (s
->allocated
== (1 << NUM_PACKETS
) - 1) {
161 for (i
= 0; i
< NUM_PACKETS
; i
++) {
162 if ((s
->allocated
& (1 << i
)) == 0)
165 s
->allocated
|= 1 << i
;
170 /* Process a pending TX allocate. */
171 static void smc91c111_tx_alloc(smc91c111_state
*s
)
173 s
->tx_alloc
= smc91c111_allocate_packet(s
);
174 if (s
->tx_alloc
== 0x80)
176 s
->int_level
|= INT_ALLOC
;
180 /* Remove and item from the RX FIFO. */
181 static void smc91c111_pop_rx_fifo(smc91c111_state
*s
)
186 if (s
->rx_fifo_len
) {
187 for (i
= 0; i
< s
->rx_fifo_len
; i
++)
188 s
->rx_fifo
[i
] = s
->rx_fifo
[i
+ 1];
189 s
->int_level
|= INT_RCV
;
191 s
->int_level
&= ~INT_RCV
;
193 smc91c111_flush_queued_packets(s
);
197 /* Remove an item from the TX completion FIFO. */
198 static void smc91c111_pop_tx_fifo_done(smc91c111_state
*s
)
202 if (s
->tx_fifo_done_len
== 0)
204 s
->tx_fifo_done_len
--;
205 for (i
= 0; i
< s
->tx_fifo_done_len
; i
++)
206 s
->tx_fifo_done
[i
] = s
->tx_fifo_done
[i
+ 1];
209 /* Release the memory allocated to a packet. */
210 static void smc91c111_release_packet(smc91c111_state
*s
, int packet
)
212 s
->allocated
&= ~(1 << packet
);
213 if (s
->tx_alloc
== 0x80)
214 smc91c111_tx_alloc(s
);
215 smc91c111_flush_queued_packets(s
);
218 /* Flush the TX FIFO. */
219 static void smc91c111_do_tx(smc91c111_state
*s
)
227 if ((s
->tcr
& TCR_TXEN
) == 0)
229 if (s
->tx_fifo_len
== 0)
231 for (i
= 0; i
< s
->tx_fifo_len
; i
++) {
232 packetnum
= s
->tx_fifo
[i
];
233 p
= &s
->data
[packetnum
][0];
234 /* Set status word. */
238 len
|= ((int)*(p
++)) << 8;
240 control
= p
[len
+ 1];
243 /* ??? This overwrites the data following the buffer.
244 Don't know what real hardware does. */
245 if (len
< 64 && (s
->tcr
& TCR_PAD_EN
)) {
246 memset(p
+ len
, 0, 64 - len
);
253 /* The card is supposed to append the CRC to the frame.
254 However none of the other network traffic has the CRC
255 appended. Suspect this is low level ethernet detail we
256 don't need to worry about. */
257 add_crc
= (control
& 0x10) || (s
->tcr
& TCR_NOCRC
) == 0;
261 crc
= crc32(~0, p
, len
);
262 memcpy(p
+ len
, &crc
, 4);
267 if (s
->ctr
& CTR_AUTO_RELEASE
)
269 smc91c111_release_packet(s
, packetnum
);
270 else if (s
->tx_fifo_done_len
< NUM_PACKETS
)
271 s
->tx_fifo_done
[s
->tx_fifo_done_len
++] = packetnum
;
272 qemu_send_packet(qemu_get_queue(s
->nic
), p
, len
);
278 /* Add a packet to the TX FIFO. */
279 static void smc91c111_queue_tx(smc91c111_state
*s
, int packet
)
281 if (s
->tx_fifo_len
== NUM_PACKETS
)
283 s
->tx_fifo
[s
->tx_fifo_len
++] = packet
;
287 static void smc91c111_reset(DeviceState
*dev
)
289 smc91c111_state
*s
= SMC91C111(dev
);
293 s
->tx_fifo_done_len
= 0;
304 s
->int_level
= INT_TX_EMPTY
;
309 #define SET_LOW(name, val) s->name = (s->name & 0xff00) | val
310 #define SET_HIGH(name, val) s->name = (s->name & 0xff) | (val << 8)
312 static void smc91c111_writeb(void *opaque
, hwaddr offset
,
315 smc91c111_state
*s
= (smc91c111_state
*)opaque
;
317 offset
= offset
& 0xf;
331 SET_HIGH(tcr
, value
);
337 SET_HIGH(rcr
, value
);
338 if (s
->rcr
& RCR_SOFT_RST
) {
339 smc91c111_reset(DEVICE(s
));
341 smc91c111_flush_queued_packets(s
);
343 case 10: case 11: /* RPCR */
346 case 12: case 13: /* Reserved */
359 case 2: case 3: /* BASE */
360 case 4: case 5: case 6: case 7: case 8: case 9: /* IA */
361 /* Not implemented. */
363 case 10: /* General Purpose */
367 SET_HIGH(gpr
, value
);
369 case 12: /* Control */
371 qemu_log_mask(LOG_UNIMP
,
372 "smc91c111: EEPROM store not implemented\n");
375 qemu_log_mask(LOG_UNIMP
,
376 "smc91c111: EEPROM reload not implemented\n");
382 SET_HIGH(ctr
, value
);
389 case 0: /* MMU Command */
390 switch (value
>> 5) {
393 case 1: /* Allocate for TX. */
395 s
->int_level
&= ~INT_ALLOC
;
397 smc91c111_tx_alloc(s
);
399 case 2: /* Reset MMU. */
402 s
->tx_fifo_done_len
= 0;
406 case 3: /* Remove from RX FIFO. */
407 smc91c111_pop_rx_fifo(s
);
409 case 4: /* Remove from RX FIFO and release. */
410 if (s
->rx_fifo_len
> 0) {
411 smc91c111_release_packet(s
, s
->rx_fifo
[0]);
413 smc91c111_pop_rx_fifo(s
);
415 case 5: /* Release. */
416 smc91c111_release_packet(s
, s
->packet_num
);
418 case 6: /* Add to TX FIFO. */
419 smc91c111_queue_tx(s
, s
->packet_num
);
421 case 7: /* Reset TX FIFO. */
423 s
->tx_fifo_done_len
= 0;
430 case 2: /* Packet Number Register */
431 s
->packet_num
= value
;
433 case 3: case 4: case 5:
434 /* Should be readonly, but linux writes to them anyway. Ignore. */
436 case 6: /* Pointer */
440 SET_HIGH(ptr
, value
);
442 case 8: case 9: case 10: case 11: /* Data */
452 if (s
->ptr
& 0x4000) {
453 s
->ptr
= (s
->ptr
& 0xf800) | ((s
->ptr
+ 1) & 0x7ff);
457 s
->data
[n
][p
] = value
;
460 case 12: /* Interrupt ACK. */
461 s
->int_level
&= ~(value
& 0xd6);
463 smc91c111_pop_tx_fifo_done(s
);
466 case 13: /* Interrupt mask. */
475 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
476 /* Multicast table. */
477 /* Not implemented. */
479 case 8: case 9: /* Management Interface. */
480 /* Not implemented. */
482 case 12: /* Early receive. */
483 s
->ercv
= value
& 0x1f;
491 qemu_log_mask(LOG_GUEST_ERROR
, "smc91c111_write(bank:%d) Illegal register"
492 " 0x%" HWADDR_PRIx
" = 0x%x\n",
493 s
->bank
, offset
, value
);
496 static uint32_t smc91c111_readb(void *opaque
, hwaddr offset
)
498 smc91c111_state
*s
= (smc91c111_state
*)opaque
;
500 offset
= offset
& 0xf;
510 return s
->tcr
& 0xff;
513 case 2: /* EPH Status */
518 return s
->rcr
& 0xff;
521 case 6: /* Counter */
523 /* Not implemented. */
525 case 8: /* Memory size. */
527 case 9: /* Free memory available. */
532 for (i
= 0; i
< NUM_PACKETS
; i
++) {
533 if (s
->allocated
& (1 << i
))
538 case 10: case 11: /* RPCR */
539 /* Not implemented. */
541 case 12: case 13: /* Reserved */
552 case 2: case 3: /* BASE */
553 /* Not implemented. */
555 case 4: case 5: case 6: case 7: case 8: case 9: /* IA */
556 return s
->conf
.macaddr
.a
[offset
- 4];
557 case 10: /* General Purpose */
558 return s
->gpr
& 0xff;
561 case 12: /* Control */
562 return s
->ctr
& 0xff;
570 case 0: case 1: /* MMUCR Busy bit. */
572 case 2: /* Packet Number. */
573 return s
->packet_num
;
574 case 3: /* Allocation Result. */
576 case 4: /* TX FIFO */
577 if (s
->tx_fifo_done_len
== 0)
580 return s
->tx_fifo_done
[0];
581 case 5: /* RX FIFO */
582 if (s
->rx_fifo_len
== 0)
585 return s
->rx_fifo
[0];
586 case 6: /* Pointer */
587 return s
->ptr
& 0xff;
589 return (s
->ptr
>> 8) & 0xf7;
590 case 8: case 9: case 10: case 11: /* Data */
600 if (s
->ptr
& 0x4000) {
601 s
->ptr
= (s
->ptr
& 0xf800) | ((s
->ptr
+ 1) & 0x07ff);
605 return s
->data
[n
][p
];
607 case 12: /* Interrupt status. */
609 case 13: /* Interrupt mask. */
616 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
617 /* Multicast table. */
618 /* Not implemented. */
620 case 8: /* Management Interface. */
621 /* Not implemented. */
625 case 10: /* Revision. */
636 qemu_log_mask(LOG_GUEST_ERROR
, "smc91c111_read(bank:%d) Illegal register"
637 " 0x%" HWADDR_PRIx
"\n",
642 static uint64_t smc91c111_readfn(void *opaque
, hwaddr addr
, unsigned size
)
647 for (i
= 0; i
< size
; i
++) {
648 val
|= smc91c111_readb(opaque
, addr
+ i
) << (i
* 8);
653 static void smc91c111_writefn(void *opaque
, hwaddr addr
,
654 uint64_t value
, unsigned size
)
658 /* 32-bit writes to offset 0xc only actually write to the bank select
659 * register (offset 0xe), so skip the first two bytes we would write.
661 if (addr
== 0xc && size
== 4) {
665 for (; i
< size
; i
++) {
666 smc91c111_writeb(opaque
, addr
+ i
,
667 extract32(value
, i
* 8, 8));
671 static bool smc91c111_can_receive_nc(NetClientState
*nc
)
673 smc91c111_state
*s
= qemu_get_nic_opaque(nc
);
675 return smc91c111_can_receive(s
);
678 static ssize_t
smc91c111_receive(NetClientState
*nc
, const uint8_t *buf
, size_t size
)
680 smc91c111_state
*s
= qemu_get_nic_opaque(nc
);
687 if ((s
->rcr
& RCR_RXEN
) == 0 || (s
->rcr
& RCR_SOFT_RST
))
689 /* Short packets are padded with zeros. Receiving a packet
690 < 64 bytes long is considered an error condition. */
694 packetsize
= (size
& ~1);
696 crc
= (s
->rcr
& RCR_STRIP_CRC
) == 0;
699 /* TODO: Flag overrun and receive errors. */
700 if (packetsize
> 2048)
702 packetnum
= smc91c111_allocate_packet(s
);
703 if (packetnum
== 0x80)
705 s
->rx_fifo
[s
->rx_fifo_len
++] = packetnum
;
707 p
= &s
->data
[packetnum
][0];
708 /* ??? Multicast packets? */
711 status
|= RS_TOOLONG
;
713 status
|= RS_ODDFRAME
;
714 *(p
++) = status
& 0xff;
715 *(p
++) = status
>> 8;
716 *(p
++) = packetsize
& 0xff;
717 *(p
++) = packetsize
>> 8;
718 memcpy(p
, buf
, size
& ~1);
720 /* Pad short packets. */
725 *(p
++) = buf
[size
- 1];
731 /* It's not clear if the CRC should go before or after the last byte in
732 odd sized packets. Linux disables the CRC, so that's no help.
733 The pictures in the documentation show the CRC aligned on a 16-bit
734 boundary before the last odd byte, so that's what we do. */
736 crc
= crc32(~0, buf
, size
);
737 *(p
++) = crc
& 0xff; crc
>>= 8;
738 *(p
++) = crc
& 0xff; crc
>>= 8;
739 *(p
++) = crc
& 0xff; crc
>>= 8;
743 *(p
++) = buf
[size
- 1];
749 /* TODO: Raise early RX interrupt? */
750 s
->int_level
|= INT_RCV
;
756 static const MemoryRegionOps smc91c111_mem_ops
= {
757 /* The special case for 32 bit writes to 0xc means we can't just
758 * set .impl.min/max_access_size to 1, unfortunately
760 .read
= smc91c111_readfn
,
761 .write
= smc91c111_writefn
,
762 .valid
.min_access_size
= 1,
763 .valid
.max_access_size
= 4,
764 .endianness
= DEVICE_NATIVE_ENDIAN
,
767 static NetClientInfo net_smc91c111_info
= {
768 .type
= NET_CLIENT_DRIVER_NIC
,
769 .size
= sizeof(NICState
),
770 .can_receive
= smc91c111_can_receive_nc
,
771 .receive
= smc91c111_receive
,
774 static void smc91c111_realize(DeviceState
*dev
, Error
**errp
)
776 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
777 smc91c111_state
*s
= SMC91C111(dev
);
779 memory_region_init_io(&s
->mmio
, OBJECT(s
), &smc91c111_mem_ops
, s
,
780 "smc91c111-mmio", 16);
781 sysbus_init_mmio(sbd
, &s
->mmio
);
782 sysbus_init_irq(sbd
, &s
->irq
);
783 qemu_macaddr_default_if_unset(&s
->conf
.macaddr
);
784 s
->nic
= qemu_new_nic(&net_smc91c111_info
, &s
->conf
,
785 object_get_typename(OBJECT(dev
)), dev
->id
,
786 &dev
->mem_reentrancy_guard
, s
);
787 qemu_format_nic_info_str(qemu_get_queue(s
->nic
), s
->conf
.macaddr
.a
);
788 /* ??? Save/restore. */
791 static Property smc91c111_properties
[] = {
792 DEFINE_NIC_PROPERTIES(smc91c111_state
, conf
),
793 DEFINE_PROP_END_OF_LIST(),
796 static void smc91c111_class_init(ObjectClass
*klass
, void *data
)
798 DeviceClass
*dc
= DEVICE_CLASS(klass
);
800 dc
->realize
= smc91c111_realize
;
801 device_class_set_legacy_reset(dc
, smc91c111_reset
);
802 dc
->vmsd
= &vmstate_smc91c111
;
803 device_class_set_props(dc
, smc91c111_properties
);
806 static const TypeInfo smc91c111_info
= {
807 .name
= TYPE_SMC91C111
,
808 .parent
= TYPE_SYS_BUS_DEVICE
,
809 .instance_size
= sizeof(smc91c111_state
),
810 .class_init
= smc91c111_class_init
,
813 static void smc91c111_register_types(void)
815 type_register_static(&smc91c111_info
);
818 /* Legacy helper function. Should go away when machine config files are
820 void smc91c111_init(uint32_t base
, qemu_irq irq
)
825 dev
= qdev_new(TYPE_SMC91C111
);
826 qemu_configure_nic_device(dev
, true, NULL
);
827 s
= SYS_BUS_DEVICE(dev
);
828 sysbus_realize_and_unref(s
, &error_fatal
);
829 sysbus_mmio_map(s
, 0, base
);
830 sysbus_connect_irq(s
, 0, irq
);
833 type_init(smc91c111_register_types
)