Warning, cross-references for /kernel/drivers/pci/pci_irq.c need to be fixed.
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
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
0026
0027
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
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
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
0072
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
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
0122
0123
0124
0125
0126
0127
0128
0129