ftp://ftp.kernel.org/pub/linux/kernel/v2.6/linux-2.6.6.tar.bz2
[linux-2.6.git] / arch / ia64 / sn / io / platform_init / sgi_io_init.c
1 /*
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
4  * for more details.
5  *
6  * Copyright (C) 1992 - 1997, 2000-2003 Silicon Graphics, Inc. All rights reserved.
7  */
8
9 #include <linux/types.h>
10 #include <linux/config.h>
11 #include <linux/slab.h>
12 #include <linux/smp.h>
13 #include <asm/sn/sgi.h>
14 #include <asm/sn/io.h>
15 #include <asm/sn/sn_cpuid.h>
16 #include <asm/sn/klconfig.h>
17 #include <asm/sn/sn_private.h>
18 #include <asm/sn/pda.h>
19
20 extern void init_all_devices(void);
21 extern void klhwg_add_all_modules(vertex_hdl_t);
22 extern void klhwg_add_all_nodes(vertex_hdl_t);
23
24 extern int init_hcl(void);
25 extern vertex_hdl_t hwgraph_root;
26 extern void io_module_init(void);
27 extern int pci_bus_to_hcl_cvlink(void);
28
29 cpuid_t master_procid;
30 nasid_t console_nasid = (nasid_t) - 1;
31 char master_baseio_wid;
32
33 nasid_t master_baseio_nasid;
34 nasid_t master_nasid = INVALID_NASID;   /* This is the partition master nasid */
35
36 /*
37  * per_hub_init
38  *
39  *      This code is executed once for each Hub chip.
40  */
41 static void
42 per_hub_init(cnodeid_t cnode)
43 {
44         nasid_t nasid;
45         nodepda_t *npdap;
46         ii_icmr_u_t ii_icmr;
47         ii_ibcr_u_t ii_ibcr;
48         ii_ilcsr_u_t ii_ilcsr;
49
50         nasid = COMPACT_TO_NASID_NODEID(cnode);
51
52         ASSERT(nasid != INVALID_NASID);
53         ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode);
54
55         npdap = NODEPDA(cnode);
56
57         /* Disable the request and reply errors. */
58         REMOTE_HUB_S(nasid, IIO_IWEIM, 0xC000);
59
60         /*
61          * Set the total number of CRBs that can be used.
62          */
63         ii_icmr.ii_icmr_regval = 0x0;
64         ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xf;
65         if (enable_shub_wars_1_1()) {
66                 // Set bit one of ICMR to prevent II from sending interrupt for II bug.
67                 ii_icmr.ii_icmr_regval |= 0x1;
68         }
69         REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval);
70
71         /*
72          * Set the number of CRBs that both of the BTEs combined
73          * can use minus 1.
74          */
75         ii_ibcr.ii_ibcr_regval = 0x0;
76         ii_ilcsr.ii_ilcsr_regval = REMOTE_HUB_L(nasid, IIO_LLP_CSR);
77         if (ii_ilcsr.ii_ilcsr_fld_s.i_llp_stat & LNK_STAT_WORKING) {
78                 ii_ibcr.ii_ibcr_fld_s.i_count = 0x8;
79         } else {
80                 /*
81                  * if the LLP is down, there is no attached I/O, so
82                  * give BTE all the CRBs.
83                  */
84                 ii_ibcr.ii_ibcr_fld_s.i_count = 0x14;
85         }
86         REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval);
87
88         /*
89          * Set CRB timeout to be 10ms.
90          */
91         REMOTE_HUB_S(nasid, IIO_ICTP, 0xffffff);
92         REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
93
94         /* Initialize error interrupts for this hub. */
95         hub_error_init(cnode);
96 }
97
98 /*
99  * This routine is responsible for the setup of all the IRIX hwgraph style
100  * stuff that's been pulled into linux.  It's called by sn_pci_find_bios which
101  * is called just before the generic Linux PCI layer does its probing (by 
102  * platform_pci_fixup aka sn_pci_fixup).
103  *
104  * It is very IMPORTANT that this call is only made by the Master CPU!
105  *
106  */
107
108 void __init
109 sgi_master_io_infr_init(void)
110 {
111         cnodeid_t cnode;
112
113         if (init_hcl() < 0) {   /* Sets up the hwgraph compatibility layer */
114                 printk("sgi_master_io_infr_init: Cannot init hcl\n");
115                 return;
116         }
117
118         /*
119          * Initialize platform-dependent vertices in the hwgraph:
120          *      module
121          *      node
122          *      cpu
123          *      memory
124          *      slot
125          *      hub
126          *      router
127          *      xbow
128          */
129
130         io_module_init();       /* Use to be called module_init() .. */
131         klhwg_add_all_modules(hwgraph_root);
132         klhwg_add_all_nodes(hwgraph_root);
133
134         for (cnode = 0; cnode < numionodes; cnode++) {
135                 extern void per_hub_init(cnodeid_t);
136                 per_hub_init(cnode);
137         }
138
139         /*
140          *
141          * Our IO Infrastructure drivers are in place .. 
142          * Initialize the whole IO Infrastructure .. xwidget/device probes.
143          *
144          */
145         init_all_devices();
146         pci_bus_to_hcl_cvlink();
147 }
148
149 inline int
150 check_nasid_equiv(nasid_t nasida, nasid_t nasidb)
151 {
152         if ((nasida == nasidb)
153             || (nasida == NODEPDA(NASID_TO_COMPACT_NODEID(nasidb))->xbow_peer))
154                 return 1;
155         else
156                 return 0;
157 }
158
159 int
160 is_master_baseio_nasid_widget(nasid_t test_nasid, xwidgetnum_t test_wid)
161 {
162         /*
163          * If the widget numbers are different, we're not the master.
164          */
165         if (test_wid != (xwidgetnum_t) master_baseio_wid) {
166                 return 0;
167         }
168
169         /*
170          * If the NASIDs are the same or equivalent, we're the master.
171          */
172         if (check_nasid_equiv(test_nasid, master_baseio_nasid)) {
173                 return 1;
174         } else {
175                 return 0;
176         }
177 }