Skip site navigation (1)Skip section navigation (2)
Date:      Sat, 18 Jun 2016 12:20:06 GMT
From:      iateaca@FreeBSD.org
To:        svn-soc-all@FreeBSD.org
Subject:   socsvn commit: r305326 - soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve
Message-ID:  <201606181220.u5ICK6NV025624@socsvn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: iateaca
Date: Sat Jun 18 12:20:05 2016
New Revision: 305326
URL: http://svnweb.FreeBSD.org/socsvn/?view=rev&rev=305326

Log:
  
  design the hda_bdle_desc, hda_stream_desc data structures
  implement the reset stream procedure
  
  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	Sat Jun 18 09:48:20 2016	(r305325)
+++ soc2016/iateaca/bhyve-hda-head/usr.sbin/bhyve/pci_hda.c	Sat Jun 18 12:20:05 2016	(r305326)
@@ -10,12 +10,18 @@
 #define INTEL_VENDORID		0x8086
 #define HDA_INTEL_82801G	0x27d8
 
+#define HDA_IOSS_NO		0x08
 #define HDA_OSS_NO		0x04
 #define HDA_ISS_NO		0x04
 #define HDA_CODEC_MAX		0x0f
 #define HDA_LAST_OFFSET		(0x80 + ((HDA_ISS_NO) * 0x20) + ((HDA_OSS_NO) * 0x20))
 #define HDA_CORB_ENTRY_LEN	0x04
 #define HDA_RIRB_ENTRY_LEN	0x08
+#define HDA_STREAM_TAGS_CNT	0x10
+#define HDA_STREAM_REGS_BASE	0x80
+#define HDA_STREAM_REGS_LEN	0x20
+
+#define HDA_BDL_MAX_LEN		0x0100
 
 /*
  * HDA data structures
@@ -25,6 +31,19 @@
 
 typedef void (*hda_set_reg_handler)(struct hda_softc *sc, uint32_t offset, uint32_t old);
 
+struct hda_bdle {
+	uint32_t addrl;
+	uint32_t addrh;
+	uint32_t len;
+	uint32_t ioc;
+} __packed;
+
+struct hda_bdle_desc {
+	void *addr;
+	uint32_t len;
+	uint8_t ioc;
+};
+
 struct hda_codec_cmd_ctl {
 	char *name;
 	void *dma_vaddr;
@@ -34,6 +53,14 @@
 	uint8_t run;
 };
 
+struct hda_stream_desc {
+	uint8_t run;
+	uint8_t dir;
+
+	struct hda_bdle_desc bdl[HDA_BDL_MAX_LEN];
+	uint32_t bdl_cnt;
+};
+
 struct hda_softc {
 	struct pci_devinst *pci_dev;
 	uint32_t regs[HDA_LAST_OFFSET];
@@ -43,6 +70,9 @@
 
 	struct hda_codec_inst *codecs[HDA_CODEC_MAX];
 	uint8_t codecs_no;
+
+	struct hda_stream_desc streams[HDA_IOSS_NO];
+	uint8_t stream_map[HDA_STREAM_TAGS_CNT];
 };
 
 /*
@@ -67,6 +97,8 @@
 hda_reset(struct hda_softc *sc);
 static void
 hda_reset_regs(struct hda_softc *sc);
+static void
+hda_reset_stream(struct hda_softc *sc, uint8_t stream_ind);
 static uint32_t
 hda_read(struct hda_softc *sc, uint32_t offset);
 static int
@@ -90,6 +122,8 @@
 
 static inline uint8_t
 hda_get_stream_by_offsets(uint32_t offset, uint8_t reg_offset);
+static inline uint32_t
+hda_get_offset_stream(uint8_t stream_ind);
 
 static void
 hda_set_gctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
@@ -355,6 +389,25 @@
 	return;
 }
 
+static void
+hda_reset_stream(struct hda_softc *sc, uint8_t stream_ind)
+{
+	struct hda_stream_desc *st = &sc->streams[stream_ind];
+	uint32_t off = hda_get_offset_stream(stream_ind);
+
+	DPRINTF("Reset the HDA stream: 0x%x\n", stream_ind);
+
+	/* Reset the Stream Descriptor registers */
+	memset(sc->regs + HDA_STREAM_REGS_BASE + off, 0, HDA_STREAM_REGS_LEN);
+
+	/* Reset the Stream Descriptor */
+	memset(st, 0, sizeof(*st));
+
+	hda_set_field_by_offset(sc, off + HDAC_SDCTL0, HDAC_SDCTL_SRST, HDAC_SDCTL_SRST);
+
+	return;
+}
+
 static uint32_t
 hda_read(struct hda_softc *sc, uint32_t offset)
 {
@@ -521,7 +574,17 @@
 static inline uint8_t
 hda_get_stream_by_offsets(uint32_t offset, uint8_t reg_offset)
 {
-	return (offset - reg_offset - 0x80) / 0x20;
+	uint8_t stream_ind = (offset - reg_offset) >> 5;
+
+	assert(stream_ind < HDA_IOSS_NO);
+
+	return stream_ind;
+}
+
+static inline uint32_t
+hda_get_offset_stream(uint8_t stream_ind)
+{
+	return stream_ind << 5;
 }
 
 static void
@@ -583,10 +646,15 @@
 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, 0x00);
+	uint8_t stream_ind = hda_get_stream_by_offsets(offset, HDAC_SDCTL0);
+	uint32_t value = hda_get_reg_by_offset(sc, offset);
 
 	DPRINTF("stream_ind: 0x%x old: 0x%x\n", stream_ind, old);
 
+	if (value & HDAC_SDCTL_SRST) {
+		hda_reset_stream(sc, stream_ind);
+	}
+
 	return;
 }
 



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