15325 bhyve upstream sync 2023 January
[illumos-gate.git] / usr / src / cmd / bhyve / pci_hda.c
bloba85935a5cae84689a2166a6635d979ff283dc607
1 /*-
2 * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
4 * Copyright (c) 2016 Alex Teaca <iateaca@FreeBSD.org>
5 * All rights reserved.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND
17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26 * SUCH DAMAGE.
30 #include <sys/cdefs.h>
31 __FBSDID("$FreeBSD$");
33 #include <time.h>
35 #include "pci_hda.h"
36 #include "bhyverun.h"
37 #include "config.h"
38 #include "pci_emul.h"
39 #include "hdac_reg.h"
42 * HDA defines
44 #define PCIR_HDCTL 0x40
45 #define INTEL_VENDORID 0x8086
46 #define HDA_INTEL_82801G 0x27d8
48 #define HDA_IOSS_NO 0x08
49 #define HDA_OSS_NO 0x04
50 #define HDA_ISS_NO 0x04
51 #define HDA_CODEC_MAX 0x0f
52 #define HDA_LAST_OFFSET \
53 (0x2084 + ((HDA_ISS_NO) * 0x20) + ((HDA_OSS_NO) * 0x20))
54 #define HDA_SET_REG_TABLE_SZ \
55 (0x80 + ((HDA_ISS_NO) * 0x20) + ((HDA_OSS_NO) * 0x20))
56 #define HDA_CORB_ENTRY_LEN 0x04
57 #define HDA_RIRB_ENTRY_LEN 0x08
58 #define HDA_BDL_ENTRY_LEN 0x10
59 #define HDA_DMA_PIB_ENTRY_LEN 0x08
60 #define HDA_STREAM_TAGS_CNT 0x10
61 #define HDA_STREAM_REGS_BASE 0x80
62 #define HDA_STREAM_REGS_LEN 0x20
64 #define HDA_DMA_ACCESS_LEN (sizeof(uint32_t))
65 #define HDA_BDL_MAX_LEN 0x0100
67 #define HDAC_SDSTS_FIFORDY (1 << 5)
69 #define HDA_RIRBSTS_IRQ_MASK (HDAC_RIRBSTS_RINTFL | HDAC_RIRBSTS_RIRBOIS)
70 #define HDA_STATESTS_IRQ_MASK ((1 << HDA_CODEC_MAX) - 1)
71 #define HDA_SDSTS_IRQ_MASK \
72 (HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS)
75 * HDA data structures
78 struct hda_softc;
80 typedef void (*hda_set_reg_handler)(struct hda_softc *sc, uint32_t offset,
81 uint32_t old);
83 struct hda_bdle {
84 uint32_t addrl;
85 uint32_t addrh;
86 uint32_t len;
87 uint32_t ioc;
88 } __packed;
90 struct hda_bdle_desc {
91 void *addr;
92 uint8_t ioc;
93 uint32_t len;
96 struct hda_codec_cmd_ctl {
97 const char *name;
98 void *dma_vaddr;
99 uint8_t run;
100 uint16_t rp;
101 uint16_t size;
102 uint16_t wp;
105 struct hda_stream_desc {
106 uint8_t dir;
107 uint8_t run;
108 uint8_t stream;
110 /* bp is the no. of bytes transferred in the current bdle */
111 uint32_t bp;
112 /* be is the no. of bdles transferred in the bdl */
113 uint32_t be;
115 uint32_t bdl_cnt;
116 struct hda_bdle_desc bdl[HDA_BDL_MAX_LEN];
119 struct hda_softc {
120 struct pci_devinst *pci_dev;
121 uint32_t regs[HDA_LAST_OFFSET];
123 uint8_t lintr;
124 uint8_t rirb_cnt;
125 uint64_t wall_clock_start;
127 struct hda_codec_cmd_ctl corb;
128 struct hda_codec_cmd_ctl rirb;
130 uint8_t codecs_no;
131 struct hda_codec_inst *codecs[HDA_CODEC_MAX];
133 /* Base Address of the DMA Position Buffer */
134 void *dma_pib_vaddr;
136 struct hda_stream_desc streams[HDA_IOSS_NO];
137 /* 2 tables for output and input */
138 uint8_t stream_map[2][HDA_STREAM_TAGS_CNT];
142 * HDA module function declarations
144 static inline void hda_set_reg_by_offset(struct hda_softc *sc, uint32_t offset,
145 uint32_t value);
146 static inline uint32_t hda_get_reg_by_offset(struct hda_softc *sc,
147 uint32_t offset);
148 static inline void hda_set_field_by_offset(struct hda_softc *sc,
149 uint32_t offset, uint32_t mask, uint32_t value);
151 static struct hda_softc *hda_init(nvlist_t *nvl);
152 static void hda_update_intr(struct hda_softc *sc);
153 static void hda_response_interrupt(struct hda_softc *sc);
154 static int hda_codec_constructor(struct hda_softc *sc,
155 struct hda_codec_class *codec, const char *play, const char *rec);
156 static struct hda_codec_class *hda_find_codec_class(const char *name);
158 static int hda_send_command(struct hda_softc *sc, uint32_t verb);
159 static int hda_notify_codecs(struct hda_softc *sc, uint8_t run,
160 uint8_t stream, uint8_t dir);
161 static void hda_reset(struct hda_softc *sc);
162 static void hda_reset_regs(struct hda_softc *sc);
163 static void hda_stream_reset(struct hda_softc *sc, uint8_t stream_ind);
164 static int hda_stream_start(struct hda_softc *sc, uint8_t stream_ind);
165 static int hda_stream_stop(struct hda_softc *sc, uint8_t stream_ind);
166 static uint32_t hda_read(struct hda_softc *sc, uint32_t offset);
167 static int hda_write(struct hda_softc *sc, uint32_t offset, uint8_t size,
168 uint32_t value);
170 static inline void hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p);
171 static int hda_corb_start(struct hda_softc *sc);
172 static int hda_corb_run(struct hda_softc *sc);
173 static int hda_rirb_start(struct hda_softc *sc);
175 static void *hda_dma_get_vaddr(struct hda_softc *sc, uint64_t dma_paddr,
176 size_t len);
177 static void hda_dma_st_dword(void *dma_vaddr, uint32_t data);
178 static uint32_t hda_dma_ld_dword(void *dma_vaddr);
180 static inline uint8_t hda_get_stream_by_offsets(uint32_t offset,
181 uint8_t reg_offset);
182 static inline uint32_t hda_get_offset_stream(uint8_t stream_ind);
184 static void hda_set_gctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
185 static void hda_set_statests(struct hda_softc *sc, uint32_t offset,
186 uint32_t old);
187 static void hda_set_corbwp(struct hda_softc *sc, uint32_t offset, uint32_t old);
188 static void hda_set_corbctl(struct hda_softc *sc, uint32_t offset,
189 uint32_t old);
190 static void hda_set_rirbctl(struct hda_softc *sc, uint32_t offset,
191 uint32_t old);
192 static void hda_set_rirbsts(struct hda_softc *sc, uint32_t offset,
193 uint32_t old);
194 static void hda_set_dpiblbase(struct hda_softc *sc, uint32_t offset,
195 uint32_t old);
196 static void hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
197 static void hda_set_sdctl2(struct hda_softc *sc, uint32_t offset, uint32_t old);
198 static void hda_set_sdsts(struct hda_softc *sc, uint32_t offset, uint32_t old);
200 static int hda_signal_state_change(struct hda_codec_inst *hci);
201 static int hda_response(struct hda_codec_inst *hci, uint32_t response,
202 uint8_t unsol);
203 static int hda_transfer(struct hda_codec_inst *hci, uint8_t stream,
204 uint8_t dir, uint8_t *buf, size_t count);
206 static void hda_set_pib(struct hda_softc *sc, uint8_t stream_ind, uint32_t pib);
207 static uint64_t hda_get_clock_ns(void);
210 * PCI HDA function declarations
212 static int pci_hda_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl);
213 static void pci_hda_write(struct vmctx *ctx, struct pci_devinst *pi,
214 int baridx, uint64_t offset, int size, uint64_t value);
215 static uint64_t pci_hda_read(struct vmctx *ctx, struct pci_devinst *pi,
216 int baridx, uint64_t offset, int size);
218 * HDA global data
221 static const hda_set_reg_handler hda_set_reg_table[] = {
222 [HDAC_GCTL] = hda_set_gctl,
223 [HDAC_STATESTS] = hda_set_statests,
224 [HDAC_CORBWP] = hda_set_corbwp,
225 [HDAC_CORBCTL] = hda_set_corbctl,
226 [HDAC_RIRBCTL] = hda_set_rirbctl,
227 [HDAC_RIRBSTS] = hda_set_rirbsts,
228 [HDAC_DPIBLBASE] = hda_set_dpiblbase,
230 #define HDAC_ISTREAM(n, iss, oss) \
231 [_HDAC_ISDCTL(n, iss, oss)] = hda_set_sdctl, \
232 [_HDAC_ISDCTL(n, iss, oss) + 2] = hda_set_sdctl2, \
233 [_HDAC_ISDSTS(n, iss, oss)] = hda_set_sdsts, \
235 #define HDAC_OSTREAM(n, iss, oss) \
236 [_HDAC_OSDCTL(n, iss, oss)] = hda_set_sdctl, \
237 [_HDAC_OSDCTL(n, iss, oss) + 2] = hda_set_sdctl2, \
238 [_HDAC_OSDSTS(n, iss, oss)] = hda_set_sdsts, \
240 HDAC_ISTREAM(0, HDA_ISS_NO, HDA_OSS_NO)
241 HDAC_ISTREAM(1, HDA_ISS_NO, HDA_OSS_NO)
242 HDAC_ISTREAM(2, HDA_ISS_NO, HDA_OSS_NO)
243 HDAC_ISTREAM(3, HDA_ISS_NO, HDA_OSS_NO)
245 HDAC_OSTREAM(0, HDA_ISS_NO, HDA_OSS_NO)
246 HDAC_OSTREAM(1, HDA_ISS_NO, HDA_OSS_NO)
247 HDAC_OSTREAM(2, HDA_ISS_NO, HDA_OSS_NO)
248 HDAC_OSTREAM(3, HDA_ISS_NO, HDA_OSS_NO)
250 [HDA_SET_REG_TABLE_SZ] = NULL,
253 static const uint16_t hda_corb_sizes[] = {
254 [HDAC_CORBSIZE_CORBSIZE_2] = 2,
255 [HDAC_CORBSIZE_CORBSIZE_16] = 16,
256 [HDAC_CORBSIZE_CORBSIZE_256] = 256,
257 [HDAC_CORBSIZE_CORBSIZE_MASK] = 0,
260 static const uint16_t hda_rirb_sizes[] = {
261 [HDAC_RIRBSIZE_RIRBSIZE_2] = 2,
262 [HDAC_RIRBSIZE_RIRBSIZE_16] = 16,
263 [HDAC_RIRBSIZE_RIRBSIZE_256] = 256,
264 [HDAC_RIRBSIZE_RIRBSIZE_MASK] = 0,
267 static const struct hda_ops hops = {
268 .signal = hda_signal_state_change,
269 .response = hda_response,
270 .transfer = hda_transfer,
273 static const struct pci_devemu pci_de_hda = {
274 .pe_emu = "hda",
275 .pe_init = pci_hda_init,
276 .pe_barwrite = pci_hda_write,
277 .pe_barread = pci_hda_read
279 PCI_EMUL_SET(pci_de_hda);
281 SET_DECLARE(hda_codec_class_set, struct hda_codec_class);
283 #if DEBUG_HDA == 1
284 FILE *dbg;
285 #endif
288 * HDA module function definitions
291 static inline void
292 hda_set_reg_by_offset(struct hda_softc *sc, uint32_t offset, uint32_t value)
294 assert(offset < HDA_LAST_OFFSET);
295 sc->regs[offset] = value;
298 static inline uint32_t
299 hda_get_reg_by_offset(struct hda_softc *sc, uint32_t offset)
301 assert(offset < HDA_LAST_OFFSET);
302 return sc->regs[offset];
305 static inline void
306 hda_set_field_by_offset(struct hda_softc *sc, uint32_t offset,
307 uint32_t mask, uint32_t value)
309 uint32_t reg_value = 0;
311 reg_value = hda_get_reg_by_offset(sc, offset);
313 reg_value &= ~mask;
314 reg_value |= (value & mask);
316 hda_set_reg_by_offset(sc, offset, reg_value);
319 static struct hda_softc *
320 hda_init(nvlist_t *nvl)
322 struct hda_softc *sc = NULL;
323 struct hda_codec_class *codec = NULL;
324 const char *value;
325 char *play;
326 char *rec;
327 int err;
329 #if DEBUG_HDA == 1
330 dbg = fopen("/tmp/bhyve_hda.log", "w+");
331 #endif
333 sc = calloc(1, sizeof(*sc));
334 if (!sc)
335 return (NULL);
337 hda_reset_regs(sc);
340 * TODO search all configured codecs
341 * For now we play with one single codec
343 codec = hda_find_codec_class("hda_codec");
344 if (codec) {
345 value = get_config_value_node(nvl, "play");
346 if (value == NULL)
347 play = NULL;
348 else
349 play = strdup(value);
350 value = get_config_value_node(nvl, "rec");
351 if (value == NULL)
352 rec = NULL;
353 else
354 rec = strdup(value);
355 DPRINTF("play: %s rec: %s", play, rec);
356 if (play != NULL || rec != NULL) {
357 err = hda_codec_constructor(sc, codec, play, rec);
358 assert(!err);
360 free(play);
361 free(rec);
364 return (sc);
367 static void
368 hda_update_intr(struct hda_softc *sc)
370 struct pci_devinst *pi = sc->pci_dev;
371 uint32_t intctl = hda_get_reg_by_offset(sc, HDAC_INTCTL);
372 uint32_t intsts = 0;
373 uint32_t sdsts = 0;
374 uint32_t rirbsts = 0;
375 uint32_t wakeen = 0;
376 uint32_t statests = 0;
377 uint32_t off = 0;
378 int i;
380 /* update the CIS bits */
381 rirbsts = hda_get_reg_by_offset(sc, HDAC_RIRBSTS);
382 if (rirbsts & (HDAC_RIRBSTS_RINTFL | HDAC_RIRBSTS_RIRBOIS))
383 intsts |= HDAC_INTSTS_CIS;
385 wakeen = hda_get_reg_by_offset(sc, HDAC_WAKEEN);
386 statests = hda_get_reg_by_offset(sc, HDAC_STATESTS);
387 if (statests & wakeen)
388 intsts |= HDAC_INTSTS_CIS;
390 /* update the SIS bits */
391 for (i = 0; i < HDA_IOSS_NO; i++) {
392 off = hda_get_offset_stream(i);
393 sdsts = hda_get_reg_by_offset(sc, off + HDAC_SDSTS);
394 if (sdsts & HDAC_SDSTS_BCIS)
395 intsts |= (1 << i);
398 /* update the GIS bit */
399 if (intsts)
400 intsts |= HDAC_INTSTS_GIS;
402 hda_set_reg_by_offset(sc, HDAC_INTSTS, intsts);
404 if ((intctl & HDAC_INTCTL_GIE) && ((intsts & \
405 ~HDAC_INTSTS_GIS) & intctl)) {
406 if (!sc->lintr) {
407 pci_lintr_assert(pi);
408 sc->lintr = 1;
410 } else {
411 if (sc->lintr) {
412 pci_lintr_deassert(pi);
413 sc->lintr = 0;
418 static void
419 hda_response_interrupt(struct hda_softc *sc)
421 uint8_t rirbctl = hda_get_reg_by_offset(sc, HDAC_RIRBCTL);
423 if ((rirbctl & HDAC_RIRBCTL_RINTCTL) && sc->rirb_cnt) {
424 sc->rirb_cnt = 0;
425 hda_set_field_by_offset(sc, HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL,
426 HDAC_RIRBSTS_RINTFL);
427 hda_update_intr(sc);
431 static int
432 hda_codec_constructor(struct hda_softc *sc, struct hda_codec_class *codec,
433 const char *play, const char *rec)
435 struct hda_codec_inst *hci = NULL;
437 if (sc->codecs_no >= HDA_CODEC_MAX)
438 return (-1);
440 hci = calloc(1, sizeof(struct hda_codec_inst));
441 if (!hci)
442 return (-1);
444 hci->hda = sc;
445 hci->hops = &hops;
446 hci->cad = sc->codecs_no;
447 hci->codec = codec;
449 sc->codecs[sc->codecs_no++] = hci;
451 if (!codec->init) {
452 DPRINTF("This codec does not implement the init function");
453 return (-1);
456 return (codec->init(hci, play, rec));
459 static struct hda_codec_class *
460 hda_find_codec_class(const char *name)
462 struct hda_codec_class **pdpp = NULL, *pdp = NULL;
464 SET_FOREACH(pdpp, hda_codec_class_set) {
465 pdp = *pdpp;
466 if (!strcmp(pdp->name, name)) {
467 return (pdp);
471 return (NULL);
474 static int
475 hda_send_command(struct hda_softc *sc, uint32_t verb)
477 struct hda_codec_inst *hci = NULL;
478 struct hda_codec_class *codec = NULL;
479 uint8_t cad = (verb >> HDA_CMD_CAD_SHIFT) & 0x0f;
481 hci = sc->codecs[cad];
482 if (!hci)
483 return (-1);
485 DPRINTF("cad: 0x%x verb: 0x%x", cad, verb);
487 codec = hci->codec;
488 assert(codec);
490 if (!codec->command) {
491 DPRINTF("This codec does not implement the command function");
492 return (-1);
495 return (codec->command(hci, verb));
498 static int
499 hda_notify_codecs(struct hda_softc *sc, uint8_t run, uint8_t stream,
500 uint8_t dir)
502 struct hda_codec_inst *hci = NULL;
503 struct hda_codec_class *codec = NULL;
504 int err;
505 int i;
507 /* Notify each codec */
508 for (i = 0; i < sc->codecs_no; i++) {
509 hci = sc->codecs[i];
510 assert(hci);
512 codec = hci->codec;
513 assert(codec);
515 if (codec->notify) {
516 err = codec->notify(hci, run, stream, dir);
517 if (!err)
518 break;
522 return (i == sc->codecs_no ? (-1) : 0);
525 static void
526 hda_reset(struct hda_softc *sc)
528 int i;
529 struct hda_codec_inst *hci = NULL;
530 struct hda_codec_class *codec = NULL;
532 hda_reset_regs(sc);
534 /* Reset each codec */
535 for (i = 0; i < sc->codecs_no; i++) {
536 hci = sc->codecs[i];
537 assert(hci);
539 codec = hci->codec;
540 assert(codec);
542 if (codec->reset)
543 codec->reset(hci);
546 sc->wall_clock_start = hda_get_clock_ns();
549 static void
550 hda_reset_regs(struct hda_softc *sc)
552 uint32_t off = 0;
553 uint8_t i;
555 DPRINTF("Reset the HDA controller registers ...");
557 memset(sc->regs, 0, sizeof(sc->regs));
559 hda_set_reg_by_offset(sc, HDAC_GCAP,
560 HDAC_GCAP_64OK |
561 (HDA_ISS_NO << HDAC_GCAP_ISS_SHIFT) |
562 (HDA_OSS_NO << HDAC_GCAP_OSS_SHIFT));
563 hda_set_reg_by_offset(sc, HDAC_VMAJ, 0x01);
564 hda_set_reg_by_offset(sc, HDAC_OUTPAY, 0x3c);
565 hda_set_reg_by_offset(sc, HDAC_INPAY, 0x1d);
566 hda_set_reg_by_offset(sc, HDAC_CORBSIZE,
567 HDAC_CORBSIZE_CORBSZCAP_256 | HDAC_CORBSIZE_CORBSIZE_256);
568 hda_set_reg_by_offset(sc, HDAC_RIRBSIZE,
569 HDAC_RIRBSIZE_RIRBSZCAP_256 | HDAC_RIRBSIZE_RIRBSIZE_256);
571 for (i = 0; i < HDA_IOSS_NO; i++) {
572 off = hda_get_offset_stream(i);
573 hda_set_reg_by_offset(sc, off + HDAC_SDFIFOS, HDA_FIFO_SIZE);
577 static void
578 hda_stream_reset(struct hda_softc *sc, uint8_t stream_ind)
580 struct hda_stream_desc *st = &sc->streams[stream_ind];
581 uint32_t off = hda_get_offset_stream(stream_ind);
583 DPRINTF("Reset the HDA stream: 0x%x", stream_ind);
585 /* Reset the Stream Descriptor registers */
586 memset(sc->regs + HDA_STREAM_REGS_BASE + off, 0, HDA_STREAM_REGS_LEN);
588 /* Reset the Stream Descriptor */
589 memset(st, 0, sizeof(*st));
591 hda_set_field_by_offset(sc, off + HDAC_SDSTS,
592 HDAC_SDSTS_FIFORDY, HDAC_SDSTS_FIFORDY);
593 hda_set_field_by_offset(sc, off + HDAC_SDCTL0,
594 HDAC_SDCTL_SRST, HDAC_SDCTL_SRST);
597 static int
598 hda_stream_start(struct hda_softc *sc, uint8_t stream_ind)
600 struct hda_stream_desc *st = &sc->streams[stream_ind];
601 struct hda_bdle_desc *bdle_desc = NULL;
602 struct hda_bdle *bdle = NULL;
603 uint32_t lvi = 0;
604 uint32_t bdl_cnt = 0;
605 uint64_t bdpl = 0;
606 uint64_t bdpu = 0;
607 uint64_t bdl_paddr = 0;
608 void *bdl_vaddr = NULL;
609 uint32_t bdle_sz = 0;
610 uint64_t bdle_addrl = 0;
611 uint64_t bdle_addrh = 0;
612 uint64_t bdle_paddr = 0;
613 void *bdle_vaddr = NULL;
614 uint32_t off = hda_get_offset_stream(stream_ind);
615 uint32_t sdctl = 0;
616 uint8_t strm = 0;
617 uint8_t dir = 0;
619 assert(!st->run);
621 lvi = hda_get_reg_by_offset(sc, off + HDAC_SDLVI);
622 bdpl = hda_get_reg_by_offset(sc, off + HDAC_SDBDPL);
623 bdpu = hda_get_reg_by_offset(sc, off + HDAC_SDBDPU);
625 bdl_cnt = lvi + 1;
626 assert(bdl_cnt <= HDA_BDL_MAX_LEN);
628 bdl_paddr = bdpl | (bdpu << 32);
629 bdl_vaddr = hda_dma_get_vaddr(sc, bdl_paddr,
630 HDA_BDL_ENTRY_LEN * bdl_cnt);
631 if (!bdl_vaddr) {
632 DPRINTF("Fail to get the guest virtual address");
633 return (-1);
636 DPRINTF("stream: 0x%x bdl_cnt: 0x%x bdl_paddr: 0x%lx",
637 stream_ind, bdl_cnt, bdl_paddr);
639 st->bdl_cnt = bdl_cnt;
641 bdle = (struct hda_bdle *)bdl_vaddr;
642 for (size_t i = 0; i < bdl_cnt; i++, bdle++) {
643 bdle_sz = bdle->len;
644 assert(!(bdle_sz % HDA_DMA_ACCESS_LEN));
646 bdle_addrl = bdle->addrl;
647 bdle_addrh = bdle->addrh;
649 bdle_paddr = bdle_addrl | (bdle_addrh << 32);
650 bdle_vaddr = hda_dma_get_vaddr(sc, bdle_paddr, bdle_sz);
651 if (!bdle_vaddr) {
652 DPRINTF("Fail to get the guest virtual address");
653 return (-1);
656 bdle_desc = &st->bdl[i];
657 bdle_desc->addr = bdle_vaddr;
658 bdle_desc->len = bdle_sz;
659 bdle_desc->ioc = bdle->ioc;
661 DPRINTF("bdle: 0x%zx bdle_sz: 0x%x", i, bdle_sz);
664 sdctl = hda_get_reg_by_offset(sc, off + HDAC_SDCTL0);
665 strm = (sdctl >> 20) & 0x0f;
666 dir = stream_ind >= HDA_ISS_NO;
668 DPRINTF("strm: 0x%x, dir: 0x%x", strm, dir);
670 sc->stream_map[dir][strm] = stream_ind;
671 st->stream = strm;
672 st->dir = dir;
673 st->bp = 0;
674 st->be = 0;
676 hda_set_pib(sc, stream_ind, 0);
678 st->run = 1;
680 hda_notify_codecs(sc, 1, strm, dir);
682 return (0);
685 static int
686 hda_stream_stop(struct hda_softc *sc, uint8_t stream_ind)
688 struct hda_stream_desc *st = &sc->streams[stream_ind];
689 uint8_t strm = st->stream;
690 uint8_t dir = st->dir;
692 DPRINTF("stream: 0x%x, strm: 0x%x, dir: 0x%x", stream_ind, strm, dir);
694 st->run = 0;
696 hda_notify_codecs(sc, 0, strm, dir);
698 return (0);
701 static uint32_t
702 hda_read(struct hda_softc *sc, uint32_t offset)
704 if (offset == HDAC_WALCLK)
705 return (24 * (hda_get_clock_ns() - \
706 sc->wall_clock_start) / 1000);
708 return (hda_get_reg_by_offset(sc, offset));
711 static int
712 hda_write(struct hda_softc *sc, uint32_t offset, uint8_t size, uint32_t value)
714 uint32_t old = hda_get_reg_by_offset(sc, offset);
715 uint32_t masks[] = {0x00000000, 0x000000ff, 0x0000ffff,
716 0x00ffffff, 0xffffffff};
717 hda_set_reg_handler set_reg_handler = hda_set_reg_table[offset];
719 hda_set_field_by_offset(sc, offset, masks[size], value);
721 if (set_reg_handler)
722 set_reg_handler(sc, offset, old);
724 return (0);
727 static inline void
728 hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p)
730 #if DEBUG_HDA == 1
731 const char *name = p->name;
732 #endif
733 DPRINTF("%s size: %d", name, p->size);
734 DPRINTF("%s dma_vaddr: %p", name, p->dma_vaddr);
735 DPRINTF("%s wp: 0x%x", name, p->wp);
736 DPRINTF("%s rp: 0x%x", name, p->rp);
739 static int
740 hda_corb_start(struct hda_softc *sc)
742 struct hda_codec_cmd_ctl *corb = &sc->corb;
743 uint8_t corbsize = 0;
744 uint64_t corblbase = 0;
745 uint64_t corbubase = 0;
746 uint64_t corbpaddr = 0;
748 corb->name = "CORB";
750 corbsize = hda_get_reg_by_offset(sc, HDAC_CORBSIZE) & \
751 HDAC_CORBSIZE_CORBSIZE_MASK;
752 corb->size = hda_corb_sizes[corbsize];
754 if (!corb->size) {
755 DPRINTF("Invalid corb size");
756 return (-1);
759 corblbase = hda_get_reg_by_offset(sc, HDAC_CORBLBASE);
760 corbubase = hda_get_reg_by_offset(sc, HDAC_CORBUBASE);
762 corbpaddr = corblbase | (corbubase << 32);
763 DPRINTF("CORB dma_paddr: %p", (void *)corbpaddr);
765 corb->dma_vaddr = hda_dma_get_vaddr(sc, corbpaddr,
766 HDA_CORB_ENTRY_LEN * corb->size);
767 if (!corb->dma_vaddr) {
768 DPRINTF("Fail to get the guest virtual address");
769 return (-1);
772 corb->wp = hda_get_reg_by_offset(sc, HDAC_CORBWP);
773 corb->rp = hda_get_reg_by_offset(sc, HDAC_CORBRP);
775 corb->run = 1;
777 hda_print_cmd_ctl_data(corb);
779 return (0);
782 static int
783 hda_corb_run(struct hda_softc *sc)
785 struct hda_codec_cmd_ctl *corb = &sc->corb;
786 uint32_t verb = 0;
787 int err;
789 corb->wp = hda_get_reg_by_offset(sc, HDAC_CORBWP);
791 while (corb->rp != corb->wp && corb->run) {
792 corb->rp++;
793 corb->rp %= corb->size;
795 verb = hda_dma_ld_dword((uint8_t *)corb->dma_vaddr +
796 HDA_CORB_ENTRY_LEN * corb->rp);
798 err = hda_send_command(sc, verb);
799 assert(!err);
802 hda_set_reg_by_offset(sc, HDAC_CORBRP, corb->rp);
804 if (corb->run)
805 hda_response_interrupt(sc);
807 return (0);
810 static int
811 hda_rirb_start(struct hda_softc *sc)
813 struct hda_codec_cmd_ctl *rirb = &sc->rirb;
814 uint8_t rirbsize = 0;
815 uint64_t rirblbase = 0;
816 uint64_t rirbubase = 0;
817 uint64_t rirbpaddr = 0;
819 rirb->name = "RIRB";
821 rirbsize = hda_get_reg_by_offset(sc, HDAC_RIRBSIZE) & \
822 HDAC_RIRBSIZE_RIRBSIZE_MASK;
823 rirb->size = hda_rirb_sizes[rirbsize];
825 if (!rirb->size) {
826 DPRINTF("Invalid rirb size");
827 return (-1);
830 rirblbase = hda_get_reg_by_offset(sc, HDAC_RIRBLBASE);
831 rirbubase = hda_get_reg_by_offset(sc, HDAC_RIRBUBASE);
833 rirbpaddr = rirblbase | (rirbubase << 32);
834 DPRINTF("RIRB dma_paddr: %p", (void *)rirbpaddr);
836 rirb->dma_vaddr = hda_dma_get_vaddr(sc, rirbpaddr,
837 HDA_RIRB_ENTRY_LEN * rirb->size);
838 if (!rirb->dma_vaddr) {
839 DPRINTF("Fail to get the guest virtual address");
840 return (-1);
843 rirb->wp = hda_get_reg_by_offset(sc, HDAC_RIRBWP);
844 rirb->rp = 0x0000;
846 rirb->run = 1;
848 hda_print_cmd_ctl_data(rirb);
850 return (0);
853 static void *
854 hda_dma_get_vaddr(struct hda_softc *sc, uint64_t dma_paddr, size_t len)
856 struct pci_devinst *pi = sc->pci_dev;
858 assert(pi);
860 return (paddr_guest2host(pi->pi_vmctx, (uintptr_t)dma_paddr, len));
863 static void
864 hda_dma_st_dword(void *dma_vaddr, uint32_t data)
866 *(uint32_t*)dma_vaddr = data;
869 static uint32_t
870 hda_dma_ld_dword(void *dma_vaddr)
872 return (*(uint32_t*)dma_vaddr);
875 static inline uint8_t
876 hda_get_stream_by_offsets(uint32_t offset, uint8_t reg_offset)
878 uint8_t stream_ind = (offset - reg_offset) >> 5;
880 assert(stream_ind < HDA_IOSS_NO);
882 return (stream_ind);
885 static inline uint32_t
886 hda_get_offset_stream(uint8_t stream_ind)
888 return (stream_ind << 5);
891 static void
892 hda_set_gctl(struct hda_softc *sc, uint32_t offset, uint32_t old __unused)
894 uint32_t value = hda_get_reg_by_offset(sc, offset);
896 if (!(value & HDAC_GCTL_CRST)) {
897 hda_reset(sc);
901 static void
902 hda_set_statests(struct hda_softc *sc, uint32_t offset, uint32_t old)
904 uint32_t value = hda_get_reg_by_offset(sc, offset);
906 hda_set_reg_by_offset(sc, offset, old);
908 /* clear the corresponding bits written by the software (guest) */
909 hda_set_field_by_offset(sc, offset, value & HDA_STATESTS_IRQ_MASK, 0);
911 hda_update_intr(sc);
914 static void
915 hda_set_corbwp(struct hda_softc *sc, uint32_t offset __unused,
916 uint32_t old __unused)
918 hda_corb_run(sc);
921 static void
922 hda_set_corbctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
924 uint32_t value = hda_get_reg_by_offset(sc, offset);
925 int err;
926 struct hda_codec_cmd_ctl *corb = NULL;
928 if (value & HDAC_CORBCTL_CORBRUN) {
929 if (!(old & HDAC_CORBCTL_CORBRUN)) {
930 err = hda_corb_start(sc);
931 assert(!err);
933 } else {
934 corb = &sc->corb;
935 memset(corb, 0, sizeof(*corb));
938 hda_corb_run(sc);
941 static void
942 hda_set_rirbctl(struct hda_softc *sc, uint32_t offset, uint32_t old __unused)
944 uint32_t value = hda_get_reg_by_offset(sc, offset);
945 int err;
946 struct hda_codec_cmd_ctl *rirb = NULL;
948 if (value & HDAC_RIRBCTL_RIRBDMAEN) {
949 err = hda_rirb_start(sc);
950 assert(!err);
951 } else {
952 rirb = &sc->rirb;
953 memset(rirb, 0, sizeof(*rirb));
957 static void
958 hda_set_rirbsts(struct hda_softc *sc, uint32_t offset, uint32_t old)
960 uint32_t value = hda_get_reg_by_offset(sc, offset);
962 hda_set_reg_by_offset(sc, offset, old);
964 /* clear the corresponding bits written by the software (guest) */
965 hda_set_field_by_offset(sc, offset, value & HDA_RIRBSTS_IRQ_MASK, 0);
967 hda_update_intr(sc);
970 static void
971 hda_set_dpiblbase(struct hda_softc *sc, uint32_t offset, uint32_t old)
973 uint32_t value = hda_get_reg_by_offset(sc, offset);
974 uint64_t dpiblbase = 0;
975 uint64_t dpibubase = 0;
976 uint64_t dpibpaddr = 0;
978 if ((value & HDAC_DPLBASE_DPLBASE_DMAPBE) != (old & \
979 HDAC_DPLBASE_DPLBASE_DMAPBE)) {
980 if (value & HDAC_DPLBASE_DPLBASE_DMAPBE) {
981 dpiblbase = value & HDAC_DPLBASE_DPLBASE_MASK;
982 dpibubase = hda_get_reg_by_offset(sc, HDAC_DPIBUBASE);
984 dpibpaddr = dpiblbase | (dpibubase << 32);
985 DPRINTF("DMA Position In Buffer dma_paddr: %p",
986 (void *)dpibpaddr);
988 sc->dma_pib_vaddr = hda_dma_get_vaddr(sc, dpibpaddr,
989 HDA_DMA_PIB_ENTRY_LEN * HDA_IOSS_NO);
990 if (!sc->dma_pib_vaddr) {
991 DPRINTF("Fail to get the guest \
992 virtual address");
993 assert(0);
995 } else {
996 DPRINTF("DMA Position In Buffer Reset");
997 sc->dma_pib_vaddr = NULL;
1002 static void
1003 hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
1005 uint8_t stream_ind = hda_get_stream_by_offsets(offset, HDAC_SDCTL0);
1006 uint32_t value = hda_get_reg_by_offset(sc, offset);
1007 int err;
1009 DPRINTF("stream_ind: 0x%x old: 0x%x value: 0x%x",
1010 stream_ind, old, value);
1012 if (value & HDAC_SDCTL_SRST) {
1013 hda_stream_reset(sc, stream_ind);
1016 if ((value & HDAC_SDCTL_RUN) != (old & HDAC_SDCTL_RUN)) {
1017 if (value & HDAC_SDCTL_RUN) {
1018 err = hda_stream_start(sc, stream_ind);
1019 assert(!err);
1020 } else {
1021 err = hda_stream_stop(sc, stream_ind);
1022 assert(!err);
1027 static void
1028 hda_set_sdctl2(struct hda_softc *sc, uint32_t offset, uint32_t old __unused)
1030 uint32_t value = hda_get_reg_by_offset(sc, offset);
1032 hda_set_field_by_offset(sc, offset - 2, 0x00ff0000, value << 16);
1035 static void
1036 hda_set_sdsts(struct hda_softc *sc, uint32_t offset, uint32_t old)
1038 uint32_t value = hda_get_reg_by_offset(sc, offset);
1040 hda_set_reg_by_offset(sc, offset, old);
1042 /* clear the corresponding bits written by the software (guest) */
1043 hda_set_field_by_offset(sc, offset, value & HDA_SDSTS_IRQ_MASK, 0);
1045 hda_update_intr(sc);
1048 static int
1049 hda_signal_state_change(struct hda_codec_inst *hci)
1051 struct hda_softc *sc = NULL;
1052 uint32_t sdiwake = 0;
1054 assert(hci);
1055 assert(hci->hda);
1057 DPRINTF("cad: 0x%x", hci->cad);
1059 sc = hci->hda;
1060 sdiwake = 1 << hci->cad;
1062 hda_set_field_by_offset(sc, HDAC_STATESTS, sdiwake, sdiwake);
1063 hda_update_intr(sc);
1065 return (0);
1068 static int
1069 hda_response(struct hda_codec_inst *hci, uint32_t response, uint8_t unsol)
1071 struct hda_softc *sc = NULL;
1072 struct hda_codec_cmd_ctl *rirb = NULL;
1073 uint32_t response_ex = 0;
1074 uint8_t rintcnt = 0;
1076 assert(hci);
1077 assert(hci->cad <= HDA_CODEC_MAX);
1079 response_ex = hci->cad | unsol;
1081 sc = hci->hda;
1082 assert(sc);
1084 rirb = &sc->rirb;
1086 if (rirb->run) {
1087 rirb->wp++;
1088 rirb->wp %= rirb->size;
1090 hda_dma_st_dword((uint8_t *)rirb->dma_vaddr +
1091 HDA_RIRB_ENTRY_LEN * rirb->wp, response);
1092 hda_dma_st_dword((uint8_t *)rirb->dma_vaddr +
1093 HDA_RIRB_ENTRY_LEN * rirb->wp + 0x04, response_ex);
1095 hda_set_reg_by_offset(sc, HDAC_RIRBWP, rirb->wp);
1097 sc->rirb_cnt++;
1100 rintcnt = hda_get_reg_by_offset(sc, HDAC_RINTCNT);
1101 if (sc->rirb_cnt == rintcnt)
1102 hda_response_interrupt(sc);
1104 return (0);
1107 static int
1108 hda_transfer(struct hda_codec_inst *hci, uint8_t stream, uint8_t dir,
1109 uint8_t *buf, size_t count)
1111 struct hda_softc *sc = NULL;
1112 struct hda_stream_desc *st = NULL;
1113 struct hda_bdle_desc *bdl = NULL;
1114 struct hda_bdle_desc *bdle_desc = NULL;
1115 uint8_t stream_ind = 0;
1116 uint32_t lpib = 0;
1117 uint32_t off = 0;
1118 size_t left = 0;
1119 uint8_t irq = 0;
1121 assert(hci);
1122 assert(hci->hda);
1123 assert(buf);
1124 assert(!(count % HDA_DMA_ACCESS_LEN));
1126 if (!stream) {
1127 DPRINTF("Invalid stream");
1128 return (-1);
1131 sc = hci->hda;
1133 assert(stream < HDA_STREAM_TAGS_CNT);
1134 stream_ind = sc->stream_map[dir][stream];
1136 if (!dir)
1137 assert(stream_ind < HDA_ISS_NO);
1138 else
1139 assert(stream_ind >= HDA_ISS_NO && stream_ind < HDA_IOSS_NO);
1141 st = &sc->streams[stream_ind];
1142 if (!st->run) {
1143 DPRINTF("Stream 0x%x stopped", stream);
1144 return (-1);
1147 assert(st->stream == stream);
1149 off = hda_get_offset_stream(stream_ind);
1151 lpib = hda_get_reg_by_offset(sc, off + HDAC_SDLPIB);
1153 bdl = st->bdl;
1155 assert(st->be < st->bdl_cnt);
1156 assert(st->bp < bdl[st->be].len);
1158 left = count;
1159 while (left) {
1160 bdle_desc = &bdl[st->be];
1162 if (dir)
1163 *(uint32_t *)buf = hda_dma_ld_dword(
1164 (uint8_t *)bdle_desc->addr + st->bp);
1165 else
1166 hda_dma_st_dword((uint8_t *)bdle_desc->addr +
1167 st->bp, *(uint32_t *)buf);
1169 buf += HDA_DMA_ACCESS_LEN;
1170 st->bp += HDA_DMA_ACCESS_LEN;
1171 lpib += HDA_DMA_ACCESS_LEN;
1172 left -= HDA_DMA_ACCESS_LEN;
1174 if (st->bp == bdle_desc->len) {
1175 st->bp = 0;
1176 if (bdle_desc->ioc)
1177 irq = 1;
1178 st->be++;
1179 if (st->be == st->bdl_cnt) {
1180 st->be = 0;
1181 lpib = 0;
1183 bdle_desc = &bdl[st->be];
1187 hda_set_pib(sc, stream_ind, lpib);
1189 if (irq) {
1190 hda_set_field_by_offset(sc, off + HDAC_SDSTS,
1191 HDAC_SDSTS_BCIS, HDAC_SDSTS_BCIS);
1192 hda_update_intr(sc);
1195 return (0);
1198 static void
1199 hda_set_pib(struct hda_softc *sc, uint8_t stream_ind, uint32_t pib)
1201 uint32_t off = hda_get_offset_stream(stream_ind);
1203 hda_set_reg_by_offset(sc, off + HDAC_SDLPIB, pib);
1204 /* LPIB Alias */
1205 hda_set_reg_by_offset(sc, 0x2000 + off + HDAC_SDLPIB, pib);
1206 if (sc->dma_pib_vaddr)
1207 *(uint32_t *)((uint8_t *)sc->dma_pib_vaddr + stream_ind *
1208 HDA_DMA_PIB_ENTRY_LEN) = pib;
1211 static uint64_t hda_get_clock_ns(void)
1213 struct timespec ts;
1214 int err;
1216 err = clock_gettime(CLOCK_MONOTONIC, &ts);
1217 assert(!err);
1219 return (ts.tv_sec * 1000000000LL + ts.tv_nsec);
1223 * PCI HDA function definitions
1225 static int
1226 pci_hda_init(struct vmctx *ctx, struct pci_devinst *pi, nvlist_t *nvl)
1228 struct hda_softc *sc = NULL;
1230 assert(ctx != NULL);
1231 assert(pi != NULL);
1233 pci_set_cfgdata16(pi, PCIR_VENDOR, INTEL_VENDORID);
1234 pci_set_cfgdata16(pi, PCIR_DEVICE, HDA_INTEL_82801G);
1236 pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_MULTIMEDIA_HDA);
1237 pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_MULTIMEDIA);
1239 /* select the Intel HDA mode */
1240 pci_set_cfgdata8(pi, PCIR_HDCTL, 0x01);
1242 /* allocate one BAR register for the Memory address offsets */
1243 pci_emul_alloc_bar(pi, 0, PCIBAR_MEM32, HDA_LAST_OFFSET);
1245 /* allocate an IRQ pin for our slot */
1246 pci_lintr_request(pi);
1248 sc = hda_init(nvl);
1249 if (!sc)
1250 return (-1);
1252 sc->pci_dev = pi;
1253 pi->pi_arg = sc;
1255 return (0);
1258 static void
1259 pci_hda_write(struct vmctx *ctx __unused,
1260 struct pci_devinst *pi, int baridx, uint64_t offset, int size,
1261 uint64_t value)
1263 struct hda_softc *sc = pi->pi_arg;
1264 int err;
1266 assert(sc);
1267 assert(baridx == 0);
1268 assert(size <= 4);
1270 DPRINTF("offset: 0x%lx value: 0x%lx", offset, value);
1272 err = hda_write(sc, offset, size, value);
1273 assert(!err);
1276 static uint64_t
1277 pci_hda_read(struct vmctx *ctx __unused,
1278 struct pci_devinst *pi, int baridx, uint64_t offset, int size)
1280 struct hda_softc *sc = pi->pi_arg;
1281 uint64_t value = 0;
1283 assert(sc);
1284 assert(baridx == 0);
1285 assert(size <= 4);
1287 value = hda_read(sc, offset);
1289 DPRINTF("offset: 0x%lx value: 0x%lx", offset, value);
1291 return (value);