ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / drivers / parisc / iosapic.c
1 /*
2 ** I/O Sapic Driver - PCI interrupt line support
3 **
4 **      (c) Copyright 1999 Grant Grundler
5 **      (c) Copyright 1999 Hewlett-Packard Company
6 **
7 **      This program is free software; you can redistribute it and/or modify
8 **      it under the terms of the GNU General Public License as published by
9 **      the Free Software Foundation; either version 2 of the License, or
10 **      (at your option) any later version.
11 **
12 ** The I/O sapic driver manages the Interrupt Redirection Table which is
13 ** the control logic to convert PCI line based interrupts into a Message
14 ** Signaled Interrupt (aka Transaction Based Interrupt, TBI).
15 **
16 ** Acronyms
17 ** --------
18 ** HPA  Hard Physical Address (aka MMIO address)
19 ** IRQ  Interrupt ReQuest. Implies Line based interrupt.
20 ** IRT  Interrupt Routing Table (provided by PAT firmware)
21 ** IRdT Interrupt Redirection Table. IRQ line to TXN ADDR/DATA
22 **      table which is implemented in I/O SAPIC.
23 ** ISR  Interrupt Service Routine. aka Interrupt handler.
24 ** MSI  Message Signaled Interrupt. PCI 2.2 functionality.
25 **      aka Transaction Based Interrupt (or TBI).
26 ** PA   Precision Architecture. HP's RISC architecture.
27 ** RISC Reduced Instruction Set Computer.
28 **
29 **
30 ** What's a Message Signalled Interrupt?
31 ** -------------------------------------
32 ** MSI is a write transaction which targets a processor and is similar
33 ** to a processor write to memory or MMIO. MSIs can be generated by I/O
34 ** devices as well as processors and require *architecture* to work.
35 **
36 ** PA only supports MSI. So I/O subsystems must either natively generate
37 ** MSIs (e.g. GSC or HP-PB) or convert line based interrupts into MSIs
38 ** (e.g. PCI and EISA).  IA64 supports MSIs via a "local SAPIC" which
39 ** acts on behalf of a processor.
40 **
41 ** MSI allows any I/O device to interrupt any processor. This makes
42 ** load balancing of the interrupt processing possible on an SMP platform.
43 ** Interrupts are also ordered WRT to DMA data.  It's possible on I/O
44 ** coherent systems to completely eliminate PIO reads from the interrupt
45 ** path. The device and driver must be designed and implemented to
46 ** guarantee all DMA has been issued (issues about atomicity here)
47 ** before the MSI is issued. I/O status can then safely be read from
48 ** DMA'd data by the ISR.
49 **
50 **
51 ** PA Firmware
52 ** -----------
53 ** PA-RISC platforms have two fundementally different types of firmware.
54 ** For PCI devices, "Legacy" PDC initializes the "INTERRUPT_LINE" register
55 ** and BARs similar to a traditional PC BIOS.
56 ** The newer "PAT" firmware supports PDC calls which return tables.
57 ** PAT firmware only initializes PCI Console and Boot interface.
58 ** With these tables, the OS can progam all other PCI devices.
59 **
60 ** One such PAT PDC call returns the "Interrupt Routing Table" (IRT).
61 ** The IRT maps each PCI slot's INTA-D "output" line to an I/O SAPIC
62 ** input line.  If the IRT is not available, this driver assumes
63 ** INTERRUPT_LINE register has been programmed by firmware. The latter
64 ** case also means online addition of PCI cards can NOT be supported
65 ** even if HW support is present.
66 **
67 ** All platforms with PAT firmware to date (Oct 1999) use one Interrupt
68 ** Routing Table for the entire platform.
69 **
70 ** Where's the iosapic?
71 ** --------------------
72 ** I/O sapic is part of the "Core Electronics Complex". And on HP platforms
73 ** it's integrated as part of the PCI bus adapter, "lba".  So no bus walk
74 ** will discover I/O Sapic. I/O Sapic driver learns about each device
75 ** when lba driver advertises the presence of the I/O sapic by calling
76 ** iosapic_register().
77 **
78 **
79 ** IRQ region notes
80 ** ----------------
81 ** The data passed to iosapic_interrupt() is per IRQ line.
82 ** Each IRQ line will get one txn_addr/data pair. Thus each IRQ region,
83 ** will have several txn_addr/data pairs (up to 7 for current I/O SAPIC
84 ** implementations).  The IRQ region "sysdata" will NOT be directly passed
85 ** to the interrupt handler like GSCtoPCI (dino.c).
86 **
87 ** iosapic interrupt handler will NOT call do_irq_mask().
88 ** It doesn't need to read a bit mask to determine which IRQ line was pulled
89 ** since it already knows based on vector_info passed to iosapic_interrupt().
90 **
91 ** One IRQ number represents both an IRQ line and a driver ISR.
92 ** The I/O sapic driver can't manage shared IRQ lines because
93 ** additional data besides the IRQ number must be passed via
94 ** irq_region_ops. do_irq() and request_irq() must manage
95 ** a sharing a bit in the mask.
96 **
97 ** iosapic_interrupt() replaces do_irq_mask() and calls do_irq().
98 ** Which IRQ line was asserted is already known since each
99 ** line has unique data associated with it. We could omit
100 ** iosapic_interrupt() from the calling path if it did NOT need
101 ** to write EOI. For unshared lines, it really doesn't.
102 **
103 ** Unfortunately, can't optimize out EOI if IRQ line isn't "shared".
104 ** N-class console "device" and some sort of heartbeat actually share
105 ** one line though only one driver is registered...<sigh>...this was
106 ** true for HP-UX at least. May not be true for parisc-linux.
107 **
108 **
109 ** Overview of exported iosapic functions
110 ** --------------------------------------
111 ** (caveat: code isn't finished yet - this is just the plan)
112 **
113 ** iosapic_init:
114 **   o initialize globals (lock, etc)
115 **   o try to read IRT. Presence of IRT determines if this is
116 **     a PAT platform or not.
117 **
118 ** iosapic_register():
119 **   o create iosapic_info instance data structure
120 **   o allocate vector_info array for this iosapic
121 **   o initialize vector_info - read corresponding IRdT?
122 **
123 ** iosapic_xlate_pin: (only called by fixup_irq for PAT platform)
124 **   o intr_pin = read cfg (INTERRUPT_PIN);
125 **   o if (device under PCI-PCI bridge)
126 **               translate slot/pin
127 **
128 ** iosapic_fixup_irq:
129 **   o if PAT platform (IRT present)
130 **         intr_pin = iosapic_xlate_pin(isi,pcidev):
131 **         intr_line = find IRT entry(isi, PCI_SLOT(pcidev), intr_pin)
132 **         save IRT entry into vector_info later
133 **         write cfg INTERRUPT_LINE (with intr_line)?
134 **     else
135 **         intr_line = pcidev->irq
136 **         IRT pointer = NULL
137 **     endif
138 **   o locate vector_info (needs: isi, intr_line)
139 **   o allocate processor "irq" and get txn_addr/data
140 **   o request_irq(processor_irq,  iosapic_interrupt, vector_info,...)
141 **   o pcidev->irq = isi->isi_region...base + intr_line;
142 **
143 ** iosapic_interrupt:
144 **   o call do_irq(vector->isi->irq_region, vector->irq_line, regs)
145 **   o assume level triggered and write EOI
146 **
147 ** iosapic_enable_irq:
148 **   o clear any pending IRQ on that line
149 **   o enable IRdT - call enable_irq(vector[line]->processor_irq)
150 **   o write EOI in case line is already asserted.
151 **
152 ** iosapic_disable_irq:
153 **   o disable IRdT - call disable_irq(vector[line]->processor_irq)
154 **
155 ** FIXME: mask/unmask
156 */
157
158
159 /* FIXME: determine which include files are really needed */
160 #include <linux/types.h>
161 #include <linux/kernel.h>
162 #include <linux/spinlock.h>
163 #include <linux/pci.h>          /* pci cfg accessor functions  */
164 #include <linux/init.h>
165 #include <linux/slab.h>
166 #include <linux/smp_lock.h>
167 #include <linux/interrupt.h>    /* irqaction */
168 #include <linux/irq.h>          /* irq_region support */
169
170 #include <asm/byteorder.h>      /* get in-line asm for swab */
171 #include <asm/pdc.h>
172 #include <asm/page.h>
173 #include <asm/segment.h>
174 #include <asm/system.h>
175 #include <asm/io.h>             /* gsc_read/write functions */
176 #ifdef CONFIG_SUPERIO
177 #include <asm/superio.h>
178 #endif
179
180 #include <asm/iosapic.h>
181 #include "./iosapic_private.h"
182
183 #define MODULE_NAME "iosapic"
184
185 /* "local" compile flags */
186 #undef PCI_BRIDGE_FUNCS
187 #undef DEBUG_IOSAPIC
188 #undef DEBUG_IOSAPIC_IRT
189
190
191 #ifdef DEBUG_IOSAPIC
192 static char assert_buf[128];
193
194 static int
195 assert_failed (char *a, char *f, int l)
196 {
197         sprintf(assert_buf,
198                         "ASSERT(%s) failed!\nline %d in %s\n",
199                         a,      /* assertion text */
200                         l,      /* line number */
201                         f);     /* file name */
202         panic(assert_buf);
203         return 0;
204 }
205
206 #undef ASSERT
207 #define ASSERT(EX) { if (!(EX)) assert_failed(# EX, __FILE__, __LINE__); }
208
209 #define DBG(x...) printk(x)
210
211 #else /* DEBUG_IOSAPIC */
212
213 #define DBG(x...)
214 #undef  ASSERT
215 #define ASSERT(EX)
216
217 #endif /* DEBUG_IOSAPIC */
218
219 #ifdef DEBUG_IOSAPIC_IRT
220 #define DBG_IRT(x...) printk(x)
221 #else
222 #define DBG_IRT(x...)
223 #endif
224
225
226 #define READ_U8(addr)  gsc_readb(addr)
227 #define READ_U16(addr) le16_to_cpu(gsc_readw((u16 *) (addr)))
228 #define READ_U32(addr) le32_to_cpu(gsc_readl((u32 *) (addr)))
229 #define READ_REG16(addr) gsc_readw((u16 *) (addr))
230 #define READ_REG32(addr) gsc_readl((u32 *) (addr))
231 #define WRITE_U8(value, addr) gsc_writeb(value, addr)
232 #define WRITE_U16(value, addr) gsc_writew(cpu_to_le16(value), (u16 *) (addr))
233 #define WRITE_U32(value, addr) gsc_writel(cpu_to_le32(value), (u32 *) (addr))
234 #define WRITE_REG16(value, addr) gsc_writew(value, (u16 *) (addr))
235 #define WRITE_REG32(value, addr) gsc_writel(value, (u32 *) (addr))
236
237
238 #define IOSAPIC_REG_SELECT              0
239 #define IOSAPIC_REG_WINDOW              0x10
240 #define IOSAPIC_REG_EOI                 0x40
241
242 #define IOSAPIC_REG_VERSION             0x1
243
244 #define IOSAPIC_IRDT_ENTRY(idx)         (0x10+(idx)*2)
245 #define IOSAPIC_IRDT_ENTRY_HI(idx)      (0x11+(idx)*2)
246
247 /*
248 ** FIXME: revisit which GFP flags we should really be using.
249 **     GFP_KERNEL includes __GFP_WAIT flag and that may not
250 **     be acceptable. Since this is boot time, we shouldn't have
251 **     to wait ever and this code should (will?) never get called
252 **     from the interrrupt context.
253 */
254 #define IOSAPIC_KALLOC(a_type, cnt) \
255                         (a_type *) kmalloc(sizeof(a_type)*(cnt), GFP_KERNEL)
256 #define IOSAPIC_FREE(addr, f_type, cnt) kfree((void *)addr)
257
258
259 #define IOSAPIC_LOCK(lck)       spin_lock_irqsave(lck, irqflags)
260 #define IOSAPIC_UNLOCK(lck)     spin_unlock_irqrestore(lck, irqflags)
261
262
263 #define IOSAPIC_VERSION_MASK            0x000000ff
264 #define IOSAPIC_VERSION_SHIFT           0x0
265 #define IOSAPIC_VERSION(ver)                            \
266                 (int) ((ver & IOSAPIC_VERSION_MASK) >> IOSAPIC_VERSION_SHIFT)
267
268 #define IOSAPIC_MAX_ENTRY_MASK          0x00ff0000
269
270 #define IOSAPIC_MAX_ENTRY_SHIFT         0x10
271 #define IOSAPIC_IRDT_MAX_ENTRY(ver)                     \
272                 (int) ((ver&IOSAPIC_MAX_ENTRY_MASK) >> IOSAPIC_MAX_ENTRY_SHIFT)
273
274 /* bits in the "low" I/O Sapic IRdT entry */
275 #define IOSAPIC_IRDT_ENABLE       0x10000
276 #define IOSAPIC_IRDT_PO_LOW       0x02000
277 #define IOSAPIC_IRDT_LEVEL_TRIG   0x08000
278 #define IOSAPIC_IRDT_MODE_LPRI    0x00100
279
280 /* bits in the "high" I/O Sapic IRdT entry */
281 #define IOSAPIC_IRDT_ID_EID_SHIFT              0x10
282
283
284
285 #define IOSAPIC_EOI(eoi_addr, eoi_data) gsc_writel(eoi_data, eoi_addr)
286
287 static struct iosapic_info *iosapic_list;
288 static spinlock_t iosapic_lock;
289 static int iosapic_count;
290
291
292 /*
293 ** REVISIT: future platforms may have more than one IRT.
294 ** If so, the following three fields form a structure which
295 ** then be linked into a list. Names are chosen to make searching
296 ** for them easy - not necessarily accurate (eg "cell").
297 **
298 ** Alternative: iosapic_info could point to the IRT it's in.
299 ** iosapic_register() could search a list of IRT's.
300 */
301 static struct irt_entry *irt_cell;
302 static size_t irt_num_entry;
303
304
305
306 /*
307 ** iosapic_load_irt
308 **
309 ** The "Get PCI INT Routing Table Size" option returns the number of 
310 ** entries in the PCI interrupt routing table for the cell specified 
311 ** in the cell_number argument.  The cell number must be for a cell 
312 ** within the caller's protection domain.
313 **
314 ** The "Get PCI INT Routing Table" option returns, for the cell 
315 ** specified in the cell_number argument, the PCI interrupt routing 
316 ** table in the caller allocated memory pointed to by mem_addr.
317 ** We assume the IRT only contains entries for I/O SAPIC and
318 ** calculate the size based on the size of I/O sapic entries.
319 **
320 ** The PCI interrupt routing table entry format is derived from the
321 ** IA64 SAL Specification 2.4.   The PCI interrupt routing table defines
322 ** the routing of PCI interrupt signals between the PCI device output
323 ** "pins" and the IO SAPICs' input "lines" (including core I/O PCI
324 ** devices).  This table does NOT include information for devices/slots
325 ** behind PCI to PCI bridges. See PCI to PCI Bridge Architecture Spec.
326 ** for the architected method of routing of IRQ's behind PPB's.
327 */
328
329
330 static int __init /* return number of entries as success/fail flag */
331 iosapic_load_irt(unsigned long cell_num, struct irt_entry **irt)
332 {
333         long status;              /* PDC return value status */
334         struct irt_entry *table;  /* start of interrupt routing tbl */
335         unsigned long num_entries = 0UL;
336
337         ASSERT(NULL != irt);
338
339         if (is_pdc_pat()) {
340
341                 /* Use pat pdc routine to get interrupt routing table size */
342                 DBG("calling get_irt_size (cell %ld)\n", cell_num);
343                 status = pdc_pat_get_irt_size(&num_entries, cell_num);
344                 DBG("get_irt_size: %ld\n", status);
345
346                 ASSERT(status == PDC_OK);
347
348                 /* save the number of entries in the table */
349                 ASSERT(0UL != num_entries);
350
351                 /*
352                 ** allocate memory for interrupt routing table
353                 ** This interface isn't really right. We are assuming
354                 ** the contents of the table are exclusively
355                 ** for I/O sapic devices.
356                 */
357                 table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
358                 if (table == NULL) {
359                         printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
360                         return 0;
361                 }
362
363                 /* get PCI INT routing table */
364                 status = pdc_pat_get_irt(table, cell_num);
365                 DBG("pdc_pat_get_irt: %ld\n", status);
366                 ASSERT(status == PDC_OK);
367         } else {
368                 /*
369                 ** C3000/J5000 (and similar) platforms with Sprockets PDC
370                 ** will return exactly one IRT for all iosapics.
371                 ** So if we have one, don't need to get it again.
372                 */
373                 if (NULL != irt_cell)
374                         return 0;
375
376                 /* Should be using the Elroy's HPA, but it's ignored anyway */
377                 status = pdc_pci_irt_size(&num_entries, 0);
378                 DBG("pdc_pci_irt_size: %ld\n", status);
379
380                 if (PDC_OK != status) {
381                         /* Not a "legacy" system with I/O SAPIC either */
382                         return 0;
383                 }
384
385                 ASSERT(0UL != num_entries);
386
387                 table = IOSAPIC_KALLOC(struct irt_entry, num_entries);
388                 if (table == NULL) {
389                         printk(KERN_WARNING MODULE_NAME ": read_irt : can not alloc mem for IRT\n");
390                         return 0;
391                 }
392
393                 /* HPA ignored by this call too. */
394                 status = pdc_pci_irt(num_entries, 0, table);
395                 ASSERT(PDC_OK == status);
396         }
397
398         /* return interrupt table address */
399         *irt = table;
400
401 #ifdef DEBUG_IOSAPIC_IRT
402 {
403         struct irt_entry *p = table;
404         int i;
405
406         printk(KERN_DEBUG MODULE_NAME " Interrupt Routing Table (cell %ld)\n", cell_num);
407         printk(KERN_DEBUG MODULE_NAME " start = 0x%p num_entries %ld entry_size %d\n",
408                 table,
409                 num_entries,
410                 (int) sizeof(struct irt_entry));
411
412         for (i = 0 ; i < num_entries ; i++, p++) {
413                 printk(KERN_DEBUG MODULE_NAME " %02x %02x %02x %02x %02x %02x %02x %02x %08x%08x\n",
414                 p->entry_type, p->entry_length, p->interrupt_type,
415                 p->polarity_trigger, p->src_bus_irq_devno, p->src_bus_id,
416                 p->src_seg_id, p->dest_iosapic_intin,
417                 ((u32 *) p)[2],
418                 ((u32 *) p)[3]
419                 );
420         }
421 }
422 #endif /* DEBUG_IOSAPIC_IRT */
423
424         return num_entries;
425 }
426
427
428
429 void __init
430 iosapic_init(void)
431 {
432         unsigned long cell = 0;
433
434         /* init global data */
435         iosapic_lock = SPIN_LOCK_UNLOCKED;
436         iosapic_list = (struct iosapic_info *) NULL;
437         iosapic_count = 0;
438
439         DBG("iosapic_init()\n");
440
441 #ifdef __LP64__
442         if (is_pdc_pat()) {
443                 int status;
444                 struct pdc_pat_cell_num cell_info;
445
446                 status = pdc_pat_cell_get_number(&cell_info);
447                 if (status == PDC_OK) {
448                         cell = cell_info.cell_num;
449                 }
450         }
451 #endif
452
453         /*
454         **  get IRT for this cell.
455         */
456         irt_num_entry =  iosapic_load_irt(cell, &irt_cell);
457         if (0 == irt_num_entry)
458                 irt_cell = NULL;        /* old PDC w/o iosapic */
459 }
460
461
462 /*
463 ** Return the IRT entry in case we need to look something else up.
464 */
465 static struct irt_entry *
466 irt_find_irqline(struct iosapic_info *isi, u8 slot, u8 intr_pin)
467 {
468         struct irt_entry *i = irt_cell;
469         int cnt;        /* track how many entries we've looked at */
470         u8 irq_devno = (slot << IRT_DEV_SHIFT) | (intr_pin-1);
471
472         DBG_IRT("irt_find_irqline() SLOT %d pin %d\n", slot, intr_pin);
473
474         for (cnt=0; cnt < irt_num_entry; cnt++, i++) {
475
476                 /*
477                 ** Validate: entry_type, entry_length, interrupt_type
478                 **
479                 ** Difference between validate vs compare is the former
480                 ** should print debug info and is not expected to "fail"
481                 ** on current platforms.
482                 */
483                 if (i->entry_type != IRT_IOSAPIC_TYPE) {
484                         DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d type %d\n", i, cnt, i->entry_type);
485                         continue;
486                 }
487                 
488                 if (i->entry_length != IRT_IOSAPIC_LENGTH) {
489                         DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry %d  length %d\n", i, cnt, i->entry_length);
490                         continue;
491                 }
492
493                 if (i->interrupt_type != IRT_VECTORED_INTR) {
494                         DBG_IRT(KERN_WARNING MODULE_NAME ":find_irqline(0x%p): skipping entry  %d interrupt_type %d\n", i, cnt, i->interrupt_type);
495                         continue;
496                 }
497
498                 /*
499                 ** Compare: dest_iosapic_addr, src_bus_irq_devno
500                 */
501                 if (i->dest_iosapic_addr != (u64) ((long) isi->isi_hpa))
502                         continue;
503
504                 if ((i->src_bus_irq_devno & IRT_IRQ_DEVNO_MASK) != irq_devno)
505                         continue;
506
507                 /*
508                 ** Ignore: src_bus_id and rc_seg_id correlate with
509                 **         iosapic_info->isi_hpa on HP platforms.
510                 **         If needed, pass in "PFA" (aka config space addr)
511                 **         instead of slot.
512                 */
513
514                 /* Found it! */
515                 return i;
516         }
517
518         printk(KERN_WARNING MODULE_NAME ": 0x%lx : no IRT entry for slot %d, pin %d\n",
519                         isi->isi_hpa, slot, intr_pin);
520         return NULL;
521 }
522
523
524 /*
525 ** xlate_pin() supports the skewing of IRQ lines done by subsidiary bridges.
526 ** Legacy PDC already does this translation for us and stores it in INTR_LINE.
527 **
528 ** PAT PDC needs to basically do what legacy PDC does:
529 ** o read PIN
530 ** o adjust PIN in case device is "behind" a PPB
531 **     (eg 4-port 100BT and SCSI/LAN "Combo Card")
532 ** o convert slot/pin to I/O SAPIC input line.
533 **
534 ** HP platforms only support:
535 ** o one level of skewing for any number of PPBs
536 ** o only support PCI-PCI Bridges.
537 */
538 static struct irt_entry *
539 iosapic_xlate_pin(struct iosapic_info *isi, struct pci_dev *pcidev)
540 {
541         u8 intr_pin, intr_slot;
542
543         pci_read_config_byte(pcidev, PCI_INTERRUPT_PIN, &intr_pin);
544
545         DBG_IRT("iosapic_xlate_pin() SLOT %d pin %d\n",
546                 PCI_SLOT(pcidev->devfn), intr_pin);
547
548         if (0 == intr_pin) {
549                 /* The device does NOT support/use IRQ lines.  */
550                 return NULL;
551         }
552
553         /* Check if pcidev behind a PPB */
554         if (NULL != pcidev->bus->self) {
555                 /* Convert pcidev INTR_PIN into something we
556                 ** can lookup in the IRT.
557                 */
558 #ifdef PCI_BRIDGE_FUNCS
559                 /*
560                 ** Proposal #1:
561                 **
562                 ** call implementation specific translation function
563                 ** This is architecturally "cleaner". HP-UX doesn't
564                 ** support other secondary bus types (eg. E/ISA) directly.
565                 ** May be needed for other processor (eg IA64) architectures
566                 ** or by some ambitous soul who wants to watch TV.
567                 */
568                 if (pci_bridge_funcs->xlate_intr_line) {
569                         intr_pin = pci_bridge_funcs->xlate_intr_line(pcidev);
570                 }
571 #else   /* PCI_BRIDGE_FUNCS */
572                 struct pci_bus *p = pcidev->bus;
573                 /*
574                 ** Proposal #2:
575                 ** The "pin" is skewed ((pin + dev - 1) % 4).
576                 **
577                 ** This isn't very clean since I/O SAPIC must assume:
578                 **   - all platforms only have PCI busses.
579                 **   - only PCI-PCI bridge (eg not PCI-EISA, PCI-PCMCIA)
580                 **   - IRQ routing is only skewed once regardless of
581                 **     the number of PPB's between iosapic and device.
582                 **     (Bit3 expansion chassis follows this rule)
583                 **
584                 ** Advantage is it's really easy to implement.
585                 */
586                 intr_pin = ((intr_pin-1)+PCI_SLOT(pcidev->devfn)) % 4;
587                 intr_pin++;     /* convert back to INTA-D (1-4) */
588 #endif /* PCI_BRIDGE_FUNCS */
589
590                 /*
591                 ** Locate the host slot the PPB nearest the Host bus
592                 ** adapter.
593                 */
594                 while (NULL != p->parent->self)
595                         p = p->parent;
596
597                 intr_slot = PCI_SLOT(p->self->devfn);
598         } else {
599                 intr_slot = PCI_SLOT(pcidev->devfn);
600         }
601         DBG_IRT("iosapic_xlate_pin:  bus %d slot %d pin %d\n",
602                                 pcidev->bus->secondary, intr_slot, intr_pin);
603
604         return irt_find_irqline(isi, intr_slot, intr_pin);
605 }
606
607
608 static irqreturn_t
609 iosapic_interrupt(int irq, void *dev_id, struct pt_regs * regs)
610 {
611         struct vector_info *vi = (struct vector_info *)dev_id;
612         extern void do_irq(struct irqaction *a, int i, struct pt_regs *p);
613         int irq_num = vi->iosapic->isi_region->data.irqbase + vi->irqline;
614
615         DBG("iosapic_interrupt(): irq %d line %d eoi %p\n",
616                 irq, vi->irqline, vi->eoi_addr);
617
618 /* FIXME: Need to mask/unmask? processor IRQ is already masked... */
619         do_irq(&vi->iosapic->isi_region->action[vi->irqline], irq_num, regs);
620
621         /*
622         ** PCI only supports level triggered in order to share IRQ lines.
623         ** I/O SAPIC must always issue EOI.
624         */
625         IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data);
626
627         return IRQ_HANDLED;
628 }
629
630
631 int
632 iosapic_fixup_irq(void *isi_obj, struct pci_dev *pcidev)
633 {
634         struct iosapic_info *isi = (struct iosapic_info *)isi_obj;
635         struct irt_entry *irte = NULL;  /* only used if PAT PDC */
636         struct vector_info *vi;
637         int isi_line;   /* line used by device */
638         int tmp;
639
640         if (NULL == isi) {
641                 printk(KERN_WARNING MODULE_NAME ": hpa not registered for %s\n",
642                         pci_name(pcidev));
643                 return(-1);
644         }
645
646 #ifdef CONFIG_SUPERIO
647         /*
648          * HACK ALERT! (non-compliant PCI device support)
649          *
650          * All SuckyIO interrupts are routed through the PIC's on function 1.
651          * But SuckyIO OHCI USB controller gets an IRT entry anyway because
652          * it advertises INT D for INT_PIN.  Use that IRT entry to get the
653          * SuckyIO interrupt routing for PICs on function 1 (*BLEECCHH*).
654          */
655         if (is_superio_device(pcidev)) {
656                 /* We must call superio_fixup_irq() to register the pdev */
657                 pcidev->irq = superio_fixup_irq(pcidev);
658
659                 /* Don't return if need to program the IOSAPIC's IRT... */
660                 if (PCI_FUNC(pcidev->devfn) != SUPERIO_USB_FN)
661                         return pcidev->irq;
662         }
663 #endif /* CONFIG_SUPERIO */
664
665         /* lookup IRT entry for isi/slot/pin set */
666         irte = iosapic_xlate_pin(isi, pcidev);
667         if (NULL == irte) {
668                 printk("iosapic: no IRTE for %s (IRQ not connected?)\n",
669                                 pci_name(pcidev));
670                 return(-1);
671         }
672         DBG_IRT("iosapic_fixup_irq(): irte %p %x %x %x %x %x %x %x %x\n",
673                 irte,
674                 irte->entry_type,
675                 irte->entry_length,
676                 irte->polarity_trigger,
677                 irte->src_bus_irq_devno,
678                 irte->src_bus_id,
679                 irte->src_seg_id,
680                 irte->dest_iosapic_intin,
681                 (u32) irte->dest_iosapic_addr);
682         isi_line = irte->dest_iosapic_intin;
683         pcidev->irq = isi->isi_region->data.irqbase + isi_line;
684
685         /* get vector info for this input line */
686         ASSERT(NULL != isi->isi_vector);
687         vi = &(isi->isi_vector[isi_line]);
688         DBG_IRT("iosapic_fixup_irq:  line %d vi 0x%p\n", isi_line, vi);
689
690         /* If this IRQ line has already been setup, skip it */
691         if (vi->irte)
692                 return pcidev->irq;
693
694         vi->irte = irte;
695
696         /* Allocate processor IRQ */
697         vi->txn_irq = txn_alloc_irq();
698
699 /* XXX/FIXME The txn_alloc_irq() code and related code should be moved
700 ** to enable_irq(). That way we only allocate processor IRQ bits
701 ** for devices that actually have drivers claiming them.
702 ** Right now we assign an IRQ to every PCI device present regardless
703 ** of whether it's used or not.
704 */
705         if (vi->txn_irq < 0)
706                 panic("I/O sapic: couldn't get TXN IRQ\n");
707
708         /* enable_irq() will use txn_* to program IRdT */
709         vi->txn_addr = txn_alloc_addr(vi->txn_irq);
710         vi->txn_data = txn_alloc_data(vi->txn_irq, 8);
711         ASSERT(vi->txn_data < 256);  /* matches 8 above */
712
713         tmp = request_irq(vi->txn_irq, iosapic_interrupt, 0,
714                                                 vi->name, vi);
715         ASSERT(tmp == 0);
716
717         vi->eoi_addr = (u32 *) (isi->isi_hpa + IOSAPIC_REG_EOI);
718         vi->eoi_data = cpu_to_le32(vi->irqline);
719
720         ASSERT(NULL != isi->isi_region);
721
722         DBG_IRT("iosapic_fixup_irq() %d:%d %x %x line %d irq %d\n",
723                 PCI_SLOT(pcidev->devfn), PCI_FUNC(pcidev->irq),
724                 pcidev->vendor, pcidev->device, isi_line, pcidev->irq);
725
726         return pcidev->irq;
727 }
728
729
730 static void
731 iosapic_rd_irt_entry(struct vector_info *vi , u32 *dp0, u32 *dp1)
732 {
733         struct iosapic_info *isp = vi->iosapic;
734         u8 idx = vi->irqline;
735
736         /* point the window register to the lower word */
737         WRITE_U32(IOSAPIC_IRDT_ENTRY(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
738         *dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
739
740         /* point the window register to the higher word */
741         WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(idx), isp->isi_hpa+IOSAPIC_REG_SELECT);
742         *dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
743 }
744
745
746 static void
747 iosapic_wr_irt_entry(struct vector_info *vi, u32 dp0, u32 dp1)
748 {
749         struct iosapic_info *isp = vi->iosapic;
750
751         ASSERT(NULL != isp);
752         ASSERT(0 != isp->isi_hpa);
753         DBG_IRT("iosapic_wr_irt_entry(): irq %d hpa %p WINDOW %p  0x%x 0x%x\n",
754                 vi->irqline,
755                 isp->isi_hpa, isp->isi_hpa+IOSAPIC_REG_WINDOW,
756                 dp0, dp1);
757
758         /* point the window register to the lower word */
759         WRITE_U32(IOSAPIC_IRDT_ENTRY(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
760         WRITE_U32( dp0, isp->isi_hpa+IOSAPIC_REG_WINDOW);
761
762         /* Read the window register to flush the writes down to HW  */
763         dp0 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
764
765         /* point the window register to the higher word */
766         WRITE_U32(IOSAPIC_IRDT_ENTRY_HI(vi->irqline), isp->isi_hpa+IOSAPIC_REG_SELECT);
767         WRITE_U32( dp1, isp->isi_hpa+IOSAPIC_REG_WINDOW);
768
769         /* Read the window register to flush the writes down to HW  */
770         dp1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
771 }
772
773
774 /*
775 ** set_irt prepares the data (dp0, dp1) according to the vector_info
776 ** and target cpu (id_eid).  dp0/dp1 are then used to program I/O SAPIC
777 ** IRdT for the given "vector" (aka IRQ line).
778 */
779 static void
780 iosapic_set_irt_data( struct vector_info *vi, u32 *dp0, u32 *dp1)
781 {
782         u32 mode = 0;
783         struct irt_entry *p = vi->irte;
784         ASSERT(NULL != vi->irte);
785
786         if ((p->polarity_trigger & IRT_PO_MASK) == IRT_ACTIVE_LO)
787                 mode |= IOSAPIC_IRDT_PO_LOW;
788
789         if (((p->polarity_trigger >> IRT_EL_SHIFT) & IRT_EL_MASK) == IRT_LEVEL_TRIG)
790                 mode |= IOSAPIC_IRDT_LEVEL_TRIG;
791
792         /*
793         ** IA64 REVISIT
794         ** PA doesn't support EXTINT or LPRIO bits.
795         */
796
797         ASSERT(vi->txn_data);
798         *dp0 = mode | (u32) vi->txn_data;
799
800         /*
801         ** Extracting id_eid isn't a real clean way of getting it.
802         ** But the encoding is the same for both PA and IA64 platforms.
803         */
804         if (is_pdc_pat()) {
805                 /*
806                 ** PAT PDC just hands it to us "right".
807                 ** txn_addr comes from cpu_data[x].txn_addr.
808                 */
809                 *dp1 = (u32) (vi->txn_addr);
810         } else {
811                 /* 
812                 ** eg if base_addr == 0xfffa0000),
813                 **    we want to get 0xa0ff0000.
814                 **
815                 ** eid  0x0ff00000 -> 0x00ff0000
816                 ** id   0x000ff000 -> 0xff000000
817                 */
818                 *dp1 = (((u32)vi->txn_addr & 0x0ff00000) >> 4) |
819                         (((u32)vi->txn_addr & 0x000ff000) << 12);
820         }
821         DBG_IRT("iosapic_set_irt_data(): 0x%x 0x%x\n", *dp0, *dp1);
822 }
823
824
825 static void
826 iosapic_disable_irq(void *irq_dev, int irq)
827 {
828         ulong irqflags;
829         struct vector_info *vi = &(((struct vector_info *) irq_dev)[irq]);
830         u32 d0, d1;
831
832         ASSERT(NULL != vi);
833
834         IOSAPIC_LOCK(&iosapic_lock);
835
836 #ifdef REVISIT_DESIGN_ISSUE
837 /* 
838 ** XXX/FIXME
839
840 disable_irq()/enable_irq(): drawback of using IRQ as a "handle"
841
842 Current disable_irq interface only allows the irq_region support routines
843 to manage sharing of "irq" objects.  The problem is the disable_irq()
844 interface specifies which IRQ line needs to be disabled but does not
845 identify the particular ISR which needs to be disabled.  IO sapic
846 (and similar code in Dino) can only support one handler per IRQ
847 since they don't further encode the meaning of the IRQ number.
848 irq_region support has to hide it's implementation of "shared IRQ"
849 behind a function call.
850
851 Encoding the IRQ would be possible by I/O SAPIC but makes life really
852 complicated for the IRQ handler and not help performance.
853
854 Need more info on how Linux supports shared IRQ lines on a PC.
855 */
856 #endif /* REVISIT_DESIGN_ISSUE */
857
858         iosapic_rd_irt_entry(vi, &d0, &d1);
859         d0 |= IOSAPIC_IRDT_ENABLE;
860         iosapic_wr_irt_entry(vi, d0, d1);
861
862         IOSAPIC_UNLOCK(&iosapic_lock);
863
864         /* disable ISR for parent */
865         disable_irq(vi->txn_irq);
866 }
867
868
869 static void
870 iosapic_enable_irq(void *dev, int irq)
871 {
872         struct vector_info *vi = &(((struct vector_info *) dev)[irq]);
873         u32 d0, d1;
874
875         ASSERT(NULL != vi);
876         ASSERT(NULL != vi->irte);
877
878         /* data is initialized by fixup_irq */
879         ASSERT(0 < vi->txn_irq);
880         ASSERT(0UL != vi->txn_data);
881
882         iosapic_set_irt_data(vi, &d0, &d1);
883         iosapic_wr_irt_entry(vi, d0, d1);
884
885
886 #ifdef DEBUG_IOSAPIC_IRT
887 {
888         u32 *t = (u32 *) ((ulong) vi->eoi_addr & ~0xffUL);
889         printk("iosapic_enable_irq(): regs %p", vi->eoi_addr);
890         while (t < vi->eoi_addr) printk(" %x", READ_U32(t++));
891         printk("\n");
892 }
893
894 printk("iosapic_enable_irq(): sel ");
895 {
896         struct iosapic_info *isp = vi->iosapic;
897
898         for (d0=0x10; d0<0x1e; d0++) {
899                 /* point the window register to the lower word */
900                 WRITE_U32(d0, isp->isi_hpa+IOSAPIC_REG_SELECT);
901
902                 /* read the word */
903                 d1 = READ_U32(isp->isi_hpa+IOSAPIC_REG_WINDOW);
904                 printk(" %x", d1);
905         }
906 }
907 printk("\n");
908 #endif
909
910         /*
911         ** KLUGE: IRQ should not be asserted when Drivers enabling their IRQ.
912         **        PCI supports level triggered in order to share IRQ lines.
913         **
914         ** Issueing I/O SAPIC an EOI causes an interrupt iff IRQ line is
915         ** asserted.
916         */
917         IOSAPIC_EOI(vi->eoi_addr, vi->eoi_data);
918 }
919
920
921 static void
922 iosapic_mask_irq(void *dev, int irq)
923 {
924         BUG();
925 }
926
927
928 static void
929 iosapic_unmask_irq(void *dev, int irq)
930 {
931         BUG();
932 }
933
934
935 static struct irq_region_ops iosapic_irq_ops = {
936         .disable_irq =  iosapic_disable_irq,
937         .enable_irq =   iosapic_enable_irq,
938         .mask_irq =     iosapic_mask_irq,
939         .unmask_irq =   iosapic_unmask_irq
940 };
941
942
943 /*
944 ** squirrel away the I/O Sapic Version
945 */
946 static unsigned int
947 iosapic_rd_version(struct iosapic_info *isi)
948 {
949         ASSERT(isi);
950         ASSERT(isi->isi_hpa);
951
952         /* point window to the version register */
953         WRITE_U32(IOSAPIC_REG_VERSION, isi->isi_hpa+IOSAPIC_REG_SELECT);
954
955         /* now read the version register */
956         return (READ_U32(isi->isi_hpa+IOSAPIC_REG_WINDOW));
957 }
958
959
960 /*
961 ** iosapic_register() is called by "drivers" with an integrated I/O SAPIC.
962 ** Caller must be certain they have an I/O SAPIC and know its MMIO address.
963 **
964 **      o allocate iosapic_info and add it to the list
965 **      o read iosapic version and squirrel that away
966 **      o read size of IRdT.
967 **      o allocate and initialize isi_vector[]
968 **      o allocate isi_region (registers region handlers)
969 */
970 void *
971 iosapic_register(unsigned long hpa)
972 {
973         struct iosapic_info *isi = NULL;
974         struct irt_entry *irte = irt_cell;
975         struct vector_info *vip;
976         int cnt;        /* track how many entries we've looked at */
977
978         /*
979         ** Astro based platforms can't support PCI OLARD if they
980         ** implement the legacy PDC (not PAT). Though Legacy PDC
981         ** supports an IRT, LBA's with no device under them
982         ** are *not* listed in the IRT.
983         ** Search the IRT and ignore iosapic's which aren't
984         ** in the IRT.
985         */
986         ASSERT(NULL != irte);   /* always have built-in devices */
987         for (cnt=0; cnt < irt_num_entry; cnt++, irte++) {
988                 ASSERT(IRT_IOSAPIC_TYPE == irte->entry_type);
989                 /*
990                 ** We need sign extension of the hpa on 32-bit kernels.
991                 ** The address in the IRT is *always* 64 bit and really
992                 ** is an unsigned quantity (like all physical addresses).
993                 */ 
994                 if (irte->dest_iosapic_addr == (s64) ((long) hpa))
995                         break;
996         }
997
998         if (cnt  >= irt_num_entry)
999                 return (NULL);
1000
1001         if ((isi = IOSAPIC_KALLOC(struct iosapic_info, 1)) == NULL) {
1002                 BUG();
1003                 return (NULL);
1004         }
1005
1006         memset(isi, 0, sizeof(struct iosapic_info));
1007
1008         isi->isi_hpa         = hpa;
1009         isi->isi_version     = iosapic_rd_version(isi);
1010         isi->isi_num_vectors = IOSAPIC_IRDT_MAX_ENTRY(isi->isi_version) + 1;
1011
1012         vip = isi->isi_vector =
1013                  IOSAPIC_KALLOC(struct vector_info, isi->isi_num_vectors);
1014
1015         if (vip == NULL) {
1016                 IOSAPIC_FREE(isi, struct iosapic_info, 1);
1017                 return (NULL);
1018         }
1019
1020         memset(vip, 0, sizeof(struct vector_info) * isi->isi_num_vectors);
1021         sprintf(isi->isi_name, "IO-SAPIC%02d", iosapic_count++);
1022
1023         /*
1024         ** Initialize vector array
1025         */
1026         for (cnt=0; cnt < isi->isi_num_vectors; cnt++, vip++) {
1027                 vip->irqline = (unsigned char) cnt;
1028                 vip->iosapic = isi;
1029                 sprintf(vip->name, "%s-L%d", isi->isi_name, cnt);
1030         }
1031
1032         isi->isi_region = alloc_irq_region(isi->isi_num_vectors,
1033                                 &iosapic_irq_ops, isi->isi_name,
1034                                 (void *) isi->isi_vector);
1035
1036         ASSERT(NULL != isi->isi_region);
1037         return ((void *) isi);
1038 }
1039
1040
1041 #ifdef DEBUG_IOSAPIC
1042
1043 static void
1044 iosapic_prt_irt(void *irt, long num_entry)
1045 {
1046         unsigned int i, *irp = (unsigned int *) irt;
1047
1048         ASSERT(NULL != irt);
1049
1050         printk(KERN_DEBUG MODULE_NAME ": Interrupt Routing Table (%lx entries)\n", num_entry);
1051
1052         for (i=0; i<num_entry; i++, irp += 4) {
1053                 printk(KERN_DEBUG "%p : %2d %.8x %.8x %.8x %.8x\n",
1054                                         irp, i, irp[0], irp[1], irp[2], irp[3]);
1055         }
1056 }
1057
1058
1059 static void
1060 iosapic_prt_vi(struct vector_info *vi)
1061 {
1062         ASSERT(NULL != vi);
1063
1064         printk(KERN_DEBUG MODULE_NAME ": vector_info[%d] is at %p\n", vi->irqline, vi);
1065         printk(KERN_DEBUG "\t\tstatus:   %.4x\n", vi->status);
1066         printk(KERN_DEBUG "\t\ttxn_irq:  %d\n",  vi->txn_irq);
1067         printk(KERN_DEBUG "\t\ttxn_addr: %lx\n", vi->txn_addr);
1068         printk(KERN_DEBUG "\t\ttxn_data: %lx\n", vi->txn_data);
1069         printk(KERN_DEBUG "\t\teoi_addr: %p\n",  vi->eoi_addr);
1070         printk(KERN_DEBUG "\t\teoi_data: %x\n",  vi->eoi_data);
1071 }
1072
1073
1074 static void
1075 iosapic_prt_isi(struct iosapic_info *isi)
1076 {
1077         ASSERT(NULL != isi);
1078         printk(KERN_DEBUG MODULE_NAME ": io_sapic_info at %p\n", isi);
1079         printk(KERN_DEBUG "\t\tisi_hpa:       %lx\n", isi->isi_hpa);
1080         printk(KERN_DEBUG "\t\tisi_status:     %x\n", isi->isi_status);
1081         printk(KERN_DEBUG "\t\tisi_version:   %x\n", isi->isi_version);
1082         printk(KERN_DEBUG "\t\tisi_vector:    %p\n", isi->isi_vector);
1083 }
1084 #endif /* DEBUG_IOSAPIC */