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);
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to