Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 3 Jul 2016 19:00:26 GMT
From:      iateaca@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r305701 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
Message-ID:  <201607031900.u63J0Qdl089099@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: iateaca
Date: Sun Jul  3 19:00:26 2016
New Revision: 305701
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=305701

Log:
  
  implement the hda_set_rirbsts function in order to clear the corresponding bits written by the software
  implement the hda_get_clock_ns function in order to get the time in ns using the clock_gettime(CLOCK_MONOTONIC)
  update the WALL CLOCK register on read using the hda_get_clock_ns function
  set the HDAC_SDSTS_FIFORDY bit in the SDSTS register on stream reset
  
  M    bhyve/pci_hda.c

Modified:
  soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c

Modified: soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c
==============================================================================
--- soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c	Sun Jul  3 18:27:00 2016	(r305700)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c	Sun Jul  3 19:00:26 2016	(r305701)
@@ -1,4 +1,6 @@
 
+#include <time.h>
+
 #include "pci_hda.h"
 #include "bhyverun.h"
 #include "pci_emul.h"
@@ -25,6 +27,11 @@
 #define HDA_DMA_ACCESS_LEN	(sizeof(uint32_t))
 #define HDA_BDL_MAX_LEN		0x0100
 
+#define HDAC_SDSTS_FIFORDY	(1 << 5)
+
+#define HDA_RIRBSTS_IRQ_MASK	(HDAC_RIRBSTS_RINTFL | HDAC_RIRBSTS_RIRBOIS)
+#define HDA_SDSTS_IRQ_MASK	(HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS)
+
 /*
  * HDA data structures
  */
@@ -74,6 +81,7 @@
 	uint32_t regs[HDA_LAST_OFFSET];
 
 	uint8_t lintr;
+	uint64_t wall_clock_start;
 
 	struct hda_codec_cmd_ctl corb;
 	struct hda_codec_cmd_ctl rirb;
@@ -152,6 +160,8 @@
 static void
 hda_set_rirbctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
 static void
+hda_set_rirbsts(struct hda_softc *sc, uint32_t offset, uint32_t old);
+static void
 hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
 static void
 hda_set_sdctl2(struct hda_softc *sc, uint32_t offset, uint32_t old);
@@ -165,6 +175,7 @@
 static int
 hda_transfer(struct hda_codec_inst *hci, uint8_t stream, uint8_t dir, void *buf, size_t count);
 
+static uint64_t hda_get_clock_ns(void);
 
 /*
  * PCI HDA function declarations
@@ -186,6 +197,7 @@
 	[HDAC_CORBWP] = hda_set_corbwp,
 	[HDAC_CORBCTL] = hda_set_corbctl,
 	[HDAC_RIRBCTL] = hda_set_rirbctl,
+	[HDAC_RIRBSTS] = hda_set_rirbsts,
 
 #define HDAC_ISTREAM(n, iss, oss)				\
 	[_HDAC_ISDCTL(n, iss, oss)] = hda_set_sdctl,		\
@@ -465,6 +477,8 @@
 			codec->reset(hci);
 	}
 
+	sc->wall_clock_start = hda_get_clock_ns();
+
 	return;
 }
 
@@ -500,6 +514,7 @@
 	/* Reset the Stream Descriptor */
 	memset(st, 0, sizeof(*st));
 
+	hda_set_field_by_offset(sc, off + HDAC_SDSTS, HDAC_SDSTS_FIFORDY, HDAC_SDSTS_FIFORDY);
 	hda_set_field_by_offset(sc, off + HDAC_SDCTL0, HDAC_SDCTL_SRST, HDAC_SDCTL_SRST);
 
 	return;
@@ -568,6 +583,8 @@
 		bdle_desc->addr = bdle_vaddr;
 		bdle_desc->len = bdle_sz;
 		bdle_desc->ioc = bdle->ioc;
+
+		DPRINTF("bdle: 0x%x bdle_sz: 0x%x\n", i, bdle_sz);
 	}
 
 	sdctl = hda_get_reg_by_offset(sc, off + HDAC_SDCTL0);
@@ -612,6 +629,9 @@
 static uint32_t
 hda_read(struct hda_softc *sc, uint32_t offset)
 {
+	if (offset == HDAC_WALCLK)
+		return (24 * (hda_get_clock_ns() - sc->wall_clock_start) / 1000);
+
 	return hda_get_reg_by_offset(sc, offset);
 }
 
@@ -846,6 +866,21 @@
 }
 
 static void
+hda_set_rirbsts(struct hda_softc *sc, uint32_t offset, uint32_t old)
+{
+	uint32_t value = hda_get_reg_by_offset(sc, offset);
+
+	hda_set_reg_by_offset(sc, offset, old);
+
+	/* clear the corresponding bits written by the software (guest) */
+	hda_set_field_by_offset(sc, offset, value & HDA_RIRBSTS_IRQ_MASK, 0);
+
+	hda_update_intr(sc);
+
+	return;
+}
+
+static void
 hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
 {
 	uint8_t stream_ind = hda_get_stream_by_offsets(offset, HDAC_SDCTL0);
@@ -886,8 +921,10 @@
 {
 	uint32_t value = hda_get_reg_by_offset(sc, offset);
 
+	hda_set_reg_by_offset(sc, offset, old);
+
 	/* clear the corresponding bits written by the software (guest) */
-	hda_set_field_by_offset(sc, offset, value, 0);
+	hda_set_field_by_offset(sc, offset, value & HDA_SDSTS_IRQ_MASK, 0);
 
 	hda_update_intr(sc);
 
@@ -966,6 +1003,11 @@
 	assert(stream < HDA_STREAM_TAGS_CNT);
 	stream_ind = sc->stream_map[stream];
 
+	if (!dir)
+		assert(stream_ind < HDA_ISS_NO);
+	else
+		assert(stream_ind >= HDA_ISS_NO && stream_ind < HDA_IOSS_NO);
+
 	st = &sc->streams[stream_ind];
 	if (!st->run) {
 		DPRINTF("Stream 0x%x stopped\n", stream);
@@ -973,7 +1015,6 @@
 	}
 
 	assert(st->stream == stream);
-	assert(st->dir == dir);
 
 	off = hda_get_offset_stream(stream_ind);
 
@@ -1021,6 +1062,17 @@
 	return 0;
 }
 
+static uint64_t hda_get_clock_ns(void)
+{
+	struct timespec ts;
+	int err;
+
+	err = clock_gettime(CLOCK_MONOTONIC, &ts);
+	assert(!err);
+
+	return ts.tv_sec * 1000000000LL + ts.tv_nsec;
+}
+
 /*
  * PCI HDA function definitions
  */



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