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