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>