source: mainline/uspace/drv/audio/hdaudio/hdactl.c@ 3fec817

lfn serial ticket/834-toolchain-update topic/msim-upgrade topic/simplify-dev-export
Last change on this file since 3fec817 was 149dd52d, checked in by Jiri Svoboda <jiri@…>, 11 years ago

Fix 64-bit issues.

  • Property mode set to 100644
File size: 16.5 KB
Line 
1/*
2 * Copyright (c) 2014 Jiri Svoboda
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * - Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * - Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * - The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/** @addtogroup hdaudio
30 * @{
31 */
32/** @file High Definition Audio controller
33 */
34
35#include <as.h>
36#include <async.h>
37#include <bitops.h>
38#include <ddf/log.h>
39#include <ddi.h>
40#include <errno.h>
41#include <fibril_synch.h>
42#include <macros.h>
43#include <stdint.h>
44
45#include "codec.h"
46#include "hdactl.h"
47#include "regif.h"
48#include "spec/regs.h"
49
50enum {
51 ctrl_init_wait_max = 10,
52 codec_enum_wait_us = 512,
53 corb_wait_max = 10,
54 rirb_wait_max = 100
55};
56
57static void hda_ctl_process_rirb(hda_ctl_t *);
58
59/** Perform set-reset handshake on a 16-bit register.
60 *
61 * The bit(s) specified in the mask are written as 1, then we wait
62 * for them to read as 1. Then we write them as 0 and we wait for them
63 * to read as 0.
64 */
65static int hda_ctl_reg16_set_reset(uint16_t *reg, uint16_t mask)
66{
67 uint16_t val;
68 int wcnt;
69
70 val = hda_reg16_read(reg);
71 hda_reg16_write(reg, val | mask);
72
73 wcnt = 1000;
74 while (wcnt > 0) {
75 val = hda_reg16_read(reg);
76 if ((val & mask) == mask)
77 break;
78
79 async_usleep(1000);
80 --wcnt;
81 }
82
83 if ((val & mask) != mask)
84 return ETIMEOUT;
85
86 val = hda_reg16_read(reg);
87 hda_reg16_write(reg, val & ~mask);
88
89 wcnt = 1000;
90 while (wcnt > 0) {
91 val = hda_reg16_read(reg);
92 if ((val & mask) == 0)
93 break;
94
95 async_usleep(1000);
96 --wcnt;
97 }
98
99 if ((val & mask) != 0)
100 return ETIMEOUT;
101
102 return EOK;
103}
104
105/** Select an appropriate CORB/RIRB size.
106 *
107 * We always use the largest available size. In @a sizecap each of bits
108 * 0, 1, 2 determine whether one of the supported size (0 == 2 entries,
109 * 1 == 16 entries, 2 == 256 entries) is supported. @a *selsz is set to
110 * one of 0, 1, 2 on success.
111 *
112 * @param sizecap CORB/RIRB Size Capability
113 * @param selsz Place to store CORB/RIRB Size
114 * @return EOK on success, EINVAL if sizecap has no valid bits set
115 *
116 */
117static int hda_rb_size_select(uint8_t sizecap, uint8_t *selsz)
118{
119 int i;
120
121 for (i = 2; i >= 0; --i) {
122 if ((sizecap & BIT_V(uint8_t, i)) != 0) {
123 *selsz = i;
124 return EOK;
125 }
126 }
127
128 return EINVAL;
129}
130
131static size_t hda_rb_entries(uint8_t selsz)
132{
133 switch (selsz) {
134 case 0:
135 return 2;
136 case 1:
137 return 16;
138 case 2:
139 return 256;
140 default:
141 assert(false);
142 return 0;
143 }
144}
145
146/** Initialize the CORB */
147static int hda_corb_init(hda_t *hda)
148{
149 uint8_t ctl;
150 uint8_t corbsz;
151 uint8_t sizecap;
152 uint8_t selsz;
153 int rc;
154
155 ddf_msg(LVL_NOTE, "hda_corb_init()");
156
157 /* Stop CORB if not stopped */
158 ctl = hda_reg8_read(&hda->regs->corbctl);
159 if ((ctl & BIT_V(uint8_t, corbctl_run)) != 0) {
160 ddf_msg(LVL_NOTE, "CORB is enabled, disabling first.");
161 hda_reg8_write(&hda->regs->corbctl, ctl & ~BIT_V(uint8_t,
162 corbctl_run));
163 }
164
165 /* Determine CORB size and allocate CORB buffer */
166 corbsz = hda_reg8_read(&hda->regs->corbsize);
167 sizecap = BIT_RANGE_EXTRACT(uint8_t, corbsize_cap_h,
168 corbsize_cap_l, corbsz);
169 rc = hda_rb_size_select(sizecap, &selsz);
170 if (rc != EOK) {
171 ddf_msg(LVL_ERROR, "Invalid CORB Size Capability");
172 goto error;
173 }
174 corbsz = corbsz & ~BIT_RANGE(uint8_t, corbsize_size_h, corbsize_size_l);
175 corbsz = corbsz | selsz;
176
177 ddf_msg(LVL_NOTE, "Setting CORB Size register to 0x%x", corbsz);
178 hda_reg8_write(&hda->regs->corbsize, corbsz);
179 hda->ctl->corb_entries = hda_rb_entries(selsz);
180
181
182 /*
183 * CORB must be aligned to 128 bytes. If 64OK is not set,
184 * it must be within the 32-bit address space.
185 */
186 hda->ctl->corb_virt = AS_AREA_ANY;
187 rc = dmamem_map_anonymous(hda->ctl->corb_entries * sizeof(uint32_t),
188 hda->ctl->ok64bit ? 0 : DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
189 &hda->ctl->corb_phys, &hda->ctl->corb_virt);
190
191 ddf_msg(LVL_NOTE, "Set CORB base registers");
192
193 /* Update CORB base registers */
194 hda_reg32_write(&hda->regs->corblbase, LOWER32(hda->ctl->corb_phys));
195 hda_reg32_write(&hda->regs->corbubase, UPPER32(hda->ctl->corb_phys));
196
197 ddf_msg(LVL_NOTE, "Reset CORB Read/Write pointers");
198
199 /* Reset CORB Read Pointer */
200 rc = hda_ctl_reg16_set_reset(&hda->regs->corbrp,
201 BIT_V(uint16_t, corbrp_rst));
202 if (rc != EOK) {
203 ddf_msg(LVL_NOTE, "Failed resetting CORBRP");
204 goto error;
205 }
206
207 /* Reset CORB Write Pointer */
208 hda_reg16_write(&hda->regs->corbwp, 0);
209
210 /* Start CORB */
211 ctl = hda_reg8_read(&hda->regs->corbctl);
212 ddf_msg(LVL_NOTE, "CORBctl (0x%x) = 0x%x",
213 (unsigned)((void *)&hda->regs->corbctl - (void *)hda->regs), ctl | BIT_V(uint8_t, corbctl_run));
214 hda_reg8_write(&hda->regs->corbctl, ctl | BIT_V(uint8_t, corbctl_run));
215
216 ddf_msg(LVL_NOTE, "CORB initialized");
217 return EOK;
218error:
219 return EIO;
220}
221
222/** Initialize the RIRB */
223static int hda_rirb_init(hda_t *hda)
224{
225 uint8_t ctl;
226 uint8_t rirbsz;
227 uint8_t sizecap;
228 uint8_t selsz;
229 int rc;
230
231 ddf_msg(LVL_NOTE, "hda_rirb_init()");
232
233 /* Stop RIRB if not stopped */
234 ctl = hda_reg8_read(&hda->regs->rirbctl);
235 if ((ctl & BIT_V(uint8_t, rirbctl_run)) != 0) {
236 ddf_msg(LVL_NOTE, "RIRB is enabled, disabling first.");
237 hda_reg8_write(&hda->regs->corbctl, ctl & ~BIT_V(uint8_t,
238 rirbctl_run));
239 }
240
241 /* Determine RIRB size and allocate RIRB buffer */
242 rirbsz = hda_reg8_read(&hda->regs->rirbsize);
243 sizecap = BIT_RANGE_EXTRACT(uint8_t, rirbsize_cap_h,
244 rirbsize_cap_l, rirbsz);
245 rc = hda_rb_size_select(sizecap, &selsz);
246 if (rc != EOK) {
247 ddf_msg(LVL_ERROR, "Invalid RIRB Size Capability");
248 goto error;
249 }
250 rirbsz = rirbsz & ~BIT_RANGE(uint8_t, rirbsize_size_h, rirbsize_size_l);
251 rirbsz = rirbsz | (selsz << rirbsize_size_l);
252
253 ddf_msg(LVL_NOTE, "Setting RIRB Size register to 0x%x", rirbsz);
254 hda_reg8_write(&hda->regs->rirbsize, rirbsz);
255 hda->ctl->rirb_entries = hda_rb_entries(selsz);
256
257 /*
258 * RIRB must be aligned to 128 bytes. If 64OK is not set,
259 * it must be within the 32-bit address space.
260 */
261 hda->ctl->rirb_virt = AS_AREA_ANY;
262 rc = dmamem_map_anonymous(hda->ctl->rirb_entries * sizeof(uint64_t),
263 hda->ctl->ok64bit ? 0 : DMAMEM_4GiB, AS_AREA_READ | AS_AREA_WRITE, 0,
264 &hda->ctl->rirb_phys, &hda->ctl->rirb_virt);
265
266 ddf_msg(LVL_NOTE, "Set RIRB base registers");
267
268 /* Update RIRB base registers */
269 hda_reg32_write(&hda->regs->rirblbase, LOWER32(hda->ctl->rirb_phys));
270 hda_reg32_write(&hda->regs->rirbubase, UPPER32(hda->ctl->rirb_phys));
271
272 ddf_msg(LVL_NOTE, "Reset RIRB Write pointer");
273
274 /* Reset RIRB Write Pointer */
275 hda_reg16_write(&hda->regs->rirbwp, BIT_V(uint16_t, rirbwp_rst));
276
277 /* Set RINTCNT - Qemu won't read from CORB if this is zero */
278 hda_reg16_write(&hda->regs->rintcnt, hda->ctl->rirb_entries / 2);
279
280 hda->ctl->rirb_rp = 0;
281
282 /* Start RIRB and enable RIRB interrupt */
283 ctl = hda_reg8_read(&hda->regs->rirbctl);
284 ddf_msg(LVL_NOTE, "RIRBctl (0x%x) = 0x%x",
285 (unsigned)((void *)&hda->regs->rirbctl - (void *)hda->regs), ctl | BIT_V(uint8_t, rirbctl_run));
286 hda_reg8_write(&hda->regs->rirbctl, ctl | BIT_V(uint8_t, rirbctl_run) |
287 BIT_V(uint8_t, rirbctl_int));
288
289 ddf_msg(LVL_NOTE, "RIRB initialized");
290 return EOK;
291error:
292 return EIO;
293}
294
295static size_t hda_get_corbrp(hda_t *hda)
296{
297 uint16_t corbrp;
298
299 corbrp = hda_reg16_read(&hda->regs->corbrp);
300 return BIT_RANGE_EXTRACT(uint16_t, corbrp_rp_h, corbrp_rp_l, corbrp);
301}
302
303static size_t hda_get_corbwp(hda_t *hda)
304{
305 uint16_t corbwp;
306
307 corbwp = hda_reg16_read(&hda->regs->corbwp);
308 return BIT_RANGE_EXTRACT(uint16_t, corbwp_wp_h, corbwp_wp_l, corbwp);
309}
310
311static void hda_set_corbwp(hda_t *hda, size_t wp)
312{
313 ddf_msg(LVL_DEBUG2, "Set CORBWP = %zu", wp);
314 hda_reg16_write(&hda->regs->corbwp, wp);
315}
316
317static size_t hda_get_rirbwp(hda_t *hda)
318{
319 uint16_t rirbwp;
320
321 rirbwp = hda_reg16_read(&hda->regs->rirbwp);
322 return BIT_RANGE_EXTRACT(uint16_t, rirbwp_wp_h, rirbwp_wp_l, rirbwp);
323}
324
325/** Determine number of free entries in CORB */
326static size_t hda_corb_avail(hda_t *hda)
327{
328 int rp, wp;
329 int avail;
330
331 rp = hda_get_corbrp(hda);
332 wp = hda_get_corbwp(hda);
333
334 avail = rp - wp - 1;
335 while (avail < 0)
336 avail += hda->ctl->corb_entries;
337
338 return avail;
339}
340
341/** Write to CORB */
342static int hda_corb_write(hda_t *hda, uint32_t *data, size_t count)
343{
344 size_t avail;
345 size_t wp;
346 size_t idx;
347 size_t now;
348 size_t i;
349 uint32_t *corb;
350 int wcnt;
351
352 avail = hda_corb_avail(hda);
353 wp = hda_get_corbwp(hda);
354 corb = (uint32_t *)hda->ctl->corb_virt;
355
356 idx = 0;
357 while (idx < count) {
358 now = min(avail, count - idx);
359
360 for (i = 0; i < now; i++) {
361 wp = (wp + 1) % hda->ctl->corb_entries;
362 corb[wp] = data[idx++];
363 }
364
365 hda_set_corbwp(hda, wp);
366
367 if (idx < count) {
368 /* We filled up CORB but still data remaining */
369 wcnt = corb_wait_max;
370 while (hda_corb_avail(hda) < 1 && wcnt > 0) {
371 async_usleep(100);
372 --wcnt;
373 }
374
375 /* If CORB is still full return timeout error */
376 if (hda_corb_avail(hda) < 1)
377 return ETIMEOUT;
378 }
379 }
380
381 return EOK;
382}
383
384static int hda_rirb_read(hda_t *hda, hda_rirb_entry_t *data)
385{
386 size_t wp;
387 hda_rirb_entry_t resp;
388 hda_rirb_entry_t *rirb;
389
390 rirb = (hda_rirb_entry_t *)hda->ctl->rirb_virt;
391
392 wp = hda_get_rirbwp(hda);
393 ddf_msg(LVL_DEBUG2, "hda_rirb_read: wp=%zu", wp);
394 if (hda->ctl->rirb_rp == wp)
395 return ENOENT;
396
397 hda->ctl->rirb_rp = (hda->ctl->rirb_rp + 1) % hda->ctl->rirb_entries;
398 resp = rirb[hda->ctl->rirb_rp];
399
400 ddf_msg(LVL_DEBUG2, "RESPONSE resp=0x%x respex=0x%x",
401 resp.resp, resp.respex);
402 *data = resp;
403 return EOK;
404}
405
406static int hda_solrb_read(hda_t *hda, hda_rirb_entry_t *data, size_t count)
407{
408 hda_rirb_entry_t resp;
409 int wcnt;
410
411 ddf_msg(LVL_DEBUG, "hda_solrb_read()");
412
413 fibril_mutex_lock(&hda->ctl->solrb_lock);
414
415 while (count > 0) {
416 while (count > 0 && hda->ctl->solrb_rp != hda->ctl->solrb_wp) {
417 hda->ctl->solrb_rp = (hda->ctl->solrb_rp + 1) % softrb_entries;
418 resp = hda->ctl->solrb[hda->ctl->solrb_rp];
419
420 ddf_msg(LVL_DEBUG2, "solrb RESPONSE resp=0x%x respex=0x%x",
421 resp.resp, resp.respex);
422 if ((resp.respex & BIT_V(uint32_t, respex_unsol)) == 0) {
423 /* Solicited response */
424 *data++ = resp;
425 --count;
426 }
427 }
428
429 if (count > 0) {
430 wcnt = 100;
431 while (wcnt > 0 && hda->ctl->solrb_wp == hda->ctl->solrb_rp) {
432 fibril_mutex_unlock(&hda->ctl->solrb_lock);
433 async_usleep(10000);
434 fibril_mutex_lock(&hda->ctl->solrb_lock);
435 --wcnt;
436 }
437
438 if (hda->ctl->solrb_wp == hda->ctl->solrb_rp) {
439 ddf_msg(LVL_NOTE, "hda_solrb_read() - last ditch effort process RIRB");
440 fibril_mutex_unlock(&hda->ctl->solrb_lock);
441 hda_ctl_process_rirb(hda->ctl);
442 fibril_mutex_lock(&hda->ctl->solrb_lock);
443 }
444
445 if (hda->ctl->solrb_wp == hda->ctl->solrb_rp) {
446 ddf_msg(LVL_NOTE, "hda_solrb_read() time out");
447 fibril_mutex_unlock(&hda->ctl->solrb_lock);
448 return ETIMEOUT;
449 }
450 }
451 }
452
453 fibril_mutex_unlock(&hda->ctl->solrb_lock);
454 return EOK;
455}
456
457hda_ctl_t *hda_ctl_init(hda_t *hda)
458{
459 hda_ctl_t *ctl;
460 uint32_t gctl;
461 uint32_t intctl;
462 int cnt;
463 int rc;
464
465 ctl = calloc(1, sizeof(hda_ctl_t));
466 if (ctl == NULL)
467 return NULL;
468
469 fibril_mutex_initialize(&ctl->solrb_lock);
470 fibril_condvar_initialize(&ctl->solrb_cv);
471
472 hda->ctl = ctl;
473 ctl->hda = hda;
474
475 uint8_t vmaj = hda_reg8_read(&hda->regs->vmaj);
476 uint8_t vmin = hda_reg8_read(&hda->regs->vmin);
477 ddf_msg(LVL_NOTE, "HDA version %d.%d", vmaj, vmin);
478
479 if (vmaj != 1 || vmin != 0) {
480 ddf_msg(LVL_ERROR, "Unsupported HDA version (%d.%d).",
481 vmaj, vmin);
482 goto error;
483 }
484
485 ddf_msg(LVL_NOTE, "reg 0x%zx STATESTS = 0x%x",
486 (void *)&hda->regs->statests - (void *)hda->regs,
487 hda_reg16_read(&hda->regs->statests));
488 /**
489 * Clear STATESTS bits so they don't generate an interrupt later
490 * when we enable interrupts.
491 */
492 hda_reg16_write(&hda->regs->statests, 0x7f);
493
494 ddf_msg(LVL_NOTE, "after clearing reg 0x%zx STATESTS = 0x%x",
495 (void *)&hda->regs->statests - (void *)hda->regs,
496 hda_reg16_read(&hda->regs->statests));
497
498 gctl = hda_reg32_read(&hda->regs->gctl);
499 if ((gctl & BIT_V(uint32_t, gctl_crst)) != 0) {
500 ddf_msg(LVL_NOTE, "Controller not in reset. Resetting.");
501 hda_reg32_write(&hda->regs->gctl, gctl & ~BIT_V(uint32_t, gctl_crst));
502 }
503
504 ddf_msg(LVL_NOTE, "Taking controller out of reset.");
505 hda_reg32_write(&hda->regs->gctl, gctl | BIT_V(uint32_t, gctl_crst));
506
507 /* Wait for CRST to read as 1 */
508 cnt = ctrl_init_wait_max;
509 while (cnt > 0) {
510 gctl = hda_reg32_read(&hda->regs->gctl);
511 if ((gctl & BIT_V(uint32_t, gctl_crst)) != 0) {
512 ddf_msg(LVL_NOTE, "gctl=0x%x", gctl);
513 break;
514 }
515
516 ddf_msg(LVL_NOTE, "Waiting for controller to initialize.");
517 async_usleep(100*1000);
518 --cnt;
519 }
520
521 if (cnt == 0) {
522 ddf_msg(LVL_ERROR, "Timed out waiting for controller to come up.");
523 goto error;
524 }
525
526 ddf_msg(LVL_NOTE, "Controller is out of reset.");
527
528 ddf_msg(LVL_NOTE, "Read GCAP");
529 uint16_t gcap = hda_reg16_read(&hda->regs->gcap);
530 ctl->ok64bit = (gcap & BIT_V(uint16_t, gcap_64ok)) != 0;
531 ctl->oss = BIT_RANGE_EXTRACT(uint16_t, gcap_oss_h, gcap_oss_l, gcap);
532 ctl->iss = BIT_RANGE_EXTRACT(uint16_t, gcap_iss_h, gcap_iss_l, gcap);
533 ctl->bss = BIT_RANGE_EXTRACT(uint16_t, gcap_bss_h, gcap_bss_l, gcap);
534 ddf_msg(LVL_NOTE, "GCAP: 0x%x (64OK=%d)", gcap, ctl->ok64bit);
535
536 /* Give codecs enough time to enumerate themselves */
537 async_usleep(codec_enum_wait_us);
538
539 ddf_msg(LVL_NOTE, "STATESTS = 0x%x",
540 hda_reg16_read(&hda->regs->statests));
541
542 /* Enable interrupts */
543 intctl = hda_reg32_read(&hda->regs->intctl);
544 ddf_msg(LVL_NOTE, "intctl (0x%x) := 0x%x",
545 (unsigned)((void *)&hda->regs->intctl - (void *)hda->regs),
546 intctl | BIT_V(uint32_t, intctl_gie) | BIT_V(uint32_t, intctl_cie));
547 hda_reg32_write(&hda->regs->intctl, intctl |
548 BIT_V(uint32_t, intctl_gie) | BIT_V(uint32_t, intctl_cie) |
549 0x3fffffff);
550
551 rc = hda_corb_init(hda);
552 if (rc != EOK)
553 goto error;
554
555 rc = hda_rirb_init(hda);
556 if (rc != EOK)
557 goto error;
558
559 ddf_msg(LVL_NOTE, "call hda_codec_init()");
560 hda->ctl->codec = hda_codec_init(hda, 0);
561 if (hda->ctl->codec == NULL) {
562 ddf_msg(LVL_NOTE, "hda_codec_init() failed");
563 goto error;
564 }
565
566 async_usleep(5*1000*1000);
567 ddf_msg(LVL_NOTE, "intsts=0x%x", hda_reg32_read(&hda->regs->intsts));
568 ddf_msg(LVL_NOTE, "sdesc[%d].sts=0x%x",
569 hda->ctl->iss, hda_reg8_read(&hda->regs->sdesc[hda->ctl->iss].sts));
570
571 return ctl;
572error:
573 free(ctl);
574 hda->ctl = NULL;
575 return NULL;
576}
577
578int hda_cmd(hda_t *hda, uint32_t verb, uint32_t *resp)
579{
580 int rc;
581 hda_rirb_entry_t rentry;
582
583 rc = hda_corb_write(hda, &verb, 1);
584 if (rc != EOK)
585 return rc;
586
587 if (resp != NULL) {
588 rc = hda_solrb_read(hda, &rentry, 1);
589 if (rc != EOK)
590 return rc;
591
592 /* XXX Verify that response came from the correct codec */
593 *resp = rentry.resp;
594 }
595
596 return EOK;
597}
598
599void hda_ctl_fini(hda_ctl_t *ctl)
600{
601 ddf_msg(LVL_NOTE, "hda_ctl_fini()");
602 free(ctl);
603}
604
605static void hda_ctl_process_rirb(hda_ctl_t *ctl)
606{
607 hda_rirb_entry_t resp;
608 int rc;
609
610 while (true) {
611 rc = hda_rirb_read(ctl->hda, &resp);
612 if (rc != EOK) {
613// ddf_msg(LVL_NOTE, "nothing in rirb");
614 break;
615 }
616
617 ddf_msg(LVL_DEBUG2, "writing to solrb");
618 fibril_mutex_lock(&ctl->solrb_lock);
619 ctl->solrb_wp = (ctl->solrb_wp + 1) % softrb_entries;
620 ctl->solrb[ctl->solrb_wp] = resp;
621 fibril_mutex_unlock(&ctl->solrb_lock);
622 fibril_condvar_broadcast(&ctl->solrb_cv);
623 }
624}
625
626void hda_ctl_interrupt(hda_ctl_t *ctl)
627{
628 hda_ctl_process_rirb(ctl);
629}
630
631void hda_ctl_dump_info(hda_ctl_t *ctl)
632{
633 ddf_msg(LVL_NOTE, "corbwp=%d, corbrp=%d",
634 hda_reg16_read(&ctl->hda->regs->corbwp),
635 hda_reg16_read(&ctl->hda->regs->corbrp));
636 ddf_msg(LVL_NOTE, "corbctl=0x%x, corbsts=0x%x",
637 hda_reg8_read(&ctl->hda->regs->corbctl),
638 hda_reg8_read(&ctl->hda->regs->corbsts));
639 ddf_msg(LVL_NOTE, "rirbwp=0x%x, soft-rirbrp=0x%zx",
640 hda_reg16_read(&ctl->hda->regs->rirbwp),
641 ctl->rirb_rp);
642 ddf_msg(LVL_NOTE, "solrb_wp=0x%zx, solrb_rp=0x%zx",
643 ctl->solrb_wp, ctl->solrb_wp);
644}
645
646/** @}
647 */
Note: See TracBrowser for help on using the repository browser.