xref: /illumos-gate/usr/src/cmd/bhyve/pci_hda.c (revision 32640292)
1 /*-
2  * SPDX-License-Identifier: BSD-2-Clause
3  *
4  * Copyright (c) 2016 Alex Teaca <iateaca@FreeBSD.org>
5  * All rights reserved.
6  *
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.
15  *
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.
27  *
28  */
29 
30 #include <sys/cdefs.h>
31 
32 #include <sys/param.h>
33 #include <time.h>
34 
35 #include "pci_hda.h"
36 #include "bhyverun.h"
37 #include "config.h"
38 #include "pci_emul.h"
39 #include "hdac_reg.h"
40 
41 /*
42  * HDA defines
43  */
44 #define PCIR_HDCTL		0x40
45 #define INTEL_VENDORID		0x8086
46 #define HDA_INTEL_82801G	0x27d8
47 
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_CORB_ENTRY_LEN	0x04
55 #define HDA_RIRB_ENTRY_LEN	0x08
56 #define HDA_BDL_ENTRY_LEN	0x10
57 #define HDA_DMA_PIB_ENTRY_LEN	0x08
58 #define HDA_STREAM_TAGS_CNT	0x10
59 #define HDA_STREAM_REGS_BASE	0x80
60 #define HDA_STREAM_REGS_LEN	0x20
61 
62 #define HDA_DMA_ACCESS_LEN	(sizeof(uint32_t))
63 #define HDA_BDL_MAX_LEN		0x0100
64 
65 #define HDAC_SDSTS_FIFORDY	(1 << 5)
66 
67 #define HDA_RIRBSTS_IRQ_MASK	(HDAC_RIRBSTS_RINTFL | HDAC_RIRBSTS_RIRBOIS)
68 #define HDA_STATESTS_IRQ_MASK	((1 << HDA_CODEC_MAX) - 1)
69 #define HDA_SDSTS_IRQ_MASK					\
70 	(HDAC_SDSTS_DESE | HDAC_SDSTS_FIFOE | HDAC_SDSTS_BCIS)
71 
72 /*
73  * HDA data structures
74  */
75 
76 struct hda_softc;
77 
78 typedef void (*hda_set_reg_handler)(struct hda_softc *sc, uint32_t offset,
79 		uint32_t old);
80 
81 struct hda_bdle {
82 	uint32_t addrl;
83 	uint32_t addrh;
84 	uint32_t len;
85 	uint32_t ioc;
86 } __packed;
87 
88 struct hda_bdle_desc {
89 	void *addr;
90 	uint8_t ioc;
91 	uint32_t len;
92 };
93 
94 struct hda_codec_cmd_ctl {
95 	const char *name;
96 	void *dma_vaddr;
97 	uint8_t run;
98 	uint16_t rp;
99 	uint16_t size;
100 	uint16_t wp;
101 };
102 
103 struct hda_stream_desc {
104 	uint8_t dir;
105 	uint8_t run;
106 	uint8_t stream;
107 
108 	/* bp is the no. of bytes transferred in the current bdle */
109 	uint32_t bp;
110 	/* be is the no. of bdles transferred in the bdl */
111 	uint32_t be;
112 
113 	uint32_t bdl_cnt;
114 	struct hda_bdle_desc bdl[HDA_BDL_MAX_LEN];
115 };
116 
117 struct hda_softc {
118 	struct pci_devinst *pci_dev;
119 	uint32_t regs[HDA_LAST_OFFSET];
120 
121 	uint8_t lintr;
122 	uint8_t rirb_cnt;
123 	uint64_t wall_clock_start;
124 
125 	struct hda_codec_cmd_ctl corb;
126 	struct hda_codec_cmd_ctl rirb;
127 
128 	uint8_t codecs_no;
129 	struct hda_codec_inst *codecs[HDA_CODEC_MAX];
130 
131 	/* Base Address of the DMA Position Buffer */
132 	void *dma_pib_vaddr;
133 
134 	struct hda_stream_desc streams[HDA_IOSS_NO];
135 	/* 2 tables for output and input */
136 	uint8_t stream_map[2][HDA_STREAM_TAGS_CNT];
137 };
138 
139 /*
140  * HDA module function declarations
141  */
142 static inline void hda_set_reg_by_offset(struct hda_softc *sc, uint32_t offset,
143     uint32_t value);
144 static inline uint32_t hda_get_reg_by_offset(struct hda_softc *sc,
145     uint32_t offset);
146 static inline void hda_set_field_by_offset(struct hda_softc *sc,
147     uint32_t offset, uint32_t mask, uint32_t value);
148 
149 static struct hda_softc *hda_init(nvlist_t *nvl);
150 static void hda_update_intr(struct hda_softc *sc);
151 static void hda_response_interrupt(struct hda_softc *sc);
152 static int hda_codec_constructor(struct hda_softc *sc,
153     struct hda_codec_class *codec, const char *play, const char *rec);
154 static struct hda_codec_class *hda_find_codec_class(const char *name);
155 
156 static int hda_send_command(struct hda_softc *sc, uint32_t verb);
157 static int hda_notify_codecs(struct hda_softc *sc, uint8_t run,
158     uint8_t stream, uint8_t dir);
159 static void hda_reset(struct hda_softc *sc);
160 static void hda_reset_regs(struct hda_softc *sc);
161 static void hda_stream_reset(struct hda_softc *sc, uint8_t stream_ind);
162 static int hda_stream_start(struct hda_softc *sc, uint8_t stream_ind);
163 static int hda_stream_stop(struct hda_softc *sc, uint8_t stream_ind);
164 static uint32_t hda_read(struct hda_softc *sc, uint32_t offset);
165 static int hda_write(struct hda_softc *sc, uint32_t offset, uint8_t size,
166     uint32_t value);
167 
168 static inline void hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p);
169 static int hda_corb_start(struct hda_softc *sc);
170 static int hda_corb_run(struct hda_softc *sc);
171 static int hda_rirb_start(struct hda_softc *sc);
172 
173 static void *hda_dma_get_vaddr(struct hda_softc *sc, uint64_t dma_paddr,
174     size_t len);
175 static void hda_dma_st_dword(void *dma_vaddr, uint32_t data);
176 static uint32_t hda_dma_ld_dword(void *dma_vaddr);
177 
178 static inline uint8_t hda_get_stream_by_offsets(uint32_t offset,
179     uint8_t reg_offset);
180 static inline uint32_t hda_get_offset_stream(uint8_t stream_ind);
181 
182 static void hda_set_gctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
183 static void hda_set_statests(struct hda_softc *sc, uint32_t offset,
184     uint32_t old);
185 static void hda_set_corbwp(struct hda_softc *sc, uint32_t offset, uint32_t old);
186 static void hda_set_corbctl(struct hda_softc *sc, uint32_t offset,
187     uint32_t old);
188 static void hda_set_rirbctl(struct hda_softc *sc, uint32_t offset,
189     uint32_t old);
190 static void hda_set_rirbsts(struct hda_softc *sc, uint32_t offset,
191     uint32_t old);
192 static void hda_set_dpiblbase(struct hda_softc *sc, uint32_t offset,
193     uint32_t old);
194 static void hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old);
195 static void hda_set_sdctl2(struct hda_softc *sc, uint32_t offset, uint32_t old);
196 static void hda_set_sdsts(struct hda_softc *sc, uint32_t offset, uint32_t old);
197 
198 static int hda_signal_state_change(struct hda_codec_inst *hci);
199 static int hda_response(struct hda_codec_inst *hci, uint32_t response,
200     uint8_t unsol);
201 static int hda_transfer(struct hda_codec_inst *hci, uint8_t stream,
202     uint8_t dir, uint8_t *buf, size_t count);
203 
204 static void hda_set_pib(struct hda_softc *sc, uint8_t stream_ind, uint32_t pib);
205 static uint64_t hda_get_clock_ns(void);
206 
207 /*
208  * PCI HDA function declarations
209  */
210 static int pci_hda_init(struct pci_devinst *pi, nvlist_t *nvl);
211 static void pci_hda_write(struct pci_devinst *pi, int baridx, uint64_t offset,
212     int size, uint64_t value);
213 static uint64_t pci_hda_read(struct pci_devinst *pi, int baridx,
214     uint64_t offset, int size);
215 /*
216  * HDA global data
217  */
218 
219 static const hda_set_reg_handler hda_set_reg_table[] = {
220 	[HDAC_GCTL] = hda_set_gctl,
221 	[HDAC_STATESTS] = hda_set_statests,
222 	[HDAC_CORBWP] = hda_set_corbwp,
223 	[HDAC_CORBCTL] = hda_set_corbctl,
224 	[HDAC_RIRBCTL] = hda_set_rirbctl,
225 	[HDAC_RIRBSTS] = hda_set_rirbsts,
226 	[HDAC_DPIBLBASE] = hda_set_dpiblbase,
227 
228 #define HDAC_ISTREAM(n, iss, oss)				\
229 	[_HDAC_ISDCTL(n, iss, oss)] = hda_set_sdctl,		\
230 	[_HDAC_ISDCTL(n, iss, oss) + 2] = hda_set_sdctl2,	\
231 	[_HDAC_ISDSTS(n, iss, oss)] = hda_set_sdsts,		\
232 
233 #define HDAC_OSTREAM(n, iss, oss)				\
234 	[_HDAC_OSDCTL(n, iss, oss)] = hda_set_sdctl,		\
235 	[_HDAC_OSDCTL(n, iss, oss) + 2] = hda_set_sdctl2,	\
236 	[_HDAC_OSDSTS(n, iss, oss)] = hda_set_sdsts,		\
237 
238 	HDAC_ISTREAM(0, HDA_ISS_NO, HDA_OSS_NO)
239 	HDAC_ISTREAM(1, HDA_ISS_NO, HDA_OSS_NO)
240 	HDAC_ISTREAM(2, HDA_ISS_NO, HDA_OSS_NO)
241 	HDAC_ISTREAM(3, HDA_ISS_NO, HDA_OSS_NO)
242 
243 	HDAC_OSTREAM(0, HDA_ISS_NO, HDA_OSS_NO)
244 	HDAC_OSTREAM(1, HDA_ISS_NO, HDA_OSS_NO)
245 	HDAC_OSTREAM(2, HDA_ISS_NO, HDA_OSS_NO)
246 	HDAC_OSTREAM(3, HDA_ISS_NO, HDA_OSS_NO)
247 };
248 
249 static const uint16_t hda_corb_sizes[] = {
250 	[HDAC_CORBSIZE_CORBSIZE_2]	= 2,
251 	[HDAC_CORBSIZE_CORBSIZE_16]	= 16,
252 	[HDAC_CORBSIZE_CORBSIZE_256]	= 256,
253 	[HDAC_CORBSIZE_CORBSIZE_MASK]	= 0,
254 };
255 
256 static const uint16_t hda_rirb_sizes[] = {
257 	[HDAC_RIRBSIZE_RIRBSIZE_2]	= 2,
258 	[HDAC_RIRBSIZE_RIRBSIZE_16]	= 16,
259 	[HDAC_RIRBSIZE_RIRBSIZE_256]	= 256,
260 	[HDAC_RIRBSIZE_RIRBSIZE_MASK]	= 0,
261 };
262 
263 static const struct hda_ops hops = {
264 	.signal		= hda_signal_state_change,
265 	.response	= hda_response,
266 	.transfer	= hda_transfer,
267 };
268 
269 static const struct pci_devemu pci_de_hda = {
270 	.pe_emu		= "hda",
271 	.pe_init	= pci_hda_init,
272 	.pe_barwrite	= pci_hda_write,
273 	.pe_barread	= pci_hda_read
274 };
275 PCI_EMUL_SET(pci_de_hda);
276 
277 SET_DECLARE(hda_codec_class_set, struct hda_codec_class);
278 
279 #if DEBUG_HDA == 1
280 FILE *dbg;
281 #endif
282 
283 /*
284  * HDA module function definitions
285  */
286 
287 static inline void
hda_set_reg_by_offset(struct hda_softc * sc,uint32_t offset,uint32_t value)288 hda_set_reg_by_offset(struct hda_softc *sc, uint32_t offset, uint32_t value)
289 {
290 	assert(offset < HDA_LAST_OFFSET);
291 	sc->regs[offset] = value;
292 }
293 
294 static inline uint32_t
hda_get_reg_by_offset(struct hda_softc * sc,uint32_t offset)295 hda_get_reg_by_offset(struct hda_softc *sc, uint32_t offset)
296 {
297 	assert(offset < HDA_LAST_OFFSET);
298 	return sc->regs[offset];
299 }
300 
301 static inline void
hda_set_field_by_offset(struct hda_softc * sc,uint32_t offset,uint32_t mask,uint32_t value)302 hda_set_field_by_offset(struct hda_softc *sc, uint32_t offset,
303     uint32_t mask, uint32_t value)
304 {
305 	uint32_t reg_value = 0;
306 
307 	reg_value = hda_get_reg_by_offset(sc, offset);
308 
309 	reg_value &= ~mask;
310 	reg_value |= (value & mask);
311 
312 	hda_set_reg_by_offset(sc, offset, reg_value);
313 }
314 
315 static struct hda_softc *
hda_init(nvlist_t * nvl)316 hda_init(nvlist_t *nvl)
317 {
318 	struct hda_softc *sc = NULL;
319 	struct hda_codec_class *codec = NULL;
320 	const char *value;
321 	char *play;
322 	char *rec;
323 	int err;
324 
325 #if DEBUG_HDA == 1
326 	dbg = fopen(DEBUG_HDA_FILE, "w+");
327 #endif
328 
329 	sc = calloc(1, sizeof(*sc));
330 	if (!sc)
331 		return (NULL);
332 
333 	hda_reset_regs(sc);
334 
335 	/*
336 	 * TODO search all configured codecs
337 	 * For now we play with one single codec
338 	 */
339 	codec = hda_find_codec_class("hda_codec");
340 	if (codec) {
341 		value = get_config_value_node(nvl, "play");
342 		if (value == NULL)
343 			play = NULL;
344 		else
345 			play = strdup(value);
346 		value = get_config_value_node(nvl, "rec");
347 		if (value == NULL)
348 			rec = NULL;
349 		else
350 			rec = strdup(value);
351 		DPRINTF("play: %s rec: %s", play, rec);
352 		if (play != NULL || rec != NULL) {
353 			err = hda_codec_constructor(sc, codec, play, rec);
354 			assert(!err);
355 		}
356 		free(play);
357 		free(rec);
358 	}
359 
360 	return (sc);
361 }
362 
363 static void
hda_update_intr(struct hda_softc * sc)364 hda_update_intr(struct hda_softc *sc)
365 {
366 	struct pci_devinst *pi = sc->pci_dev;
367 	uint32_t intctl = hda_get_reg_by_offset(sc, HDAC_INTCTL);
368 	uint32_t intsts = 0;
369 	uint32_t sdsts = 0;
370 	uint32_t rirbsts = 0;
371 	uint32_t wakeen = 0;
372 	uint32_t statests = 0;
373 	uint32_t off = 0;
374 	int i;
375 
376 	/* update the CIS bits */
377 	rirbsts = hda_get_reg_by_offset(sc, HDAC_RIRBSTS);
378 	if (rirbsts & (HDAC_RIRBSTS_RINTFL | HDAC_RIRBSTS_RIRBOIS))
379 		intsts |= HDAC_INTSTS_CIS;
380 
381 	wakeen = hda_get_reg_by_offset(sc, HDAC_WAKEEN);
382 	statests = hda_get_reg_by_offset(sc, HDAC_STATESTS);
383 	if (statests & wakeen)
384 		intsts |= HDAC_INTSTS_CIS;
385 
386 	/* update the SIS bits */
387 	for (i = 0; i < HDA_IOSS_NO; i++) {
388 		off = hda_get_offset_stream(i);
389 		sdsts = hda_get_reg_by_offset(sc, off + HDAC_SDSTS);
390 		if (sdsts & HDAC_SDSTS_BCIS)
391 			intsts |= (1 << i);
392 	}
393 
394 	/* update the GIS bit */
395 	if (intsts)
396 		intsts |= HDAC_INTSTS_GIS;
397 
398 	hda_set_reg_by_offset(sc, HDAC_INTSTS, intsts);
399 
400 	if ((intctl & HDAC_INTCTL_GIE) && ((intsts &			\
401 		~HDAC_INTSTS_GIS) & intctl)) {
402 		if (!sc->lintr) {
403 			pci_lintr_assert(pi);
404 			sc->lintr = 1;
405 		}
406 	} else {
407 		if (sc->lintr) {
408 			pci_lintr_deassert(pi);
409 			sc->lintr = 0;
410 		}
411 	}
412 }
413 
414 static void
hda_response_interrupt(struct hda_softc * sc)415 hda_response_interrupt(struct hda_softc *sc)
416 {
417 	uint8_t rirbctl = hda_get_reg_by_offset(sc, HDAC_RIRBCTL);
418 
419 	if ((rirbctl & HDAC_RIRBCTL_RINTCTL) && sc->rirb_cnt) {
420 		sc->rirb_cnt = 0;
421 		hda_set_field_by_offset(sc, HDAC_RIRBSTS, HDAC_RIRBSTS_RINTFL,
422 				HDAC_RIRBSTS_RINTFL);
423 		hda_update_intr(sc);
424 	}
425 }
426 
427 static int
hda_codec_constructor(struct hda_softc * sc,struct hda_codec_class * codec,const char * play,const char * rec)428 hda_codec_constructor(struct hda_softc *sc, struct hda_codec_class *codec,
429     const char *play, const char *rec)
430 {
431 	struct hda_codec_inst *hci = NULL;
432 
433 	if (sc->codecs_no >= HDA_CODEC_MAX)
434 		return (-1);
435 
436 	hci = calloc(1, sizeof(struct hda_codec_inst));
437 	if (!hci)
438 		return (-1);
439 
440 	hci->hda = sc;
441 	hci->hops = &hops;
442 	hci->cad = sc->codecs_no;
443 	hci->codec = codec;
444 
445 	sc->codecs[sc->codecs_no++] = hci;
446 
447 	if (!codec->init) {
448 		DPRINTF("This codec does not implement the init function");
449 		return (-1);
450 	}
451 
452 	return (codec->init(hci, play, rec));
453 }
454 
455 static struct hda_codec_class *
hda_find_codec_class(const char * name)456 hda_find_codec_class(const char *name)
457 {
458 	struct hda_codec_class **pdpp = NULL, *pdp = NULL;
459 
460 	SET_FOREACH(pdpp, hda_codec_class_set) {
461 		pdp = *pdpp;
462 		if (!strcmp(pdp->name, name)) {
463 			return (pdp);
464 		}
465 	}
466 
467 	return (NULL);
468 }
469 
470 static int
hda_send_command(struct hda_softc * sc,uint32_t verb)471 hda_send_command(struct hda_softc *sc, uint32_t verb)
472 {
473 	struct hda_codec_inst *hci = NULL;
474 	struct hda_codec_class *codec = NULL;
475 	uint8_t cad = (verb >> HDA_CMD_CAD_SHIFT) & 0x0f;
476 
477 	if (cad >= sc->codecs_no)
478 		return (-1);
479 
480 	DPRINTF("cad: 0x%x verb: 0x%x", cad, verb);
481 
482 	hci = sc->codecs[cad];
483 	assert(hci);
484 
485 	codec = hci->codec;
486 	assert(codec);
487 
488 	if (!codec->command) {
489 		DPRINTF("This codec does not implement the command function");
490 		return (-1);
491 	}
492 
493 	return (codec->command(hci, verb));
494 }
495 
496 static int
hda_notify_codecs(struct hda_softc * sc,uint8_t run,uint8_t stream,uint8_t dir)497 hda_notify_codecs(struct hda_softc *sc, uint8_t run, uint8_t stream,
498     uint8_t dir)
499 {
500 	struct hda_codec_inst *hci = NULL;
501 	struct hda_codec_class *codec = NULL;
502 	int err;
503 	int i;
504 
505 	/* Notify each codec */
506 	for (i = 0; i < sc->codecs_no; i++) {
507 		hci = sc->codecs[i];
508 		assert(hci);
509 
510 		codec = hci->codec;
511 		assert(codec);
512 
513 		if (codec->notify) {
514 			err = codec->notify(hci, run, stream, dir);
515 			if (!err)
516 				break;
517 		}
518 	}
519 
520 	return (i == sc->codecs_no ? (-1) : 0);
521 }
522 
523 static void
hda_reset(struct hda_softc * sc)524 hda_reset(struct hda_softc *sc)
525 {
526 	int i;
527 	struct hda_codec_inst *hci = NULL;
528 	struct hda_codec_class *codec = NULL;
529 
530 	hda_reset_regs(sc);
531 
532 	/* Reset each codec */
533 	for (i = 0; i < sc->codecs_no; i++) {
534 		hci = sc->codecs[i];
535 		assert(hci);
536 
537 		codec = hci->codec;
538 		assert(codec);
539 
540 		if (codec->reset)
541 			codec->reset(hci);
542 	}
543 
544 	sc->wall_clock_start = hda_get_clock_ns();
545 }
546 
547 static void
hda_reset_regs(struct hda_softc * sc)548 hda_reset_regs(struct hda_softc *sc)
549 {
550 	uint32_t off = 0;
551 	uint8_t i;
552 
553 	DPRINTF("Reset the HDA controller registers ...");
554 
555 	memset(sc->regs, 0, sizeof(sc->regs));
556 
557 	hda_set_reg_by_offset(sc, HDAC_GCAP,
558 			HDAC_GCAP_64OK |
559 			(HDA_ISS_NO << HDAC_GCAP_ISS_SHIFT) |
560 			(HDA_OSS_NO << HDAC_GCAP_OSS_SHIFT));
561 	hda_set_reg_by_offset(sc, HDAC_VMAJ, 0x01);
562 	hda_set_reg_by_offset(sc, HDAC_OUTPAY, 0x3c);
563 	hda_set_reg_by_offset(sc, HDAC_INPAY, 0x1d);
564 	hda_set_reg_by_offset(sc, HDAC_CORBSIZE,
565 	    HDAC_CORBSIZE_CORBSZCAP_256 | HDAC_CORBSIZE_CORBSIZE_256);
566 	hda_set_reg_by_offset(sc, HDAC_RIRBSIZE,
567 	    HDAC_RIRBSIZE_RIRBSZCAP_256 | HDAC_RIRBSIZE_RIRBSIZE_256);
568 
569 	for (i = 0; i < HDA_IOSS_NO; i++) {
570 		off = hda_get_offset_stream(i);
571 		hda_set_reg_by_offset(sc, off + HDAC_SDFIFOS, HDA_FIFO_SIZE);
572 	}
573 }
574 
575 static void
hda_stream_reset(struct hda_softc * sc,uint8_t stream_ind)576 hda_stream_reset(struct hda_softc *sc, uint8_t stream_ind)
577 {
578 	struct hda_stream_desc *st = &sc->streams[stream_ind];
579 	uint32_t off = hda_get_offset_stream(stream_ind);
580 
581 	DPRINTF("Reset the HDA stream: 0x%x", stream_ind);
582 
583 	/* Reset the Stream Descriptor registers */
584 	memset(sc->regs + HDA_STREAM_REGS_BASE + off, 0, HDA_STREAM_REGS_LEN);
585 
586 	/* Reset the Stream Descriptor */
587 	memset(st, 0, sizeof(*st));
588 
589 	hda_set_field_by_offset(sc, off + HDAC_SDSTS,
590 	    HDAC_SDSTS_FIFORDY, HDAC_SDSTS_FIFORDY);
591 	hda_set_field_by_offset(sc, off + HDAC_SDCTL0,
592 	    HDAC_SDCTL_SRST, HDAC_SDCTL_SRST);
593 }
594 
595 static int
hda_stream_start(struct hda_softc * sc,uint8_t stream_ind)596 hda_stream_start(struct hda_softc *sc, uint8_t stream_ind)
597 {
598 	struct hda_stream_desc *st = &sc->streams[stream_ind];
599 	struct hda_bdle_desc *bdle_desc = NULL;
600 	struct hda_bdle *bdle = NULL;
601 	uint32_t lvi = 0;
602 	uint32_t bdl_cnt = 0;
603 	uint64_t bdpl = 0;
604 	uint64_t bdpu = 0;
605 	uint64_t bdl_paddr = 0;
606 	void *bdl_vaddr = NULL;
607 	uint32_t bdle_sz = 0;
608 	uint64_t bdle_addrl = 0;
609 	uint64_t bdle_addrh = 0;
610 	uint64_t bdle_paddr = 0;
611 	void *bdle_vaddr = NULL;
612 	uint32_t off = hda_get_offset_stream(stream_ind);
613 	uint32_t sdctl = 0;
614 	uint8_t strm = 0;
615 	uint8_t dir = 0;
616 
617 	assert(!st->run);
618 
619 	lvi = hda_get_reg_by_offset(sc, off + HDAC_SDLVI);
620 	bdpl = hda_get_reg_by_offset(sc, off + HDAC_SDBDPL);
621 	bdpu = hda_get_reg_by_offset(sc, off + HDAC_SDBDPU);
622 
623 	bdl_cnt = lvi + 1;
624 	assert(bdl_cnt <= HDA_BDL_MAX_LEN);
625 
626 	bdl_paddr = bdpl | (bdpu << 32);
627 	bdl_vaddr = hda_dma_get_vaddr(sc, bdl_paddr,
628 	    HDA_BDL_ENTRY_LEN * bdl_cnt);
629 	if (!bdl_vaddr) {
630 		DPRINTF("Fail to get the guest virtual address");
631 		return (-1);
632 	}
633 
634 	DPRINTF("stream: 0x%x bdl_cnt: 0x%x bdl_paddr: 0x%lx",
635 	    stream_ind, bdl_cnt, bdl_paddr);
636 
637 	st->bdl_cnt = bdl_cnt;
638 
639 	bdle = (struct hda_bdle *)bdl_vaddr;
640 	for (size_t i = 0; i < bdl_cnt; i++, bdle++) {
641 		bdle_sz = bdle->len;
642 		assert(!(bdle_sz % HDA_DMA_ACCESS_LEN));
643 
644 		bdle_addrl = bdle->addrl;
645 		bdle_addrh = bdle->addrh;
646 
647 		bdle_paddr = bdle_addrl | (bdle_addrh << 32);
648 		bdle_vaddr = hda_dma_get_vaddr(sc, bdle_paddr, bdle_sz);
649 		if (!bdle_vaddr) {
650 			DPRINTF("Fail to get the guest virtual address");
651 			return (-1);
652 		}
653 
654 		bdle_desc = &st->bdl[i];
655 		bdle_desc->addr = bdle_vaddr;
656 		bdle_desc->len = bdle_sz;
657 		bdle_desc->ioc = bdle->ioc;
658 
659 		DPRINTF("bdle: 0x%zx bdle_sz: 0x%x", i, bdle_sz);
660 	}
661 
662 	sdctl = hda_get_reg_by_offset(sc, off + HDAC_SDCTL0);
663 	strm = (sdctl >> 20) & 0x0f;
664 	dir = stream_ind >= HDA_ISS_NO;
665 
666 	DPRINTF("strm: 0x%x, dir: 0x%x", strm, dir);
667 
668 	sc->stream_map[dir][strm] = stream_ind;
669 	st->stream = strm;
670 	st->dir = dir;
671 	st->bp = 0;
672 	st->be = 0;
673 
674 	hda_set_pib(sc, stream_ind, 0);
675 
676 	st->run = 1;
677 
678 	hda_notify_codecs(sc, 1, strm, dir);
679 
680 	return (0);
681 }
682 
683 static int
hda_stream_stop(struct hda_softc * sc,uint8_t stream_ind)684 hda_stream_stop(struct hda_softc *sc, uint8_t stream_ind)
685 {
686 	struct hda_stream_desc *st = &sc->streams[stream_ind];
687 	uint8_t strm = st->stream;
688 	uint8_t dir = st->dir;
689 
690 	DPRINTF("stream: 0x%x, strm: 0x%x, dir: 0x%x", stream_ind, strm, dir);
691 
692 	st->run = 0;
693 
694 	hda_notify_codecs(sc, 0, strm, dir);
695 
696 	return (0);
697 }
698 
699 static uint32_t
hda_read(struct hda_softc * sc,uint32_t offset)700 hda_read(struct hda_softc *sc, uint32_t offset)
701 {
702 	if (offset == HDAC_WALCLK)
703 		return (24 * (hda_get_clock_ns() -			\
704 			sc->wall_clock_start) / 1000);
705 
706 	return (hda_get_reg_by_offset(sc, offset));
707 }
708 
709 static int
hda_write(struct hda_softc * sc,uint32_t offset,uint8_t size,uint32_t value)710 hda_write(struct hda_softc *sc, uint32_t offset, uint8_t size, uint32_t value)
711 {
712 	uint32_t old = hda_get_reg_by_offset(sc, offset);
713 	uint32_t masks[] = {0x00000000, 0x000000ff, 0x0000ffff,
714 			0x00ffffff, 0xffffffff};
715 	hda_set_reg_handler set_reg_handler = NULL;
716 
717 	if (offset < nitems(hda_set_reg_table))
718 		set_reg_handler = hda_set_reg_table[offset];
719 
720 	hda_set_field_by_offset(sc, offset, masks[size], value);
721 
722 	if (set_reg_handler)
723 		set_reg_handler(sc, offset, old);
724 
725 	return (0);
726 }
727 
728 #if DEBUG_HDA == 1
729 static inline void
hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl * p)730 hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p)
731 {
732 	DPRINTF("%s size: %d", p->name, p->size);
733 	DPRINTF("%s dma_vaddr: %p", p->name, p->dma_vaddr);
734 	DPRINTF("%s wp: 0x%x", p->name, p->wp);
735 	DPRINTF("%s rp: 0x%x", p->name, p->rp);
736 }
737 #else
738 static inline void
hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl * p __unused)739 hda_print_cmd_ctl_data(struct hda_codec_cmd_ctl *p __unused) {}
740 #endif
741 
742 static int
hda_corb_start(struct hda_softc * sc)743 hda_corb_start(struct hda_softc *sc)
744 {
745 	struct hda_codec_cmd_ctl *corb = &sc->corb;
746 	uint8_t corbsize = 0;
747 	uint64_t corblbase = 0;
748 	uint64_t corbubase = 0;
749 	uint64_t corbpaddr = 0;
750 
751 	corb->name = "CORB";
752 
753 	corbsize = hda_get_reg_by_offset(sc, HDAC_CORBSIZE) &		\
754 		   HDAC_CORBSIZE_CORBSIZE_MASK;
755 	corb->size = hda_corb_sizes[corbsize];
756 
757 	if (!corb->size) {
758 		DPRINTF("Invalid corb size");
759 		return (-1);
760 	}
761 
762 	corblbase = hda_get_reg_by_offset(sc, HDAC_CORBLBASE);
763 	corbubase = hda_get_reg_by_offset(sc, HDAC_CORBUBASE);
764 
765 	corbpaddr = corblbase | (corbubase << 32);
766 	DPRINTF("CORB dma_paddr: %p", (void *)corbpaddr);
767 
768 	corb->dma_vaddr = hda_dma_get_vaddr(sc, corbpaddr,
769 			HDA_CORB_ENTRY_LEN * corb->size);
770 	if (!corb->dma_vaddr) {
771 		DPRINTF("Fail to get the guest virtual address");
772 		return (-1);
773 	}
774 
775 	corb->wp = hda_get_reg_by_offset(sc, HDAC_CORBWP);
776 	corb->rp = hda_get_reg_by_offset(sc, HDAC_CORBRP);
777 
778 	corb->run = 1;
779 
780 	hda_print_cmd_ctl_data(corb);
781 
782 	return (0);
783 }
784 
785 static int
hda_corb_run(struct hda_softc * sc)786 hda_corb_run(struct hda_softc *sc)
787 {
788 	struct hda_codec_cmd_ctl *corb = &sc->corb;
789 	uint32_t verb = 0;
790 	int err;
791 
792 	corb->wp = hda_get_reg_by_offset(sc, HDAC_CORBWP);
793 
794 	while (corb->rp != corb->wp && corb->run) {
795 		corb->rp++;
796 		corb->rp %= corb->size;
797 
798 		verb = hda_dma_ld_dword((uint8_t *)corb->dma_vaddr +
799 		    HDA_CORB_ENTRY_LEN * corb->rp);
800 
801 		err = hda_send_command(sc, verb);
802 		assert(!err);
803 	}
804 
805 	hda_set_reg_by_offset(sc, HDAC_CORBRP, corb->rp);
806 
807 	if (corb->run)
808 		hda_response_interrupt(sc);
809 
810 	return (0);
811 }
812 
813 static int
hda_rirb_start(struct hda_softc * sc)814 hda_rirb_start(struct hda_softc *sc)
815 {
816 	struct hda_codec_cmd_ctl *rirb = &sc->rirb;
817 	uint8_t rirbsize = 0;
818 	uint64_t rirblbase = 0;
819 	uint64_t rirbubase = 0;
820 	uint64_t rirbpaddr = 0;
821 
822 	rirb->name = "RIRB";
823 
824 	rirbsize = hda_get_reg_by_offset(sc, HDAC_RIRBSIZE) &		\
825 		   HDAC_RIRBSIZE_RIRBSIZE_MASK;
826 	rirb->size = hda_rirb_sizes[rirbsize];
827 
828 	if (!rirb->size) {
829 		DPRINTF("Invalid rirb size");
830 		return (-1);
831 	}
832 
833 	rirblbase = hda_get_reg_by_offset(sc, HDAC_RIRBLBASE);
834 	rirbubase = hda_get_reg_by_offset(sc, HDAC_RIRBUBASE);
835 
836 	rirbpaddr = rirblbase | (rirbubase << 32);
837 	DPRINTF("RIRB dma_paddr: %p", (void *)rirbpaddr);
838 
839 	rirb->dma_vaddr = hda_dma_get_vaddr(sc, rirbpaddr,
840 			HDA_RIRB_ENTRY_LEN * rirb->size);
841 	if (!rirb->dma_vaddr) {
842 		DPRINTF("Fail to get the guest virtual address");
843 		return (-1);
844 	}
845 
846 	rirb->wp = hda_get_reg_by_offset(sc, HDAC_RIRBWP);
847 	rirb->rp = 0x0000;
848 
849 	rirb->run = 1;
850 
851 	hda_print_cmd_ctl_data(rirb);
852 
853 	return (0);
854 }
855 
856 static void *
hda_dma_get_vaddr(struct hda_softc * sc,uint64_t dma_paddr,size_t len)857 hda_dma_get_vaddr(struct hda_softc *sc, uint64_t dma_paddr, size_t len)
858 {
859 	struct pci_devinst *pi = sc->pci_dev;
860 
861 	assert(pi);
862 
863 	return (paddr_guest2host(pi->pi_vmctx, (uintptr_t)dma_paddr, len));
864 }
865 
866 static void
hda_dma_st_dword(void * dma_vaddr,uint32_t data)867 hda_dma_st_dword(void *dma_vaddr, uint32_t data)
868 {
869 	*(uint32_t*)dma_vaddr = data;
870 }
871 
872 static uint32_t
hda_dma_ld_dword(void * dma_vaddr)873 hda_dma_ld_dword(void *dma_vaddr)
874 {
875 	return (*(uint32_t*)dma_vaddr);
876 }
877 
878 static inline uint8_t
hda_get_stream_by_offsets(uint32_t offset,uint8_t reg_offset)879 hda_get_stream_by_offsets(uint32_t offset, uint8_t reg_offset)
880 {
881 	uint8_t stream_ind = (offset - reg_offset) >> 5;
882 
883 	assert(stream_ind < HDA_IOSS_NO);
884 
885 	return (stream_ind);
886 }
887 
888 static inline uint32_t
hda_get_offset_stream(uint8_t stream_ind)889 hda_get_offset_stream(uint8_t stream_ind)
890 {
891 	return (stream_ind << 5);
892 }
893 
894 static void
hda_set_gctl(struct hda_softc * sc,uint32_t offset,uint32_t old __unused)895 hda_set_gctl(struct hda_softc *sc, uint32_t offset, uint32_t old __unused)
896 {
897 	uint32_t value = hda_get_reg_by_offset(sc, offset);
898 
899 	if (!(value & HDAC_GCTL_CRST)) {
900 		hda_reset(sc);
901 	}
902 }
903 
904 static void
hda_set_statests(struct hda_softc * sc,uint32_t offset,uint32_t old)905 hda_set_statests(struct hda_softc *sc, uint32_t offset, uint32_t old)
906 {
907 	uint32_t value = hda_get_reg_by_offset(sc, offset);
908 
909 	hda_set_reg_by_offset(sc, offset, old);
910 
911 	/* clear the corresponding bits written by the software (guest) */
912 	hda_set_field_by_offset(sc, offset, value & HDA_STATESTS_IRQ_MASK, 0);
913 
914 	hda_update_intr(sc);
915 }
916 
917 static void
hda_set_corbwp(struct hda_softc * sc,uint32_t offset __unused,uint32_t old __unused)918 hda_set_corbwp(struct hda_softc *sc, uint32_t offset __unused,
919     uint32_t old __unused)
920 {
921 	hda_corb_run(sc);
922 }
923 
924 static void
hda_set_corbctl(struct hda_softc * sc,uint32_t offset,uint32_t old)925 hda_set_corbctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
926 {
927 	uint32_t value = hda_get_reg_by_offset(sc, offset);
928 	int err;
929 	struct hda_codec_cmd_ctl *corb = NULL;
930 
931 	if (value & HDAC_CORBCTL_CORBRUN) {
932 		if (!(old & HDAC_CORBCTL_CORBRUN)) {
933 			err = hda_corb_start(sc);
934 			assert(!err);
935 		}
936 	} else {
937 		corb = &sc->corb;
938 		memset(corb, 0, sizeof(*corb));
939 	}
940 
941 	hda_corb_run(sc);
942 }
943 
944 static void
hda_set_rirbctl(struct hda_softc * sc,uint32_t offset,uint32_t old __unused)945 hda_set_rirbctl(struct hda_softc *sc, uint32_t offset, uint32_t old __unused)
946 {
947 	uint32_t value = hda_get_reg_by_offset(sc, offset);
948 	int err;
949 	struct hda_codec_cmd_ctl *rirb = NULL;
950 
951 	if (value & HDAC_RIRBCTL_RIRBDMAEN) {
952 		err = hda_rirb_start(sc);
953 		assert(!err);
954 	} else {
955 		rirb = &sc->rirb;
956 		memset(rirb, 0, sizeof(*rirb));
957 	}
958 }
959 
960 static void
hda_set_rirbsts(struct hda_softc * sc,uint32_t offset,uint32_t old)961 hda_set_rirbsts(struct hda_softc *sc, uint32_t offset, uint32_t old)
962 {
963 	uint32_t value = hda_get_reg_by_offset(sc, offset);
964 
965 	hda_set_reg_by_offset(sc, offset, old);
966 
967 	/* clear the corresponding bits written by the software (guest) */
968 	hda_set_field_by_offset(sc, offset, value & HDA_RIRBSTS_IRQ_MASK, 0);
969 
970 	hda_update_intr(sc);
971 }
972 
973 static void
hda_set_dpiblbase(struct hda_softc * sc,uint32_t offset,uint32_t old)974 hda_set_dpiblbase(struct hda_softc *sc, uint32_t offset, uint32_t old)
975 {
976 	uint32_t value = hda_get_reg_by_offset(sc, offset);
977 	uint64_t dpiblbase = 0;
978 	uint64_t dpibubase = 0;
979 	uint64_t dpibpaddr = 0;
980 
981 	if ((value & HDAC_DPLBASE_DPLBASE_DMAPBE) != (old &		\
982 				HDAC_DPLBASE_DPLBASE_DMAPBE)) {
983 		if (value & HDAC_DPLBASE_DPLBASE_DMAPBE) {
984 			dpiblbase = value & HDAC_DPLBASE_DPLBASE_MASK;
985 			dpibubase = hda_get_reg_by_offset(sc, HDAC_DPIBUBASE);
986 
987 			dpibpaddr = dpiblbase | (dpibubase << 32);
988 			DPRINTF("DMA Position In Buffer dma_paddr: %p",
989 			    (void *)dpibpaddr);
990 
991 			sc->dma_pib_vaddr = hda_dma_get_vaddr(sc, dpibpaddr,
992 					HDA_DMA_PIB_ENTRY_LEN * HDA_IOSS_NO);
993 			if (!sc->dma_pib_vaddr) {
994 				DPRINTF("Fail to get the guest \
995 					 virtual address");
996 				assert(0);
997 			}
998 		} else {
999 			DPRINTF("DMA Position In Buffer Reset");
1000 			sc->dma_pib_vaddr = NULL;
1001 		}
1002 	}
1003 }
1004 
1005 static void
hda_set_sdctl(struct hda_softc * sc,uint32_t offset,uint32_t old)1006 hda_set_sdctl(struct hda_softc *sc, uint32_t offset, uint32_t old)
1007 {
1008 	uint8_t stream_ind = hda_get_stream_by_offsets(offset, HDAC_SDCTL0);
1009 	uint32_t value = hda_get_reg_by_offset(sc, offset);
1010 	int err;
1011 
1012 	DPRINTF("stream_ind: 0x%x old: 0x%x value: 0x%x",
1013 	    stream_ind, old, value);
1014 
1015 	if (value & HDAC_SDCTL_SRST) {
1016 		hda_stream_reset(sc, stream_ind);
1017 	}
1018 
1019 	if ((value & HDAC_SDCTL_RUN) != (old & HDAC_SDCTL_RUN)) {
1020 		if (value & HDAC_SDCTL_RUN) {
1021 			err = hda_stream_start(sc, stream_ind);
1022 			assert(!err);
1023 		} else {
1024 			err = hda_stream_stop(sc, stream_ind);
1025 			assert(!err);
1026 		}
1027 	}
1028 }
1029 
1030 static void
hda_set_sdctl2(struct hda_softc * sc,uint32_t offset,uint32_t old __unused)1031 hda_set_sdctl2(struct hda_softc *sc, uint32_t offset, uint32_t old __unused)
1032 {
1033 	uint32_t value = hda_get_reg_by_offset(sc, offset);
1034 
1035 	hda_set_field_by_offset(sc, offset - 2, 0x00ff0000, value << 16);
1036 }
1037 
1038 static void
hda_set_sdsts(struct hda_softc * sc,uint32_t offset,uint32_t old)1039 hda_set_sdsts(struct hda_softc *sc, uint32_t offset, uint32_t old)
1040 {
1041 	uint32_t value = hda_get_reg_by_offset(sc, offset);
1042 
1043 	hda_set_reg_by_offset(sc, offset, old);
1044 
1045 	/* clear the corresponding bits written by the software (guest) */
1046 	hda_set_field_by_offset(sc, offset, value & HDA_SDSTS_IRQ_MASK, 0);
1047 
1048 	hda_update_intr(sc);
1049 }
1050 
1051 static int
hda_signal_state_change(struct hda_codec_inst * hci)1052 hda_signal_state_change(struct hda_codec_inst *hci)
1053 {
1054 	struct hda_softc *sc = NULL;
1055 	uint32_t sdiwake = 0;
1056 
1057 	assert(hci);
1058 	assert(hci->hda);
1059 
1060 	DPRINTF("cad: 0x%x", hci->cad);
1061 
1062 	sc = hci->hda;
1063 	sdiwake = 1 << hci->cad;
1064 
1065 	hda_set_field_by_offset(sc, HDAC_STATESTS, sdiwake, sdiwake);
1066 	hda_update_intr(sc);
1067 
1068 	return (0);
1069 }
1070 
1071 static int
hda_response(struct hda_codec_inst * hci,uint32_t response,uint8_t unsol)1072 hda_response(struct hda_codec_inst *hci, uint32_t response, uint8_t unsol)
1073 {
1074 	struct hda_softc *sc = NULL;
1075 	struct hda_codec_cmd_ctl *rirb = NULL;
1076 	uint32_t response_ex = 0;
1077 	uint8_t rintcnt = 0;
1078 
1079 	assert(hci);
1080 	assert(hci->cad <= HDA_CODEC_MAX);
1081 
1082 	response_ex = hci->cad | unsol;
1083 
1084 	sc = hci->hda;
1085 	assert(sc);
1086 
1087 	rirb = &sc->rirb;
1088 
1089 	if (rirb->run) {
1090 		rirb->wp++;
1091 		rirb->wp %= rirb->size;
1092 
1093 		hda_dma_st_dword((uint8_t *)rirb->dma_vaddr +
1094 		    HDA_RIRB_ENTRY_LEN * rirb->wp, response);
1095 		hda_dma_st_dword((uint8_t *)rirb->dma_vaddr +
1096 		    HDA_RIRB_ENTRY_LEN * rirb->wp + 0x04, response_ex);
1097 
1098 		hda_set_reg_by_offset(sc, HDAC_RIRBWP, rirb->wp);
1099 
1100 		sc->rirb_cnt++;
1101 	}
1102 
1103 	rintcnt = hda_get_reg_by_offset(sc, HDAC_RINTCNT);
1104 	if (sc->rirb_cnt == rintcnt)
1105 		hda_response_interrupt(sc);
1106 
1107 	return (0);
1108 }
1109 
1110 static int
hda_transfer(struct hda_codec_inst * hci,uint8_t stream,uint8_t dir,uint8_t * buf,size_t count)1111 hda_transfer(struct hda_codec_inst *hci, uint8_t stream, uint8_t dir,
1112     uint8_t *buf, size_t count)
1113 {
1114 	struct hda_softc *sc = NULL;
1115 	struct hda_stream_desc *st = NULL;
1116 	struct hda_bdle_desc *bdl = NULL;
1117 	struct hda_bdle_desc *bdle_desc = NULL;
1118 	uint8_t stream_ind = 0;
1119 	uint32_t lpib = 0;
1120 	uint32_t off = 0;
1121 	size_t left = 0;
1122 	uint8_t irq = 0;
1123 
1124 	assert(hci);
1125 	assert(hci->hda);
1126 	assert(buf);
1127 	assert(!(count % HDA_DMA_ACCESS_LEN));
1128 
1129 	if (!stream) {
1130 		DPRINTF("Invalid stream");
1131 		return (-1);
1132 	}
1133 
1134 	sc = hci->hda;
1135 
1136 	assert(stream < HDA_STREAM_TAGS_CNT);
1137 	stream_ind = sc->stream_map[dir][stream];
1138 
1139 	if (!dir)
1140 		assert(stream_ind < HDA_ISS_NO);
1141 	else
1142 		assert(stream_ind >= HDA_ISS_NO && stream_ind < HDA_IOSS_NO);
1143 
1144 	st = &sc->streams[stream_ind];
1145 	if (!st->run) {
1146 		DPRINTF("Stream 0x%x stopped", stream);
1147 		return (-1);
1148 	}
1149 
1150 	assert(st->stream == stream);
1151 
1152 	off = hda_get_offset_stream(stream_ind);
1153 
1154 	lpib = hda_get_reg_by_offset(sc, off + HDAC_SDLPIB);
1155 
1156 	bdl = st->bdl;
1157 
1158 	assert(st->be < st->bdl_cnt);
1159 	assert(st->bp < bdl[st->be].len);
1160 
1161 	left = count;
1162 	while (left) {
1163 		bdle_desc = &bdl[st->be];
1164 
1165 		if (dir)
1166 			*(uint32_t *)buf = hda_dma_ld_dword(
1167 			    (uint8_t *)bdle_desc->addr + st->bp);
1168 		else
1169 			hda_dma_st_dword((uint8_t *)bdle_desc->addr +
1170 			    st->bp, *(uint32_t *)buf);
1171 
1172 		buf += HDA_DMA_ACCESS_LEN;
1173 		st->bp += HDA_DMA_ACCESS_LEN;
1174 		lpib += HDA_DMA_ACCESS_LEN;
1175 		left -= HDA_DMA_ACCESS_LEN;
1176 
1177 		if (st->bp == bdle_desc->len) {
1178 			st->bp = 0;
1179 			if (bdle_desc->ioc)
1180 				irq = 1;
1181 			st->be++;
1182 			if (st->be == st->bdl_cnt) {
1183 				st->be = 0;
1184 				lpib = 0;
1185 			}
1186 			bdle_desc = &bdl[st->be];
1187 		}
1188 	}
1189 
1190 	hda_set_pib(sc, stream_ind, lpib);
1191 
1192 	if (irq) {
1193 		hda_set_field_by_offset(sc, off + HDAC_SDSTS,
1194 				HDAC_SDSTS_BCIS, HDAC_SDSTS_BCIS);
1195 		hda_update_intr(sc);
1196 	}
1197 
1198 	return (0);
1199 }
1200 
1201 static void
hda_set_pib(struct hda_softc * sc,uint8_t stream_ind,uint32_t pib)1202 hda_set_pib(struct hda_softc *sc, uint8_t stream_ind, uint32_t pib)
1203 {
1204 	uint32_t off = hda_get_offset_stream(stream_ind);
1205 
1206 	hda_set_reg_by_offset(sc, off + HDAC_SDLPIB, pib);
1207 	/* LPIB Alias */
1208 	hda_set_reg_by_offset(sc, 0x2000 + off + HDAC_SDLPIB, pib);
1209 	if (sc->dma_pib_vaddr)
1210 		*(uint32_t *)((uint8_t *)sc->dma_pib_vaddr + stream_ind *
1211 		    HDA_DMA_PIB_ENTRY_LEN) = pib;
1212 }
1213 
hda_get_clock_ns(void)1214 static uint64_t hda_get_clock_ns(void)
1215 {
1216 	struct timespec ts;
1217 	int err;
1218 
1219 	err = clock_gettime(CLOCK_MONOTONIC, &ts);
1220 	assert(!err);
1221 
1222 	return (ts.tv_sec * 1000000000LL + ts.tv_nsec);
1223 }
1224 
1225 /*
1226  * PCI HDA function definitions
1227  */
1228 static int
pci_hda_init(struct pci_devinst * pi,nvlist_t * nvl)1229 pci_hda_init(struct pci_devinst *pi, nvlist_t *nvl)
1230 {
1231 	struct hda_softc *sc = NULL;
1232 
1233 	assert(pi != NULL);
1234 
1235 	pci_set_cfgdata16(pi, PCIR_VENDOR, INTEL_VENDORID);
1236 	pci_set_cfgdata16(pi, PCIR_DEVICE, HDA_INTEL_82801G);
1237 
1238 	pci_set_cfgdata8(pi, PCIR_SUBCLASS, PCIS_MULTIMEDIA_HDA);
1239 	pci_set_cfgdata8(pi, PCIR_CLASS, PCIC_MULTIMEDIA);
1240 
1241 	/* select the Intel HDA mode */
1242 	pci_set_cfgdata8(pi, PCIR_HDCTL, 0x01);
1243 
1244 	/* allocate one BAR register for the Memory address offsets */
1245 	pci_emul_alloc_bar(pi, 0, PCIBAR_MEM32, HDA_LAST_OFFSET);
1246 
1247 	/* allocate an IRQ pin for our slot */
1248 	pci_lintr_request(pi);
1249 
1250 	sc = hda_init(nvl);
1251 	if (!sc)
1252 		return (-1);
1253 
1254 	sc->pci_dev = pi;
1255 	pi->pi_arg = sc;
1256 
1257 	return (0);
1258 }
1259 
1260 static void
pci_hda_write(struct pci_devinst * pi,int baridx,uint64_t offset,int size,uint64_t value)1261 pci_hda_write(struct pci_devinst *pi, int baridx, uint64_t offset, int size,
1262     uint64_t value)
1263 {
1264 	struct hda_softc *sc = pi->pi_arg;
1265 	int err;
1266 
1267 	assert(sc);
1268 	assert(baridx == 0);
1269 	assert(size <= 4);
1270 
1271 	DPRINTF("offset: 0x%lx value: 0x%lx", offset, value);
1272 
1273 	err = hda_write(sc, offset, size, value);
1274 	assert(!err);
1275 }
1276 
1277 static uint64_t
pci_hda_read(struct pci_devinst * pi,int baridx,uint64_t offset,int size)1278 pci_hda_read(struct pci_devinst *pi, int baridx, uint64_t offset, int size)
1279 {
1280 	struct hda_softc *sc = pi->pi_arg;
1281 	uint64_t value = 0;
1282 
1283 	assert(sc);
1284 	assert(baridx == 0);
1285 	assert(size <= 4);
1286 
1287 	value = hda_read(sc, offset);
1288 
1289 	DPRINTF("offset: 0x%lx value: 0x%lx", offset, value);
1290 
1291 	return (value);
1292 }
1293