2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
6 * Copyright (C) 2001-2004 Silicon Graphics, Inc. All rights reserved.
9 #include <linux/types.h>
10 #include <linux/interrupt.h>
11 #include <linux/pci.h>
12 #include <asm/sn/sn_sal.h>
13 #include "xtalk/xwidgetdev.h"
14 #include <asm/sn/geo.h>
15 #include "xtalk/hubdev.h"
16 #include <asm/sn/pcibus_provider_defs.h>
17 #include <asm/sn/pcidev.h>
18 #include "pci/pcibr_provider.h"
19 #include <asm/sn/addrs.h>
22 static int sal_pcibr_error_interrupt(struct pcibus_info
*soft
)
24 struct ia64_sal_retval ret_stuff
;
31 busnum
= soft
->pbi_buscommon
.bs_persist_busnum
;
32 SAL_CALL_NOLOCK(ret_stuff
,
33 (u64
) SN_SAL_IOIF_ERROR_INTERRUPT
,
34 (u64
) segment
, (u64
) busnum
, 0, 0, 0, 0, 0);
36 return (int)ret_stuff
.v0
;
40 * PCI Bridge Error interrupt handler. Gets invoked whenever a PCI
41 * bridge sends an error interrupt.
44 pcibr_error_intr_handler(int irq
, void *arg
, struct pt_regs
*regs
)
46 struct pcibus_info
*soft
= (struct pcibus_info
*)arg
;
48 if (sal_pcibr_error_interrupt(soft
) < 0) {
49 panic("pcibr_error_intr_handler(): Fatal Bridge Error");
55 pcibr_bus_fixup(struct pcibus_bussoft
*prom_bussoft
)
58 struct hubdev_info
*hubdev_info
;
59 struct pcibus_info
*soft
;
60 struct sn_flush_device_list
*sn_flush_device_list
;
62 if (! IS_PCI_BRIDGE_ASIC(prom_bussoft
->bs_asic_type
)) {
67 * Allocate kernel bus soft and copy from prom.
70 soft
= kmalloc(sizeof(struct pcibus_info
), GFP_KERNEL
);
75 memcpy(soft
, prom_bussoft
, sizeof(struct pcibus_info
));
76 soft
->pbi_buscommon
.bs_base
=
77 (((u64
) soft
->pbi_buscommon
.
78 bs_base
<< 4) >> 4) | __IA64_UNCACHED_OFFSET
;
80 spin_lock_init(&soft
->pbi_lock
);
83 * register the bridge's error interrupt handler
85 if (request_irq(SGI_PCIBR_ERROR
, (void *)pcibr_error_intr_handler
,
86 SA_SHIRQ
, "PCIBR error", (void *)(soft
))) {
88 "pcibr cannot allocate interrupt for error handler\n");
92 * Update the Bridge with the "kernel" pagesize
94 if (PAGE_SIZE
< 16384) {
95 pcireg_control_bit_clr(soft
, PCIBR_CTRL_PAGE_SIZE
);
97 pcireg_control_bit_set(soft
, PCIBR_CTRL_PAGE_SIZE
);
100 nasid
= NASID_GET(soft
->pbi_buscommon
.bs_base
);
101 cnode
= nasid_to_cnodeid(nasid
);
102 hubdev_info
= (struct hubdev_info
*)(NODEPDA(cnode
)->pdinfo
);
104 if (hubdev_info
->hdi_flush_nasid_list
.widget_p
) {
105 sn_flush_device_list
= hubdev_info
->hdi_flush_nasid_list
.
106 widget_p
[(int)soft
->pbi_buscommon
.bs_xid
];
107 if (sn_flush_device_list
) {
108 for (j
= 0; j
< DEV_PER_WIDGET
;
109 j
++, sn_flush_device_list
++) {
110 if (sn_flush_device_list
->sfdl_slot
== -1)
112 if (sn_flush_device_list
->
113 sfdl_persistent_busnum
==
114 soft
->pbi_buscommon
.bs_persist_busnum
)
115 sn_flush_device_list
->sfdl_pcibus_info
=
121 /* Setup the PMU ATE map */
122 soft
->pbi_int_ate_resource
.lowest_free_index
= 0;
123 soft
->pbi_int_ate_resource
.ate
=
124 kmalloc(soft
->pbi_int_ate_size
* sizeof(uint64_t), GFP_KERNEL
);
125 memset(soft
->pbi_int_ate_resource
.ate
, 0,
126 (soft
->pbi_int_ate_size
* sizeof(uint64_t)));
131 void pcibr_force_interrupt(struct sn_irq_info
*sn_irq_info
)
133 struct pcidev_info
*pcidev_info
;
134 struct pcibus_info
*pcibus_info
;
135 int bit
= sn_irq_info
->irq_int_bit
;
137 pcidev_info
= (struct pcidev_info
*)sn_irq_info
->irq_pciioinfo
;
140 (struct pcibus_info
*)pcidev_info
->pdi_host_pcidev_info
->
142 pcireg_force_intr_set(pcibus_info
, bit
);
146 void pcibr_change_devices_irq(struct sn_irq_info
*sn_irq_info
)
148 struct pcidev_info
*pcidev_info
;
149 struct pcibus_info
*pcibus_info
;
150 int bit
= sn_irq_info
->irq_int_bit
;
151 uint64_t xtalk_addr
= sn_irq_info
->irq_xtalkaddr
;
153 pcidev_info
= (struct pcidev_info
*)sn_irq_info
->irq_pciioinfo
;
156 (struct pcibus_info
*)pcidev_info
->pdi_host_pcidev_info
->
159 /* Disable the device's IRQ */
160 pcireg_intr_enable_bit_clr(pcibus_info
, bit
);
162 /* Change the device's IRQ */
163 pcireg_intr_addr_addr_set(pcibus_info
, bit
, xtalk_addr
);
165 /* Re-enable the device's IRQ */
166 pcireg_intr_enable_bit_set(pcibus_info
, bit
);
168 pcibr_force_interrupt(sn_irq_info
);
173 * Provider entries for PIC/CP
176 struct sn_pcibus_provider pcibr_provider
= {
177 .dma_map
= pcibr_dma_map
,
178 .dma_map_consistent
= pcibr_dma_map_consistent
,
179 .dma_unmap
= pcibr_dma_unmap
,
180 .bus_fixup
= pcibr_bus_fixup
,
184 pcibr_init_provider(void)
186 sn_pci_provider
[PCIIO_ASIC_TYPE_PIC
] = &pcibr_provider
;
187 sn_pci_provider
[PCIIO_ASIC_TYPE_TIOCP
] = &pcibr_provider
;