17a188f2bSPhilippe Mathieu-Daudé /*
27a188f2bSPhilippe Mathieu-Daudé * QEMU NE2000 emulation (PCI bus)
37a188f2bSPhilippe Mathieu-Daudé *
47a188f2bSPhilippe Mathieu-Daudé * Copyright (c) 2003-2004 Fabrice Bellard
57a188f2bSPhilippe Mathieu-Daudé *
67a188f2bSPhilippe Mathieu-Daudé * Permission is hereby granted, free of charge, to any person obtaining a copy
77a188f2bSPhilippe Mathieu-Daudé * of this software and associated documentation files (the "Software"), to deal
87a188f2bSPhilippe Mathieu-Daudé * in the Software without restriction, including without limitation the rights
97a188f2bSPhilippe Mathieu-Daudé * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
107a188f2bSPhilippe Mathieu-Daudé * copies of the Software, and to permit persons to whom the Software is
117a188f2bSPhilippe Mathieu-Daudé * furnished to do so, subject to the following conditions:
127a188f2bSPhilippe Mathieu-Daudé *
137a188f2bSPhilippe Mathieu-Daudé * The above copyright notice and this permission notice shall be included in
147a188f2bSPhilippe Mathieu-Daudé * all copies or substantial portions of the Software.
157a188f2bSPhilippe Mathieu-Daudé *
167a188f2bSPhilippe Mathieu-Daudé * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
177a188f2bSPhilippe Mathieu-Daudé * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
187a188f2bSPhilippe Mathieu-Daudé * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
197a188f2bSPhilippe Mathieu-Daudé * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
207a188f2bSPhilippe Mathieu-Daudé * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
217a188f2bSPhilippe Mathieu-Daudé * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
227a188f2bSPhilippe Mathieu-Daudé * THE SOFTWARE.
237a188f2bSPhilippe Mathieu-Daudé */
2464552b6bSMarkus Armbruster
257a188f2bSPhilippe Mathieu-Daudé #include "qemu/osdep.h"
2664552b6bSMarkus Armbruster #include "hw/irq.h"
27edf5ca5dSMarkus Armbruster #include "hw/pci/pci_device.h"
28a27bd6c7SMarkus Armbruster #include "hw/qdev-properties.h"
29d6454270SMarkus Armbruster #include "migration/vmstate.h"
307a188f2bSPhilippe Mathieu-Daudé #include "ne2000.h"
317a188f2bSPhilippe Mathieu-Daudé #include "sysemu/sysemu.h"
327a188f2bSPhilippe Mathieu-Daudé
337a188f2bSPhilippe Mathieu-Daudé typedef struct PCINE2000State {
347a188f2bSPhilippe Mathieu-Daudé PCIDevice dev;
357a188f2bSPhilippe Mathieu-Daudé NE2000State ne2000;
367a188f2bSPhilippe Mathieu-Daudé } PCINE2000State;
377a188f2bSPhilippe Mathieu-Daudé
387a188f2bSPhilippe Mathieu-Daudé static const VMStateDescription vmstate_pci_ne2000 = {
397a188f2bSPhilippe Mathieu-Daudé .name = "ne2000",
407a188f2bSPhilippe Mathieu-Daudé .version_id = 3,
417a188f2bSPhilippe Mathieu-Daudé .minimum_version_id = 3,
42*1de81b42SRichard Henderson .fields = (const VMStateField[]) {
437a188f2bSPhilippe Mathieu-Daudé VMSTATE_PCI_DEVICE(dev, PCINE2000State),
447a188f2bSPhilippe Mathieu-Daudé VMSTATE_STRUCT(ne2000, PCINE2000State, 0, vmstate_ne2000, NE2000State),
457a188f2bSPhilippe Mathieu-Daudé VMSTATE_END_OF_LIST()
467a188f2bSPhilippe Mathieu-Daudé }
477a188f2bSPhilippe Mathieu-Daudé };
487a188f2bSPhilippe Mathieu-Daudé
497a188f2bSPhilippe Mathieu-Daudé static NetClientInfo net_ne2000_info = {
507a188f2bSPhilippe Mathieu-Daudé .type = NET_CLIENT_DRIVER_NIC,
517a188f2bSPhilippe Mathieu-Daudé .size = sizeof(NICState),
527a188f2bSPhilippe Mathieu-Daudé .receive = ne2000_receive,
537a188f2bSPhilippe Mathieu-Daudé };
547a188f2bSPhilippe Mathieu-Daudé
pci_ne2000_realize(PCIDevice * pci_dev,Error ** errp)557a188f2bSPhilippe Mathieu-Daudé static void pci_ne2000_realize(PCIDevice *pci_dev, Error **errp)
567a188f2bSPhilippe Mathieu-Daudé {
577a188f2bSPhilippe Mathieu-Daudé PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
587a188f2bSPhilippe Mathieu-Daudé NE2000State *s;
597a188f2bSPhilippe Mathieu-Daudé uint8_t *pci_conf;
607a188f2bSPhilippe Mathieu-Daudé
617a188f2bSPhilippe Mathieu-Daudé pci_conf = d->dev.config;
627a188f2bSPhilippe Mathieu-Daudé pci_conf[PCI_INTERRUPT_PIN] = 1; /* interrupt pin A */
637a188f2bSPhilippe Mathieu-Daudé
647a188f2bSPhilippe Mathieu-Daudé s = &d->ne2000;
657a188f2bSPhilippe Mathieu-Daudé ne2000_setup_io(s, DEVICE(pci_dev), 0x100);
667a188f2bSPhilippe Mathieu-Daudé pci_register_bar(&d->dev, 0, PCI_BASE_ADDRESS_SPACE_IO, &s->io);
677a188f2bSPhilippe Mathieu-Daudé s->irq = pci_allocate_irq(&d->dev);
687a188f2bSPhilippe Mathieu-Daudé
697a188f2bSPhilippe Mathieu-Daudé qemu_macaddr_default_if_unset(&s->c.macaddr);
707a188f2bSPhilippe Mathieu-Daudé ne2000_reset(s);
717a188f2bSPhilippe Mathieu-Daudé
727a188f2bSPhilippe Mathieu-Daudé s->nic = qemu_new_nic(&net_ne2000_info, &s->c,
737a188f2bSPhilippe Mathieu-Daudé object_get_typename(OBJECT(pci_dev)),
747d0fefdfSAkihiko Odaki pci_dev->qdev.id,
757d0fefdfSAkihiko Odaki &pci_dev->qdev.mem_reentrancy_guard, s);
767a188f2bSPhilippe Mathieu-Daudé qemu_format_nic_info_str(qemu_get_queue(s->nic), s->c.macaddr.a);
777a188f2bSPhilippe Mathieu-Daudé }
787a188f2bSPhilippe Mathieu-Daudé
pci_ne2000_exit(PCIDevice * pci_dev)797a188f2bSPhilippe Mathieu-Daudé static void pci_ne2000_exit(PCIDevice *pci_dev)
807a188f2bSPhilippe Mathieu-Daudé {
817a188f2bSPhilippe Mathieu-Daudé PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
827a188f2bSPhilippe Mathieu-Daudé NE2000State *s = &d->ne2000;
837a188f2bSPhilippe Mathieu-Daudé
847a188f2bSPhilippe Mathieu-Daudé qemu_del_nic(s->nic);
857a188f2bSPhilippe Mathieu-Daudé qemu_free_irq(s->irq);
867a188f2bSPhilippe Mathieu-Daudé }
877a188f2bSPhilippe Mathieu-Daudé
ne2000_instance_init(Object * obj)887a188f2bSPhilippe Mathieu-Daudé static void ne2000_instance_init(Object *obj)
897a188f2bSPhilippe Mathieu-Daudé {
907a188f2bSPhilippe Mathieu-Daudé PCIDevice *pci_dev = PCI_DEVICE(obj);
917a188f2bSPhilippe Mathieu-Daudé PCINE2000State *d = DO_UPCAST(PCINE2000State, dev, pci_dev);
927a188f2bSPhilippe Mathieu-Daudé NE2000State *s = &d->ne2000;
937a188f2bSPhilippe Mathieu-Daudé
947a188f2bSPhilippe Mathieu-Daudé device_add_bootindex_property(obj, &s->c.bootindex,
957a188f2bSPhilippe Mathieu-Daudé "bootindex", "/ethernet-phy@0",
9640c2281cSMarkus Armbruster &pci_dev->qdev);
977a188f2bSPhilippe Mathieu-Daudé }
987a188f2bSPhilippe Mathieu-Daudé
997a188f2bSPhilippe Mathieu-Daudé static Property ne2000_properties[] = {
1007a188f2bSPhilippe Mathieu-Daudé DEFINE_NIC_PROPERTIES(PCINE2000State, ne2000.c),
1017a188f2bSPhilippe Mathieu-Daudé DEFINE_PROP_END_OF_LIST(),
1027a188f2bSPhilippe Mathieu-Daudé };
1037a188f2bSPhilippe Mathieu-Daudé
ne2000_class_init(ObjectClass * klass,void * data)1047a188f2bSPhilippe Mathieu-Daudé static void ne2000_class_init(ObjectClass *klass, void *data)
1057a188f2bSPhilippe Mathieu-Daudé {
1067a188f2bSPhilippe Mathieu-Daudé DeviceClass *dc = DEVICE_CLASS(klass);
1077a188f2bSPhilippe Mathieu-Daudé PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
1087a188f2bSPhilippe Mathieu-Daudé
1097a188f2bSPhilippe Mathieu-Daudé k->realize = pci_ne2000_realize;
1107a188f2bSPhilippe Mathieu-Daudé k->exit = pci_ne2000_exit;
1117a188f2bSPhilippe Mathieu-Daudé k->romfile = "efi-ne2k_pci.rom",
1127a188f2bSPhilippe Mathieu-Daudé k->vendor_id = PCI_VENDOR_ID_REALTEK;
1137a188f2bSPhilippe Mathieu-Daudé k->device_id = PCI_DEVICE_ID_REALTEK_8029;
1147a188f2bSPhilippe Mathieu-Daudé k->class_id = PCI_CLASS_NETWORK_ETHERNET;
1157a188f2bSPhilippe Mathieu-Daudé dc->vmsd = &vmstate_pci_ne2000;
1164f67d30bSMarc-André Lureau device_class_set_props(dc, ne2000_properties);
1177a188f2bSPhilippe Mathieu-Daudé set_bit(DEVICE_CATEGORY_NETWORK, dc->categories);
1187a188f2bSPhilippe Mathieu-Daudé }
1197a188f2bSPhilippe Mathieu-Daudé
1207a188f2bSPhilippe Mathieu-Daudé static const TypeInfo ne2000_info = {
1217a188f2bSPhilippe Mathieu-Daudé .name = "ne2k_pci",
1227a188f2bSPhilippe Mathieu-Daudé .parent = TYPE_PCI_DEVICE,
1237a188f2bSPhilippe Mathieu-Daudé .instance_size = sizeof(PCINE2000State),
1247a188f2bSPhilippe Mathieu-Daudé .class_init = ne2000_class_init,
1257a188f2bSPhilippe Mathieu-Daudé .instance_init = ne2000_instance_init,
1267a188f2bSPhilippe Mathieu-Daudé .interfaces = (InterfaceInfo[]) {
1277a188f2bSPhilippe Mathieu-Daudé { INTERFACE_CONVENTIONAL_PCI_DEVICE },
1287a188f2bSPhilippe Mathieu-Daudé { },
1297a188f2bSPhilippe Mathieu-Daudé },
1307a188f2bSPhilippe Mathieu-Daudé };
1317a188f2bSPhilippe Mathieu-Daudé
ne2000_register_types(void)1327a188f2bSPhilippe Mathieu-Daudé static void ne2000_register_types(void)
1337a188f2bSPhilippe Mathieu-Daudé {
1347a188f2bSPhilippe Mathieu-Daudé type_register_static(&ne2000_info);
1357a188f2bSPhilippe Mathieu-Daudé }
1367a188f2bSPhilippe Mathieu-Daudé
1377a188f2bSPhilippe Mathieu-Daudé type_init(ne2000_register_types)
138