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"
18 #include "qemu/module.h"
22 /* Number of 2k memory pages available. */
25 #define TYPE_SMC91C111 "smc91c111"
26 #define SMC91C111(obj) OBJECT_CHECK(smc91c111_state, (obj), TYPE_SMC91C111)
29 SysBusDevice parent_obj
;
44 /* Bitmask of allocated packets. */
47 int tx_fifo
[NUM_PACKETS
];
49 int rx_fifo
[NUM_PACKETS
];
51 int tx_fifo_done
[NUM_PACKETS
];
52 /* Packet buffer memory. */
53 uint8_t data
[NUM_PACKETS
][2048];
59 static const VMStateDescription vmstate_smc91c111
= {
62 .minimum_version_id
= 1,
63 .fields
= (VMStateField
[]) {
64 VMSTATE_UINT16(tcr
, smc91c111_state
),
65 VMSTATE_UINT16(rcr
, smc91c111_state
),
66 VMSTATE_UINT16(cr
, smc91c111_state
),
67 VMSTATE_UINT16(ctr
, smc91c111_state
),
68 VMSTATE_UINT16(gpr
, smc91c111_state
),
69 VMSTATE_UINT16(ptr
, smc91c111_state
),
70 VMSTATE_UINT16(ercv
, smc91c111_state
),
71 VMSTATE_INT32(bank
, smc91c111_state
),
72 VMSTATE_INT32(packet_num
, smc91c111_state
),
73 VMSTATE_INT32(tx_alloc
, smc91c111_state
),
74 VMSTATE_INT32(allocated
, smc91c111_state
),
75 VMSTATE_INT32(tx_fifo_len
, smc91c111_state
),
76 VMSTATE_INT32_ARRAY(tx_fifo
, smc91c111_state
, NUM_PACKETS
),
77 VMSTATE_INT32(rx_fifo_len
, smc91c111_state
),
78 VMSTATE_INT32_ARRAY(rx_fifo
, smc91c111_state
, NUM_PACKETS
),
79 VMSTATE_INT32(tx_fifo_done_len
, smc91c111_state
),
80 VMSTATE_INT32_ARRAY(tx_fifo_done
, smc91c111_state
, NUM_PACKETS
),
81 VMSTATE_BUFFER_UNSAFE(data
, smc91c111_state
, 0, NUM_PACKETS
* 2048),
82 VMSTATE_UINT8(int_level
, smc91c111_state
),
83 VMSTATE_UINT8(int_mask
, smc91c111_state
),
88 #define RCR_SOFT_RST 0x8000
89 #define RCR_STRIP_CRC 0x0200
90 #define RCR_RXEN 0x0100
92 #define TCR_EPH_LOOP 0x2000
93 #define TCR_NOCRC 0x0100
94 #define TCR_PAD_EN 0x0080
95 #define TCR_FORCOL 0x0004
96 #define TCR_LOOP 0x0002
97 #define TCR_TXEN 0x0001
100 #define INT_ERCV 0x40
102 #define INT_RX_OVRN 0x10
103 #define INT_ALLOC 0x08
104 #define INT_TX_EMPTY 0x04
108 #define CTR_AUTO_RELEASE 0x0800
109 #define CTR_RELOAD 0x0002
110 #define CTR_STORE 0x0001
112 #define RS_ALGNERR 0x8000
113 #define RS_BRODCAST 0x4000
114 #define RS_BADCRC 0x2000
115 #define RS_ODDFRAME 0x1000
116 #define RS_TOOLONG 0x0800
117 #define RS_TOOSHORT 0x0400
118 #define RS_MULTICAST 0x0001
120 /* Update interrupt status. */
121 static void smc91c111_update(smc91c111_state
*s
)
125 if (s
->tx_fifo_len
== 0)
126 s
->int_level
|= INT_TX_EMPTY
;
127 if (s
->tx_fifo_done_len
!= 0)
128 s
->int_level
|= INT_TX
;
129 level
= (s
->int_level
& s
->int_mask
) != 0;
130 qemu_set_irq(s
->irq
, level
);
133 static int smc91c111_can_receive(smc91c111_state
*s
)
135 if ((s
->rcr
& RCR_RXEN
) == 0 || (s
->rcr
& RCR_SOFT_RST
)) {
138 if (s
->allocated
== (1 << NUM_PACKETS
) - 1 ||
139 s
->rx_fifo_len
== NUM_PACKETS
) {
145 static inline void smc91c111_flush_queued_packets(smc91c111_state
*s
)
147 if (smc91c111_can_receive(s
)) {
148 qemu_flush_queued_packets(qemu_get_queue(s
->nic
));
152 /* Try to allocate a packet. Returns 0x80 on failure. */
153 static int smc91c111_allocate_packet(smc91c111_state
*s
)
156 if (s
->allocated
== (1 << NUM_PACKETS
) - 1) {
160 for (i
= 0; i
< NUM_PACKETS
; i
++) {
161 if ((s
->allocated
& (1 << i
)) == 0)
164 s
->allocated
|= 1 << i
;
169 /* Process a pending TX allocate. */
170 static void smc91c111_tx_alloc(smc91c111_state
*s
)
172 s
->tx_alloc
= smc91c111_allocate_packet(s
);
173 if (s
->tx_alloc
== 0x80)
175 s
->int_level
|= INT_ALLOC
;
179 /* Remove and item from the RX FIFO. */
180 static void smc91c111_pop_rx_fifo(smc91c111_state
*s
)
185 if (s
->rx_fifo_len
) {
186 for (i
= 0; i
< s
->rx_fifo_len
; i
++)
187 s
->rx_fifo
[i
] = s
->rx_fifo
[i
+ 1];
188 s
->int_level
|= INT_RCV
;
190 s
->int_level
&= ~INT_RCV
;
192 smc91c111_flush_queued_packets(s
);
196 /* Remove an item from the TX completion FIFO. */
197 static void smc91c111_pop_tx_fifo_done(smc91c111_state
*s
)
201 if (s
->tx_fifo_done_len
== 0)
203 s
->tx_fifo_done_len
--;
204 for (i
= 0; i
< s
->tx_fifo_done_len
; i
++)
205 s
->tx_fifo_done
[i
] = s
->tx_fifo_done
[i
+ 1];
208 /* Release the memory allocated to a packet. */
209 static void smc91c111_release_packet(smc91c111_state
*s
, int packet
)
211 s
->allocated
&= ~(1 << packet
);
212 if (s
->tx_alloc
== 0x80)
213 smc91c111_tx_alloc(s
);
214 smc91c111_flush_queued_packets(s
);
217 /* Flush the TX FIFO. */
218 static void smc91c111_do_tx(smc91c111_state
*s
)
226 if ((s
->tcr
& TCR_TXEN
) == 0)
228 if (s
->tx_fifo_len
== 0)
230 for (i
= 0; i
< s
->tx_fifo_len
; i
++) {
231 packetnum
= s
->tx_fifo
[i
];
232 p
= &s
->data
[packetnum
][0];
233 /* Set status word. */
237 len
|= ((int)*(p
++)) << 8;
239 control
= p
[len
+ 1];
242 /* ??? This overwrites the data following the buffer.
243 Don't know what real hardware does. */
244 if (len
< 64 && (s
->tcr
& TCR_PAD_EN
)) {
245 memset(p
+ len
, 0, 64 - len
);
252 /* The card is supposed to append the CRC to the frame.
253 However none of the other network traffic has the CRC
254 appended. Suspect this is low level ethernet detail we
255 don't need to worry about. */
256 add_crc
= (control
& 0x10) || (s
->tcr
& TCR_NOCRC
) == 0;
260 crc
= crc32(~0, p
, len
);
261 memcpy(p
+ len
, &crc
, 4);
266 if (s
->ctr
& CTR_AUTO_RELEASE
)
268 smc91c111_release_packet(s
, packetnum
);
269 else if (s
->tx_fifo_done_len
< NUM_PACKETS
)
270 s
->tx_fifo_done
[s
->tx_fifo_done_len
++] = packetnum
;
271 qemu_send_packet(qemu_get_queue(s
->nic
), p
, len
);
277 /* Add a packet to the TX FIFO. */
278 static void smc91c111_queue_tx(smc91c111_state
*s
, int packet
)
280 if (s
->tx_fifo_len
== NUM_PACKETS
)
282 s
->tx_fifo
[s
->tx_fifo_len
++] = packet
;
286 static void smc91c111_reset(DeviceState
*dev
)
288 smc91c111_state
*s
= SMC91C111(dev
);
292 s
->tx_fifo_done_len
= 0;
303 s
->int_level
= INT_TX_EMPTY
;
308 #define SET_LOW(name, val) s->name = (s->name & 0xff00) | val
309 #define SET_HIGH(name, val) s->name = (s->name & 0xff) | (val << 8)
311 static void smc91c111_writeb(void *opaque
, hwaddr offset
,
314 smc91c111_state
*s
= (smc91c111_state
*)opaque
;
316 offset
= offset
& 0xf;
330 SET_HIGH(tcr
, value
);
336 SET_HIGH(rcr
, value
);
337 if (s
->rcr
& RCR_SOFT_RST
) {
338 smc91c111_reset(DEVICE(s
));
340 smc91c111_flush_queued_packets(s
);
342 case 10: case 11: /* RPCR */
345 case 12: case 13: /* Reserved */
358 case 2: case 3: /* BASE */
359 case 4: case 5: case 6: case 7: case 8: case 9: /* IA */
360 /* Not implemented. */
362 case 10: /* Genral Purpose */
366 SET_HIGH(gpr
, value
);
368 case 12: /* Control */
370 qemu_log_mask(LOG_UNIMP
,
371 "smc91c111: EEPROM store not implemented\n");
374 qemu_log_mask(LOG_UNIMP
,
375 "smc91c111: EEPROM reload not implemented\n");
381 SET_HIGH(ctr
, value
);
388 case 0: /* MMU Command */
389 switch (value
>> 5) {
392 case 1: /* Allocate for TX. */
394 s
->int_level
&= ~INT_ALLOC
;
396 smc91c111_tx_alloc(s
);
398 case 2: /* Reset MMU. */
401 s
->tx_fifo_done_len
= 0;
405 case 3: /* Remove from RX FIFO. */
406 smc91c111_pop_rx_fifo(s
);
408 case 4: /* Remove from RX FIFO and release. */
409 if (s
->rx_fifo_len
> 0) {
410 smc91c111_release_packet(s
, s
->rx_fifo
[0]);
412 smc91c111_pop_rx_fifo(s
);
414 case 5: /* Release. */
415 smc91c111_release_packet(s
, s
->packet_num
);
417 case 6: /* Add to TX FIFO. */
418 smc91c111_queue_tx(s
, s
->packet_num
);
420 case 7: /* Reset TX FIFO. */
422 s
->tx_fifo_done_len
= 0;
429 case 2: /* Packet Number Register */
430 s
->packet_num
= value
;
432 case 3: case 4: case 5:
433 /* Should be readonly, but linux writes to them anyway. Ignore. */
435 case 6: /* Pointer */
439 SET_HIGH(ptr
, value
);
441 case 8: case 9: case 10: case 11: /* Data */
451 if (s
->ptr
& 0x4000) {
452 s
->ptr
= (s
->ptr
& 0xf800) | ((s
->ptr
+ 1) & 0x7ff);
456 s
->data
[n
][p
] = value
;
459 case 12: /* Interrupt ACK. */
460 s
->int_level
&= ~(value
& 0xd6);
462 smc91c111_pop_tx_fifo_done(s
);
465 case 13: /* Interrupt mask. */
474 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
475 /* Multicast table. */
476 /* Not implemented. */
478 case 8: case 9: /* Management Interface. */
479 /* Not implemented. */
481 case 12: /* Early receive. */
482 s
->ercv
= value
& 0x1f;
490 qemu_log_mask(LOG_GUEST_ERROR
, "smc91c111_write(bank:%d) Illegal register"
491 " 0x%" HWADDR_PRIx
" = 0x%x\n",
492 s
->bank
, offset
, value
);
495 static uint32_t smc91c111_readb(void *opaque
, hwaddr offset
)
497 smc91c111_state
*s
= (smc91c111_state
*)opaque
;
499 offset
= offset
& 0xf;
509 return s
->tcr
& 0xff;
512 case 2: /* EPH Status */
517 return s
->rcr
& 0xff;
520 case 6: /* Counter */
522 /* Not implemented. */
524 case 8: /* Memory size. */
526 case 9: /* Free memory available. */
531 for (i
= 0; i
< NUM_PACKETS
; i
++) {
532 if (s
->allocated
& (1 << i
))
537 case 10: case 11: /* RPCR */
538 /* Not implemented. */
540 case 12: case 13: /* Reserved */
551 case 2: case 3: /* BASE */
552 /* Not implemented. */
554 case 4: case 5: case 6: case 7: case 8: case 9: /* IA */
555 return s
->conf
.macaddr
.a
[offset
- 4];
556 case 10: /* General Purpose */
557 return s
->gpr
& 0xff;
560 case 12: /* Control */
561 return s
->ctr
& 0xff;
569 case 0: case 1: /* MMUCR Busy bit. */
571 case 2: /* Packet Number. */
572 return s
->packet_num
;
573 case 3: /* Allocation Result. */
575 case 4: /* TX FIFO */
576 if (s
->tx_fifo_done_len
== 0)
579 return s
->tx_fifo_done
[0];
580 case 5: /* RX FIFO */
581 if (s
->rx_fifo_len
== 0)
584 return s
->rx_fifo
[0];
585 case 6: /* Pointer */
586 return s
->ptr
& 0xff;
588 return (s
->ptr
>> 8) & 0xf7;
589 case 8: case 9: case 10: case 11: /* Data */
599 if (s
->ptr
& 0x4000) {
600 s
->ptr
= (s
->ptr
& 0xf800) | ((s
->ptr
+ 1) & 0x07ff);
604 return s
->data
[n
][p
];
606 case 12: /* Interrupt status. */
608 case 13: /* Interrupt mask. */
615 case 0: case 1: case 2: case 3: case 4: case 5: case 6: case 7:
616 /* Multicast table. */
617 /* Not implemented. */
619 case 8: /* Management Interface. */
620 /* Not implemented. */
624 case 10: /* Revision. */
635 qemu_log_mask(LOG_GUEST_ERROR
, "smc91c111_read(bank:%d) Illegal register"
636 " 0x%" HWADDR_PRIx
"\n",
641 static uint64_t smc91c111_readfn(void *opaque
, hwaddr addr
, unsigned size
)
646 for (i
= 0; i
< size
; i
++) {
647 val
|= smc91c111_readb(opaque
, addr
+ i
) << (i
* 8);
652 static void smc91c111_writefn(void *opaque
, hwaddr addr
,
653 uint64_t value
, unsigned size
)
657 /* 32-bit writes to offset 0xc only actually write to the bank select
658 * register (offset 0xe), so skip the first two bytes we would write.
660 if (addr
== 0xc && size
== 4) {
664 for (; i
< size
; i
++) {
665 smc91c111_writeb(opaque
, addr
+ i
,
666 extract32(value
, i
* 8, 8));
670 static int smc91c111_can_receive_nc(NetClientState
*nc
)
672 smc91c111_state
*s
= qemu_get_nic_opaque(nc
);
674 return smc91c111_can_receive(s
);
677 static ssize_t
smc91c111_receive(NetClientState
*nc
, const uint8_t *buf
, size_t size
)
679 smc91c111_state
*s
= qemu_get_nic_opaque(nc
);
686 if ((s
->rcr
& RCR_RXEN
) == 0 || (s
->rcr
& RCR_SOFT_RST
))
688 /* Short packets are padded with zeros. Receiving a packet
689 < 64 bytes long is considered an error condition. */
693 packetsize
= (size
& ~1);
695 crc
= (s
->rcr
& RCR_STRIP_CRC
) == 0;
698 /* TODO: Flag overrun and receive errors. */
699 if (packetsize
> 2048)
701 packetnum
= smc91c111_allocate_packet(s
);
702 if (packetnum
== 0x80)
704 s
->rx_fifo
[s
->rx_fifo_len
++] = packetnum
;
706 p
= &s
->data
[packetnum
][0];
707 /* ??? Multicast packets? */
710 status
|= RS_TOOLONG
;
712 status
|= RS_ODDFRAME
;
713 *(p
++) = status
& 0xff;
714 *(p
++) = status
>> 8;
715 *(p
++) = packetsize
& 0xff;
716 *(p
++) = packetsize
>> 8;
717 memcpy(p
, buf
, size
& ~1);
719 /* Pad short packets. */
724 *(p
++) = buf
[size
- 1];
730 /* It's not clear if the CRC should go before or after the last byte in
731 odd sized packets. Linux disables the CRC, so that's no help.
732 The pictures in the documentation show the CRC aligned on a 16-bit
733 boundary before the last odd byte, so that's what we do. */
735 crc
= crc32(~0, buf
, size
);
736 *(p
++) = crc
& 0xff; crc
>>= 8;
737 *(p
++) = crc
& 0xff; crc
>>= 8;
738 *(p
++) = crc
& 0xff; crc
>>= 8;
742 *(p
++) = buf
[size
- 1];
748 /* TODO: Raise early RX interrupt? */
749 s
->int_level
|= INT_RCV
;
755 static const MemoryRegionOps smc91c111_mem_ops
= {
756 /* The special case for 32 bit writes to 0xc means we can't just
757 * set .impl.min/max_access_size to 1, unfortunately
759 .read
= smc91c111_readfn
,
760 .write
= smc91c111_writefn
,
761 .valid
.min_access_size
= 1,
762 .valid
.max_access_size
= 4,
763 .endianness
= DEVICE_NATIVE_ENDIAN
,
766 static NetClientInfo net_smc91c111_info
= {
767 .type
= NET_CLIENT_DRIVER_NIC
,
768 .size
= sizeof(NICState
),
769 .can_receive
= smc91c111_can_receive_nc
,
770 .receive
= smc91c111_receive
,
773 static void smc91c111_realize(DeviceState
*dev
, Error
**errp
)
775 SysBusDevice
*sbd
= SYS_BUS_DEVICE(dev
);
776 smc91c111_state
*s
= SMC91C111(dev
);
778 memory_region_init_io(&s
->mmio
, OBJECT(s
), &smc91c111_mem_ops
, s
,
779 "smc91c111-mmio", 16);
780 sysbus_init_mmio(sbd
, &s
->mmio
);
781 sysbus_init_irq(sbd
, &s
->irq
);
782 qemu_macaddr_default_if_unset(&s
->conf
.macaddr
);
783 s
->nic
= qemu_new_nic(&net_smc91c111_info
, &s
->conf
,
784 object_get_typename(OBJECT(dev
)), dev
->id
, s
);
785 qemu_format_nic_info_str(qemu_get_queue(s
->nic
), s
->conf
.macaddr
.a
);
786 /* ??? Save/restore. */
789 static Property smc91c111_properties
[] = {
790 DEFINE_NIC_PROPERTIES(smc91c111_state
, conf
),
791 DEFINE_PROP_END_OF_LIST(),
794 static void smc91c111_class_init(ObjectClass
*klass
, void *data
)
796 DeviceClass
*dc
= DEVICE_CLASS(klass
);
798 dc
->realize
= smc91c111_realize
;
799 dc
->reset
= smc91c111_reset
;
800 dc
->vmsd
= &vmstate_smc91c111
;
801 dc
->props
= smc91c111_properties
;
804 static const TypeInfo smc91c111_info
= {
805 .name
= TYPE_SMC91C111
,
806 .parent
= TYPE_SYS_BUS_DEVICE
,
807 .instance_size
= sizeof(smc91c111_state
),
808 .class_init
= smc91c111_class_init
,
811 static void smc91c111_register_types(void)
813 type_register_static(&smc91c111_info
);
816 /* Legacy helper function. Should go away when machine config files are
818 void smc91c111_init(NICInfo
*nd
, uint32_t base
, qemu_irq irq
)
823 qemu_check_nic_model(nd
, "smc91c111");
824 dev
= qdev_create(NULL
, TYPE_SMC91C111
);
825 qdev_set_nic_properties(dev
, nd
);
826 qdev_init_nofail(dev
);
827 s
= SYS_BUS_DEVICE(dev
);
828 sysbus_mmio_map(s
, 0, base
);
829 sysbus_connect_irq(s
, 0, irq
);
832 type_init(smc91c111_register_types
)