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