socsvn commit: r302391 - soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve
iateaca at FreeBSD.org
iateaca at FreeBSD.org
Sun May 8 20:29:21 UTC 2016
Author: iateaca
Date: Sun May 8 20:29:20 2016
New Revision: 302391
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=302391
Log:
design the layout of registers, implement the read and write access to the registers
Modified:
soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_hda.c
Modified: soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_hda.c
==============================================================================
--- soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_hda.c Sun May 8 19:14:05 2016 (r302390)
+++ soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve/pci_hda.c Sun May 8 20:29:20 2016 (r302391)
@@ -1,6 +1,7 @@
#include <stdio.h>
#include <stdlib.h>
+#include <string.h>
#include "pci_emul.h"
@@ -23,6 +24,10 @@
#define INTEL_VENDORID 0x8086
#define HDA_INTEL_82801G 0x27d8
+#define HDA_OSS_NO 0x04
+#define HDA_ISS_NO 0x04
+#define HDA_LAST_OFFSET (0x80 + ((HDA_ISS_NO) * 0x20) + ((HDA_OSS_NO) * 0x20))
+
/*
* HDA Controller Register Offsets
*/
@@ -94,14 +99,34 @@
#define _HDAC_OSDBDPL(n, iss, oss) (0x18 + _HDAC_OSDOFFSET(n, iss, oss))
#define _HDAC_OSDBDPU(n, iss, oss) (0x1c + _HDAC_OSDOFFSET(n, iss, oss))
-
/*
* HDA data structures
*/
+struct hda_softc;
+
+typedef void (*hda_set_reg_handler)(struct hda_softc *sc, uint32_t old);
+
+struct hda_softc {
+ uint32_t regs[HDA_LAST_OFFSET];
+};
+
/*
* HDA module function declarations
*/
+static void
+hda_set_reg_by_offset(struct hda_softc *sc, uint32_t offset, uint32_t value);
+static uint32_t
+hda_get_reg_by_offset(struct hda_softc *sc, uint32_t offset);
+static void
+hda_set_field_by_offset(struct hda_softc *sc, uint32_t offset, uint32_t mask, uint32_t value);
+
+static struct hda_softc *hda_init(const char *opts);
+static void hda_reset_regs(struct hda_softc *sc);
+static uint32_t
+hda_read(struct hda_softc *sc, uint32_t offset);
+static int
+hda_write(struct hda_softc *sc, uint32_t offset, uint32_t value);
/*
* PCI HDA function declarations
@@ -118,6 +143,10 @@
* HDA global data
*/
+static const hda_set_reg_handler hda_set_reg_table[] = {
+ [HDA_LAST_OFFSET] = NULL,
+};
+
struct pci_devemu pci_de_hda = {
.pe_emu = "hda",
.pe_init = pci_hda_init,
@@ -131,21 +160,98 @@
* HDA module function definitions
*/
+static void
+hda_set_reg_by_offset(struct hda_softc *sc, uint32_t offset, uint32_t value)
+{
+ assert(offset < HDA_LAST_OFFSET);
+ sc->regs[offset] = value;
+
+ return;
+}
+
+static uint32_t
+hda_get_reg_by_offset(struct hda_softc *sc, uint32_t offset)
+{
+ assert(offset < HDA_LAST_OFFSET);
+ return sc->regs[offset];
+}
+
+static void
+hda_set_field_by_offset(struct hda_softc *sc, uint32_t offset, uint32_t mask, uint32_t value)
+{
+ uint32_t reg_value = 0;
+
+ reg_value = hda_get_reg_by_offset(sc, offset);
+
+ reg_value &= ~mask;
+ reg_value |= value;
+
+ hda_set_reg_by_offset(sc, offset, reg_value);
+
+ return;
+}
+
+static struct hda_softc *hda_init(const char *opts)
+{
+ struct hda_softc *sc = NULL;
+
+#if DEBUG_HDA == 1
+ dbg = fopen("/tmp/bhyve_hda.log", "w+");
+#endif
+
+ DPRINTF("opts: %s\n", opts);
+
+ sc = calloc(1, sizeof(*sc));
+ if (!sc)
+ return NULL;
+
+ hda_reset_regs(sc);
+
+ return sc;
+}
+
+static void hda_reset_regs(struct hda_softc *sc)
+{
+ memset(sc->regs, 0, sizeof(sc->regs));
+
+ hda_set_reg_by_offset(sc, HDAC_GCAP, 0x4401);
+ hda_set_reg_by_offset(sc, HDAC_CORBSIZE, 0x42);
+ hda_set_reg_by_offset(sc, HDAC_RIRBSIZE, 0x42);
+
+ return;
+}
+
+static uint32_t
+hda_read(struct hda_softc *sc, uint32_t offset)
+{
+ return hda_get_reg_by_offset(sc, offset);
+}
+
+static int
+hda_write(struct hda_softc *sc, uint32_t offset, uint32_t value)
+{
+ uint32_t old = hda_get_reg_by_offset(sc, offset);
+ hda_set_reg_handler set_reg_handler = hda_set_reg_table[offset];
+
+ hda_set_reg_by_offset(sc, offset, value);
+
+ if (set_reg_handler)
+ set_reg_handler(sc, old);
+
+ return 0;
+}
+
/*
* PCI HDA function definitions
*/
static int
pci_hda_init(struct vmctx *ctx, struct pci_devinst *pi, char *opts)
{
+ struct hda_softc *sc = NULL;
+
assert(ctx != NULL);
assert(pi != NULL);
-#if DEBUG_HDA == 1
- dbg = fopen("/tmp/bhyve_hda.log", "w+");
-#endif
-
- DPRINTF("PCI HDA\n");
-
pci_set_cfgdata16(pi, PCIR_VENDOR, INTEL_VENDORID);
pci_set_cfgdata16(pi, PCIR_DEVICE, HDA_INTEL_82801G);
@@ -154,11 +260,17 @@
/* TODO check the right size */
/* allocate one BAR register for the Memory address offsets */
- pci_emul_alloc_bar(pi, 0, PCIBAR_MEM32, 0x0fff);
+ pci_emul_alloc_bar(pi, 0, PCIBAR_MEM32, 0x1000);
/* allocate an IRQ pin for our slot */
pci_lintr_request(pi);
+ sc = hda_init(opts);
+ if (!sc)
+ return -1;
+
+ pi->pi_arg = sc;
+
return 0;
}
@@ -166,9 +278,17 @@
pci_hda_write(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
int baridx, uint64_t offset, int size, uint64_t value)
{
+ struct hda_softc *sc = pi->pi_arg;
+ int err;
+
+ assert(sc);
assert(baridx == 0);
+ assert(size <= 4);
- DPRINTF("offset: 0x%lx size: %d\n", offset, size);
+ DPRINTF("offset: 0x%lx value: 0x%lx\n", offset, value);
+
+ err = hda_write(sc, offset, value);
+ assert(!err);
return;
}
@@ -177,11 +297,18 @@
pci_hda_read(struct vmctx *ctx, int vcpu, struct pci_devinst *pi,
int baridx, uint64_t offset, int size)
{
+ struct hda_softc *sc = pi->pi_arg;
+ uint64_t value = 0;
+
+ assert(sc);
assert(baridx == 0);
+ assert(size <= 4);
- DPRINTF("offset: 0x%lx size: %d\n", offset, size);
+ value = hda_read(sc, offset);
- return 0;
+ DPRINTF("offset: 0x%lx value: 0x%lx\n", offset, value);
+
+ return value;
}
More information about the svn-soc-all
mailing list