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