]> git.lizzy.rs Git - plan9front.git/commitdiff
audiohda: make it work with qemu (thanks mischief)
authorcinap_lenrek <cinap_lenrek@felloff.net>
Tue, 27 Oct 2020 14:16:03 +0000 (15:16 +0100)
committercinap_lenrek <cinap_lenrek@felloff.net>
Tue, 27 Oct 2020 14:16:03 +0000 (15:16 +0100)
the driver was not using irb interrupts
and was just polling the irb write pointer
to wait for command completion.

this is not supported by qemu.

qemu requires the use of irb interrupt handshake
and it refuses to accept the next command until we
acknowledge the irb interrupt.

sys/src/9/pc/audiohda.c

index 56bb06ec81f56361d906e4c00c1bb68e8f87228b..92c7eedde78a6a290e536067f0369cdc94e28eee 100644 (file)
@@ -462,10 +462,9 @@ waitup32(Ctlr *ctlr, int reg, uint mask, uint set)
 static int
 hdacmd(Ctlr *ctlr, uint request, uint reply[2])
 {
-       uint rp, wp;
-       uint re;
-       int wait;
-       
+       uint rp, wp, re;
+       int wait, ret;
+
        re = csr16(ctlr, Rirbwp);
        rp = csr16(ctlr, Corbrp);
        wp = (csr16(ctlr, Corbwp) + 1) % ctlr->corbsize;
@@ -476,15 +475,22 @@ hdacmd(Ctlr *ctlr, uint request, uint reply[2])
        ctlr->corb[wp] = request;
        coherence();
        csr16(ctlr, Corbwp) = wp;
+
+       ret = 0;
        for(wait=0; wait < Maxrirbwait; wait++){
                if(csr16(ctlr, Rirbwp) != re){
                        re = (re + 1) % ctlr->rirbsize;
                        memmove(reply, &ctlr->rirb[re*2], 8);
-                       return 1;
+                       ret = 1;
+                       break;
                }
                microdelay(1);
        }
-       return 0;
+
+       /* reset intcnt for qemu */
+       csr8(ctlr, Rirbsts) = Rirbrover|Rirbrint;
+
+       return ret;
 }
 
 static int
@@ -1732,7 +1738,15 @@ hdastart(Ctlr *ctlr)
        csr32(ctlr, Rirblbase) = pa;
        csr32(ctlr, Rirbubase) = pa >> 32;
        csr16(ctlr, Rirbwp) = Rirbptrrst;
-       csr8(ctlr, Rirbctl) = Rirbdma;
+
+       /*
+        * qemu requires interrupt handshake,
+        * even tho we just poll the irb write
+        * pointer for command completion.
+        */
+       csr16(ctlr, Rintcnt) = 1;
+       csr8(ctlr, Rirbctl) = Rirbdma|Rirbint;
+
        waitup8(ctlr, Rirbctl, Rirbdma, Rirbdma);
        
        /* enable interrupts */