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