xref: /openbmc/qemu/hw/net/smc91c111.c (revision 500eb6db)
1 /*
2  * SMSC 91C111 Ethernet interface emulation
3  *
4  * Copyright (c) 2005 CodeSourcery, LLC.
5  * Written by Paul Brook
6  *
7  * This code is licensed under the GPL
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 /* For crc32 */
17 #include <zlib.h>
18 
19 /* Number of 2k memory pages available.  */
20 #define NUM_PACKETS 4
21 
22 #define TYPE_SMC91C111 "smc91c111"
23 #define SMC91C111(obj) OBJECT_CHECK(smc91c111_state, (obj), TYPE_SMC91C111)
24 
25 typedef 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     /* Bitmask of allocated packets.  */
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     /* Packet buffer memory.  */
50     uint8_t data[NUM_PACKETS][2048];
51     uint8_t int_level;
52     uint8_t int_mask;
53     MemoryRegion mmio;
54 } smc91c111_state;
55 
56 static 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 /* Update interrupt status.  */
118 static 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 
130 static 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 
142 static 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 /* Try to allocate a packet.  Returns 0x80 on failure.  */
150 static 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 /* Process a pending TX allocate.  */
167 static 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 /* Remove and item from the RX FIFO.  */
177 static 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 /* Remove an item from the TX completion FIFO.  */
194 static 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 /* Release the memory allocated to a packet.  */
206 static 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 /* Flush the TX FIFO.  */
215 static 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         /* Set status word.  */
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         /* ??? This overwrites the data following the buffer.
240            Don't know what real hardware does.  */
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             /* The card is supposed to append the CRC to the frame.
250                However none of the other network traffic has the CRC
251                appended.  Suspect this is low level ethernet detail we
252                don't need to worry about.  */
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             /* Race?  */
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 /* Add a packet to the TX FIFO.  */
275 static 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 
283 static 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 
308 static 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: /* TCR */
324             SET_LOW(tcr, value);
325             return;
326         case 1:
327             SET_HIGH(tcr, value);
328             return;
329         case 4: /* RCR */
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: /* RPCR */
340             /* Ignored */
341             return;
342         case 12: case 13: /* Reserved */
343             return;
344         }
345         break;
346 
347     case 1:
348         switch (offset) {
349         case 0: /* CONFIG */
350             SET_LOW(cr, value);
351             return;
352         case 1:
353             SET_HIGH(cr,value);
354             return;
355         case 2: case 3: /* BASE */
356         case 4: case 5: case 6: case 7: case 8: case 9: /* IA */
357             /* Not implemented.  */
358             return;
359         case 10: /* Genral Purpose */
360             SET_LOW(gpr, value);
361             return;
362         case 11:
363             SET_HIGH(gpr, value);
364             return;
365         case 12: /* Control */
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: /* MMU Command */
386             switch (value >> 5) {
387             case 0: /* no-op */
388                 break;
389             case 1: /* Allocate for TX.  */
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: /* Reset MMU.  */
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: /* Remove from RX FIFO.  */
403                 smc91c111_pop_rx_fifo(s);
404                 break;
405             case 4: /* Remove from RX FIFO and release.  */
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: /* Release.  */
412                 smc91c111_release_packet(s, s->packet_num);
413                 break;
414             case 6: /* Add to TX FIFO.  */
415                 smc91c111_queue_tx(s, s->packet_num);
416                 break;
417             case 7: /* Reset TX FIFO.  */
418                 s->tx_fifo_len = 0;
419                 s->tx_fifo_done_len = 0;
420                 break;
421             }
422             return;
423         case 1:
424             /* Ignore.  */
425             return;
426         case 2: /* Packet Number Register */
427             s->packet_num = value;
428             return;
429         case 3: case 4: case 5:
430             /* Should be readonly, but linux writes to them anyway. Ignore.  */
431             return;
432         case 6: /* Pointer */
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: /* Data */
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: /* Interrupt ACK.  */
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: /* Interrupt mask.  */
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             /* Multicast table.  */
473             /* Not implemented.  */
474             return;
475         case 8: case 9: /* Management Interface.  */
476             /* Not implemented.  */
477             return;
478         case 12: /* Early receive.  */
479             s->ercv = value & 0x1f;
480             return;
481         case 13:
482             /* Ignore.  */
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 
492 static 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: /* TCR */
506             return s->tcr & 0xff;
507         case 1:
508             return s->tcr >> 8;
509         case 2: /* EPH Status */
510             return 0;
511         case 3:
512             return 0x40;
513         case 4: /* RCR */
514             return s->rcr & 0xff;
515         case 5:
516             return s->rcr >> 8;
517         case 6: /* Counter */
518         case 7:
519             /* Not implemented.  */
520             return 0;
521         case 8: /* Memory size.  */
522             return NUM_PACKETS;
523         case 9: /* Free memory available.  */
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: /* RPCR */
535             /* Not implemented.  */
536             return 0;
537         case 12: case 13: /* Reserved */
538             return 0;
539         }
540         break;
541 
542     case 1:
543         switch (offset) {
544         case 0: /* CONFIG */
545             return s->cr & 0xff;
546         case 1:
547             return s->cr >> 8;
548         case 2: case 3: /* BASE */
549             /* Not implemented.  */
550             return 0;
551         case 4: case 5: case 6: case 7: case 8: case 9: /* IA */
552             return s->conf.macaddr.a[offset - 4];
553         case 10: /* General Purpose */
554             return s->gpr & 0xff;
555         case 11:
556             return s->gpr >> 8;
557         case 12: /* Control */
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: /* MMUCR Busy bit.  */
567             return 0;
568         case 2: /* Packet Number.  */
569             return s->packet_num;
570         case 3: /* Allocation Result.  */
571             return s->tx_alloc;
572         case 4: /* TX FIFO */
573             if (s->tx_fifo_done_len == 0)
574                 return 0x80;
575             else
576                 return s->tx_fifo_done[0];
577         case 5: /* RX FIFO */
578             if (s->rx_fifo_len == 0)
579                 return 0x80;
580             else
581                 return s->rx_fifo[0];
582         case 6: /* Pointer */
583             return s->ptr & 0xff;
584         case 7:
585             return (s->ptr >> 8) & 0xf7;
586         case 8: case 9: case 10: case 11: /* Data */
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: /* Interrupt status.  */
604             return s->int_level;
605         case 13: /* Interrupt mask.  */
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             /* Multicast table.  */
614             /* Not implemented.  */
615             return 0;
616         case 8: /* Management Interface.  */
617             /* Not implemented.  */
618             return 0x30;
619         case 9:
620             return 0x33;
621         case 10: /* Revision.  */
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 
638 static 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 
649 static void smc91c111_writefn(void *opaque, hwaddr addr,
650                                uint64_t value, unsigned size)
651 {
652     int i = 0;
653 
654     /* 32-bit writes to offset 0xc only actually write to the bank select
655      * register (offset 0xe), so skip the first two bytes we would write.
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 
667 static 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 
674 static 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     /* Short packets are padded with zeros.  Receiving a packet
686        < 64 bytes long is considered an error condition.  */
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     /* TODO: Flag overrun and receive errors.  */
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     /* ??? Multicast packets?  */
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     /* Pad short packets.  */
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     /* It's not clear if the CRC should go before or after the last byte in
728        odd sized packets.  Linux disables the CRC, so that's no help.
729        The pictures in the documentation show the CRC aligned on a 16-bit
730        boundary before the last odd byte, so that's what we do.  */
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     /* TODO: Raise early RX interrupt?  */
746     s->int_level |= INT_RCV;
747     smc91c111_update(s);
748 
749     return size;
750 }
751 
752 static const MemoryRegionOps smc91c111_mem_ops = {
753     /* The special case for 32 bit writes to 0xc means we can't just
754      * set .impl.min/max_access_size to 1, unfortunately
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 
763 static 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 
770 static 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     /* ??? Save/restore.  */
784 }
785 
786 static Property smc91c111_properties[] = {
787     DEFINE_NIC_PROPERTIES(smc91c111_state, conf),
788     DEFINE_PROP_END_OF_LIST(),
789 };
790 
791 static 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 
801 static 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 
808 static void smc91c111_register_types(void)
809 {
810     type_register_static(&smc91c111_info);
811 }
812 
813 /* Legacy helper function.  Should go away when machine config files are
814    implemented.  */
815 void 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 
829 type_init(smc91c111_register_types)
830