--- qemu/hw/intel-hda.c 2018/04/24 18:37:52 1.1.1.1 +++ qemu/hw/intel-hda.c 2018/04/24 19:47:16 1.1.1.4 @@ -24,6 +24,7 @@ #include "audiodev.h" #include "intel-hda.h" #include "intel-hda-defs.h" +#include "dma.h" /* --------------------------------------------------------------------- */ /* hda bus */ @@ -46,13 +47,12 @@ void hda_codec_bus_init(DeviceState *dev bus->xfer = xfer; } -static int hda_codec_dev_init(DeviceState *qdev, DeviceInfo *base) +static int hda_codec_dev_init(DeviceState *qdev) { HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, qdev->parent_bus); HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev); - HDACodecDeviceInfo *info = DO_UPCAST(HDACodecDeviceInfo, qdev, base); + HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev); - dev->info = info; if (dev->cad == -1) { dev->cad = bus->next_cad; } @@ -60,33 +60,26 @@ static int hda_codec_dev_init(DeviceStat return -1; } bus->next_cad = dev->cad + 1; - return info->init(dev); + return cdc->init(dev); } static int hda_codec_dev_exit(DeviceState *qdev) { HDACodecDevice *dev = DO_UPCAST(HDACodecDevice, qdev, qdev); + HDACodecDeviceClass *cdc = HDA_CODEC_DEVICE_GET_CLASS(dev); - if (dev->info->exit) { - dev->info->exit(dev); + if (cdc->exit) { + cdc->exit(dev); } return 0; } -void hda_codec_register(HDACodecDeviceInfo *info) -{ - info->qdev.init = hda_codec_dev_init; - info->qdev.exit = hda_codec_dev_exit; - info->qdev.bus_info = &hda_codec_bus_info; - qdev_register(&info->qdev); -} - HDACodecDevice *hda_codec_find(HDACodecBus *bus, uint32_t cad) { DeviceState *qdev; HDACodecDevice *cdev; - QLIST_FOREACH(qdev, &bus->qbus.children, sibling) { + QTAILQ_FOREACH(qdev, &bus->qbus.children, sibling) { cdev = DO_UPCAST(HDACodecDevice, qdev, qdev); if (cdev->cad == cad) { return cdev; @@ -177,7 +170,7 @@ struct IntelHDAState { IntelHDAStream st[8]; /* state */ - int mmio_addr; + MemoryRegion mmio; uint32_t rirb_count; int64_t wall_base_ns; @@ -224,19 +217,6 @@ static target_phys_addr_t intel_hda_addr return addr; } -static void stl_phys_le(target_phys_addr_t addr, uint32_t value) -{ - uint32_t value_le = cpu_to_le32(value); - cpu_physical_memory_write(addr, (uint8_t*)(&value_le), sizeof(value_le)); -} - -static uint32_t ldl_phys_le(target_phys_addr_t addr) -{ - uint32_t value_le; - cpu_physical_memory_read(addr, (uint8_t*)(&value_le), sizeof(value_le)); - return le32_to_cpu(value_le); -} - static void intel_hda_update_int_sts(IntelHDAState *d) { uint32_t sts = 0; @@ -295,6 +275,7 @@ static int intel_hda_send_command(IntelH { uint32_t cad, nid, data; HDACodecDevice *codec; + HDACodecDeviceClass *cdc; cad = (verb >> 28) & 0x0f; if (verb & (1 << 27)) { @@ -310,7 +291,8 @@ static int intel_hda_send_command(IntelH dprint(d, 1, "%s: addressed non-existing codec\n", __FUNCTION__); return -1; } - codec->info->command(codec, nid, data); + cdc = HDA_CODEC_DEVICE_GET_CLASS(codec); + cdc->command(codec, nid, data); return 0; } @@ -341,7 +323,7 @@ static void intel_hda_corb_run(IntelHDAS rp = (d->corb_rp + 1) & 0xff; addr = intel_hda_addr(d->corb_lbase, d->corb_ubase); - verb = ldl_phys_le(addr + 4*rp); + verb = ldl_le_pci_dma(&d->pci, addr + 4*rp); d->corb_rp = rp; dprint(d, 2, "%s: [rp 0x%x] verb 0x%08x\n", __FUNCTION__, rp, verb); @@ -373,8 +355,8 @@ static void intel_hda_response(HDACodecD ex = (solicited ? 0 : (1 << 4)) | dev->cad; wp = (d->rirb_wp + 1) & 0xff; addr = intel_hda_addr(d->rirb_lbase, d->rirb_ubase); - stl_phys_le(addr + 8*wp, response); - stl_phys_le(addr + 8*wp + 4, ex); + stl_le_pci_dma(&d->pci, addr + 8*wp, response); + stl_le_pci_dma(&d->pci, addr + 8*wp + 4, ex); d->rirb_wp = wp; dprint(d, 2, "%s: [wp 0x%x] response 0x%x, extra 0x%x\n", @@ -402,18 +384,19 @@ static bool intel_hda_xfer(HDACodecDevic { HDACodecBus *bus = DO_UPCAST(HDACodecBus, qbus, dev->qdev.parent_bus); IntelHDAState *d = container_of(bus, IntelHDAState, codecs); - IntelHDAStream *st = NULL; target_phys_addr_t addr; uint32_t s, copy, left; + IntelHDAStream *st; bool irq = false; - for (s = 0; s < ARRAY_SIZE(d->st); s++) { - if (stnr == ((d->st[s].ctl >> 20) & 0x0f)) { - st = d->st + s; + st = output ? d->st + 4 : d->st; + for (s = 0; s < 4; s++) { + if (stnr == ((st[s].ctl >> 20) & 0x0f)) { + st = st + s; break; } } - if (st == NULL) { + if (s == 4) { return false; } if (st->bpl == NULL) { @@ -438,8 +421,7 @@ static bool intel_hda_xfer(HDACodecDevic dprint(d, 3, "dma: entry %d, pos %d/%d, copy %d\n", st->be, st->bp, st->bpl[st->be].len, copy); - cpu_physical_memory_rw(st->bpl[st->be].addr + st->bp, - buf, copy, !output); + pci_dma_rw(&d->pci, st->bpl[st->be].addr + st->bp, buf, copy, !output); st->lpib += copy; st->bp += copy; buf += copy; @@ -461,7 +443,7 @@ static bool intel_hda_xfer(HDACodecDevic } if (d->dp_lbase & 0x01) { addr = intel_hda_addr(d->dp_lbase & ~0x01, d->dp_ubase); - stl_phys_le(addr + 8*s, st->lpib); + stl_le_pci_dma(&d->pci, addr + 8*s, st->lpib); } dprint(d, 3, "dma: --\n"); @@ -480,10 +462,10 @@ static void intel_hda_parse_bdl(IntelHDA addr = intel_hda_addr(st->bdlp_lbase, st->bdlp_ubase); st->bentries = st->lvi +1; - qemu_free(st->bpl); - st->bpl = qemu_malloc(sizeof(bpl) * st->bentries); + g_free(st->bpl); + st->bpl = g_malloc(sizeof(bpl) * st->bentries); for (i = 0; i < st->bentries; i++, addr += 16) { - cpu_physical_memory_read(addr, buf, 16); + pci_dma_read(&d->pci, addr, buf, 16); st->bpl[i].addr = le64_to_cpu(*(uint64_t *)buf); st->bpl[i].len = le32_to_cpu(*(uint32_t *)(buf + 8)); st->bpl[i].flags = le32_to_cpu(*(uint32_t *)(buf + 12)); @@ -497,15 +479,18 @@ static void intel_hda_parse_bdl(IntelHDA st->bp = 0; } -static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool running) +static void intel_hda_notify_codecs(IntelHDAState *d, uint32_t stream, bool running, bool output) { DeviceState *qdev; HDACodecDevice *cdev; - QLIST_FOREACH(qdev, &d->codecs.qbus.children, sibling) { + QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) { + HDACodecDeviceClass *cdc; + cdev = DO_UPCAST(HDACodecDevice, qdev, qdev); - if (cdev->info->stream) { - cdev->info->stream(cdev, stream, running); + cdc = HDA_CODEC_DEVICE_GET_CLASS(cdev); + if (cdc->stream) { + cdc->stream(cdev, stream, running, output); } } } @@ -579,6 +564,7 @@ static void intel_hda_set_ics(IntelHDASt static void intel_hda_set_st_ctl(IntelHDAState *d, const IntelHDAReg *reg, uint32_t old) { + bool output = reg->stream >= 4; IntelHDAStream *st = d->st + reg->stream; if (st->ctl & 0x01) { @@ -594,11 +580,11 @@ static void intel_hda_set_st_ctl(IntelHD dprint(d, 1, "st #%d: start %d (ring buf %d bytes)\n", reg->stream, stnr, st->cbl); intel_hda_parse_bdl(d, st); - intel_hda_notify_codecs(d, stnr, true); + intel_hda_notify_codecs(d, stnr, true, output); } else { /* stop */ dprint(d, 1, "st #%d: stop %d\n", reg->stream, stnr); - intel_hda_notify_codecs(d, stnr, false); + intel_hda_notify_codecs(d, stnr, false, output); } } intel_hda_update_irq(d); @@ -1097,26 +1083,22 @@ static uint32_t intel_hda_mmio_readl(voi return intel_hda_reg_read(d, reg, 0xffffffff); } -static CPUReadMemoryFunc * const intel_hda_mmio_read[3] = { - intel_hda_mmio_readb, - intel_hda_mmio_readw, - intel_hda_mmio_readl, -}; - -static CPUWriteMemoryFunc * const intel_hda_mmio_write[3] = { - intel_hda_mmio_writeb, - intel_hda_mmio_writew, - intel_hda_mmio_writel, +static const MemoryRegionOps intel_hda_mmio_ops = { + .old_mmio = { + .read = { + intel_hda_mmio_readb, + intel_hda_mmio_readw, + intel_hda_mmio_readl, + }, + .write = { + intel_hda_mmio_writeb, + intel_hda_mmio_writew, + intel_hda_mmio_writel, + }, + }, + .endianness = DEVICE_NATIVE_ENDIAN, }; -static void intel_hda_map(PCIDevice *pci, int region_num, - pcibus_t addr, pcibus_t size, int type) -{ - IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci); - - cpu_register_physical_memory(addr, 0x4000, d->mmio_addr); -} - /* --------------------------------------------------------------------- */ static void intel_hda_reset(DeviceState *dev) @@ -1125,15 +1107,16 @@ static void intel_hda_reset(DeviceState DeviceState *qdev; HDACodecDevice *cdev; + if (d->msi) { + msi_reset(&d->pci); + } intel_hda_regs_reset(d); - d->wall_base_ns = qemu_get_clock(vm_clock); + d->wall_base_ns = qemu_get_clock_ns(vm_clock); /* reset codecs */ - QLIST_FOREACH(qdev, &d->codecs.qbus.children, sibling) { + QTAILQ_FOREACH(qdev, &d->codecs.qbus.children, sibling) { cdev = DO_UPCAST(HDACodecDevice, qdev, qdev); - if (qdev->info->reset) { - qdev->info->reset(qdev); - } + device_reset(DEVICE(cdev)); d->state_sts |= (1 << cdev->cad); } intel_hda_update_irq(d); @@ -1144,22 +1127,16 @@ static int intel_hda_init(PCIDevice *pci IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci); uint8_t *conf = d->pci.config; - d->name = d->pci.qdev.info->name; + d->name = object_get_typename(OBJECT(d)); - pci_config_set_vendor_id(conf, PCI_VENDOR_ID_INTEL); - pci_config_set_device_id(conf, 0x2668); - pci_config_set_revision(conf, 1); - pci_config_set_class(conf, PCI_CLASS_MULTIMEDIA_HD_AUDIO); pci_config_set_interrupt_pin(conf, 1); /* HDCTL off 0x40 bit 0 selects signaling mode (1-HDA, 0 - Ac97) 18.1.19 */ conf[0x40] = 0x01; - d->mmio_addr = cpu_register_io_memory(intel_hda_mmio_read, - intel_hda_mmio_write, d, - DEVICE_NATIVE_ENDIAN); - pci_register_bar(&d->pci, 0, 0x4000, PCI_BASE_ADDRESS_SPACE_MEMORY, - intel_hda_map); + memory_region_init_io(&d->mmio, &intel_hda_mmio_ops, d, + "intel-hda", 0x4000); + pci_register_bar(&d->pci, 0, 0, &d->mmio); if (d->msi) { msi_init(&d->pci, 0x50, 1, true, false); } @@ -1174,10 +1151,8 @@ static int intel_hda_exit(PCIDevice *pci { IntelHDAState *d = DO_UPCAST(IntelHDAState, pci, pci); - if (d->msi) { - msi_uninit(&d->pci); - } - cpu_unregister_io_memory(d->mmio_addr); + msi_uninit(&d->pci); + memory_region_destroy(&d->mmio); return 0; } @@ -1267,27 +1242,61 @@ static const VMStateDescription vmstate_ } }; -static PCIDeviceInfo intel_hda_info = { - .qdev.name = "intel-hda", - .qdev.desc = "Intel HD Audio Controller", - .qdev.size = sizeof(IntelHDAState), - .qdev.vmsd = &vmstate_intel_hda, - .qdev.reset = intel_hda_reset, - .init = intel_hda_init, - .exit = intel_hda_exit, - .config_write = intel_hda_write_config, - .qdev.props = (Property[]) { - DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0), - DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1), - DEFINE_PROP_END_OF_LIST(), - } +static Property intel_hda_properties[] = { + DEFINE_PROP_UINT32("debug", IntelHDAState, debug, 0), + DEFINE_PROP_UINT32("msi", IntelHDAState, msi, 1), + DEFINE_PROP_END_OF_LIST(), }; -static void intel_hda_register(void) +static void intel_hda_class_init(ObjectClass *klass, void *data) { - pci_qdev_register(&intel_hda_info); + DeviceClass *dc = DEVICE_CLASS(klass); + PCIDeviceClass *k = PCI_DEVICE_CLASS(klass); + + k->init = intel_hda_init; + k->exit = intel_hda_exit; + k->config_write = intel_hda_write_config; + k->vendor_id = PCI_VENDOR_ID_INTEL; + k->device_id = 0x2668; + k->revision = 1; + k->class_id = PCI_CLASS_MULTIMEDIA_HD_AUDIO; + dc->desc = "Intel HD Audio Controller"; + dc->reset = intel_hda_reset; + dc->vmsd = &vmstate_intel_hda; + dc->props = intel_hda_properties; +} + +static TypeInfo intel_hda_info = { + .name = "intel-hda", + .parent = TYPE_PCI_DEVICE, + .instance_size = sizeof(IntelHDAState), + .class_init = intel_hda_class_init, +}; + +static void hda_codec_device_class_init(ObjectClass *klass, void *data) +{ + DeviceClass *k = DEVICE_CLASS(klass); + k->init = hda_codec_dev_init; + k->exit = hda_codec_dev_exit; + k->bus_info = &hda_codec_bus_info; +} + +static TypeInfo hda_codec_device_type_info = { + .name = TYPE_HDA_CODEC_DEVICE, + .parent = TYPE_DEVICE, + .instance_size = sizeof(HDACodecDevice), + .abstract = true, + .class_size = sizeof(HDACodecDeviceClass), + .class_init = hda_codec_device_class_init, +}; + +static void intel_hda_register_types(void) +{ + type_register_static(&intel_hda_info); + type_register_static(&hda_codec_device_type_info); } -device_init(intel_hda_register); + +type_init(intel_hda_register_types) /* * create intel hda controller with codec attached to it,