git: 9front

Download patch

ref: faee6c5f1da7a6fc03aa9da4dd9ff2f02e3f1d37
parent: 8d411ddf3b716d4efdedecdc774a90e570229a60
author: cinap_lenrek <cinap_lenrek@felloff.net>
date: Tue Oct 27 11:16:03 EDT 2020

audiohda: make it work with qemu (thanks mischief)

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.

--- a/sys/src/9/pc/audiohda.c
+++ b/sys/src/9/pc/audiohda.c
@@ -462,10 +462,9 @@
 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 @@
 	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 @@
 	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 */
--