Back to home page

Quest Cross Reference

 
 

    


Warning, cross-references for /kernel/drivers/pci/pci_irq.c need to be fixed.

0001 /*                    The Quest Operating System
0002  *  Copyright (C) 2005-2010  Richard West, Boston University
0003  *
0004  *  This program is free software: you can redistribute it and/or modify
0005  *  it under the terms of the GNU General Public License as published by
0006  *  the Free Software Foundation, either version 3 of the License, or
0007  *  (at your option) any later version.
0008  *
0009  *  This program is distributed in the hope that it will be useful,
0010  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
0011  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0012  *  GNU General Public License for more details.
0013  *
0014  *  You should have received a copy of the GNU General Public License
0015  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
0016  */
0017 
0018 #include "drivers/pci/pci.h"
0019 #include "arch/i386.h"
0020 #include "util/printf.h"
0021 #include "smp/smp.h"
0022 #include "smp/apic.h"
0023 #include "kernel.h"
0024 
0025 /* A generic interface for storing and looking up PCI IRQ routing
0026  * information that is typically supplied by ACPI or Intel
0027  * Multiprocessor Specification tables. */
0028 
0029 #define DEBUG_PCI_IRQ
0030 
0031 #ifdef DEBUG_PCI_IRQ
0032 #define DLOG(fmt,...) DLOG_PREFIX("PCI_IRQ",fmt,##__VA_ARGS__)
0033 #else
0034 #define DLOG(fmt,...) ;
0035 #endif
0036 
0037 
0038 #define PCI_IRQ_MAX_COUNT 1024
0039 static uint32 num_pci_irqs=0;
0040 pci_irq_t pci_irqs[PCI_IRQ_MAX_COUNT];
0041 
0042 /* Create a PCI IRQ routing entry */
0043 extern void
0044 pci_irq_register (pci_irq_t *irq)
0045 {
0046   if (num_pci_irqs >= PCI_IRQ_MAX_COUNT) {
0047     DLOG ("Exceeded PCI_IRQ_MAX_COUNT");
0048     return;
0049   }
0050   DLOG ("Registering %.02X:%.02X Pin %d as GSI=0x%.02X (T=%d P=%d)",
0051         irq->bus, irq->dev, irq->pin, irq->gsi, irq->trigger, irq->polarity);
0052   memcpy (&pci_irqs[num_pci_irqs], irq, sizeof (pci_irq_t));
0053 
0054   num_pci_irqs++;
0055 }
0056 
0057 /* Look up a PCI IRQ routing entry by PCI bus:dev:pin */
0058 extern bool
0059 pci_irq_find (uint8 bus, uint8 dev, uint8 pin, pci_irq_t *irq_out)
0060 {
0061   uint i;
0062   for (i=0; i<num_pci_irqs; i++) {
0063     if (pci_irqs[i].bus == bus && pci_irqs[i].dev == dev && pci_irqs[i].pin == pin) {
0064       memcpy (irq_out, &pci_irqs[i], sizeof (pci_irq_t));
0065       return TRUE;
0066     }
0067   }
0068   return FALSE;
0069 }
0070 
0071 /* Map a PCI IRQ routing entry to a given vector with specified CPU
0072  * destination mask, destination mode, and delivery mode. */
0073 extern bool
0074 pci_irq_map (pci_irq_t *irq, uint8 vector,
0075              uint8 destmask,
0076              IOAPIC_destination_mode_t destmode,
0077              IOAPIC_delivery_mode_t delivmode)
0078 {
0079   uint64 flags = (uint64) vector;
0080   flags |= ((uint64) destmask) << 56;
0081   flags |= (uint64) destmode;
0082   flags |= (uint64) delivmode;
0083   if (irq->polarity == POLARITY_LOW ||
0084       (irq->polarity == POLARITY_DEFAULT && PCI_DEFAULT_POLARITY == POLARITY_LOW))
0085     flags |= (uint64) IOAPIC_POLARITY_LOW;
0086   else
0087     flags |= (uint64) IOAPIC_POLARITY_HIGH;
0088   if (irq->trigger == TRIGGER_LEVEL ||
0089       (irq->trigger == TRIGGER_DEFAULT && PCI_DEFAULT_TRIGGER == TRIGGER_LEVEL))
0090     flags |= (uint64) IOAPIC_TRIGGER_LEVEL;
0091   else
0092     flags |= (uint64) IOAPIC_TRIGGER_EDGE;
0093 
0094   return IOAPIC_map_GSI (irq->gsi, vector, flags) >= 0;
0095 }
0096 
0097 extern bool
0098 pci_irq_map_handler (pci_irq_t *irq, vector_handler handler,
0099                      uint8 destmask,
0100                      IOAPIC_destination_mode_t destmode,
0101                      IOAPIC_delivery_mode_t delivmode)
0102 {
0103   u8 vector = find_unused_vector (MINIMUM_VECTOR_PRIORITY);
0104   DLOG ("vector=0x%X", vector);
0105   if (!vector)
0106     return FALSE;
0107   if (!pci_irq_map (irq, vector, destmask, destmode, delivmode))
0108     return FALSE;
0109   set_vector_handler (vector, handler);
0110   return TRUE;
0111 }
0112 
0113 /* Unmap given PCI IRQ routing entry */
0114 extern bool
0115 pci_irq_unmap (pci_irq_t *irq)
0116 {
0117   return IOAPIC_map_GSI (irq->gsi, 0, 0x0000000000010000LL) >= 0;
0118 }
0119 
0120 /*
0121  * Local Variables:
0122  * indent-tabs-mode: nil
0123  * mode: C
0124  * c-file-style: "gnu"
0125  * c-basic-offset: 2
0126  * End:
0127  */
0128 
0129 /* vi: set et sw=2 sts=2: */