Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 8 May 2016 20:29:21 GMT
From:      iateaca@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r302391 - soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve
Message-ID:  <201605082029.u48KTL1d097623@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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;
 }
 
 



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201605082029.u48KTL1d097623>