Skip site navigation (1)Skip section navigation (2)
Date:      Mon, 28 Apr 2014 18:41:26 +0000 (UTC)
From:      Peter Grehan <grehan@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r265058 - head/usr.sbin/bhyve
Message-ID:  <201404281841.s3SIfQ4F080289@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: grehan
Date: Mon Apr 28 18:41:25 2014
New Revision: 265058
URL: http://svnweb.freebsd.org/changeset/base/265058

Log:
  Implement legacy interrupts for the AHCI device emulation
  according to the method outlined in the AHCI spec.
  
  Tested with FreeBSD 9/10/11 with MSI disabled,
  and also NetBSD/amd64 (lightly).
  
  Reviewed by:	neel, tychon
  MFC after:	3 weeks

Modified:
  head/usr.sbin/bhyve/pci_ahci.c

Modified: head/usr.sbin/bhyve/pci_ahci.c
==============================================================================
--- head/usr.sbin/bhyve/pci_ahci.c	Mon Apr 28 18:25:21 2014	(r265057)
+++ head/usr.sbin/bhyve/pci_ahci.c	Mon Apr 28 18:41:25 2014	(r265058)
@@ -192,6 +192,7 @@ struct pci_ahci_softc {
 	uint32_t em_ctl;
 	uint32_t cap2;
 	uint32_t bohc;
+	uint32_t lintr;
 	struct ahci_port port[MAX_PORTS];
 };
 #define	ahci_ctx(sc)	((sc)->asc_pi->pi_vmctx)
@@ -211,8 +212,11 @@ static inline void lba_to_msf(uint8_t *b
 static void
 ahci_generate_intr(struct pci_ahci_softc *sc)
 {
+	struct pci_devinst *pi;
 	int i;
 
+	pi = sc->asc_pi;
+
 	for (i = 0; i < sc->ports; i++) {
 		struct ahci_port *pr;
 		pr = &sc->port[i];
@@ -222,8 +226,28 @@ ahci_generate_intr(struct pci_ahci_softc
 
 	DPRINTF("%s %x\n", __func__, sc->is);
 
-	if (sc->is && (sc->ghc & AHCI_GHC_IE))
-		pci_generate_msi(sc->asc_pi, 0);
+	if (sc->is && (sc->ghc & AHCI_GHC_IE)) {		
+		if (pci_msi_enabled(pi)) {
+			/*
+			 * Generate an MSI interrupt on every edge
+			 */
+			pci_generate_msi(pi, 0);
+		} else if (!sc->lintr) {
+			/*
+			 * Only generate a pin-based interrupt if one wasn't
+			 * in progress
+			 */
+			sc->lintr = 1;
+			pci_lintr_assert(pi);
+		}
+	} else if (sc->lintr) {
+		/*
+		 * No interrupts: deassert pin-based signal if it had
+		 * been asserted
+		 */
+		pci_lintr_deassert(pi);
+		sc->lintr = 0;
+	}
 }
 
 static void
@@ -367,6 +391,12 @@ ahci_reset(struct pci_ahci_softc *sc)
 
 	sc->ghc = AHCI_GHC_AE;
 	sc->is = 0;
+
+	if (sc->lintr) {
+		pci_lintr_deassert(sc->asc_pi);
+		sc->lintr = 0;
+	}
+
 	for (i = 0; i < sc->ports; i++) {
 		sc->port[i].ie = 0;
 		sc->port[i].is = 0;
@@ -1814,6 +1844,8 @@ pci_ahci_init(struct vmctx *ctx, struct 
 	pci_emul_alloc_bar(pi, 5, PCIBAR_MEM32,
 	    AHCI_OFFSET + sc->ports * AHCI_STEP);
 
+	pci_lintr_request(pi);
+
 open_fail:
 	if (ret) {
 		blockif_close(sc->port[0].bctx);



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201404281841.s3SIfQ4F080289>