patch-2_6_7-vs1_9_1_12
[linux-2.6.git] / arch / ia64 / sn / io / sn2 / pic.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) 2001-2003 Silicon Graphics, Inc. All rights reserved.
7  */
8
9 #include <linux/interrupt.h>
10 #include <asm/sn/sn_cpuid.h>
11 #include <asm/sn/iograph.h>
12 #include <asm/sn/hcl_util.h>
13 #include <asm/sn/pci/pciio.h>
14 #include <asm/sn/pci/pcibr.h>
15 #include <asm/sn/pci/pcibr_private.h>
16 #include <asm/sn/pci/pci_defs.h>
17 #include <asm/sn/pci/pic.h>
18 #include <asm/sn/sn_private.h>
19
20 extern struct file_operations pcibr_fops;
21 extern pcibr_list_p     pcibr_list;
22
23 static int              pic_attach2(vertex_hdl_t, void *, vertex_hdl_t,
24                                 int, pcibr_soft_t *);
25
26 extern int              isIO9(nasid_t);
27 extern char            *dev_to_name(vertex_hdl_t dev, char *buf, uint buflen);
28 extern int              pcibr_widget_to_bus(vertex_hdl_t pcibr_vhdl);
29 extern pcibr_hints_t    pcibr_hints_get(vertex_hdl_t, int);
30 extern unsigned         pcibr_intr_bits(pciio_info_t info,
31                                 pciio_intr_line_t lines, int nslots);
32 extern void             pcibr_setwidint(xtalk_intr_t);
33 extern int              pcibr_error_handler_wrapper(error_handler_arg_t, int,
34                                 ioerror_mode_t, ioerror_t *);
35 extern void             pcibr_error_intr_handler(intr_arg_t);
36 extern void             pcibr_directmap_init(pcibr_soft_t);
37 extern int              pcibr_slot_info_init(vertex_hdl_t,pciio_slot_t);
38 extern int              pcibr_slot_addr_space_init(vertex_hdl_t,pciio_slot_t);
39 extern int              pcibr_slot_device_init(vertex_hdl_t, pciio_slot_t);
40 extern int              pcibr_slot_pcix_rbar_init(pcibr_soft_t, pciio_slot_t);
41 extern int              pcibr_slot_guest_info_init(vertex_hdl_t,pciio_slot_t);
42 extern int              pcibr_slot_call_device_attach(vertex_hdl_t,
43                                 pciio_slot_t, int);
44 extern void             pcibr_rrb_alloc_init(pcibr_soft_t, int, int, int);
45 extern int              pcibr_pcix_rbars_calc(pcibr_soft_t);
46 extern pcibr_info_t     pcibr_device_info_new(pcibr_soft_t, pciio_slot_t,
47                                 pciio_function_t, pciio_vendor_id_t,
48                                 pciio_device_id_t);
49 extern int              pcibr_initial_rrb(vertex_hdl_t, pciio_slot_t, 
50                                 pciio_slot_t);
51 extern void             xwidget_error_register(vertex_hdl_t, error_handler_f *,
52                                 error_handler_arg_t);
53 extern void             pcibr_clearwidint(pcibr_soft_t);
54
55
56
57 /*
58  * copy xwidget_info_t from conn_v to peer_conn_v
59  */
60 static int
61 pic_bus1_widget_info_dup(vertex_hdl_t conn_v, vertex_hdl_t peer_conn_v,
62                                         cnodeid_t xbow_peer, char *peer_path)
63 {
64         xwidget_info_t widget_info, peer_widget_info;
65         vertex_hdl_t peer_hubv;
66         hubinfo_t peer_hub_info;
67
68         /* get the peer hub's widgetid */
69         peer_hubv = NODEPDA(xbow_peer)->node_vertex;
70         peer_hub_info = NULL;
71         hubinfo_get(peer_hubv, &peer_hub_info);
72         if (peer_hub_info == NULL)
73                 return 0;
74
75         if (hwgraph_info_get_LBL(conn_v, INFO_LBL_XWIDGET,
76                         (arbitrary_info_t *)&widget_info) == GRAPH_SUCCESS) {
77                 peer_widget_info = kmalloc(sizeof (*(peer_widget_info)), GFP_KERNEL);
78                 if ( !peer_widget_info ) {
79                         return -ENOMEM;
80                 }
81                 memset(peer_widget_info, 0, sizeof (*(peer_widget_info)));
82
83                 peer_widget_info->w_fingerprint = widget_info_fingerprint;
84                 peer_widget_info->w_vertex = peer_conn_v;
85                 peer_widget_info->w_id = widget_info->w_id;
86                 peer_widget_info->w_master = peer_hubv;
87                 peer_widget_info->w_masterid = peer_hub_info->h_widgetid;
88                 /* structure copy */
89                 peer_widget_info->w_hwid = widget_info->w_hwid;
90                 peer_widget_info->w_efunc = 0;
91                 peer_widget_info->w_einfo = 0;
92                 peer_widget_info->w_name = kmalloc(strlen(peer_path) + 1, GFP_KERNEL);
93                 if (!peer_widget_info->w_name) {
94                         kfree(peer_widget_info);
95                         return -ENOMEM;
96                 }
97                 strcpy(peer_widget_info->w_name, peer_path);
98
99                 if (hwgraph_info_add_LBL(peer_conn_v, INFO_LBL_XWIDGET,
100                         (arbitrary_info_t)peer_widget_info) != GRAPH_SUCCESS) {
101                         kfree(peer_widget_info->w_name);
102                                 kfree(peer_widget_info);
103                                 return 0;
104                 }
105
106                 xwidget_info_set(peer_conn_v, peer_widget_info);
107
108                 return 1;
109         }
110
111         printk("pic_bus1_widget_info_dup: "
112                         "cannot get INFO_LBL_XWIDGET from 0x%lx\n", (uint64_t)conn_v);
113         return 0;
114 }
115
116 /*
117  * If this PIC is attached to two Cbricks ("dual-ported") then
118  * attach each bus to opposite Cbricks.
119  *
120  * If successful, return a new vertex suitable for attaching the PIC bus.
121  * If not successful, return zero and both buses will attach to the
122  * vertex passed into pic_attach().
123  */
124 static vertex_hdl_t
125 pic_bus1_redist(nasid_t nasid, vertex_hdl_t conn_v)
126 {
127         cnodeid_t cnode = nasid_to_cnodeid(nasid);
128         cnodeid_t xbow_peer = -1;
129         char pathname[256], peer_path[256], tmpbuf[256];
130         char *p;
131         int rc;
132         vertex_hdl_t peer_conn_v, hubv;
133         int pos;
134         slabid_t slab;
135
136         if (NODEPDA(cnode)->xbow_peer >= 0) {                   /* if dual-ported */
137                 /* create a path for this widget on the peer Cbrick */
138                 /* pcibr widget hw/module/001c11/slab/0/Pbrick/xtalk/12 */
139                 /* sprintf(pathname, "%v", conn_v); */
140                 xbow_peer = nasid_to_cnodeid(NODEPDA(cnode)->xbow_peer);
141                 pos = hwgfs_generate_path(conn_v, tmpbuf, 256);
142                 strcpy(pathname, &tmpbuf[pos]);
143                 p = pathname + strlen("hw/module/001c01/slab/0/");
144
145                 memset(tmpbuf, 0, 16);
146                 format_module_id(tmpbuf, geo_module((NODEPDA(xbow_peer))->geoid), MODULE_FORMAT_BRIEF);
147                 slab = geo_slab((NODEPDA(xbow_peer))->geoid);
148                 sprintf(peer_path, "module/%s/slab/%d/%s", tmpbuf, (int)slab, p); 
149                 
150                 /* Look for vertex for this widget on the peer Cbrick.
151                  * Expect GRAPH_NOT_FOUND.
152                  */
153                 rc = hwgraph_traverse(hwgraph_root, peer_path, &peer_conn_v);
154                 if (GRAPH_SUCCESS == rc)
155                         printk("pic_attach: found unexpected vertex: 0x%lx\n",
156                                                                 (uint64_t)peer_conn_v);
157                 else if (GRAPH_NOT_FOUND != rc) {
158                         printk("pic_attach: hwgraph_traverse unexpectedly"
159                                         " returned 0x%x\n", rc);
160                 } else {
161                         /* try to add the widget vertex to the peer Cbrick */
162                         rc = hwgraph_path_add(hwgraph_root, peer_path, &peer_conn_v);
163
164                         if (GRAPH_SUCCESS != rc)
165                             printk("pic_attach: hwgraph_path_add"
166                                                 " failed with 0x%x\n", rc);
167                         else {
168                             PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
169                                         "pic_bus1_redist: added vertex %v\n", peer_conn_v)); 
170
171                             /* Now hang appropiate stuff off of the new
172                              * vertex.  We bail out if we cannot add something.
173                              * In that case, we don't remove the newly added
174                              * vertex but that should be safe and we don't
175                              * really expect the additions to fail anyway.
176                              */
177                             if (!pic_bus1_widget_info_dup(conn_v, peer_conn_v, 
178                                                           xbow_peer, peer_path))
179                                         return 0;
180
181                             hubv = cnodeid_to_vertex(xbow_peer);
182                             ASSERT(hubv != GRAPH_VERTEX_NONE);
183                             device_master_set(peer_conn_v, hubv);
184                             xtalk_provider_register(hubv, &hub_provider);
185                             xtalk_provider_startup(hubv);
186                             return peer_conn_v;
187                         }
188                 }
189         }
190         return 0;
191 }
192
193 /*
194  * PIC has two buses under a single widget.  pic_attach() calls pic_attach2()
195  * to attach each of those buses.
196  */
197 int
198 pic_attach(vertex_hdl_t conn_v)
199 {
200         int             rc;
201         void    *bridge0, *bridge1 = (void *)0;
202         vertex_hdl_t    pcibr_vhdl0, pcibr_vhdl1 = (vertex_hdl_t)0;
203         pcibr_soft_t    bus0_soft, bus1_soft = (pcibr_soft_t)0;
204         vertex_hdl_t  conn_v0, conn_v1, peer_conn_v;
205         int             bricktype;
206         int             iobrick_type_get_nasid(nasid_t nasid);
207
208         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v, "pic_attach()\n"));
209
210         bridge0 = pcibr_bridge_ptr_get(conn_v, 0);
211         bridge1 = pcibr_bridge_ptr_get(conn_v, 1);
212
213         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
214                     "pic_attach: bridge0=0x%lx, bridge1=0x%lx\n", 
215                     bridge0, bridge1));
216
217         conn_v0 = conn_v1 = conn_v;
218
219         /* If dual-ported then split the two PIC buses across both Cbricks */
220         peer_conn_v = pic_bus1_redist(NASID_GET(bridge0), conn_v);
221         if (peer_conn_v)
222                 conn_v1 = peer_conn_v;
223
224         /*
225          * Create the vertex for the PCI buses, which we
226          * will also use to hold the pcibr_soft and
227          * which will be the "master" vertex for all the
228          * pciio connection points we will hang off it.
229          * This needs to happen before we call nic_bridge_vertex_info
230          * as we are some of the *_vmc functions need access to the edges.
231          *
232          * Opening this vertex will provide access to
233          * the Bridge registers themselves.
234          */
235         bricktype = iobrick_type_get_nasid(NASID_GET(bridge0));
236         if ( bricktype == MODULE_CGBRICK ) {
237                 rc = hwgraph_path_add(conn_v0, EDGE_LBL_AGP_0, &pcibr_vhdl0);
238                 ASSERT(rc == GRAPH_SUCCESS);
239                 rc = hwgraph_path_add(conn_v1, EDGE_LBL_AGP_1, &pcibr_vhdl1);
240                 ASSERT(rc == GRAPH_SUCCESS);
241         } else {
242                 rc = hwgraph_path_add(conn_v0, EDGE_LBL_PCIX_0, &pcibr_vhdl0);
243                 ASSERT(rc == GRAPH_SUCCESS);
244                 rc = hwgraph_path_add(conn_v1, EDGE_LBL_PCIX_1, &pcibr_vhdl1);
245                 ASSERT(rc == GRAPH_SUCCESS);
246         }
247
248         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
249                     "pic_attach: pcibr_vhdl0=0x%lx, pcibr_vhdl1=0x%lx\n",
250                     pcibr_vhdl0, pcibr_vhdl1));
251
252         /* register pci provider array */
253         pciio_provider_register(pcibr_vhdl0, &pci_pic_provider);
254         pciio_provider_register(pcibr_vhdl1, &pci_pic_provider);
255
256         pciio_provider_startup(pcibr_vhdl0);
257         pciio_provider_startup(pcibr_vhdl1);
258
259         pic_attach2(conn_v0, bridge0, pcibr_vhdl0, 0, &bus0_soft);
260         pic_attach2(conn_v1, bridge1, pcibr_vhdl1, 1, &bus1_soft);
261
262         {
263             /* If we're dual-ported finish duplicating the peer info structure.
264              * The error handler and arg are done in pic_attach2().
265              */
266             xwidget_info_t info0, info1;
267                 if (conn_v0 != conn_v1) {       /* dual ported */
268                         info0 = xwidget_info_get(conn_v0);
269                         info1 = xwidget_info_get(conn_v1);
270                         if (info1->w_efunc == (error_handler_f *)NULL)
271                                 info1->w_efunc = info0->w_efunc;
272                         if (info1->w_einfo == (error_handler_arg_t)0)
273                                 info1->w_einfo = bus1_soft;
274                 }
275         }
276
277         /* save a pointer to the PIC's other bus's soft struct */
278         bus0_soft->bs_peers_soft = bus1_soft;
279         bus1_soft->bs_peers_soft = bus0_soft;
280
281         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, conn_v,
282                     "pic_attach: bus0_soft=0x%lx, bus1_soft=0x%lx\n",
283                     bus0_soft, bus1_soft));
284
285         return 0;
286 }
287
288
289 /*
290  * PIC has two buses under a single widget.  pic_attach() calls pic_attach2()
291  * to attach each of those buses.
292  */
293 static int
294 pic_attach2(vertex_hdl_t xconn_vhdl, void *bridge,
295               vertex_hdl_t pcibr_vhdl, int busnum, pcibr_soft_t *ret_softp)
296 {
297     vertex_hdl_t            ctlr_vhdl;
298     pcibr_soft_t            pcibr_soft;
299     pcibr_info_t            pcibr_info;
300     xwidget_info_t          info;
301     xtalk_intr_t            xtalk_intr;
302     pcibr_list_p            self;
303     int                     entry, slot, ibit, i;
304     vertex_hdl_t            noslot_conn;
305     char                    devnm[MAXDEVNAME], *s;
306     pcibr_hints_t           pcibr_hints;
307     picreg_t                id;
308     picreg_t                int_enable;
309     picreg_t                pic_ctrl_reg;
310
311     int                     iobrick_type_get_nasid(nasid_t nasid);
312     int                     iomoduleid_get(nasid_t nasid);
313     int                     irq;
314     int                     cpu;
315
316     PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,
317                 "pic_attach2: bridge=0x%lx, busnum=%d\n", bridge, busnum));
318
319     ctlr_vhdl = NULL;
320     ctlr_vhdl = hwgraph_register(pcibr_vhdl, EDGE_LBL_CONTROLLER, 0,
321                 0, 0, 0,
322                 S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
323                 (struct file_operations *)&pcibr_fops, (void *)pcibr_vhdl);
324     ASSERT(ctlr_vhdl != NULL);
325
326     id = pcireg_bridge_id_get(bridge);
327     hwgraph_info_add_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV,
328                          (arbitrary_info_t)XWIDGET_PART_REV_NUM(id));
329
330     /*
331      * Get the hint structure; if some NIC callback marked this vertex as
332      * "hands-off" then we just return here, before doing anything else.
333      */
334     pcibr_hints = pcibr_hints_get(xconn_vhdl, 0);
335
336     if (pcibr_hints && pcibr_hints->ph_hands_off)
337         return -1;
338
339     /* allocate soft structure to hang off the vertex.  Link the new soft
340      * structure to the pcibr_list linked list
341      */
342     pcibr_soft = kmalloc(sizeof (*(pcibr_soft)), GFP_KERNEL);
343     if ( !pcibr_soft )
344         return -ENOMEM;
345
346     self = kmalloc(sizeof (*(self)), GFP_KERNEL);
347     if ( !self ) {
348         kfree(pcibr_soft);
349         return -ENOMEM;
350     }
351     memset(pcibr_soft, 0, sizeof (*(pcibr_soft)));
352     memset(self, 0, sizeof (*(self)));
353
354     self->bl_soft = pcibr_soft;
355     self->bl_vhdl = pcibr_vhdl;
356     self->bl_next = pcibr_list;
357     pcibr_list = self;
358
359     if (ret_softp)
360         *ret_softp = pcibr_soft;
361
362     memset(pcibr_soft, 0, sizeof *pcibr_soft);
363     pcibr_soft_set(pcibr_vhdl, pcibr_soft);
364
365     s = dev_to_name(pcibr_vhdl, devnm, MAXDEVNAME);
366     pcibr_soft->bs_name = kmalloc(strlen(s) + 1, GFP_KERNEL);
367     if (!pcibr_soft->bs_name)
368             return -ENOMEM;
369
370     strcpy(pcibr_soft->bs_name, s);
371
372     pcibr_soft->bs_conn = xconn_vhdl;
373     pcibr_soft->bs_vhdl = pcibr_vhdl;
374     pcibr_soft->bs_base = (void *)bridge;
375     pcibr_soft->bs_rev_num = XWIDGET_PART_REV_NUM(id);
376     pcibr_soft->bs_intr_bits = (pcibr_intr_bits_f *)pcibr_intr_bits;
377     pcibr_soft->bsi_err_intr = 0;
378     pcibr_soft->bs_min_slot = 0;
379     pcibr_soft->bs_max_slot = 3;
380     pcibr_soft->bs_busnum = busnum;
381     pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_PIC;
382     pcibr_soft->bs_int_ate_size = PIC_INTERNAL_ATES;
383     /* Make sure this is called after setting the bs_base and bs_bridge_type */
384     pcibr_soft->bs_bridge_mode = (pcireg_speed_get(pcibr_soft) << 1) |
385                                   pcireg_mode_get(pcibr_soft);
386
387     info = xwidget_info_get(xconn_vhdl);
388     pcibr_soft->bs_xid = xwidget_info_id_get(info);
389     pcibr_soft->bs_master = xwidget_info_master_get(info);
390     pcibr_soft->bs_mxid = xwidget_info_masterid_get(info);
391
392     strcpy(pcibr_soft->bs_asic_name, "PIC");
393
394     PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,
395                 "pic_attach2: pcibr_soft=0x%lx, mode=0x%x\n",
396                 pcibr_soft, pcibr_soft->bs_bridge_mode));
397
398     PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,
399                 "pic_attach2: %s ASIC: rev %s (code=0x%x)\n",
400                 pcibr_soft->bs_asic_name,
401                 (IS_PIC_PART_REV_A(pcibr_soft->bs_rev_num)) ? "A" :
402                 (IS_PIC_PART_REV_B(pcibr_soft->bs_rev_num)) ? "B" :
403                 (IS_PIC_PART_REV_C(pcibr_soft->bs_rev_num)) ? "C" :
404                 "unknown", pcibr_soft->bs_rev_num));
405
406     /* PV854845: Must clear write request buffer to avoid parity errors */
407     for (i=0; i < PIC_WR_REQ_BUFSIZE; i++) {
408         ((pic_t *)bridge)->p_wr_req_lower[i] = 0;
409         ((pic_t *)bridge)->p_wr_req_upper[i] = 0;
410         ((pic_t *)bridge)->p_wr_req_parity[i] = 0;
411     }
412
413     pcibr_soft->bs_nasid = NASID_GET(bridge);
414
415     pcibr_soft->bs_bricktype = iobrick_type_get_nasid(pcibr_soft->bs_nasid);
416     if (pcibr_soft->bs_bricktype < 0)
417         printk(KERN_WARNING "%s: bricktype was unknown by L1 (ret val = 0x%x)\n",
418                 pcibr_soft->bs_name, pcibr_soft->bs_bricktype);
419
420     pcibr_soft->bs_moduleid = iomoduleid_get(pcibr_soft->bs_nasid);
421
422     if (pcibr_soft->bs_bricktype > 0) {
423         switch (pcibr_soft->bs_bricktype) {
424         case MODULE_PXBRICK:
425         case MODULE_IXBRICK:
426         case MODULE_OPUSBRICK:
427             pcibr_soft->bs_first_slot = 0;
428             pcibr_soft->bs_last_slot = 1;
429             pcibr_soft->bs_last_reset = 1;
430
431             /* Bus 1 of IXBrick has a IO9, so there are 4 devices, not 2 */
432             if ((pcibr_widget_to_bus(pcibr_vhdl) == 1) 
433                     && isIO9(pcibr_soft->bs_nasid)) {
434                 pcibr_soft->bs_last_slot = 3;
435                 pcibr_soft->bs_last_reset = 3;
436             }
437             break;
438
439         case MODULE_CGBRICK:
440             pcibr_soft->bs_first_slot = 0;
441             pcibr_soft->bs_last_slot = 0;
442             pcibr_soft->bs_last_reset = 0;
443             break;
444
445         default:
446             printk(KERN_WARNING "%s: Unknown bricktype: 0x%x\n",
447                     pcibr_soft->bs_name, pcibr_soft->bs_bricktype);
448             break;
449         }
450
451         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,
452                     "pic_attach2: bricktype=%d, brickbus=%d, "
453                     "slots %d-%d\n", pcibr_soft->bs_bricktype,
454                     pcibr_widget_to_bus(pcibr_vhdl),
455                     pcibr_soft->bs_first_slot, pcibr_soft->bs_last_slot));
456     }
457
458     /*
459      * Initialize bridge and bus locks
460      */
461     spin_lock_init(&pcibr_soft->bs_lock);
462
463     /*
464      * If we have one, process the hints structure.
465      */
466     if (pcibr_hints) {
467         unsigned        rrb_fixed;
468         PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, pcibr_vhdl,
469                     "pic_attach2: pcibr_hints=0x%lx\n", pcibr_hints));
470
471         rrb_fixed = pcibr_hints->ph_rrb_fixed;
472
473         pcibr_soft->bs_rrb_fixed = rrb_fixed;
474
475         if (pcibr_hints->ph_intr_bits)
476             pcibr_soft->bs_intr_bits = pcibr_hints->ph_intr_bits;
477
478
479         for (slot = pcibr_soft->bs_min_slot;
480                                 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
481             int hslot = pcibr_hints->ph_host_slot[slot] - 1;
482
483             if (hslot < 0) {
484                 pcibr_soft->bs_slot[slot].host_slot = slot;
485             } else {
486                 pcibr_soft->bs_slot[slot].has_host = 1;
487                 pcibr_soft->bs_slot[slot].host_slot = hslot;
488             }
489         }
490     }
491
492     /*
493      * Set-up initial values for state fields
494      */
495     for (slot = pcibr_soft->bs_min_slot;
496                                 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
497         pcibr_soft->bs_slot[slot].bss_devio.bssd_space = PCIIO_SPACE_NONE;
498         pcibr_soft->bs_slot[slot].bss_devio.bssd_ref_cnt = 0;
499         pcibr_soft->bs_slot[slot].bss_d64_base = PCIBR_D64_BASE_UNSET;
500         pcibr_soft->bs_slot[slot].bss_d32_base = PCIBR_D32_BASE_UNSET;
501         pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN0] = -1;
502     }
503
504     for (ibit = 0; ibit < 8; ++ibit) {
505         pcibr_soft->bs_intr[ibit].bsi_xtalk_intr = 0;
506         pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_soft = pcibr_soft;
507         pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_list = NULL;
508         pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_ibit = ibit;
509         pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_hdlrcnt = 0;
510         pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_shared = 0;
511         pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_connected = 0;
512     }
513
514
515     /*
516      * connect up our error handler.  PIC has 2 busses (thus resulting in 2
517      * pcibr_soft structs under 1 widget), so only register a xwidget error
518      * handler for PIC's bus0.  NOTE: for PIC pcibr_error_handler_wrapper()
519      * is a wrapper routine we register that will call the real error handler
520      * pcibr_error_handler() with the correct pcibr_soft struct.
521      */
522     if (busnum == 0) {
523         xwidget_error_register(xconn_vhdl,
524                                 pcibr_error_handler_wrapper, pcibr_soft);
525     }
526
527     /*
528      * Clear all pending interrupts.  Assume all interrupts are from slot 3
529      * until otherise setup.
530      */
531     pcireg_intr_reset_set(pcibr_soft, PIC_IRR_ALL_CLR);
532     pcireg_intr_device_set(pcibr_soft, 0x006db6db);
533
534     /* Setup the mapping register used for direct mapping */
535     pcibr_directmap_init(pcibr_soft);
536
537     /*
538      * Initialize the PICs control register.
539      */
540     pic_ctrl_reg = pcireg_control_get(pcibr_soft);
541
542     /* Bridges Requester ID: bus = busnum, dev = 0, func = 0 */
543     pic_ctrl_reg &= ~PIC_CTRL_BUS_NUM_MASK;
544     pic_ctrl_reg |= PIC_CTRL_BUS_NUM(busnum);
545     pic_ctrl_reg &= ~PIC_CTRL_DEV_NUM_MASK;
546     pic_ctrl_reg &= ~PIC_CTRL_FUN_NUM_MASK;
547
548     pic_ctrl_reg &= ~PIC_CTRL_NO_SNOOP;
549     pic_ctrl_reg &= ~PIC_CTRL_RELAX_ORDER;
550
551     /* enable parity checking on PICs internal RAM */
552     pic_ctrl_reg |= PIC_CTRL_PAR_EN_RESP;
553     pic_ctrl_reg |= PIC_CTRL_PAR_EN_ATE;
554
555     /* PIC BRINGUP WAR (PV# 862253): dont enable write request parity */
556     if (!PCIBR_WAR_ENABLED(PV862253, pcibr_soft)) {
557         pic_ctrl_reg |= PIC_CTRL_PAR_EN_REQ;
558     }
559
560     pic_ctrl_reg |= PIC_CTRL_PAGE_SIZE;
561
562     pcireg_control_set(pcibr_soft, pic_ctrl_reg);
563
564     /* Initialize internal mapping entries (ie. the ATEs) */
565     for (entry = 0; entry < pcibr_soft->bs_int_ate_size; entry++)
566         pcireg_int_ate_set(pcibr_soft, entry, 0);
567
568     pcibr_soft->bs_int_ate_resource.start = 0;
569     pcibr_soft->bs_int_ate_resource.end = pcibr_soft->bs_int_ate_size - 1;
570
571     /* Setup the PICs error interrupt handler. */
572     xtalk_intr = xtalk_intr_alloc(xconn_vhdl, (device_desc_t)0, pcibr_vhdl);
573
574     ASSERT(xtalk_intr != NULL);
575
576     irq = ((hub_intr_t)xtalk_intr)->i_bit;
577     cpu = ((hub_intr_t)xtalk_intr)->i_cpuid;
578
579     intr_unreserve_level(cpu, irq);
580     ((hub_intr_t)xtalk_intr)->i_bit = SGI_PCIBR_ERROR;
581     xtalk_intr->xi_vector = SGI_PCIBR_ERROR;
582
583     pcibr_soft->bsi_err_intr = xtalk_intr;
584
585     /*
586      * On IP35 with XBridge, we do some extra checks in pcibr_setwidint
587      * in order to work around some addressing limitations.  In order
588      * for that fire wall to work properly, we need to make sure we
589      * start from a known clean state.
590      */
591     pcibr_clearwidint(pcibr_soft);
592
593     xtalk_intr_connect(xtalk_intr,
594                        (intr_func_t) pcibr_error_intr_handler,
595                        (intr_arg_t) pcibr_soft,
596                        (xtalk_intr_setfunc_t) pcibr_setwidint,
597                        (void *) pcibr_soft);
598
599     request_irq(SGI_PCIBR_ERROR, (void *)pcibr_error_intr_handler, SA_SHIRQ, 
600                         "PCIBR error", (intr_arg_t) pcibr_soft);
601
602     PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_vhdl,
603                 "pcibr_setwidint: target_id=0x%lx, int_addr=0x%lx\n",
604                 pcireg_intr_dst_target_id_get(pcibr_soft),
605                 pcireg_intr_dst_addr_get(pcibr_soft)));
606
607     /* now we can start handling error interrupts */
608     int_enable = pcireg_intr_enable_get(pcibr_soft);
609     int_enable |= PIC_ISR_ERRORS;
610
611     /* PIC BRINGUP WAR (PV# 856864 & 856865): allow the tnums that are
612      * locked out to be freed up sooner (by timing out) so that the
613      * read tnums are never completely used up.
614      */
615     if (PCIBR_WAR_ENABLED(PV856864, pcibr_soft)) {
616         int_enable &= ~PIC_ISR_PCIX_REQ_TOUT;
617         int_enable &= ~PIC_ISR_XREAD_REQ_TIMEOUT;
618
619         pcireg_req_timeout_set(pcibr_soft, 0x750);
620     }
621
622     pcireg_intr_enable_set(pcibr_soft, int_enable);
623     pcireg_intr_mode_set(pcibr_soft, 0); /* dont send 'clear interrupt' pkts */
624     pcireg_tflush_get(pcibr_soft);       /* wait until Bridge PIO complete */
625
626     /*
627      * PIC BRINGUP WAR (PV# 856866, 859504, 861476, 861478): Don't use
628      * RRB0, RRB8, RRB1, and RRB9.  Assign them to DEVICE[2|3]--VCHAN3
629      * so they are not used.  This works since there is currently no
630      * API to penable VCHAN3.
631      */
632     if (PCIBR_WAR_ENABLED(PV856866, pcibr_soft)) {
633         pcireg_rrb_bit_set(pcibr_soft, 0, 0x000f000f);  /* even rrb reg */
634         pcireg_rrb_bit_set(pcibr_soft, 1, 0x000f000f);  /* odd rrb reg */
635     }
636
637     /* PIC only supports 64-bit direct mapping in PCI-X mode.  Since
638      * all PCI-X devices that initiate memory transactions must be
639      * capable of generating 64-bit addressed, we force 64-bit DMAs.
640      */
641     pcibr_soft->bs_dma_flags = 0;
642     if (IS_PCIX(pcibr_soft)) {
643         pcibr_soft->bs_dma_flags |= PCIIO_DMA_A64;
644     }
645
646     {
647
648     iopaddr_t               prom_base_addr = pcibr_soft->bs_xid << 24;
649     int                     prom_base_size = 0x1000000;
650     int                     status;
651     struct resource         *res;
652
653     /* Allocate resource maps based on bus page size; for I/O and memory
654      * space, free all pages except those in the base area and in the
655      * range set by the PROM.
656      *
657      * PROM creates BAR addresses in this format: 0x0ws00000 where w is
658      * the widget number and s is the device register offset for the slot.
659      */
660
661     /* Setup the Bus's PCI IO Root Resource. */
662     pcibr_soft->bs_io_win_root_resource.start = PCIBR_BUS_IO_BASE;
663     pcibr_soft->bs_io_win_root_resource.end = 0xffffffff;
664     res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL);
665     if (!res)
666         panic("PCIBR:Unable to allocate resource structure\n");
667
668     /* Block off the range used by PROM. */
669     res->start = prom_base_addr;
670     res->end = prom_base_addr + (prom_base_size - 1);
671     status = request_resource(&pcibr_soft->bs_io_win_root_resource, res);
672     if (status)
673         panic("PCIBR:Unable to request_resource()\n");
674
675     /* Setup the Small Window Root Resource */
676     pcibr_soft->bs_swin_root_resource.start = PAGE_SIZE;
677     pcibr_soft->bs_swin_root_resource.end = 0x000FFFFF;
678
679     /* Setup the Bus's PCI Memory Root Resource */
680     pcibr_soft->bs_mem_win_root_resource.start = 0x200000;
681     pcibr_soft->bs_mem_win_root_resource.end = 0xffffffff;
682     res = (struct resource *) kmalloc( sizeof(struct resource), GFP_KERNEL);
683     if (!res)
684         panic("PCIBR:Unable to allocate resource structure\n");
685
686     /* Block off the range used by PROM. */
687     res->start = prom_base_addr;
688     res->end = prom_base_addr + (prom_base_size - 1);
689     status = request_resource(&pcibr_soft->bs_mem_win_root_resource, res);
690     if (status)
691         panic("PCIBR:Unable to request_resource()\n");
692
693     }
694
695
696     /* build "no-slot" connection point */
697     pcibr_info = pcibr_device_info_new(pcibr_soft, PCIIO_SLOT_NONE,
698                  PCIIO_FUNC_NONE, PCIIO_VENDOR_ID_NONE, PCIIO_DEVICE_ID_NONE);
699     noslot_conn = pciio_device_info_register(pcibr_vhdl, &pcibr_info->f_c);
700
701     /* Store no slot connection point info for tearing it down during detach. */
702     pcibr_soft->bs_noslot_conn = noslot_conn;
703     pcibr_soft->bs_noslot_info = pcibr_info;
704
705     for (slot = pcibr_soft->bs_min_slot;
706                                 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
707         /* Find out what is out there */
708         (void)pcibr_slot_info_init(pcibr_vhdl, slot);
709     }
710
711     for (slot = pcibr_soft->bs_min_slot;
712                                 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
713         /* Set up the address space for this slot in the PCI land */
714         (void)pcibr_slot_addr_space_init(pcibr_vhdl, slot);
715     }
716
717     for (slot = pcibr_soft->bs_min_slot;
718                                 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
719         /* Setup the device register */
720         (void)pcibr_slot_device_init(pcibr_vhdl, slot);
721     }
722
723     if (IS_PCIX(pcibr_soft)) {
724         pcibr_soft->bs_pcix_rbar_inuse = 0;
725         pcibr_soft->bs_pcix_rbar_avail = NUM_RBAR;
726         pcibr_soft->bs_pcix_rbar_percent_allowed =
727                                         pcibr_pcix_rbars_calc(pcibr_soft);
728
729         for (slot = pcibr_soft->bs_min_slot;
730                                 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
731             /* Setup the PCI-X Read Buffer Attribute Registers (RBARs) */
732             (void)pcibr_slot_pcix_rbar_init(pcibr_soft, slot);
733         }
734     }
735
736     for (slot = pcibr_soft->bs_min_slot;
737                                 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
738         /* Setup host/guest relations */
739         (void)pcibr_slot_guest_info_init(pcibr_vhdl, slot);
740     }
741
742     /* Handle initial RRB management */
743     pcibr_initial_rrb(pcibr_vhdl,
744                       pcibr_soft->bs_first_slot, pcibr_soft->bs_last_slot);
745
746    /* Before any drivers get called that may want to re-allocate RRB's,
747     * let's get some special cases pre-allocated. Drivers may override
748     * these pre-allocations, but by doing pre-allocations now we're
749     * assured not to step all over what the driver intended.
750     */
751     if (pcibr_soft->bs_bricktype > 0) {
752         switch (pcibr_soft->bs_bricktype) {
753         case MODULE_PXBRICK:
754         case MODULE_IXBRICK:
755         case MODULE_OPUSBRICK:
756                 /*
757                  * If IO9 in bus 1, allocate RRBs to all the IO9 devices
758                  */
759                 if ((pcibr_widget_to_bus(pcibr_vhdl) == 1) &&
760                     (pcibr_soft->bs_slot[0].bss_vendor_id == 0x10A9) &&
761                     (pcibr_soft->bs_slot[0].bss_device_id == 0x100A)) {
762                         pcibr_rrb_alloc_init(pcibr_soft, 0, VCHAN0, 4);
763                         pcibr_rrb_alloc_init(pcibr_soft, 1, VCHAN0, 4);
764                         pcibr_rrb_alloc_init(pcibr_soft, 2, VCHAN0, 4);
765                         pcibr_rrb_alloc_init(pcibr_soft, 3, VCHAN0, 4);
766                 } else {
767                         pcibr_rrb_alloc_init(pcibr_soft, 0, VCHAN0, 4);
768                         pcibr_rrb_alloc_init(pcibr_soft, 1, VCHAN0, 4);
769                 }
770                 break;
771
772         case MODULE_CGBRICK:
773                 pcibr_rrb_alloc_init(pcibr_soft, 0, VCHAN0, 8);
774                 break;
775         } /* switch */
776     }
777
778
779     for (slot = pcibr_soft->bs_min_slot;
780                                 slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
781         /* Call the device attach */
782         (void)pcibr_slot_call_device_attach(pcibr_vhdl, slot, 0);
783     }
784
785     pciio_device_attach(noslot_conn, 0);
786
787     return 0;
788 }
789
790
791 /*
792  * pci provider functions
793  *
794  * mostly in pcibr.c but if any are needed here then
795  * this might be a way to get them here.
796  */
797 pciio_provider_t        pci_pic_provider =
798 {
799     PCIIO_ASIC_TYPE_PIC,
800
801     (pciio_piomap_alloc_f *) pcibr_piomap_alloc,
802     (pciio_piomap_free_f *) pcibr_piomap_free,
803     (pciio_piomap_addr_f *) pcibr_piomap_addr,
804     (pciio_piomap_done_f *) pcibr_piomap_done,
805     (pciio_piotrans_addr_f *) pcibr_piotrans_addr,
806     (pciio_piospace_alloc_f *) pcibr_piospace_alloc,
807     (pciio_piospace_free_f *) pcibr_piospace_free,
808
809     (pciio_dmamap_alloc_f *) pcibr_dmamap_alloc,
810     (pciio_dmamap_free_f *) pcibr_dmamap_free,
811     (pciio_dmamap_addr_f *) pcibr_dmamap_addr,
812     (pciio_dmamap_done_f *) pcibr_dmamap_done,
813     (pciio_dmatrans_addr_f *) pcibr_dmatrans_addr,
814     (pciio_dmamap_drain_f *) pcibr_dmamap_drain,
815     (pciio_dmaaddr_drain_f *) pcibr_dmaaddr_drain,
816
817     (pciio_intr_alloc_f *) pcibr_intr_alloc,
818     (pciio_intr_free_f *) pcibr_intr_free,
819     (pciio_intr_connect_f *) pcibr_intr_connect,
820     (pciio_intr_disconnect_f *) pcibr_intr_disconnect,
821     (pciio_intr_cpu_get_f *) pcibr_intr_cpu_get,
822
823     (pciio_provider_startup_f *) pcibr_provider_startup,
824     (pciio_provider_shutdown_f *) pcibr_provider_shutdown,
825     (pciio_reset_f *) pcibr_reset,
826     (pciio_endian_set_f *) pcibr_endian_set,
827     (pciio_config_get_f *) pcibr_config_get,
828     (pciio_config_set_f *) pcibr_config_set,
829
830     (pciio_error_extract_f *) pcibr_error_extract,
831
832     (pciio_driver_reg_callback_f *) pcibr_driver_reg_callback,
833     (pciio_driver_unreg_callback_f *) pcibr_driver_unreg_callback,
834     (pciio_device_unregister_f  *) pcibr_device_unregister,
835 };