From owner-svn-soc-all@freebsd.org Sun May 8 20:29:21 2016 Return-Path: Delivered-To: svn-soc-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id CB5F3B33342 for ; Sun, 8 May 2016 20:29:21 +0000 (UTC) (envelope-from iateaca@FreeBSD.org) Received: from socsvn.freebsd.org (socsvn.freebsd.org [IPv6:2001:1900:2254:206a::50:2]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id B01C2131F for ; Sun, 8 May 2016 20:29:21 +0000 (UTC) (envelope-from iateaca@FreeBSD.org) Received: from socsvn.freebsd.org ([127.0.1.124]) by socsvn.freebsd.org (8.15.2/8.15.2) with ESMTP id u48KTLac097647 for ; Sun, 8 May 2016 20:29:21 GMT (envelope-from iateaca@FreeBSD.org) Received: (from www@localhost) by socsvn.freebsd.org (8.15.2/8.15.2/Submit) id u48KTL1d097623 for svn-soc-all@FreeBSD.org; Sun, 8 May 2016 20:29:21 GMT (envelope-from iateaca@FreeBSD.org) Date: Sun, 8 May 2016 20:29:21 GMT Message-Id: <201605082029.u48KTL1d097623@socsvn.freebsd.org> X-Authentication-Warning: socsvn.freebsd.org: www set sender to iateaca@FreeBSD.org using -f From: iateaca@FreeBSD.org To: svn-soc-all@FreeBSD.org Subject: socsvn commit: r302391 - soc2015/iateaca/bhyve-ne2000-head/usr.sbin/bhyve MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-soc-all@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: SVN commit messages for the entire Summer of Code repository List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 08 May 2016 20:29:21 -0000 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 #include +#include #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; }