fix inconsistent user interface naming. don't show compile paths to users
[coreboot.git] / src / arch / i386 / boot / pirq_routing.c
1 #include <console/console.h>
2 #include <arch/pirq_routing.h>
3 #include <string.h>
4 #include <device/pci.h>
5
6 #if (DEBUG==1 && HAVE_PIRQ_TABLE==1)
7 static void check_pirq_routing_table(struct irq_routing_table *rt)
8 {
9         uint8_t *addr = (uint8_t *)rt;
10         uint8_t sum=0;
11         int i;
12
13         printk_info("Checking Interrupt Routing Table consistency...\n");
14
15 #if defined(IRQ_SLOT_COUNT)
16         if (sizeof(struct irq_routing_table) != rt->size) {
17                 printk_warning("Inconsistent Interrupt Routing Table size (0x%x/0x%x).\n",
18                                sizeof(struct irq_routing_table),
19                                rt->size
20                         );
21                 rt->size=sizeof(struct irq_routing_table);
22         }
23 #endif
24
25         for (i = 0; i < rt->size; i++)
26                 sum += addr[i];
27
28         printk_debug("%s(): Interrupt Routing Table located at 0x%p.\n",
29                      __FUNCTION__, addr);
30
31         
32         sum = rt->checksum - sum;
33
34         if (sum != rt->checksum) {
35                 printk_warning("Interrupt Routing Table checksum is: 0x%02x but should be: 0x%02x.\n",
36                                rt->checksum, sum);
37                 rt->checksum = sum;
38         }
39
40         if (rt->signature != PIRQ_SIGNATURE || rt->version != PIRQ_VERSION ||
41             rt->size % 16 ) {
42                 printk_warning("Interrupt Routing Table not valid.\n");
43                 return;
44         }
45
46         sum = 0;
47         for (i=0; i<rt->size; i++)
48                 sum += addr[i];
49
50         /* We're manually fixing the checksum above. This warning can probably
51          * never happen because if the target location is read-only this
52          * function would have bailed out earlier.
53          */
54         if (sum) {
55                 printk_warning("Checksum error in Interrupt Routing Table "
56                                 "could not be fixed.\n");
57         }
58
59         printk_info("done.\n");
60 }
61
62 static int verify_copy_pirq_routing_table(unsigned long addr)
63 {
64         int i;
65         uint8_t *rt_orig, *rt_curr;
66
67         rt_curr = (uint8_t*)addr;
68         rt_orig = (uint8_t*)&intel_irq_routing_table;
69         printk_info("Verifing copy of Interrupt Routing Table at 0x%08x... ", addr);
70         for (i = 0; i < intel_irq_routing_table.size; i++) {
71                 if (*(rt_curr + i) != *(rt_orig + i)) {
72                         printk_info("failed\n");
73                         return -1;
74                 }
75         }
76         printk_info("done\n");
77         
78         check_pirq_routing_table((struct irq_routing_table *)addr);
79         
80         return 0;
81 }
82 #else
83 #define verify_copy_pirq_routing_table(addr)
84 #endif
85
86 #if HAVE_PIRQ_TABLE==1
87 unsigned long copy_pirq_routing_table(unsigned long addr)
88 {
89         /* Align the table to be 16 byte aligned. */
90         addr += 15;
91         addr &= ~15;
92
93         /* This table must be betweeen 0xf0000 & 0x100000 */
94         printk_info("Copying Interrupt Routing Table to 0x%08x... ", addr);
95         memcpy((void *)addr, &intel_irq_routing_table, intel_irq_routing_table.size);
96         printk_info("done.\n");
97         verify_copy_pirq_routing_table(addr);
98         pirq_routing_irqs(addr);
99         return addr + intel_irq_routing_table.size;
100 }
101 #endif
102
103 #if (PIRQ_ROUTE==1 && HAVE_PIRQ_TABLE==1)
104 void pirq_routing_irqs(unsigned long addr)
105 {
106         int i, j, k, num_entries;
107         unsigned char irq_slot[4];
108         unsigned char pirq[4] = {0, 0, 0, 0};
109         struct irq_routing_table *pirq_tbl;
110         device_t pdev;
111
112         pirq_tbl = (struct irq_routing_table *)(addr);
113         num_entries = (pirq_tbl->size - 32) / 16;
114
115         /* Set PCI IRQs. */
116         for (i = 0; i < num_entries; i++) {
117
118                 printk_debug("PIRQ Entry %d Dev/Fn: %X Slot: %d\n", i,
119                         pirq_tbl->slots[i].devfn >> 3, pirq_tbl->slots[i].slot);
120
121                 for (j = 0; j < 4; j++) {
122
123                         int link = pirq_tbl->slots[i].irq[j].link;
124                         int bitmap = pirq_tbl->slots[i].irq[j].bitmap;
125                         int irq = 0;
126
127                         printk_debug("INT: %c link: %x bitmap: %x  ",
128                                 'A' + j, link, bitmap);
129
130                         if (!bitmap|| !link || link > 4) {
131
132                                 printk_debug("not routed\n");
133                                 irq_slot[j] = irq;
134                                 continue;
135                         }
136
137                         /* yet not routed */
138                         if (!pirq[link - 1]) {
139
140                                 for (k = 2; k <= 15; k++) {
141
142                                         if (!((bitmap >> k) & 1))
143                                                 continue;
144
145                                         irq = k;
146
147                                         /* yet not routed */
148                                         if (pirq[0] != irq && pirq[1] != irq && pirq[2] != irq && pirq[3] != irq)
149                                                 break;
150                                 }
151
152                                 if (irq)
153                                         pirq[link - 1] = irq;
154                         }
155                         else
156                                 irq = pirq[link - 1];
157
158                         printk_debug("IRQ: %d\n", irq);
159                         irq_slot[j] = irq;
160                 }
161
162                 /* Bus, device, slots IRQs for {A,B,C,D}. */
163                 pci_assign_irqs(pirq_tbl->slots[i].bus,
164                         pirq_tbl->slots[i].devfn >> 3, irq_slot);
165         }
166
167         printk_debug("PIRQ1: %d\n", pirq[0]);
168         printk_debug("PIRQ2: %d\n", pirq[1]);
169         printk_debug("PIRQ3: %d\n", pirq[2]);
170         printk_debug("PIRQ4: %d\n", pirq[3]);
171
172         pirq_assign_irqs(pirq);
173 }
174 #endif