patch-2.4.4 linux/arch/ia64/sn/io/pcibr.c

Next file: linux/arch/ia64/sn/io/pciio.c
Previous file: linux/arch/ia64/sn/io/pciba.c
Back to the patch index
Back to the overall index

diff -u --recursive --new-file v2.4.3/linux/arch/ia64/sn/io/pcibr.c linux/arch/ia64/sn/io/pcibr.c
@@ -15,6 +15,7 @@
 #include <linux/types.h>
 #include <linux/config.h>
 #include <linux/slab.h>
+#include <linux/module.h>
 #include <asm/sn/sgi.h>
 #include <asm/sn/addrs.h>
 #include <asm/sn/arch.h>
@@ -22,7 +23,6 @@
 #include <asm/sn/invent.h>
 #include <asm/sn/hcl.h>
 #include <asm/sn/labelcl.h>
-#include <asm/sn/cmn_err.h>
 #include <asm/sn/xtalk/xwidget.h>
 #include <asm/sn/pci/bridge.h>
 #include <asm/sn/pci/pciio.h>
@@ -41,6 +41,14 @@
 #include <asm/sn/sn1/hubio_next.h>
 #endif
 
+#ifdef __ia64
+#define rmallocmap atemapalloc
+#define rmfreemap atemapfree
+#define rmfree atefree
+#define rmalloc atealloc
+#endif
+
+#undef PCIBR_ATE_DEBUG
 #if defined(BRINGUP)
 #if 0
 #define DEBUG 1	 /* To avoid lots of bad printk() formats leave off */
@@ -54,6 +62,24 @@
 #define	LOCAL		static
 #endif
 
+/*
+ * Macros related to the Lucent USS 302/312 usb timeout workaround.  It
+ * appears that if the lucent part can get into a retry loop if it sees a
+ * DAC on the bus during a pio read retry.  The loop is broken after about
+ * 1ms, so we need to set up bridges holding this part to allow at least
+ * 1ms for pio.
+ */
+
+#define USS302_TIMEOUT_WAR
+
+#ifdef USS302_TIMEOUT_WAR
+#include <asm/sn/io.h>
+#define LUCENT_USBHC_VENDOR_ID_NUM	0x11c1
+#define LUCENT_USBHC302_DEVICE_ID_NUM	0x5801
+#define LUCENT_USBHC312_DEVICE_ID_NUM	0x5802
+#define USS302_BRIDGE_TIMEOUT_HLD	4
+#endif
+
 #define PCIBR_LLP_CONTROL_WAR
 #if defined (PCIBR_LLP_CONTROL_WAR)
 int                     pcibr_llp_control_war_cnt;
@@ -69,6 +95,7 @@
 
 int                     pcibr_devflag = D_MP;
 
+#ifdef LATER
 #define F(s,n)		{ 1l<<(s),-(s), n }
 
 struct reg_desc         bridge_int_status_desc[] =
@@ -246,6 +273,7 @@
     {0}
 };
 #endif
+#endif	/* LATER */
 
 /* kbrick widgetnum-to-bus layout */
 int p_busnum[MAX_PORT_NUM] = {                  /* widget#      */
@@ -275,8 +303,8 @@
  * CPU to a particular IO device are synched before the start of the next
  * set of PIO operations to the same device.
  */
-#define pcibr_lock(pcibr_soft)		io_splock(pcibr_soft->bs_lock)
-#define pcibr_unlock(pcibr_soft, s)	io_spunlock(pcibr_soft->bs_lock,s)
+#define pcibr_lock(pcibr_soft)		io_splock(&pcibr_soft->bs_lock)
+#define pcibr_unlock(pcibr_soft,s)	io_spunlock(&pcibr_soft->bs_lock,s)
 
 #if PCIBR_SOFT_LIST
 typedef struct pcibr_list_s *pcibr_list_p;
@@ -302,6 +330,31 @@
 extern int      hub_device_flags_set(devfs_handle_t       widget_dev,
                                      hub_widget_flags_t flags);
 #endif
+extern pciio_dmamap_t get_free_pciio_dmamap(devfs_handle_t);
+
+/*
+ * This is the file operation table for the pcibr driver.
+ * As each of the functions are implemented, put the 
+ * appropriate function name below.
+ */
+struct file_operations pcibr_fops = {
+        owner:  THIS_MODULE,
+        llseek: NULL,
+        read: NULL,
+        write: NULL,
+        readdir: NULL,
+        poll: NULL,
+        ioctl: NULL,
+        mmap: NULL,
+        open: NULL,
+        flush: NULL,
+        release: NULL,
+        fsync: NULL,
+        fasync: NULL,
+        lock: NULL,
+        readv: NULL,
+        writev: NULL
+};
 
 extern devfs_handle_t hwgraph_root;
 extern graph_error_t hwgraph_vertex_unref(devfs_handle_t vhdl);
@@ -317,7 +370,7 @@
 extern struct map *rmallocmap(uint64_t mapsiz);
 extern void rmfreemap(struct map *mp);
 extern int compare_and_swap_ptr(void **location, void *old_ptr, void *new_ptr);
-extern void cmn_err_tag(int seqnumber, register int level, char *fmt, ...);
+extern int io_path_map_widget(devfs_handle_t vertex);
 
 
 
@@ -363,17 +416,13 @@
 
 void                    pcibr_freeblock_sub(iopaddr_t *, iopaddr_t *, iopaddr_t, size_t);
 
-#ifndef BRINGUP
 LOCAL int               pcibr_init_ext_ate_ram(bridge_t *);
-#endif
 LOCAL int               pcibr_ate_alloc(pcibr_soft_t, int);
 LOCAL void              pcibr_ate_free(pcibr_soft_t, int, int);
 
 LOCAL pcibr_info_t      pcibr_info_get(devfs_handle_t);
 LOCAL pcibr_info_t      pcibr_device_info_new(pcibr_soft_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t);
 LOCAL void		pcibr_device_info_free(devfs_handle_t, pciio_slot_t);
-LOCAL int		pcibr_device_attach(devfs_handle_t,pciio_slot_t);
-LOCAL int		pcibr_device_detach(devfs_handle_t,pciio_slot_t);
 LOCAL iopaddr_t         pcibr_addr_pci_to_xio(devfs_handle_t, pciio_slot_t, pciio_space_t, iopaddr_t, size_t, unsigned);
 
 pcibr_piomap_t          pcibr_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned);
@@ -411,7 +460,7 @@
 
 devfs_handle_t            pcibr_intr_cpu_get(pcibr_intr_t);
 void                    pcibr_xintr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);
-void                    pcibr_intr_list_func(intr_arg_t);
+void                    pcibr_intr_func(intr_arg_t);
 
 LOCAL void              print_bridge_errcmd(uint32_t, char *);
 
@@ -450,21 +499,32 @@
 void			pcibr_hints_intr_bits(devfs_handle_t, pcibr_intr_bits_f *);
 void                    pcibr_set_rrb_callback(devfs_handle_t, rrb_alloc_funct_t);
 void                    pcibr_hints_handsoff(devfs_handle_t);
-void                    pcibr_hints_subdevs(devfs_handle_t, pciio_slot_t, uint64_t);
+void                    pcibr_hints_subdevs(devfs_handle_t, pciio_slot_t, ulong);
 
-LOCAL int		pcibr_slot_reset(devfs_handle_t,pciio_slot_t);
 LOCAL int		pcibr_slot_info_init(devfs_handle_t,pciio_slot_t);
 LOCAL int		pcibr_slot_info_free(devfs_handle_t,pciio_slot_t);
+
+#ifdef LATER
+LOCAL int	        pcibr_slot_info_return(pcibr_soft_t, pciio_slot_t,
+                                               pcibr_slot_info_resp_t);
+LOCAL void       	pcibr_slot_func_info_return(pcibr_info_h, int,
+                                                    pcibr_slot_func_info_resp_t);
+#endif	/* LATER */
+
 LOCAL int		pcibr_slot_addr_space_init(devfs_handle_t,pciio_slot_t);
 LOCAL int		pcibr_slot_device_init(devfs_handle_t, pciio_slot_t);
 LOCAL int		pcibr_slot_guest_info_init(devfs_handle_t,pciio_slot_t);
 LOCAL int		pcibr_slot_initial_rrb_alloc(devfs_handle_t,pciio_slot_t);
-LOCAL int		pcibr_slot_call_device_attach(devfs_handle_t,pciio_slot_t);
-LOCAL int		pcibr_slot_call_device_detach(devfs_handle_t,pciio_slot_t);
+LOCAL int		pcibr_slot_call_device_attach(devfs_handle_t,
+						      pciio_slot_t, int);
+LOCAL int		pcibr_slot_call_device_detach(devfs_handle_t,
+						      pciio_slot_t, int);
 
-int			pcibr_slot_powerup(devfs_handle_t,pciio_slot_t);
-int			pcibr_slot_shutdown(devfs_handle_t,pciio_slot_t);
-int			pcibr_slot_inquiry(devfs_handle_t,pciio_slot_t);		
+LOCAL int               pcibr_slot_detach(devfs_handle_t, pciio_slot_t, int);
+LOCAL int 		pcibr_is_slot_sys_critical(devfs_handle_t, pciio_slot_t);
+#ifdef LATER
+LOCAL int		pcibr_slot_query(devfs_handle_t, pcibr_slot_info_req_t);
+#endif
 
 /* =====================================================================
  *    RRB management
@@ -754,7 +814,7 @@
     int                     final_vchan0;
     int                     final_vchan1;
     int                     avail_rrbs;
-    unsigned                s;
+    unsigned long           s;
     int                     error;
 
     /*
@@ -930,7 +990,7 @@
     pciio_info_t            pciio_info;
     pciio_slot_t            pciio_slot;
     pcibr_soft_t            pcibr_soft;
-    unsigned                s;
+    unsigned long           s;
     int                     error = -1;
 
     if ((pciio_info = pciio_info_get(pconn_vhdl)) &&
@@ -978,11 +1038,7 @@
 		     int dev_3_rrbs, int virt3, int dev_4_rrbs, int virt4)
 {
     devfs_handle_t            pcibr_vhdl;
-#ifdef colin
-    pcibr_soft_t            pcibr_soft;
-#else
-    pcibr_soft_t	pcibr_soft = NULL;
-#endif
+    pcibr_soft_t            pcibr_soft = NULL;
     bridge_t               *bridge = NULL;
 
     uint32_t              rrb_setting = 0;
@@ -991,7 +1047,7 @@
     int                     dev_rrbs[4];
     int                     virt[4];
     int                     i, j;
-    unsigned                s;
+    unsigned long           s;
 
     if (GRAPH_SUCCESS ==
 	hwgraph_traverse(vhdl, EDGE_LBL_PCI, &pcibr_vhdl)) {
@@ -1089,7 +1145,7 @@
     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
     pciio_slot_t            pciio_slot = pciio_info_slot_get(pciio_info);
     bridge_t               *bridge = pcibr_soft->bs_base;
-    unsigned                s;
+    unsigned long           s;
     reg_p                   rrbp;
     unsigned                rrbm;
     int                     i;
@@ -1141,7 +1197,7 @@
     bridgereg_t             badd32;
     bridgereg_t             badd64;
     bridgereg_t             fix;
-    unsigned                s;
+    unsigned long           s;
     bridgereg_t             xmask;
 
     xmask = mask;
@@ -1203,29 +1259,16 @@
     /* Generic macro flags
      */
     if (flags & PCIIO_DMA_DATA) {
-#ifdef colin
-	new = new
-	    & ~BRIDGE_DEV_BARRIER	/* barrier off */
-	    | BRIDGE_DEV_PREF;		/* prefetch on */
-#else
 	new = (new
             & ~BRIDGE_DEV_BARRIER)      /* barrier off */
             | BRIDGE_DEV_PREF;          /* prefetch on */
-#endif
 
     }
     if (flags & PCIIO_DMA_CMD) {
-#ifdef colin
-	new = new
-	    & ~BRIDGE_DEV_PREF		/* prefetch off */
-	    & ~BRIDGE_DEV_WRGA_BITS	/* write gather off */
-	    | BRIDGE_DEV_BARRIER;	/* barrier on */
-#else
         new = ((new
             & ~BRIDGE_DEV_PREF)         /* prefetch off */
             & ~BRIDGE_DEV_WRGA_BITS)    /* write gather off */
             | BRIDGE_DEV_BARRIER;       /* barrier on */
-#endif
     }
     /* Generic detail flags
      */
@@ -1297,13 +1340,8 @@
 	     * but the alternative is not allowing
 	     * the new stream at all.
 	     */
-#ifdef colin
-	    if (fix = bad & (BRIDGE_DEV_PRECISE |
-			     BRIDGE_DEV_BARRIER)) {
-#else
             if ( (fix = bad & (BRIDGE_DEV_PRECISE |
                              BRIDGE_DEV_BARRIER)) ){
-#endif
 		bad &= ~fix;
 		/* don't change these bits if
 		 * they are already set in "old"
@@ -1317,13 +1355,8 @@
 	     * but the alternative is not allowing
 	     * the new stream at all.
 	     */
-#ifdef colin
-	    if (fix = bad & (BRIDGE_DEV_WRGA_BITS |
-			     BRIDGE_DEV_PREF)) {
-#else
 	    if ( (fix = bad & (BRIDGE_DEV_WRGA_BITS |
-			     BRIDGE_DEV_PREF)) ){
-#endif
+			     BRIDGE_DEV_PREF)) ) {
 		bad &= ~fix;
 		/* don't change these bits if
 		 * we wanted to turn them on.
@@ -1379,7 +1412,7 @@
 		     bridgereg_t mask)
 {
     pcibr_soft_slot_t       slotp;
-    unsigned                s;
+    unsigned long           s;
 
     slotp = &pcibr_soft->bs_slot[slot];
 
@@ -1403,7 +1436,7 @@
               pciio_slot_t slot)
 {
     bridge_t               *bridge;
-    unsigned                s;
+    unsigned long          s;
     volatile uint32_t     wrf;
     s = pcibr_lock(pcibr_soft);
     bridge = pcibr_soft->bs_base;
@@ -1429,14 +1462,14 @@
 {
     int                     rv;
     bridgereg_t             old_enable, new_enable;
+    int badaddr_val(volatile void *, int, volatile void *);
+
 
     old_enable = bridge->b_int_enable;
     new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT;
 
     bridge->b_int_enable = new_enable;
 
-#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
-#if defined(BRINGUP)
 	/*
 	 * The xbridge doesn't clear b_err_int_view unless
 	 * multi-err is cleared...
@@ -1445,8 +1478,6 @@
 	    if (bridge->b_err_int_view & BRIDGE_ISR_PCI_MST_TIMEOUT) {
 		bridge->b_int_rst_stat = BRIDGE_IRR_MULTI_CLR;
 	    }
-#endif	/* BRINGUP */
-#endif	/* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */
 
     if (bridge->b_int_status & BRIDGE_IRR_PCI_GRP) {
 	bridge->b_int_rst_stat = BRIDGE_IRR_PCI_GRP_CLR;
@@ -1454,8 +1485,6 @@
     }
     rv = badaddr_val((void *) cfg, 4, valp);
 
-#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
-#if defined(BRINGUP)
 	/*
 	 * The xbridge doesn't set master timeout in b_int_status
 	 * here.  Fortunately it's in error_interrupt_view.
@@ -1465,8 +1494,6 @@
 		bridge->b_int_rst_stat = BRIDGE_IRR_MULTI_CLR;
 		rv = 1;		/* unoccupied slot */
 	    }
-#endif	/* BRINGUP */
-#endif /* CONFIG_SGI_IP35 */
 
     bridge->b_int_enable = old_enable;
     bridge->b_wid_tflush;		/* wait until Bridge PIO complete */
@@ -1514,10 +1541,6 @@
 int
 pcibr_open(devfs_handle_t *devp, int oflag, int otyp, cred_t *credp)
 {
-#ifndef CONFIG_IA64_SGI_IO
-    if (!_CAP_CRABLE((uint64_t)credp, (uint64_t)CAP_DEVICE_MGT))
-	return EPERM;
-#endif
     return 0;
 }
 
@@ -1630,42 +1653,10 @@
 
     return slot;
 }
+
 /*==========================================================================
  *	BRIDGE PCI SLOT RELATED IOCTLs
  */
-/*
- * pcibr_slot_powerup
- *	Software initialize the pci slot.
- */
-int
-pcibr_slot_powerup(devfs_handle_t pcibr_vhdl,pciio_slot_t slot)
-{
-    /* Check for the valid slot */
-    if (!PCIBR_VALID_SLOT(slot))
-	return(EINVAL);
-
-    if (pcibr_device_attach(pcibr_vhdl,slot))
-	return(EINVAL);
-
-    return(0);
-}
-/*
- * pcibr_slot_shutdown
- *	Software shutdown the pci slot
- */
-int
-pcibr_slot_shutdown(devfs_handle_t pcibr_vhdl,pciio_slot_t slot)
-{
-    /* Check for valid slot */
-    if (!PCIBR_VALID_SLOT(slot))
-	return(EINVAL);
-
-    if (pcibr_device_detach(pcibr_vhdl,slot))
-	return(EINVAL);
-
-    return(0);
-}
-
 char *pci_space_name[] = {"NONE", 
 			  "ROM",
 			  "IO",
@@ -1683,177 +1674,163 @@
 			  "",
 			  "BAD"};
 
+
+#ifdef LATER
+
 void
-pcibr_slot_func_info_print(pcibr_info_h pcibr_infoh, int func, int verbose)
+pcibr_slot_func_info_return(pcibr_info_h pcibr_infoh,
+                            int func,
+                            pcibr_slot_func_info_resp_t funcp)
 {
-    pcibr_info_t	pcibr_info = pcibr_infoh[func];
-    char		name[MAXDEVNAME];
-    int			win;
-    
-    if (!pcibr_info)
-	return;
+    pcibr_info_t                 pcibr_info = pcibr_infoh[func];
+    int                          win;
 
+    funcp->resp_f_status = 0;
+
+    if (!pcibr_info) {
+        return;
+    }
+
+    funcp->resp_f_status |= FUNC_IS_VALID;
 #ifdef SUPPORT_PRINTING_V_FORMAT
-    sprintf(name, "%v", pcibr_info->f_vertex);
-#endif
-    if (!verbose) {
-	printk("\tSlot Name : %s\n",name);
-    } else {
-	printk("\tPER-SLOT FUNCTION INFO\n");
-#ifdef SUPPORT_PRINTING_V_FORMAT
-	sprintf(name, "%v", pcibr_info->f_vertex);
+    sprintf(funcp->resp_f_slot_name, "%v", pcibr_info->f_vertex);
+#else
+    sprintf(funcp->resp_f_slot_name, "%x", pcibr_info->f_vertex);
 #endif
-	printk("\tSlot Name : %s\n",name);
-	printk("\tPCI Bus : %d ",pcibr_info->f_bus);
-	printk("Slot : %d ", pcibr_info->f_slot);
-	printk("Function : %d\n", pcibr_info->f_func);
+
+    if(is_sys_critical_vertex(pcibr_info->f_vertex)) {
+        funcp->resp_f_status |= FUNC_IS_SYS_CRITICAL;
+    }
+
+    funcp->resp_f_bus = pcibr_info->f_bus;
+    funcp->resp_f_slot = pcibr_info->f_slot;
+    funcp->resp_f_func = pcibr_info->f_func;
 #ifdef SUPPORT_PRINTING_V_FORMAT
-	sprintf(name, "%v", pcibr_info->f_master);
+    sprintf(funcp->resp_f_master_name, "%v", pcibr_info->f_master);
+#else
+    sprintf(funcp->resp_f_master_name, "%x", pcibr_info->f_master);
 #endif
-	printk("\tBus provider : %s\n",name);
-	printk("\tProvider Fns : 0x%p ", pcibr_info->f_pops);
-	printk("Error Handler : 0x%p Arg 0x%p\n", 
-		pcibr_info->f_efunc,pcibr_info->f_einfo);
+    funcp->resp_f_pops = pcibr_info->f_pops;
+    funcp->resp_f_efunc = pcibr_info->f_efunc;
+    funcp->resp_f_einfo = pcibr_info->f_einfo;
+
+    funcp->resp_f_vendor = pcibr_info->f_vendor;
+    funcp->resp_f_device = pcibr_info->f_device;
+
+    for(win = 0 ; win < 6 ; win++) {
+        funcp->resp_f_window[win].resp_w_base =
+                                  pcibr_info->f_window[win].w_base;
+        funcp->resp_f_window[win].resp_w_size =
+                                  pcibr_info->f_window[win].w_size;
+        sprintf(funcp->resp_f_window[win].resp_w_space,
+                "%s",
+                pci_space_name[pcibr_info->f_window[win].w_space]);
     }
-    printk("\tVendorId : 0x%x " , pcibr_info->f_vendor);
-    printk("DeviceId : 0x%x\n", pcibr_info->f_device);
 
-    printk("\n\tBase Register Info\n");
-    printk("\t\tReg#\tBase\t\tSize\t\tSpace\n");
-    for(win = 0 ; win < 6 ; win++) 
-	printk("\t\t%d\t0x%lx\t%s0x%lx\t%s%s\n",
-		win,
-		pcibr_info->f_window[win].w_base,
-		pcibr_info->f_window[win].w_base >= 0x100000 ? "": "\t",
-		pcibr_info->f_window[win].w_size,
-		pcibr_info->f_window[win].w_size >= 0x100000 ? "": "\t",
-		pci_space_name[pcibr_info->f_window[win].w_space]);
-
-    printk("\t\t7\t0x%x\t%s0x%x\t%sROM\n", 
-	    pcibr_info->f_rbase,
-	    pcibr_info->f_rbase > 0x100000 ? "" : "\t",
-	    pcibr_info->f_rsize,
-	    pcibr_info->f_rsize > 0x100000 ? "" : "\t");
+    funcp->resp_f_rbase = pcibr_info->f_rbase;
+    funcp->resp_f_rsize = pcibr_info->f_rsize;
 
-    printk("\n\tInterrupt Bit Map\n");
-    printk("\t\tPCI Int#\tBridge Pin#\n");
-    for (win = 0 ; win < 4; win++)
-	printk("\t\tINT%c\t\t%d\n",win+'A',pcibr_info->f_ibit[win]);
-    printk("\n");
-}
+    for (win = 0 ; win < 4; win++) {
+        funcp->resp_f_ibit[win] = pcibr_info->f_ibit[win];
+    }
 
+    funcp->resp_f_att_det_error = pcibr_info->f_att_det_error;
 
-void
-pcibr_slot_info_print(pcibr_soft_t 	pcibr_soft, 
-		      pciio_slot_t 	slot, 
-		      int	   	verbose)
-{
-    pcibr_soft_slot_t	pss;
-    char		slot_conn_name[MAXDEVNAME];
-    int			func;
-    bridge_t		*bridge = pcibr_soft->bs_base;
-    bridgereg_t		b_resp;
-    reg_p		b_respp;
-    int			dev;
-    bridgereg_t		b_int_device;
-    bridgereg_t		b_int_host;
-    bridgereg_t		b_int_enable;
-    int			pin = 0;
-    int			int_bits = 0;
+}
+
+int
+pcibr_slot_info_return(pcibr_soft_t             pcibr_soft,
+                       pciio_slot_t             slot,
+                       pcibr_slot_info_resp_t   respp)
+{
+    pcibr_soft_slot_t            pss;
+    int                          func;
+    bridge_t                    *bridge = pcibr_soft->bs_base;
+    reg_p                        b_respp;
+    pcibr_slot_info_resp_t       slotp;
+    pcibr_slot_func_info_resp_t  funcp;
+
+    slotp = kmem_zalloc(sizeof(*slotp), KM_SLEEP);
+    if (slotp == NULL) {
+        return(ENOMEM);
+    }
 
     pss = &pcibr_soft->bs_slot[slot];
     
     printk("\nPCI INFRASTRUCTURAL INFO FOR SLOT %d\n\n", slot);
 
-    if (verbose) {
-	printk("\tHost Present ? %s ", pss->has_host ? "yes" : "no");
-	printk("\tHost Slot : %d\n",pss->host_slot);
+    slotp->resp_has_host = pss->has_host;
+    slotp->resp_host_slot = pss->host_slot;
 #ifdef SUPPORT_PRINTING_V_FORMAT
-	sprintf(slot_conn_name, "%v", pss->slot_conn);
+    sprintf(slotp->resp_slot_conn_name, "%v", pss->slot_conn);
+#else
+    sprintf(slotp->resp_slot_conn_name, "%x", pss->slot_conn);
 #endif
-	printk("\tSlot Conn : %s\n",slot_conn_name);	
-	printk("\t#Functions : %d\n",pss->bss_ninfo);
+    slotp->resp_slot_status = pss->slot_status;
+    slotp->resp_l1_bus_num = io_path_map_widget(pcibr_soft->bs_vhdl);
+
+    if (is_sys_critical_vertex(pss->slot_conn)) {
+        slotp->resp_slot_status |= SLOT_IS_SYS_CRITICAL;
     }
-    for (func = 0; func < pss->bss_ninfo; func++)
-	pcibr_slot_func_info_print(pss->bss_infos,func, verbose);
-    printk("\tDevio[Space:%s,Base:0x%lx,Shadow:0x%x]\n",
-	    pci_space_name[pss->bss_devio.bssd_space],
-	    pss->bss_devio.bssd_base,
-	    pss->bss_device);
-
-    if (verbose) {
-	printk("\tUsage counts : pmu %d d32 %d d64 %d\n",
-		pss->bss_pmu_uctr,pss->bss_d32_uctr,pss->bss_d64_uctr);
-    
-	printk("\tDirect Trans Info : d64_base 0x%x d64_flags 0x%x"
-		"d32_base 0x%x d32_flags 0x%x\n",
-		(unsigned int)pss->bss_d64_base, pss->bss_d64_flags,
-		(unsigned int)pss->bss_d32_base, pss->bss_d32_flags);
-    
-	printk("\tExt ATEs active ? %s", 
-		pss->bss_ext_ates_active ? "yes" : "no");
-	printk(" Command register : 0x%p ", pss->bss_cmd_pointer);
-	printk(" Shadow command val : 0x%x\n", pss->bss_cmd_shadow);
+
+    slotp->resp_bss_ninfo = pss->bss_ninfo;
+
+    for (func = 0; func < pss->bss_ninfo; func++) {
+        funcp = &(slotp->resp_func[func]);
+        pcibr_slot_func_info_return(pss->bss_infos, func, funcp);
     }
 
-    printk("\tSoft RRB Info[Valid %d+%d, Reserved %d]\n",
-	    pcibr_soft->bs_rrb_valid[slot],
-	    pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL],
-	    pcibr_soft->bs_rrb_res[slot]);
+    sprintf(slotp->resp_bss_devio_bssd_space, "%s",
+            pci_space_name[pss->bss_devio.bssd_space]);
+    slotp->resp_bss_devio_bssd_base = pss->bss_devio.bssd_base;
+    slotp->resp_bss_device = pss->bss_device;
 
+    slotp->resp_bss_pmu_uctr = pss->bss_pmu_uctr;
+    slotp->resp_bss_d32_uctr = pss->bss_d32_uctr;
+    slotp->resp_bss_d64_uctr = pss->bss_d64_uctr;
 
-    if (slot & 1)
-	b_respp = &bridge->b_odd_resp;
-    else
-	b_respp = &bridge->b_even_resp;
+    slotp->resp_bss_d64_base = pss->bss_d64_base;
+    slotp->resp_bss_d64_flags = pss->bss_d64_flags;
+    slotp->resp_bss_d32_base = pss->bss_d32_base;
+    slotp->resp_bss_d32_flags = pss->bss_d32_flags;
 
-    b_resp = *b_respp;
+    slotp->resp_bss_ext_ates_active = atomic_read(&pss->bss_ext_ates_active);
 
-    printk("\n\tBridge RRB Info\n");
-    printk("\t\tRRB#\tVirtual\n");
-    for (dev = 0; dev < 8; dev++) {
-	if ((b_resp & BRIDGE_RRB_EN) &&
-	    (b_resp & BRIDGE_RRB_PDEV) == (slot >> 1))
-	    printk( "\t\t%d\t%s\n", 
-		    dev,
-		    (b_resp & BRIDGE_RRB_VDEV) ? "yes" : "no");
-	b_resp >>= 4;
-	    
-    }
-    b_int_device = bridge->b_int_device;
-    b_int_enable = bridge->b_int_enable;
+    slotp->resp_bss_cmd_pointer = pss->bss_cmd_pointer;
+    slotp->resp_bss_cmd_shadow = pss->bss_cmd_shadow;
 
-    printk("\n\tBridge Interrupt Info\n"
-	    "\t\tInt_device 0x%x\n\t\tInt_enable 0x%x "
-	    "\n\t\tEnabled pin#s for this slot: ",
-	    b_int_device,
-	    b_int_enable);
+    slotp->resp_bs_rrb_valid = pcibr_soft->bs_rrb_valid[slot];
+    slotp->resp_bs_rrb_valid_v = pcibr_soft->bs_rrb_valid[slot +
+                                                      PCIBR_RRB_SLOT_VIRTUAL];
+    slotp->resp_bs_rrb_res = pcibr_soft->bs_rrb_res[slot];
 
-    while (b_int_device) {
-	if (((b_int_device & 7) == slot) &&
-	    (b_int_enable & (1 << pin))) {
-	    int_bits |= (1 << pin);
-	    printk("%d ", pin); 
-	}
-	pin++;
-	b_int_device >>= 3;
+    if (slot & 1) {
+        b_respp = &bridge->b_odd_resp;
+    } else {
+        b_respp = &bridge->b_even_resp;
     }
 
-    if (!int_bits)
-	printk("NONE ");
+    slotp->resp_b_resp = *b_respp;
 
-    b_int_host = bridge->b_int_addr[slot].addr;
+    slotp->resp_b_int_device = bridge->b_int_device;
+    slotp->resp_b_int_enable = bridge->b_int_enable;
+    slotp->resp_b_int_host = bridge->b_int_addr[slot].addr;
 
-    printk("\n\t\tInt_host_addr 0x%x\n",
-	    b_int_host);
-    
+    if (COPYOUT(slotp, respp, sizeof(*respp))) {
+        return(EFAULT);
+    }
+
+    kmem_free(slotp, sizeof(*slotp));
+
+    return(0);
 }
 
-int verbose = 0;
 /*
- * pcibr_slot_inquiry
- *	Print information about the pci slot maintained by the infrastructure.
- *	Current information displayed
+ * pcibr_slot_query
+ *	Return information about the PCI slot maintained by the infrastructure.
+ *	Information is requested in the request structure.
+ *
+ *      Information returned in the response structure:
  *		Slot hwgraph name
  *		Vendor/Device info
  *		Base register info
@@ -1861,7 +1838,6 @@
  *		Devio register
  *		Software RRB info
  *		RRB register info
- *	In verbose mode following additional info is displayed
  *		Host/Gues info
  *		PCI Bus #,slot #, function #
  *		Slot provider hwgraph name
@@ -1872,28 +1848,76 @@
  *		External SSRAM workaround info
  */
 int
-pcibr_slot_inquiry(devfs_handle_t pcibr_vhdl, pciio_slot_t slot)
+pcibr_slot_query(devfs_handle_t pcibr_vhdl, pcibr_slot_info_req_t reqp)
 {
-    pcibr_soft_t	pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    pcibr_soft_t            pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    pciio_slot_t            slot = reqp->req_slot;
+    pciio_slot_t            tmp_slot;
+    pcibr_slot_info_resp_t  respp = (pcibr_slot_info_resp_t) reqp->req_respp;
+    int                     size = reqp->req_size;
+    int                     error;
 
     /* Make sure that we are dealing with a bridge device vertex */
-    if (!pcibr_soft)
-	return(EINVAL);
+    if (!pcibr_soft) {
+        return(EINVAL);
+    }
 
-    /* Make sure that we have a valid pci slot number or PCIIO_SLOT_NONE */
-    if ((!PCIBR_VALID_SLOT(slot)) && (slot != PCIIO_SLOT_NONE))
-	return(EINVAL);
+    /* Make sure that we have a valid PCI slot number or PCIIO_SLOT_NONE */
+    if ((!PCIBR_VALID_SLOT(slot)) && (slot != PCIIO_SLOT_NONE)) {
+        return(EINVAL);
+    }
 
-    /* Print information for the requested pci slot */
+#ifdef LATER
+    /* Do not allow a query of a slot in a shoehorn */
+    if(nic_vertex_info_match(pcibr_soft->bs_conn, XTALK_PCI_PART_NUM)) {
+       return(EPERM);
+    }
+#endif
+
+    /* Return information for the requested PCI slot */
     if (slot != PCIIO_SLOT_NONE) {
-	pcibr_slot_info_print(pcibr_soft,slot,verbose);
-	return(0);
+        if (size < sizeof(*respp)) {
+            return(EINVAL);
+        }
+
+        /* Acquire read access to the slot */
+        mrlock(pcibr_soft->bs_slot[slot].slot_lock, MR_ACCESS, PZERO);
+
+        error = pcibr_slot_info_return(pcibr_soft, slot, respp);
+
+        /* Release the slot lock */
+        mrunlock(pcibr_soft->bs_slot[slot].slot_lock);
+
+        return(error);
     }
-    /* Print information for all the slots */
-    for (slot = 0; slot < 8; slot++)
-	pcibr_slot_info_print(pcibr_soft, slot,verbose);
-    return(0);
+
+    /* Return information for all the slots */
+    for (tmp_slot = 0; tmp_slot < 8; tmp_slot++) {
+
+        if (size < sizeof(*respp)) {
+            return(EINVAL);
+        }
+
+        /* Acquire read access to the slot */
+        mrlock(pcibr_soft->bs_slot[tmp_slot].slot_lock, MR_ACCESS, PZERO);
+
+        error = pcibr_slot_info_return(pcibr_soft, tmp_slot, respp);
+
+        /* Release the slot lock */
+        mrunlock(pcibr_soft->bs_slot[tmp_slot].slot_lock);
+
+        if (error) {
+            return(error);
+        }
+
+        ++respp;
+        size -= sizeof(*respp);
+    }
+
+    return(error);
 }
+#endif	/* LATER */
+
 
 /*ARGSUSED */
 int
@@ -1905,7 +1929,7 @@
 	    int *rvalp)
 {
     devfs_handle_t            pcibr_vhdl = hwgraph_connectpt_get((devfs_handle_t)dev);
-#ifdef colin
+#ifdef LATER
     pcibr_soft_t            pcibr_soft = pcibr_soft_get(pcibr_vhdl);
 #endif
     int                     error = 0;
@@ -1913,7 +1937,7 @@
     hwgraph_vertex_unref(pcibr_vhdl);
 
     switch (cmd) {
-#ifdef colin
+#ifdef LATER
     case GIOCSETBW:
 	{
 	    grio_ioctl_info_t       info;
@@ -1969,7 +1993,6 @@
 		pcibr_priority_bits_set(pcibr_soft, slot, PCI_PRIO_LOW);
 	    break;
 	}
-#endif /* colin */
 
     case PCIBR_SLOT_POWERUP:
 	{
@@ -1985,31 +2008,33 @@
 	    break;
 	}
     case PCIBR_SLOT_SHUTDOWN:
-	{
-	    pciio_slot_t	slot;
-
 	    if (!cap_able(CAP_DEVICE_MGT)) {
 		error = EPERM;
 		break;
 	    }
 
 	    slot = (pciio_slot_t)(uint64_t)arg;
-	    error = pcibr_slot_shutdown(pcibr_vhdl,slot);
+	    error = pcibr_slot_powerup(pcibr_vhdl,slot);
 	    break;
 	}
-    case PCIBR_SLOT_INQUIRY:
+    case PCIBR_SLOT_QUERY:
 	{
-	    pciio_slot_t	slot;
+	    struct pcibr_slot_info_req_s        req;
 
 	    if (!cap_able(CAP_DEVICE_MGT)) {
 		error = EPERM;
 		break;
 	    }
 
-	    slot = (pciio_slot_t)(uint64_t)arg;
-	    error = pcibr_slot_inquiry(pcibr_vhdl,slot);
+            if (COPYIN(arg, &req, sizeof(req))) {
+                error = EFAULT;
+                break;
+            }
+
+            error = pcibr_slot_query(pcibr_vhdl, &req);
 	    break;
 	}
+#endif	/* LATER */
     default:
 	break;
 
@@ -2055,7 +2080,6 @@
 	*free_basep = last + 1;		/* keep upper chunk */
 }
 
-#ifdef IRIX
 /* Convert from ssram_bits in control register to number of SSRAM entries */
 #define ATE_NUM_ENTRIES(n) _ate_info[n]
 
@@ -2070,14 +2094,12 @@
 
 #define ATE_NUM_SIZES (sizeof(_ate_info) / sizeof(int))
 #define ATE_PROBE_VALUE 0x0123456789abcdefULL
-#endif	/* IRIX */
 
 /*
  * Determine the size of this bridge's external mapping SSRAM, and set
  * the control register appropriately to reflect this size, and initialize
  * the external SSRAM.
  */
-#ifndef BRINGUP
 LOCAL int
 pcibr_init_ext_ate_ram(bridge_t *bridge)
 {
@@ -2087,9 +2109,6 @@
     bridgereg_t             old_enable, new_enable;
     int                     s;
 
-    if (is_xbridge(bridge))
-	return 0;
-
     /* Probe SSRAM to determine its size. */
     old_enable = bridge->b_int_enable;
     new_enable = old_enable & ~BRIDGE_IMR_PCI_MST_TIMEOUT;
@@ -2116,11 +2135,9 @@
      */
 
     s = splhi();
-#ifdef colin
     bridge->b_wid_control = (bridge->b_wid_control
 	& ~BRIDGE_CTRL_SSRAM_SIZE_MASK)
 	| BRIDGE_CTRL_SSRAM_SIZE(largest_working_size);
-#endif
     bridge->b_wid_control;		/* inval addr bug war */
     splx(s);
 
@@ -2139,7 +2156,6 @@
 
     return (num_entries);
 }
-#endif	/* !BRINGUP */
 
 /*
  * Allocate "count" contiguous Bridge Address Translation Entries
@@ -2155,6 +2171,7 @@
     int                     index = 0;
 
     index = (int) rmalloc(pcibr_soft->bs_int_ate_map, (size_t) count);
+/* printk("Colin: pcibr_ate_alloc - index %d count %d \n", index, count); */
 
     if (!index && pcibr_soft->bs_ext_ate_map)
 	index = (int) rmalloc(pcibr_soft->bs_ext_ate_map, (size_t) count);
@@ -2174,6 +2191,8 @@
     /* note the "+1" since rmalloc handles 1..n but
      * we start counting ATEs at zero.
      */
+/* printk("Colin: pcibr_ate_free - index %d count %d\n", index, count); */
+
     rmfree((index < pcibr_soft->bs_int_ate_size)
 	   ? pcibr_soft->bs_int_ate_map
 	   : pcibr_soft->bs_ext_ate_map,
@@ -2233,8 +2252,6 @@
 	/*
 	 * Record the info in the sparse func info space.
 	 */
-printk("pcibr_device_info_new: slot= %d  func= %d  bss_ninfo= %d  pcibr_info= 0x%p\n", slot, func, pcibr_soft->bs_slot[slot].bss_ninfo, pcibr_info);
-
 	if (func < pcibr_soft->bs_slot[slot].bss_ninfo)
 	    pcibr_soft->bs_slot[slot].bss_infos[func] = pcibr_info;
     }
@@ -2281,7 +2298,7 @@
     slotp->bss_d32_flags = 0;
 
     /* Clear out shadow info necessary for the external SSRAM workaround */
-    slotp->bss_ext_ates_active = 0;
+    slotp->bss_ext_ates_active = ATOMIC_INIT(0);
     slotp->bss_cmd_pointer = 0;
     slotp->bss_cmd_shadow = 0;
 
@@ -2336,55 +2353,10 @@
 	   pcibr_soft->bs_spinfo.pci_mem_last);
 
 /*
- * pcibr_slot_reset
- *	Reset the pci device in the particular slot .
- */
-int
-pcibr_slot_reset(devfs_handle_t pcibr_vhdl,pciio_slot_t slot)
-{
-	pcibr_soft_t		pcibr_soft = pcibr_soft_get(pcibr_vhdl);
-	bridge_t		*bridge;
-	bridgereg_t		ctrlreg,tmp;
-	volatile bridgereg_t	*wrb_flush;
-
-	if (!PCIBR_VALID_SLOT(slot))
-		return(1);
-
-	if (!pcibr_soft)
-		return(1);
-
-	/* Enable the DMA operations from this device of the xtalk widget
-	 * (PCI host bridge in this case).
-	 */
-	xtalk_widgetdev_enable(pcibr_soft->bs_conn, slot);
-	/* Set the reset slot bit in the bridge's wid control register
-	 * to reset the pci slot 
-	 */
-	bridge = pcibr_soft->bs_base;
-	/* Read the bridge widget control and clear out the reset pin
-	 * bit for the corresponding slot. 
-	 */
-	tmp = ctrlreg = bridge->b_wid_control;
-	tmp &= ~BRIDGE_CTRL_RST_PIN(slot); 
-	bridge->b_wid_control = tmp;
-	tmp = bridge->b_wid_control;
-	/* Restore the old control register back.
-	 * NOTE : pci card gets reset when the reset pin bit
-	 * changes from 0 (set above) to 1 (going to be set now).
-	 */
-	bridge->b_wid_control = ctrlreg;
-
-	/* Flush the write buffers if any !! */
-	wrb_flush = &(bridge->b_wr_req_buf[slot].reg);
-	while (*wrb_flush);
-
-	return(0);
-}
-/*
  * pcibr_slot_info_init
  *	Probe for this slot and see if it is populated.
- *	If it is populated initialize the generic pci infrastructural
- * 	information associated with this particular pci device.
+ *	If it is populated initialize the generic PCI infrastructural
+ * 	information associated with this particular PCI device.
  */
 int
 pcibr_slot_info_init(devfs_handle_t 	pcibr_vhdl,
@@ -2401,6 +2373,9 @@
     pciio_vendor_id_t       vendor;
     pciio_device_id_t       device;
     unsigned                htype;
+#if !defined(CONFIG_IA64_SGI_SN1)
+    int			    nbars;
+#endif
     cfg_p                   wptr;
     int                     win;
     pciio_space_t           space;
@@ -2416,40 +2391,41 @@
     /* Get the basic software information required to proceed */
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
     if (!pcibr_soft)
-	return(1);
+	return(EINVAL);
 
     bridge = pcibr_soft->bs_base;
     if (!PCIBR_VALID_SLOT(slot))
-	return(1);
-
-    slotp = &pcibr_soft->bs_slot[slot];
-
-    /* Load the current values of allocated pci address spaces */
-    PCI_ADDR_SPACE_LIMITS_LOAD();
+	return(EINVAL);
 
-    /* If we have a host slot (eg:- IOC3 has 2 pci slots and the initialization
+    /* If we have a host slot (eg:- IOC3 has 2 PCI slots and the initialization
      * is done by the host slot then we are done.
      */
-    if (pcibr_soft->bs_slot[slot].has_host)
-	return(0);
+    if (pcibr_soft->bs_slot[slot].has_host) {
+	return(0);    
+    }
+
+    /* Check for a slot with any system critical functions */
+    if (pcibr_is_slot_sys_critical(pcibr_vhdl, slot))
+        return(EPERM);
+
+    /* Load the current values of allocated PCI address spaces */
+    PCI_ADDR_SPACE_LIMITS_LOAD();
     
     /* Try to read the device-id/vendor-id from the config space */
     cfgw = bridge->b_type0_cfg_dev[slot].l;
 
-#ifdef BRINGUP
-    if (slot < 3  || slot == 7) 
-	return (0);
-    else
-#endif /* BRINGUP */
-    if (pcibr_probe_slot(bridge, cfgw, &idword))
-	return(0);
+    if (pcibr_probe_slot(bridge, cfgw, &idword)) 
+	return(ENODEV);
+
+    slotp = &pcibr_soft->bs_slot[slot];
+    slotp->slot_status |= SLOT_POWER_UP;
 
     vendor = 0xFFFF & idword;
     /* If the vendor id is not valid then the slot is not populated
      * and we are done.
      */
-    if (vendor == 0xFFFF)
-	return(0);			/* next slot */
+    if (vendor == 0xFFFF) 
+	return(ENODEV);			
     
     device = 0xFFFF & (idword >> 16);
     htype = do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1);
@@ -2503,7 +2479,13 @@
 	if (htype != 0x00) {
 	    PRINT_WARNING("%s pcibr: pci slot %d func %d has strange header type 0x%x\n",
 		    pcibr_soft->bs_name, slot, func, htype);
+#if defined(CONFIG_IA64_SGI_SN1)
 	    continue;
+#else
+	    nbars = 2;
+	} else {
+	    nbars = PCI_CFG_BASE_ADDRS;
+#endif
 	}
 #if DEBUG && ATTACH_DEBUG
 	PRINT_NOTICE( 
@@ -2516,13 +2498,17 @@
 	conn_vhdl = pciio_device_info_register(pcibr_vhdl, &pcibr_info->f_c);
 	if (func == 0)
 	    slotp->slot_conn = conn_vhdl;
-	
+
 	cmd_reg = cfgw[PCI_CFG_COMMAND / 4];
 	
 	wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4;
 
-
-	for (win = 0; win < PCI_CFG_BASE_ADDRS; ++win) {
+#if defined(CONFIG_IA64_SGI_SN1)
+	for (win = 0; win < PCI_CFG_BASE_ADDRS; ++win)
+#else
+	for (win = 0; win < nbars; ++win)
+#endif
+	{
 	    iopaddr_t               base, mask, code;
 	    size_t                  size;
 
@@ -2573,9 +2559,9 @@
 	    base = wptr[((win*4)^4)/4];
 #else
 	    base = wptr[win];
-#endif /* LITTLE_ENDIAN */
+#endif
 
-	    if (base & 1) {
+	    if (base & PCI_BA_IO_SPACE) {
 		/* BASE is in I/O space. */
 		space = PCIIO_SPACE_IO;
 		mask = -4;
@@ -2590,7 +2576,7 @@
 		/* BASE is in MEM space. */
 		space = PCIIO_SPACE_MEM;
 		mask = -16;
-		code = base & 15;
+		code = base & PCI_BA_MEM_LOCATION;	/* extract BAR type */
 		base = base & mask;
 		if (base == 0) {
 		    ;		/* not assigned */
@@ -2697,37 +2683,30 @@
 	}				/* next win */
     }				/* next func */
 
-    /* Store back the values for allocated pci address spaces */
+    /* Store back the values for allocated PCI address spaces */
     PCI_ADDR_SPACE_LIMITS_STORE();
     return(0);
 }					
 
 /*
  * pcibr_slot_info_free
- *	Remove all the pci infrastructural information associated
- * 	with a particular pci device.
+ *	Remove all the PCI infrastructural information associated
+ * 	with a particular PCI device.
  */
 int
-pcibr_slot_info_free(devfs_handle_t 	pcibr_vhdl,
-		     pciio_slot_t	slot)
+pcibr_slot_info_free(devfs_handle_t pcibr_vhdl,
+                     pciio_slot_t slot)
 {
     pcibr_soft_t	pcibr_soft;
     pcibr_info_h	pcibr_infoh;
     int			nfunc;
-#if defined(PCI_HOTSWAP_DEBUG)
-    cfg_p		cfgw;
-    bridge_t		*bridge;
-    int			win;
-    cfg_p		wptr;
-#endif /* PCI_HOTSWAP_DEBUG */
-
-    
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
-#if defined(PCI_HOTSWAP_DEBUG)
+#if !defined(CONFIG_IA64_SGI_SN1)
     /* Clean out all the base registers */
     bridge = pcibr_soft->bs_base;
     cfgw = bridge->b_type0_cfg_dev[slot].l;
@@ -2739,7 +2718,7 @@
 #else
 	wptr[win] = 0;
 #endif  /* LITTLE_ENDIAN */
-#endif /* PCI_HOTSWAP_DEBUG */
+#endif	/* !CONFIG_IA64_SGI_SN1 */
 
     nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;
 
@@ -2750,13 +2729,12 @@
     pcibr_soft->bs_slot[slot].bss_ninfo = 0;
 
     return(0);
-    
-
 }
+
 int as_debug = 0;
 /*
  * pcibr_slot_addr_space_init
- *	Reserve chunks of pci address space as required by 
+ *	Reserve chunks of PCI address space as required by 
  * 	the base registers in the card.
  */
 int
@@ -2772,38 +2750,40 @@
     iopaddr_t		pci_hi_fb, pci_hi_fl;
     size_t              align;
     iopaddr_t           mask;
+    int		    	nbars;
     int		       	nfunc;
     int			func;
     int			win;
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
     bridge = pcibr_soft->bs_base;
 
-    /* Get the current values for the allocated pci address spaces */
+    /* Get the current values for the allocated PCI address spaces */
     PCI_ADDR_SPACE_LIMITS_LOAD();
 
     if (as_debug)
-#ifdef colin
+#ifdef LATER
     PCI_ADDR_SPACE_LIMITS_PRINT();
 #endif
     /* allocate address space,
      * for windows that have not been
      * previously assigned.
      */
-
-    if (pcibr_soft->bs_slot[slot].has_host)
+    if (pcibr_soft->bs_slot[slot].has_host) {
 	return(0);
+    }
 
     nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;
     if (nfunc < 1)
-	return(0);
+	return(EINVAL);
 
     pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;
     if (!pcibr_infoh)
-	return(0);
+	return(EINVAL);
 
     /*
      * Try to make the DevIO windows not
@@ -2842,7 +2822,16 @@
 	cfgw = bridge->b_type0_cfg_dev[slot].f[func].l;
 	wptr = cfgw + PCI_CFG_BASE_ADDR_0 / 4;
 
-	for (win = 0; win < PCI_CFG_BASE_ADDRS; ++win) {
+#if defined(CONFIG_IA64_SGI_SN1)
+	nbars = PCI_CFG_BASE_ADDRS;
+#else
+	if ((do_pcibr_config_get(cfgw, PCI_CFG_HEADER_TYPE, 1) & 0x7f) != 0)
+	    nbars = 2;
+	else
+	    nbars = PCI_CFG_BASE_ADDRS;
+#endif
+
+	for (win = 0; win < nbars; ++win) {
 
 	    space = pcibr_info->f_window[win].w_space;
 	    base = pcibr_info->f_window[win].w_base;
@@ -2908,7 +2897,9 @@
 	    pcibr_info->f_window[win].w_base = base;
 #ifdef LITTLE_ENDIAN
 	    wptr[((win*4)^4)/4] = base;
+#if DEBUG && PCI_DEBUG
 		printk("Setting base address 0x%p base 0x%x\n", &(wptr[((win*4)^4)/4]), base);
+#endif
 #else
 	    wptr[win] = base;
 #endif  /* LITTLE_ENDIAN */
@@ -2976,7 +2967,22 @@
 	 * be sure are set.
 	 */
 	pci_cfg_cmd_reg_add |= PCI_CMD_IO_SPACE;
-	pci_cfg_cmd_reg_add |= PCI_CMD_MEM_SPACE;
+
+	/*
+	 * The Adaptec 1160 FC Controller WAR #767995:
+	 * The part incorrectly ignores the upper 32 bits of a 64 bit
+	 * address when decoding references to it's registers so to
+	 * keep it from responding to a bus cycle that it shouldn't
+	 * we only use I/O space to get at it's registers.  Don't
+	 * enable memory space accesses on that PCI device.
+	 */
+	#define FCADP_VENDID 0x9004 /* Adaptec Vendor ID from fcadp.h */
+	#define FCADP_DEVID 0x1160  /* Adaptec 1160 Device ID from fcadp.h */
+
+	if ((pcibr_info->f_vendor != FCADP_VENDID) ||
+	    (pcibr_info->f_device != FCADP_DEVID))
+	    pci_cfg_cmd_reg_add |= PCI_CMD_MEM_SPACE;
+
 	pci_cfg_cmd_reg_add |= PCI_CMD_BUS_MASTER;
 
 	pci_cfg_cmd_reg_p = cfgw + PCI_CFG_COMMAND / 4;
@@ -2991,28 +2997,30 @@
 	
     }				/* next func */
 
-    /* Now that we have allocated new chunks of pci address spaces to this
+    /* Now that we have allocated new chunks of PCI address spaces to this
      * card we need to update the bookkeeping values which indicate
-     * the current pci address space allocations.
+     * the current PCI address space allocations.
      */
     PCI_ADDR_SPACE_LIMITS_STORE();
     return(0);
 }
+
 /*
  * pcibr_slot_device_init
- * 	Setup the device register in the bridge for this pci slot.
+ * 	Setup the device register in the bridge for this PCI slot.
  */
 int
-pcibr_slot_device_init(devfs_handle_t 	pcibr_vhdl,
-		       pciio_slot_t    	slot)
+pcibr_slot_device_init(devfs_handle_t pcibr_vhdl,
+		       pciio_slot_t slot)
 {
-    pcibr_soft_t	pcibr_soft;
+    pcibr_soft_t	 pcibr_soft;
     bridge_t		*bridge;
-    bridgereg_t		devreg;
+    bridgereg_t		 devreg;
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
     bridge = pcibr_soft->bs_base;
 
@@ -3036,13 +3044,13 @@
 #if DEBUG && PCI_DEBUG
     printk("pcibr: PCI space allocation done.\n");
 #endif
-	
+
     return(0);
 }
 
 /*
  * pcibr_slot_guest_info_init
- *	Setup the host/guest relations for a pci slot.
+ *	Setup the host/guest relations for a PCI slot.
  */
 int
 pcibr_slot_guest_info_init(devfs_handle_t pcibr_vhdl,
@@ -3056,7 +3064,7 @@
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
 
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
     slotp = &pcibr_soft->bs_slot[slot];
 
@@ -3103,17 +3111,17 @@
 
     return(0);
 }
+
 /*
  * pcibr_slot_initial_rrb_alloc
  *	Allocate a default number of rrbs for this slot on 
- * 	the two channels. This is dictated by the rrb allocation
+ * 	the two channels.  This is dictated by the rrb allocation
  * 	strategy routine defined per platform.
  */
 
 int
-pcibr_slot_initial_rrb_alloc(devfs_handle_t 	pcibr_vhdl,
-			     pciio_slot_t	slot)
-
+pcibr_slot_initial_rrb_alloc(devfs_handle_t pcibr_vhdl,
+			     pciio_slot_t slot)
 {
     pcibr_soft_t	pcibr_soft;
     pcibr_info_h	pcibr_infoh;
@@ -3123,16 +3131,17 @@
     int			r;
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
     bridge = pcibr_soft->bs_base;
 
-
     /* How may RRBs are on this slot?
      */
     c0 = do_pcibr_rrb_count_valid(bridge, slot);
     c1 = do_pcibr_rrb_count_valid(bridge, slot + PCIBR_RRB_SLOT_VIRTUAL);
+
 #if PCIBR_RRB_DEBUG
     printk("pcibr_attach: slot %d started with %d+%d\n", slot, c0, c1);
 #endif
@@ -3149,7 +3158,7 @@
 	    do_pcibr_rrb_free(bridge, slot + PCIBR_RRB_SLOT_VIRTUAL, c1);
 	pcibr_soft->bs_rrb_valid[slot] = 0x1000;
 	pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = 0x1000;
-	return(0);
+	return(ENODEV);
     }
 
     pcibr_soft->bs_rrb_avail[slot & 1] -= c0 + c1;
@@ -3173,17 +3182,19 @@
 	    pcibr_soft->bs_rrb_res[slot]);
     printk("\n");
 #endif
+
     return(0);
 }
 
 /*
  * pcibr_slot_call_device_attach
- *	This calls the associated driver attach routine for the pci
+ *	This calls the associated driver attach routine for the PCI
  * 	card in this slot.
  */
 int
-pcibr_slot_call_device_attach(devfs_handle_t	pcibr_vhdl,
-			      pciio_slot_t	slot)
+pcibr_slot_call_device_attach(devfs_handle_t pcibr_vhdl,
+			      pciio_slot_t slot,
+			      int          drv_flags)
 {
     pcibr_soft_t	pcibr_soft;
     pcibr_info_h	pcibr_infoh;
@@ -3192,14 +3203,19 @@
     int			func;
     devfs_handle_t	xconn_vhdl,conn_vhdl;
     int			nfunc;
+    int                 error_func;
+    int                 error_slot = 0;
+    int                 error = ENODEV;
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+
     if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
+	return(EINVAL);
 
 
-    if (pcibr_soft->bs_slot[slot].has_host)
-        return(0);
+    if (pcibr_soft->bs_slot[slot].has_host) {
+        return(EPERM);
+    }
     
     xconn_vhdl = pcibr_soft->bs_conn;
     aa = async_attach_get_info(xconn_vhdl);
@@ -3207,8 +3223,6 @@
     nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;
     pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;
 
-    printk("\npcibr_slot_call_device_attach: link 0x%p pci bus 0x%p slot %d\n", xconn_vhdl, pcibr_vhdl, slot);
-
     for (func = 0; func < nfunc; ++func) {
 
 	pcibr_info = pcibr_infoh[func];
@@ -3221,51 +3235,77 @@
 
 	conn_vhdl = pcibr_info->f_vertex;
 
-	/* If the pci device has been disabled in the prom,
+	/* If the PCI device has been disabled in the prom,
 	 * do not set it up for driver attach. NOTE: usrpci
 	 * and pciba will not "see" this connection point!
 	 */
 	if (device_admin_info_get(conn_vhdl, ADMIN_LBL_DISABLED)) {
 #ifdef SUPPORT_PRINTING_V_FORMAT
-	    PRINT_WARNING( "pcibr_slot_call_device_attach: %v disabled\n", 
+	    PRINT_WARNING("pcibr_slot_call_device_attach: %v disabled\n", 
 		    conn_vhdl);
 #endif
 	    continue;
 	}
+#ifdef LATER
+	/*
+	 * Activate if and when we support cdl.
+	 */
 	if (aa)
 	    async_attach_add_info(conn_vhdl, aa);
-	pciio_device_attach(conn_vhdl);
-    }				/* next func */
+#endif	/* LATER */
 
-    printk("\npcibr_slot_call_device_attach: DONE\n");
+	error_func = pciio_device_attach(conn_vhdl, drv_flags);
 
-    return(0);
+        pcibr_info->f_att_det_error = error_func;
+
+	if (error_func)
+	    error_slot = error_func;
+
+        error = error_slot;
+
+    }				/* next func */
+
+    if (error) {
+	if ((error != ENODEV) && (error != EUNATCH))
+	    pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_INCMPLT;
+    } else {
+        pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT;
+    }
+        
+    return(error);
 }
+
 /*
  * pcibr_slot_call_device_detach
- *	This calls the associated driver detach routine for the pci
+ *	This calls the associated driver detach routine for the PCI
  * 	card in this slot.
  */
 int
-pcibr_slot_call_device_detach(devfs_handle_t	pcibr_vhdl,
-			      pciio_slot_t	slot)
+pcibr_slot_call_device_detach(devfs_handle_t pcibr_vhdl,
+			      pciio_slot_t slot,
+			      int          drv_flags)
 {
     pcibr_soft_t	pcibr_soft;
     pcibr_info_h	pcibr_infoh;
     pcibr_info_t	pcibr_info;
     int			func;
-    devfs_handle_t	conn_vhdl;
+    devfs_handle_t	conn_vhdl = GRAPH_VERTEX_NONE;
     int			nfunc;
-    int			ndetach = 1;
+    int                 error_func;
+    int                 error_slot = 0;
+    int                 error = ENODEV;
 
     pcibr_soft = pcibr_soft_get(pcibr_vhdl);
-    if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
-	return(1);
 
+    if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
+	return(EINVAL);
 
     if (pcibr_soft->bs_slot[slot].has_host)
-        return(0);
-    
+        return(EPERM);
+
+    /* Make sure that we do not detach a system critical function vertex */
+    if(pcibr_is_slot_sys_critical(pcibr_vhdl, slot))
+        return(EPERM);
 
     nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;
     pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;
@@ -3281,94 +3321,120 @@
 	    continue;
 
 	conn_vhdl = pcibr_info->f_vertex;
-	
-	/* Make sure that we do not detach a system critical device
-	 * vertex.
-	 */
-	if (is_sys_critical_vertex(conn_vhdl)) {
-#ifdef SUPPORT_PRINTING_V_FORMAT
-	    PRINT_WARNING( "%v is a system critical device vertex\n",
-		    conn_vhdl);
-#endif
-	    continue;
-	}
-	
-	ndetach = 0;
-	pciio_device_detach(conn_vhdl);
+
+	error_func = pciio_device_detach(conn_vhdl, drv_flags);
+
+        pcibr_info->f_att_det_error = error_func;
+
+	if (error_func)
+	    error_slot = error_func;
+
+	error = error_slot;
+
     }				/* next func */
 
+    pcibr_soft->bs_slot[slot].slot_status &= ~SLOT_STATUS_MASK;
 
-    return(ndetach);
+    if (error) {
+	if ((error != ENODEV) && (error != EUNATCH))
+            pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_INCMPLT;
+    } else {
+        if (conn_vhdl != GRAPH_VERTEX_NONE) 
+            pcibr_device_unregister(conn_vhdl);
+        pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT;
+    }
+        
+    return(error);
 }
 
 /*
- * pcibr_device_attach
+ * pcibr_slot_detach
  *	This is a place holder routine to keep track of all the
- *	slot-specific initialization that needs to be done.
- *	This is usually called when we want to initialize a new
- * 	pci card on the bus.
+ *	slot-specific freeing that needs to be done.
  */
 int
-pcibr_device_attach(devfs_handle_t 	pcibr_vhdl,
-		    pciio_slot_t	slot)
+pcibr_slot_detach(devfs_handle_t pcibr_vhdl,
+		  pciio_slot_t slot,
+		  int          drv_flags)
 {
-    return (
-	    /* Reset the slot */
-	    pcibr_slot_reset(pcibr_vhdl,slot)			||
-	    /* FInd out what is out there */
-	    pcibr_slot_info_init(pcibr_vhdl,slot)		||
-
-	    /* Set up the address space for this slot in the pci land */
-	    pcibr_slot_addr_space_init(pcibr_vhdl,slot) 	||
-
-	    /* Setup the device register */
-	    pcibr_slot_device_init(pcibr_vhdl, slot)		||
-
-	    /* Setup host/guest relations */
-	    pcibr_slot_guest_info_init(pcibr_vhdl,slot)		||
-
-	    /* Initial RRB management */
-	    pcibr_slot_initial_rrb_alloc(pcibr_vhdl,slot)	||
-
-	    /* Call the device attach */
-	    pcibr_slot_call_device_attach(pcibr_vhdl,slot)
-	    );
+    int		  error;
+    
+    /* Call the device detach function */
+    error = (pcibr_slot_call_device_detach(pcibr_vhdl, slot, drv_flags));
+    return (error);
 
 }
+
 /*
- * pcibr_device_detach
- *	This is a place holder routine to keep track of all the
- *	slot-specific freeing that needs to be done.
+ * pcibr_is_slot_sys_critical
+ *      Check slot for any functions that are system critical.
+ *      Return 1 if any are system critical or 0 otherwise.
+ *
+ *      This function will always return 0 when called by 
+ *      pcibr_attach() because the system critical vertices 
+ *      have not yet been set in the hwgraph.
  */
 int
-pcibr_device_detach(devfs_handle_t 	pcibr_vhdl,
-		    pciio_slot_t	slot)
+pcibr_is_slot_sys_critical(devfs_handle_t pcibr_vhdl,
+                      pciio_slot_t slot)
 {
-    
-    /* Call the device detach */
-    return (pcibr_slot_call_device_detach(pcibr_vhdl,slot));
+    pcibr_soft_t        pcibr_soft;
+    pcibr_info_h        pcibr_infoh;
+    pcibr_info_t        pcibr_info;
+    devfs_handle_t        conn_vhdl = GRAPH_VERTEX_NONE;
+    int                 nfunc;
+    int                 func;
+
+    pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+    if (!pcibr_soft || !PCIBR_VALID_SLOT(slot))
+        return(0);
+
+    nfunc = pcibr_soft->bs_slot[slot].bss_ninfo;
+    pcibr_infoh = pcibr_soft->bs_slot[slot].bss_infos;
+
+    for (func = 0; func < nfunc; ++func) {
+
+        pcibr_info = pcibr_infoh[func];
+        if (!pcibr_info)
+            continue;
+
+        if (pcibr_info->f_vendor == PCIIO_VENDOR_ID_NONE)
+            continue;
+
+        conn_vhdl = pcibr_info->f_vertex;
+        if (is_sys_critical_vertex(conn_vhdl)) { 
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+            PRINT_WARNING("%v is a system critical device vertex\n", conn_vhdl);
+#else
+            PRINT_WARNING("%p is a system critical device vertex\n", conn_vhdl);
+#endif
+            return(1); 
+        }
+
+    }
 
+    return(0);
 }
+
 /*
  * pcibr_device_unregister
- *	This frees up any hardware resources reserved for this pci device
- * 	and removes any pci infrastructural information setup for it.
- *	This is usually used at the time of shutting down of the pci card.
+ *	This frees up any hardware resources reserved for this PCI device
+ * 	and removes any PCI infrastructural information setup for it.
+ *	This is usually used at the time of shutting down of the PCI card.
  */
-void
+int
 pcibr_device_unregister(devfs_handle_t pconn_vhdl)
 {
-    pciio_info_t	pciio_info;
-    devfs_handle_t	pcibr_vhdl;
-    pciio_slot_t	slot;
-    pcibr_soft_t	pcibr_soft;
+    pciio_info_t	 pciio_info;
+    devfs_handle_t	 pcibr_vhdl;
+    pciio_slot_t	 slot;
+    pcibr_soft_t	 pcibr_soft;
     bridge_t		*bridge;
+    int			 error_call;
+    int			 error = 0;
 
     pciio_info = pciio_info_get(pconn_vhdl);
 
-    /* Detach the pciba name space */
-    pciio_device_detach(pconn_vhdl);
-
     pcibr_vhdl = pciio_info_master_get(pciio_info);
     slot = pciio_info_slot_get(pciio_info);
 
@@ -3382,19 +3448,31 @@
     pcibr_rrb_flush(pconn_vhdl);
 
     /* Free the rrbs allocated to this slot */
-    do_pcibr_rrb_free(bridge, slot, 
-		      pcibr_soft->bs_rrb_valid[slot] +
-		      pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL]);
+    error_call = do_pcibr_rrb_free(bridge, slot, 
+		                   pcibr_soft->bs_rrb_valid[slot] +
+		                   pcibr_soft->bs_rrb_valid[slot + 
+                                   PCIBR_RRB_SLOT_VIRTUAL]);
 
+    if (error_call)
+        error = ERANGE;
 
     pcibr_soft->bs_rrb_valid[slot] = 0;
     pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL] = 0;
     pcibr_soft->bs_rrb_res[slot] = 0;
 
     /* Flush the write buffers !! */
-    (void)pcibr_wrb_flush(pconn_vhdl);
+    error_call = pcibr_wrb_flush(pconn_vhdl);
+
+    if (error_call)
+        error = error_call;
+
     /* Clear the information specific to the slot */
-    (void)pcibr_slot_info_free(pcibr_vhdl, slot);
+    error_call = pcibr_slot_info_free(pcibr_vhdl, slot);
+
+    if (error_call)
+        error = error_call;
+
+    return(error);
     
 }
 
@@ -3467,6 +3545,7 @@
 	return (rv == GRAPH_SUCCESS);
 }
 
+
 /*
  *    pcibr_attach: called every time the crosstalk
  *      infrastructure is asked to initialize a widget
@@ -3502,11 +3581,15 @@
     iopaddr_t               pci_hi_fb, pci_hi_fl;
 
     int                     spl_level;
+#ifdef LATER
     char		    *nicinfo = (char *)0;
+#endif
 
 #if PCI_FBBE
     int                     fast_back_to_back_enable;
 #endif
+    l1sc_t		    *scp;
+    nasid_t		    nasid;
 
     async_attach_t          aa = NULL;
 
@@ -3542,8 +3625,6 @@
 	NeedXbridgeSwap = 1;
 #endif
 
-	printk("pcibr_attach: Called with vertex 0x%p, b_wid_stat 0x%x, gio 0x%x\n",xconn_vhdl, bridge->b_wid_stat, BRIDGE_STAT_PCI_GIO_N);
-
     /*
      * Create the vertex for the PCI bus, which we
      * will also use to hold the pcibr_soft and
@@ -3558,8 +3639,14 @@
     rc = hwgraph_path_add(xconn_vhdl, EDGE_LBL_PCI, &pcibr_vhdl);
     ASSERT(rc == GRAPH_SUCCESS);
 
-    rc = hwgraph_char_device_add(pcibr_vhdl, EDGE_LBL_CONTROLLER, "pcibr_", &ctlr_vhdl);
-    ASSERT(rc == GRAPH_SUCCESS);
+    ctlr_vhdl = NULL;
+    ctlr_vhdl = hwgraph_register(pcibr_vhdl, EDGE_LBL_CONTROLLER,
+                0, DEVFS_FL_AUTO_DEVNUM,
+                0, 0,
+                S_IFCHR | S_IRUSR | S_IWUSR | S_IRGRP, 0, 0,
+                &pcibr_fops, NULL);
+
+    ASSERT(ctlr_vhdl != NULL);
 
     /*
      * decode the nic, and hang its stuff off our
@@ -3606,6 +3693,10 @@
 	pcibr_soft->bs_xbridge = 0;
     }
 
+    nasid = NASID_GET(bridge);
+    scp = &NODEPDA( NASID_TO_COMPACT_NODEID(nasid) )->module->elsc;
+    pcibr_soft->bs_l1sc = scp;
+    pcibr_soft->bs_moduleid = iobrick_module_get(scp);
     pcibr_soft->bsi_err_intr = 0;
 
     /* Bridges up through REV C
@@ -3660,7 +3751,7 @@
     /*
      * Init bridge lock.
      */
-    spinlock_init(&pcibr_soft->bs_lock, "pcibr_loc");
+    spin_lock_init(&pcibr_soft->bs_lock);
 
     /*
      * If we have one, process the hints structure.
@@ -3691,12 +3782,18 @@
 	pcibr_soft->bs_slot[slot].bss_devio.bssd_space = PCIIO_SPACE_NONE;
 	pcibr_soft->bs_slot[slot].bss_d64_base = PCIBR_D64_BASE_UNSET;
 	pcibr_soft->bs_slot[slot].bss_d32_base = PCIBR_D32_BASE_UNSET;
-	pcibr_soft->bs_slot[slot].bss_ext_ates_active = 0;
+	pcibr_soft->bs_slot[slot].bss_ext_ates_active = ATOMIC_INIT(0);
     }
 
     for (ibit = 0; ibit < 8; ++ibit) {
 	pcibr_soft->bs_intr[ibit].bsi_xtalk_intr = 0;
-	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_list = 0;
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_soft = pcibr_soft;
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_list = NULL;
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_stat = 
+							&(bridge->b_int_status);
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_hdlrcnt = 0;
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_shared = 0;
+	pcibr_soft->bs_intr[ibit].bsi_pcibr_intr_wrap.iw_connected = 0;
     }
 
     /*
@@ -3733,7 +3830,7 @@
 	iopaddr_t               xbase;
 	xwidgetnum_t            xport;
 	iopaddr_t               offset;
-	int                     num_entries;
+	int                     num_entries = 0;
 	int                     entry;
 	cnodeid_t		cnodeid;
 	nasid_t			nasid;
@@ -3801,10 +3898,6 @@
 
 	    dirmap = xport << BRIDGE_DIRMAP_W_ID_SHFT;
 
-#ifdef IRIX
-	    dirmap |= BRIDGE_DIRMAP_RMF_64;
-#endif
-
 	    if (xbase)
 		dirmap |= BRIDGE_DIRMAP_OFF & xbase;
 	    else if (offset >= (512 << 20))
@@ -3855,15 +3948,10 @@
 	 * recomparing against BRIDGE_INTERNAL_ATES every
 	 * time.
 	 */
-#ifdef BRINGUP
-	/*
-	 * 082799: for some reason pcibr_init_ext_ate_ram is causing
-	 * a Data Bus Error.  It should be zero anyway so just force it.
-	 */
-	num_entries = 0;
-#else
-	num_entries = pcibr_init_ext_ate_ram(bridge);
-#endif
+	if (is_xbridge(bridge))
+		num_entries = 0;
+	else
+		num_entries = pcibr_init_ext_ate_ram(bridge);
 
 	/* we always have 128 ATEs (512 for Xbridge) inside the chip
 	 * even if disabled for debugging.
@@ -3947,7 +4035,6 @@
 
     pcibr_soft->bsi_err_intr = xtalk_intr;
 
-#if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
     /*
      * On IP35 with XBridge, we do some extra checks in pcibr_setwidint
      * in order to work around some addressing limitations.  In order
@@ -3955,9 +4042,6 @@
      * start from a known clean state.
      */
     pcibr_clearwidint(bridge);
-#endif
-
-    printk("pribr_attach:  FIXME Error Interrupt not registered\n");
 
     xtalk_intr_connect(xtalk_intr,
 		       (intr_func_t) pcibr_error_intr_handler,
@@ -4054,13 +4138,13 @@
     }
 #endif
 
-#ifdef IRIX
+#ifdef LATER
     /* If the bridge has been reset then there is no need to reset
      * the individual PCI slots.
      */
     for (slot = 0; slot < 8; ++slot)  
 	/* Reset all the slots */
-	(void)pcibr_slot_reset(pcibr_vhdl,slot);
+	(void)pcibr_slot_reset(pcibr_vhdl, slot);
 #endif
 
     for (slot = 0; slot < 8; ++slot)
@@ -4075,6 +4159,7 @@
 	/* Setup the device register */
 	(void)pcibr_slot_device_init(pcibr_vhdl, slot);
 
+#ifndef __ia64
 #if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
     for (slot = 0; slot < 8; ++slot)  
 	/* Set up convenience links */
@@ -4082,6 +4167,7 @@
 		if (pcibr_soft->bs_slot[slot].bss_ninfo > 0) /* if occupied */
 			pcibr_bus_cnvlink(pcibr_info->f_vertex, slot);
 #endif
+#endif
 
     for (slot = 0; slot < 8; ++slot)  
 	/* Setup host/guest relations */
@@ -4091,12 +4177,34 @@
 	/* Initial RRB management */
 	(void)pcibr_slot_initial_rrb_alloc(pcibr_vhdl,slot);
 
-#ifdef dagum
     /* driver attach routines should be called out from generic linux code */
     for (slot = 0; slot < 8; ++slot)  
 	/* Call the device attach */
-	(void)pcibr_slot_call_device_attach(pcibr_vhdl,slot);
-#endif /* dagum */
+	(void)pcibr_slot_call_device_attach(pcibr_vhdl, slot, 0);
+
+    /*
+     * Each Pbrick PCI bus only has slots 1 and 2.   Similarly for
+     * widget 0xe on Ibricks.  Allocate RRB's accordingly.
+     */
+    if (pcibr_soft->bs_moduleid > 0) {
+	switch (MODULE_GET_BTCHAR(pcibr_soft->bs_moduleid)) {
+	case 'p':		/* Pbrick */
+		do_pcibr_rrb_autoalloc(pcibr_soft, 1, 8);
+		do_pcibr_rrb_autoalloc(pcibr_soft, 2, 8);
+		break;
+	case 'i':		/* Ibrick */
+	  	/* port 0xe on the Ibrick only has slots 1 and 2 */
+		if (pcibr_soft->bs_xid == 0xe) {
+			do_pcibr_rrb_autoalloc(pcibr_soft, 1, 8);
+			do_pcibr_rrb_autoalloc(pcibr_soft, 2, 8);
+		}
+		else {
+		    	/* allocate one RRB for the serial port */
+			do_pcibr_rrb_autoalloc(pcibr_soft, 0, 1);
+		}
+		break;
+	} /* switch */
+    }
 
 #ifdef LATER
     if (strstr(nicinfo, XTALK_PCI_PART_NUM)) {
@@ -4119,13 +4227,13 @@
 #endif
     }
 #else
-	printk("pcibr_attach: FIXME to call do_pcibr_rrb_autoalloc nicinfo 0x%p\n", nicinfo);
+	FIXME("pcibr_attach: Call do_pcibr_rrb_autoalloc nicinfo\n");
 #endif
 
     if (aa)
 	    async_attach_add_info(noslot_conn, aa);
 
-    pciio_device_attach(noslot_conn);
+    pciio_device_attach(noslot_conn, 0);
 
 
     /* 
@@ -4166,14 +4274,14 @@
 	printk("pcibr_device_detach called for %p/%d\n",
 		pcibr_vhdl,slot);
 #endif
-	pcibr_device_detach(pcibr_vhdl, slot);
+	pcibr_slot_detach(pcibr_vhdl, slot, 0);
     }
 
     /* Unregister the no-slot connection point */
     pciio_device_info_unregister(pcibr_vhdl,
 				 &(pcibr_soft->bs_noslot_info->f_c));
 
-    spinlock_destroy(&pcibr_soft->bs_lock);
+    spin_lock_destroy(&pcibr_soft->bs_lock);
     kfree(pcibr_soft->bs_name);
     
     /* Error handler gets unregistered when the widget info is 
@@ -4264,7 +4372,7 @@
     size_t                  msize;	/* size of devio(x) mapped area on PCI */
     size_t                  mmask;	/* addr bits stored in Device(x) */
 
-    unsigned                s;
+    unsigned long           s;
 
     s = pcibr_lock(pcibr_soft);
 
@@ -4327,7 +4435,7 @@
 	if (wspace == PCIIO_SPACE_NONE)
 	    goto done;
 
-	/* get pci base and size */
+	/* get PCI base and size */
 	wbase = pcibr_info->f_window[bar].w_base;
 	wsize = pcibr_info->f_window[bar].w_size;
 
@@ -4587,7 +4695,7 @@
     pcibr_piomap_t          pcibr_piomap;
     iopaddr_t               xio_addr;
     xtalk_piomap_t          xtalk_piomap;
-    unsigned                s;
+    unsigned long           s;
 
     /* Make sure that the req sizes are non-zero */
     if ((req_size < 1) || (req_size_max < 1))
@@ -4631,7 +4739,7 @@
     pcibr_piomap->bp_pciaddr = pci_addr;
     pcibr_piomap->bp_mapsz = req_size;
     pcibr_piomap->bp_soft = pcibr_soft;
-    pcibr_piomap->bp_toc[0] = 0;
+    pcibr_piomap->bp_toc[0] = ATOMIC_INIT(0);
 
     if (mapptr) {
 	s = pcibr_lock(pcibr_soft);
@@ -4733,7 +4841,7 @@
     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
 
     pciio_piospace_t        piosp;
-    int                     s;
+    unsigned long           s;
 
     iopaddr_t              *pciaddr, *pcilast;
     iopaddr_t               start_addr;
@@ -4751,7 +4859,7 @@
     /*
      * First look if a previously allocated chunk exists.
      */
-    if ((piosp = pcibr_info->f_piospace) != (pciio_piospace_t)0) {
+    if ((piosp = pcibr_info->f_piospace)) {
 	/*
 	 * Look through the list for a right sized free chunk.
 	 */
@@ -4825,7 +4933,7 @@
     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast;
 
     pciio_piospace_t        piosp;
-    int                     s;
+    unsigned long           s;
     char                    name[1024];
 
     /*
@@ -4901,7 +5009,7 @@
     iopaddr_t               attributes = 0;
 
     /* Sanity check: Bridge only allows use of VCHAN1 via 64-bit addrs */
-#ifdef IRIX
+#ifdef LATER
     ASSERT_ALWAYS(!(flags & PCIBR_VCHAN1) || (flags & PCIIO_DMA_A64));
 #endif
 
@@ -5031,7 +5139,16 @@
     /* merge in forced flags */
     flags |= pcibr_soft->bs_dma_flags;
 
+#ifdef IRIX
     NEWf(pcibr_dmamap, flags);
+#else
+    /*
+     * On SNIA64, these maps are pre-allocated because pcibr_dmamap_alloc()
+     * can be called within an interrupt thread.
+     */
+    pcibr_dmamap = (pcibr_dmamap_t)get_free_pciio_dmamap(pcibr_soft->bs_vhdl);
+#endif
+
     if (!pcibr_dmamap)
 	return 0;
 
@@ -5162,7 +5279,7 @@
 	    pcibr_dmamap->bd_pci_addr =
 		PCI32_MAPPED_BASE + IOPGSIZE * ate_index;
 	    /*
-	     * for xbridge the byte-swap bit == bit 29 of pci address
+	     * for xbridge the byte-swap bit == bit 29 of PCI address
 	     */
 	    if (pcibr_soft->bs_xbridge) {
 		    if (flags & PCIIO_BYTE_STREAM)
@@ -5201,7 +5318,7 @@
 		bridge_t               *bridge = pcibr_soft->bs_base;
 		volatile unsigned      *cmd_regp;
 		unsigned                cmd_reg;
-		unsigned                s;
+		unsigned long           s;
 
 		pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_SSRAM;
 
@@ -5239,20 +5356,15 @@
     pcibr_soft_t            pcibr_soft = pcibr_dmamap->bd_soft;
     pciio_slot_t            slot = pcibr_dmamap->bd_slot;
 
-#ifdef IRIX
     unsigned                flags = pcibr_dmamap->bd_flags;
-#endif
 
     /* Make sure that bss_ext_ates_active
      * is properly kept up to date.
      */
-#ifdef IRIX
+
     if (PCIBR_DMAMAP_BUSY & flags)
 	if (PCIBR_DMAMAP_SSRAM & flags)
-	    atomicAddInt(&(pcibr_soft->
-			   bs_slot[slot].
-			   bss_ext_ates_active), -1);
-#endif
+	    atomic_dec(&(pcibr_soft->bs_slot[slot]. bss_ext_ates_active));
 
     xtalk_dmamap_free(pcibr_dmamap->bd_xtalk);
 
@@ -5265,7 +5377,9 @@
 		       pcibr_dmamap->bd_ate_count);
 	pcibr_release_device(pcibr_soft, slot, BRIDGE_DEV_PMU_BITS);
     }
+#ifdef IRIX
     DEL(pcibr_dmamap);
+#endif
 }
 
 /*
@@ -5325,7 +5439,6 @@
 /* We are starting to get more complexity
  * surrounding writing ATEs, so pull
  * the writing code into this new function.
- * XXX mail ranga@engr for IP27 prom!
  */
 
 #if PCIBR_FREEZE_TIME
@@ -5342,13 +5455,13 @@
 	   unsigned *cmd_regs)
 {
     pcibr_soft_t            pcibr_soft = pcibr_dmamap->bd_soft;
-#ifdef IRIX
+#ifdef LATER
     int                     dma_slot = pcibr_dmamap->bd_slot;
 #endif
     int                     ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM;
     int                     slot;
 
-    unsigned                s;
+    unsigned long           s;
     unsigned                cmd_reg;
     volatile unsigned      *cmd_lwa;
     unsigned                cmd_lwd;
@@ -5371,27 +5484,22 @@
      */
     s = pcibr_lock(pcibr_soft);
 
-#ifdef IRIX
+#ifdef LATER
     /* just in case pcibr_dmamap_done was not called */
     if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_BUSY) {
 	pcibr_dmamap->bd_flags &= ~PCIBR_DMAMAP_BUSY;
 	if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM)
-	    atomicAddInt(&(pcibr_soft->
-			   bs_slot[dma_slot].
-			   bss_ext_ates_active), -1);
+	    atomic_dec(&(pcibr_soft->bs_slot[dma_slot]. bss_ext_ates_active));
 	xtalk_dmamap_done(pcibr_dmamap->bd_xtalk);
     }
-#endif
+#endif	/* LATER */
 #if PCIBR_FREEZE_TIME
     *freeze_time_ptr = get_timestamp();
 #endif
 
     cmd_lwa = 0;
     for (slot = 0; slot < 8; ++slot)
-	if (pcibr_soft->
-	    bs_slot[slot].
-	    bss_ext_ates_active) {
-
+	if (atomic_read(&pcibr_soft->bs_slot[slot].bss_ext_ates_active)) {
 	    cmd_reg = pcibr_soft->
 		bs_slot[slot].
 		bss_cmd_shadow;
@@ -5418,9 +5526,7 @@
 
 	    /* Flush all the write buffers in the bridge */
 	    for (slot = 0; slot < 8; ++slot)
-		    if (pcibr_soft->
-			bs_slot[slot].
-			bss_ext_ates_active) {
+		    if (atomic_read(&pcibr_soft->bs_slot[slot].bss_ext_ates_active)) {
 			    /* Flush the write buffer associated with this
 			     * PCI device which might be using dma map RAM.
 			     */
@@ -5462,9 +5568,7 @@
 	 unsigned s)
 {
     pcibr_soft_t            pcibr_soft = pcibr_dmamap->bd_soft;
-#ifdef IRIX
     int                     dma_slot = pcibr_dmamap->bd_slot;
-#endif
     int                     slot;
     bridge_t               *bridge = pcibr_soft->bs_base;
     int                     ext_ates = pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM;
@@ -5486,11 +5590,7 @@
 	    bridge->b_type0_cfg_dev[slot].l[PCI_CFG_COMMAND / 4] = cmd_reg;
 
     pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_BUSY;
-#ifdef IRIX
-    atomicAddInt(&(pcibr_soft->
-		   bs_slot[dma_slot].
-		   bss_ext_ates_active), 1);
-#endif
+    atomic_inc(&(pcibr_soft->bs_slot[dma_slot]. bss_ext_ates_active));
 
 #if PCIBR_FREEZE_TIME
     freeze_time = get_timestamp() - freeze_time_start;
@@ -5685,11 +5785,7 @@
 		  unsigned flags)
 {
     pcibr_soft_t            pcibr_soft;
-#ifdef IRIX
-    bridge_t               *bridge;
-#else
     bridge_t               *bridge=NULL;
-#endif
 
     unsigned                al_flags = (flags & PCIIO_NOSLEEP) ? AL_NOSLEEP : 0;
     int                     inplace = flags & PCIIO_INPLACE;
@@ -5699,19 +5795,11 @@
     size_t                  length;
     iopaddr_t               offset;
     unsigned                direct64;
-#ifdef IRIX
-    int                     ate_index;
-    int                     ate_count;
-    int                     ate_total = 0;
-    bridge_ate_p            ate_ptr;
-    bridge_ate_t            ate_proto;
-#else
     int                     ate_index = 0;
     int                     ate_count = 0;
     int                     ate_total = 0;
     bridge_ate_p            ate_ptr = (bridge_ate_p)0;
     bridge_ate_t            ate_proto = (bridge_ate_t)0;
-#endif
     bridge_ate_t            ate_prev;
     bridge_ate_t            ate;
     alenaddr_t              xio_addr;
@@ -5899,16 +5987,12 @@
      * between _addr/_list and _done, but Hub does.
      */
 
-#ifdef IRIX
     if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_BUSY) {
 	pcibr_dmamap->bd_flags &= ~PCIBR_DMAMAP_BUSY;
 
 	if (pcibr_dmamap->bd_flags & PCIBR_DMAMAP_SSRAM)
-	    atomicAddInt(&(pcibr_dmamap->bd_soft->
-			   bs_slot[pcibr_dmamap->bd_slot].
-			   bss_ext_ates_active), -1);
+	    atomic_dec(&(pcibr_dmamap->bd_soft->bs_slot[pcibr_dmamap->bd_slot]. bss_ext_ates_active));
     }
-#endif
 
     xtalk_dmamap_done(pcibr_dmamap->bd_xtalk);
 }
@@ -6332,11 +6416,7 @@
 	 */
 	if (xio_port == pcibr_soft->bs_xid) {
 	    pci_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, xio_size);
-#ifdef IRIX
-	    if (pci_addr == NULL)
-#else
 	    if ( (pci_addr == (alenaddr_t)NULL) )
-#endif
 		goto fail;
 	} else if (direct64) {
 	    ASSERT(xio_port != 0);
@@ -6371,11 +6451,7 @@
 	}
     }
 
-#ifdef IRIX
-    if (relbits)
-#else
     if (relbits) {
-#endif
 	if (direct64) {
 	    slotp->bss_d64_flags = flags;
 	    slotp->bss_d64_base = pci_base;
@@ -6383,9 +6459,7 @@
 	    slotp->bss_d32_flags = flags;
 	    slotp->bss_d32_base = pci_base;
 	}
-#ifndef IRIX
     }
-#endif
     if (!inplace)
 	alenlist_done(xtalk_alenlist);
 
@@ -6480,26 +6554,155 @@
     return bbits;
 }
 
-#ifdef IRIX
+
+/*
+ *	Get the next wrapper pointer queued in the interrupt circular buffer.
+ */
+#ifdef KERNEL_THREADS
+pcibr_intr_wrap_t
+pcibr_wrap_get(pcibr_intr_cbuf_t cbuf)
+{
+    pcibr_intr_wrap_t	wrap;
+
+	if (cbuf->ib_in == cbuf->ib_out)
+	    PRINT_PANIC("pcibr intr circular buffer empty, cbuf=0x%x, ib_in=ib_out=%d\n",
+		cbuf, cbuf->ib_out);
+
+	wrap = cbuf->ib_cbuf[cbuf->ib_out++];
+	cbuf->ib_out = cbuf->ib_out % IBUFSIZE;
+	return(wrap);
+}
+
+/* 
+ *	Queue a wrapper pointer in the interrupt circular buffer.
+ */
+void
+pcibr_wrap_put(pcibr_intr_wrap_t wrap, pcibr_intr_cbuf_t cbuf)
+{
+	int	in;
+	unsigned long	s;
+
+	/*
+	 * Multiple CPUs could be executing this code simultaneously
+	 * if a handler has registered multiple interrupt lines and
+	 * the interrupts are directed to different CPUs.
+	 */
+	s = mutex_spinlock(&cbuf->ib_lock);
+	in = (cbuf->ib_in + 1) % IBUFSIZE;
+	if (in == cbuf->ib_out) 
+	    PRINT_PANIC("pcibr intr circular buffer full, cbuf=0x%x, ib_in=%d\n",
+		cbuf, cbuf->ib_in);
+
+	cbuf->ib_cbuf[cbuf->ib_in] = wrap;
+	cbuf->ib_in = in;
+	mutex_spinunlock(&cbuf->ib_lock, s);
+	return;
+}
+#endif	/* KERNEL_THREADS */
+
+/*
+ *	There are end cases where a deadlock can occur if interrupt 
+ *	processing completes and the Bridge b_int_status bit is still set.
+ *
+ *	One scenerio is if a second PCI interrupt occurs within 60ns of
+ *	the previous interrupt being cleared. In this case the Bridge
+ *	does not detect the transition, the Bridge b_int_status bit
+ *	remains set, and because no transition was detected no interrupt
+ *	packet is sent to the Hub/Heart.
+ *
+ *	A second scenerio is possible when a b_int_status bit is being
+ *	shared by multiple devices:
+ *						Device #1 generates interrupt
+ *						Bridge b_int_status bit set
+ *						Device #2 generates interrupt
+ *		interrupt processing begins
+ *		  ISR for device #1 runs and
+ *			clears interrupt
+ *						Device #1 generates interrupt
+ *		  ISR for device #2 runs and
+ *			clears interrupt
+ *						(b_int_status bit still set)
+ *		interrupt processing completes
+ *		  
+ *	Interrupt processing is now complete, but an interrupt is still
+ *	outstanding for Device #1. But because there was no transition of
+ *	the b_int_status bit, no interrupt packet will be generated and
+ *	a deadlock will occur.
+ *
+ *	To avoid these deadlock situations, this function is used
+ *	to check if a specific Bridge b_int_status bit is set, and if so,
+ *	cause the setting of the corresponding interrupt bit.
+ *
+ *	On a XBridge (IP35), we do this by writing the appropriate Bridge Force 
+ *	Interrupt register.
+ */
+void
+pcibr_force_interrupt(pcibr_intr_wrap_t wrap)
+{
+	unsigned	bit;
+	pcibr_soft_t    pcibr_soft = wrap->iw_soft;
+	bridge_t       *bridge = pcibr_soft->bs_base;
+	cpuid_t cpuvertex_to_cpuid(devfs_handle_t vhdl);
+
+	bit = wrap->iw_intr;
+
+	if (pcibr_soft->bs_xbridge) {
+	    bridge->b_force_pin[bit].intr = 1;
+	} else if ((1 << bit) & *wrap->iw_stat) {
+	    cpuid_t	    cpu;
+	    unsigned        intr_bit;
+	    xtalk_intr_t    xtalk_intr =
+				pcibr_soft->bs_intr[bit].bsi_xtalk_intr;
+
+	    intr_bit = (short) xtalk_intr_vector_get(xtalk_intr);
+	    cpu = cpuvertex_to_cpuid(xtalk_intr_cpu_get(xtalk_intr));
+	    REMOTE_CPU_SEND_INTR(cpu, intr_bit);
+	}
+}
+
 /* Wrapper for pcibr interrupt threads. */
+#ifdef KERNEL_THREADS
 static void
 pcibr_intrd(pcibr_intr_t intr)
 {
+    pcibr_intr_wrap_t	wrap;
+
 	/* Called on each restart */
 	ASSERT(cpuid() == intr->bi_mustruncpu);
 
 #ifdef ITHREAD_LATENCY
-	xthread_update_latstats(intr->bi_tinfo->thd_latstats);
+	xthread_update_latstats(intr->bi_tinfo.thd_latstats);
 #endif /* ITHREAD_LATENCY */
 
 	ASSERT(intr->bi_func != NULL);
 	intr->bi_func(intr->bi_arg);		/* Invoke the interrupt handler */
 
+	/*
+	 * The pcibr_intrd thread needs access to the wrapper struct
+	 * specific to the current interrupt it is processing. Because
+	 * multiple calls/wakeups to the thread could be queued, each
+	 * potentially from a different interrupt line (PCIIO_INTR_LINE_A,
+	 * etc), multiple wrapper struct pointers need to be queued. This 
+	 * is done via a circular buffer of wrapper struct pointers. 
+	 */
+	wrap = pcibr_wrap_get(&intr->bi_ibuf);
+
+	/* 
+	 * The interrupt handler has completed. Now decrement the running
+	 * count tracking the number of handlers still running for this line.
+	 * If this was the last handler to complete (i.e., iw_hdlrcnt == 0),
+	 * avoid a potential deadlock condition and ensure that another
+	 * interrupt will occur if the Bridge b_int_status bit is still
+	 * set. 
+	 */
+	atomicAddInt(&(wrap->iw_hdlrcnt), -1);
+	if (wrap->iw_hdlrcnt == 0)
+		pcibr_force_interrupt(wrap);
+
 	ipsema(&intr->bi_tinfo.thd_isync);	/* Sleep 'till next interrupt */
 	/* NOTREACHED */
 }
 
-
 static void
 pcibr_intrd_start(pcibr_intr_t intr)
 {
@@ -6519,14 +6722,16 @@
 	char thread_name[32];
 
 	sprintf(thread_name, "pcibr_intrd[0x%x]", bridge_levels);
+	thread_name[IT_NAMELEN-1] = '\0';
 
 	/* XXX need to adjust priority whenever an interrupt is connected */
+	intr->bi_tinfo.thd_pri = intr_swlevel;
 	atomicSetInt(&intr->bi_tinfo.thd_flags, THD_ISTHREAD | THD_REG);
 	xthread_setup(thread_name, intr_swlevel, &intr->bi_tinfo,
 			(xt_func_t *)pcibr_intrd_start,
 			(void *)intr);
 }
-#endif	/* IRIX */
+#endif	/* KERNEL_THREADS */
 
 
 
@@ -6542,13 +6747,16 @@
     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast;
     devfs_handle_t            xconn_vhdl = pcibr_soft->bs_conn;
     bridge_t               *bridge = pcibr_soft->bs_base;
-    int                     is_threaded;
+    int                     is_threaded = 0;
+#ifdef KERNEL_THREADS
+    cpuid_t		    mustruncpu = CPU_NONE;
+    cpuid_t		    old_intrcpu = CPU_NONE;
+#endif
     int                     thread_swlevel;
 
     xtalk_intr_t           *xtalk_intr_p;
     pcibr_intr_t           *pcibr_intr_p;
     pcibr_intr_list_t      *intr_list_p;
-    pcibr_intr_wrap_t      *intr_wrap_p;
 
     unsigned                pcibr_int_bits;
     unsigned                pcibr_int_bit;
@@ -6557,7 +6765,6 @@
     pcibr_intr_t            pcibr_intr;
     pcibr_intr_list_t       intr_entry;
     pcibr_intr_list_t       intr_list;
-    pcibr_intr_wrap_t       intr_wrap;
     bridgereg_t             int_dev;
 
 #if DEBUG && INTR_DEBUG
@@ -6576,9 +6783,29 @@
 	return NULL;
 
     if (dev_desc) {
+	cpuid_t intr_target_from_desc(device_desc_t, int);
+
+#ifdef KERNEL_THREADS
 	is_threaded = !(device_desc_flags_get(dev_desc) & D_INTR_NOTHREAD);
-	if (is_threaded)
+	if (is_threaded) {
+	    /*
+	     * If the device descriptor contains interrupt target info,
+	     * save the CPU requested. This is the CPU the pcibr_intrd
+	     * thread will be set to run on. 
+	     *
+	     * We need to get the interrupt target info at this time, because
+	     * the original intr_target value can be overwritten, as part of
+	     * the xtalk_intr_alloc_nothd() call, with the actual interrupt CPU.
+	     * This can be different than the requested CPU if the lower layers
+	     * could not direct the hardware interrupt to the requested CPU. 
+	     * Regardless of which CPU processes the hardware interrupt, the 
+	     * ISR thread will still be setup to run on the CPU originally 
+	     * requested.
+	     */
+		mustruncpu = intr_target_from_desc(dev_desc, SUBNODE_ANY);
 		thread_swlevel = device_desc_intr_swlevel_get(dev_desc);
+	}
+#endif	/* KERNEL_THREADS */
     } else {
 	extern int default_intr_pri;
 
@@ -6594,6 +6821,11 @@
     pcibr_intr->bi_arg = 0;		/* unset until connect */
     pcibr_intr->bi_flags = is_threaded ? 0 : PCIIO_INTR_NOTHREAD;
     pcibr_intr->bi_mustruncpu = CPU_NONE;
+#ifdef KERNEL_THREADS
+    pcibr_intr->bi_ibuf.ib_in = 0;
+    pcibr_intr->bi_ibuf.ib_out = 0;
+#endif
+    mutex_spinlock_init(&pcibr_intr->bi_ibuf.ib_lock);
 
     pcibr_int_bits = pcibr_soft->bs_intr_bits((pciio_info_t)pcibr_info, lines);
 
@@ -6626,7 +6858,17 @@
 		 *    single Bridge. (IP35-specific code forces this, and we
 		 *    verify in pcibr_setwidint.)
 		 */
-		xtalk_intr = xtalk_intr_alloc(xconn_vhdl, dev_desc, owner_dev);
+
+		/*
+		 * All code dealing with threaded PCI interrupt handlers
+		 * is located at the pcibr level. Because of this,
+		 * we always want the lower layers (hub/heart_intr_alloc, 
+		 * intr_level_connect) to treat us as non-threaded so we
+		 * don't set up a duplicate threaded environment. We make
+		 * this happen by calling a special xtalk interface.
+		 */
+		xtalk_intr = xtalk_intr_alloc_nothd(xconn_vhdl, dev_desc, 
+			owner_dev);
 #if DEBUG && INTR_DEBUG
 		printk("%v: xtalk_intr=0x%X\n", xconn_vhdl, xtalk_intr);
 #endif
@@ -6690,32 +6932,64 @@
 		}
 	    }
 
-	    /*
-	     * For threaded drivers, set the interrupt thread to run wherever
-	     * the interrupt is targeted.
-	     */
-#ifdef notyet
+#ifdef KERNEL_THREADS
 	    if (is_threaded) {
-		cpuid_t old_mustrun = pcibr_intr->bi_mustruncpu;
-		pcibr_intr->bi_mustruncpu = cpuvertex_to_cpuid(xtalk_intr_cpu_get(xtalk_intr));
-		ASSERT(pcibr_intr->bi_mustruncpu >= 0);
+		cpuid_t intrcpu = cpuvertex_to_cpuid(xtalk_intr_cpu_get(xtalk_intr));
 
 		/*
-		 * This is possible, but very unlikely: It means that 2 (or more) interrupts
-		 * originating on a single Bridge and used by a single device were unable to
-		 * find sufficient xtalk interrupt resources that would allow them all to be
-		 * handled by the same CPU.  If someone tries to target lots of interrupts to
-		 * a single CPU, we might hit this case.  Things should still operate correctly,
-		 * but it's a sub-optimal configuration.
+		 * It is possible that 2 (or more) interrupts originating on a
+		 * single Bridge and used by a single device were assigned to
+		 * different CPUs. If this occurs issue a warning message for
+		 * this sub-optimal configuration. There are two ways this 
+		 * could happen:
+		 *
+		 *  - There were insufficient xtalk interrupt resources to
+		 *    allow all interrupts to be assigned to the same CPU.
+		 *    This is an unlikely case, but could happen if someone
+		 *    tries to target a lot of interrupts to a single CPU.
+		 *
+		 * - If there is no device descriptor associated with this
+		 *   device, the xtalk/hub/heart layers will not know to
+		 *   assign the same CPU to any additional interrupts this
+		 *   driver has specified, and will perform the normal load
+		 *   leveling of interrupts across CPUs.
+		 *   (The lower layers store the CPU assigned to the first
+		 *   interrupt in the device desc, if present, and then when
+		 *   called again for additional interrupts for the same device,
+		 *   use this information to assign the same CPU to these
+		 *   interrupts.)
 		 */
-		if ((old_mustrun != CPU_NONE) && (old_mustrun != pcibr_intr->bi_mustruncpu)) {
-#ifdef SUPPORT_PRINTING_V_FORMAT
-			PRINT_WARNING( "Conflict on where to schedule interrupts for %v\n", pconn_vhdl);
+		if ((old_intrcpu != CPU_NONE) && (old_intrcpu != intrcpu)) {
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+			PRINT_WARNING("Conflict on where to schedule interrupts for %v\n", pconn_vhdl);
+#else
+			PRINT_WARNING("Conflict on where to schedule interrupts for 0x%x\n", pconn_vhdl);
 #endif
-			PRINT_WARNING( "(on cpu %d or on cpu %d)\n", old_mustrun, pcibr_intr->bi_mustruncpu);
+			PRINT_WARNING("(on cpu %d or on cpu %d), cpu %d used\n", old_intrcpu, intrcpu, intrcpu);
+		}
+		if (old_intrcpu == CPU_NONE)
+			old_intrcpu = intrcpu;
+	    /*
+	     * For threaded drivers, set the interrupt thread to run wherever
+	     * the interrupt is targeted, or where requested in the dev_desc.
+	     */
+		if (mustruncpu != CPU_NONE) {
+			pcibr_intr->bi_mustruncpu = mustruncpu;
+			if (mustruncpu != intrcpu) {
+				PRINT_WARNING("Request to target PCI interrupts to CPU %d could not\n"
+                		"      be satisfied, CPU %d used. However, interrupt thread\n"
+                		"      pcibr_intrd will run on CPU %d as requested.\n"
+                		"      %v (0x%x)\n",
+                		mustruncpu, intrcpu, mustruncpu, owner_dev,
+				owner_dev);
+			}
+		} else {
+			pcibr_intr->bi_mustruncpu = intrcpu;
 		}
+		ASSERT(pcibr_intr->bi_mustruncpu >= 0);
+
 	    }
-#endif
+#endif	/* KERNEL_THREADS */
 
 	    pcibr_intr->bi_ibits |= 1 << pcibr_int_bit;
 
@@ -6723,8 +6997,20 @@
 	    intr_entry->il_next = NULL;
 	    intr_entry->il_intr = pcibr_intr;
 	    intr_entry->il_wrbf = &(bridge->b_wr_req_buf[pciio_slot].reg);
+	    intr_list_p = 
+		&pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_list;
+#if DEBUG && INTR_DEBUG
+#if defined(SUPPORT_PRINTING_V_FORMAT)
+	    printk("0x%x: Bridge bit %d wrap=0x%x\n",
+		pconn_vhdl, pcibr_int_bit,
+		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap);
+#else
+	    printk("%v: Bridge bit %d wrap=0x%x\n",
+		pconn_vhdl, pcibr_int_bit,
+		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap);
+#endif
+#endif
 
-	    intr_list_p = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_list;
 	    if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) {
 		/* we are the first interrupt on this bridge bit.
 		 */
@@ -6751,29 +7037,12 @@
 	    intr_list_p = &intr_list->il_next;
 	    if (compare_and_swap_ptr((void **) intr_list_p, NULL, intr_entry)) {
 		/* we are the new second interrupt on this bit.
-		 * switch to local wrapper.
 		 */
+		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared = 1;
 #if DEBUG && INTR_DEBUG
 		printk("%v INT 0x%x (bridge bit %d) is new SECOND\n",
 			pconn_vhdl, pcibr_int_bits, pcibr_int_bit);
 #endif
-		NEW(intr_wrap);
-		intr_wrap->iw_soft = pcibr_soft;
-		intr_wrap->iw_stat = &(bridge->b_int_status);
-		intr_wrap->iw_intr = 1 << pcibr_int_bit;
-		intr_wrap->iw_list = intr_list;
-		intr_wrap_p = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
-		if (!compare_and_swap_ptr((void **) intr_wrap_p, NULL, intr_wrap)) {
-		    /* someone else set up the wrapper.
-		     */
-		    DEL(intr_wrap);
-		    continue;
-#if DEBUG && INTR_DEBUG
-		} else {
-		    printk("%v bridge bit %d wrapper state created\n",
-			    pconn_vhdl, pcibr_int_bit);
-#endif
-		}
 		continue;
 	    }
 	    while (1) {
@@ -6807,13 +7076,13 @@
 	}
     }
 
-#ifdef IRIX
+#ifdef KERNEL_THREADS
     if (is_threaded) {
 	/* Set pcibr_intr->bi_tinfo */
 	pcibr_thread_setup(pcibr_intr, pcibr_int_bits, thread_swlevel);
 	ASSERT(!(pcibr_intr->bi_flags & PCIIO_INTR_CONNECTED));
     }
-#endif
+#endif	/* KERNEL_THREADS */
 
 #if DEBUG && INTR_DEBUG
     printk("%v pcibr_intr_alloc complete\n", pconn_vhdl);
@@ -6832,13 +7101,13 @@
     pcibr_soft_t            pcibr_soft = pcibr_intr->bi_soft;
     unsigned                pcibr_int_bit;
     pcibr_intr_list_t       intr_list;
-    pcibr_intr_wrap_t	    intr_wrap;
+    int			    intr_shared;
     xtalk_intr_t	    *xtalk_intrp;
 
     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++) {
 	if (pcibr_int_bits & (1 << pcibr_int_bit)) {
 	    for (intr_list = 
-		     pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_list;
+		     pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_list;
 		 intr_list != NULL;
 		 intr_list = intr_list->il_next)
 		if (compare_and_swap_ptr((void **) &intr_list->il_intr, 
@@ -6852,10 +7121,11 @@
 	    /* If this interrupt line is not being shared between multiple
 	     * devices release the xtalk interrupt resources.
 	     */
-	    intr_wrap = 
-		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
+	    intr_shared = 
+		pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared;
 	    xtalk_intrp = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr;
-	    if ((intr_wrap == NULL) && (*xtalk_intrp)) {
+
+	    if ((!intr_shared) && (*xtalk_intrp)) {
 
 		bridge_t 	*bridge = pcibr_soft->bs_base;
 		bridgereg_t	int_dev;
@@ -6900,7 +7170,7 @@
     unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;
     unsigned                pcibr_int_bit;
     bridgereg_t             b_int_enable;
-    unsigned                s;
+    unsigned long           s;
 
     if (pcibr_intr == NULL)
 	return -1;
@@ -6924,59 +7194,29 @@
 	if (pcibr_int_bits & (1 << pcibr_int_bit)) {
 	    pcibr_intr_wrap_t       intr_wrap;
 	    xtalk_intr_t            xtalk_intr;
-	    int                    *setptr;
 
 	    xtalk_intr = pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr;
 
-	    /* if we have no wrap structure,
-	     * tell xtalk to deliver the interrupt
-	     * directly to the client.
+	    intr_wrap = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
+	    /*
+	     * If this interrupt line is being shared and the connect has
+	     * already been done, no need to do it again.
 	     */
-	    intr_wrap = pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
-	    if (intr_wrap == NULL) {
-		xtalk_intr_connect(xtalk_intr,
-				   (intr_func_t) intr_func,
-				   (intr_arg_t) intr_arg,
-				   (xtalk_intr_setfunc_t) pcibr_setpciint,
-				   (void *) &(bridge->b_int_addr[pcibr_int_bit].addr),
-				   thread);
-#if DEBUG && INTR_DEBUG
-		printk("%v bridge bit %d routed by xtalk\n",
-			pcibr_intr->bi_dev, pcibr_int_bit);
-#endif
+	    if (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected)
 		continue;
-	    }
-
-	    setptr = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_wrap_set;
-	    if (*setptr)
-		continue;
-
 
-	    /* We have a wrap structure, so we're sharing a Bridge interrupt level */
-
-	    xtalk_intr_disconnect(xtalk_intr); /* Disconnect old interrupt */
 
 	    /*
-		If the existing xtalk_intr was allocated without the NOTHREAD flag,
-		we need to allocate a new one that's NOTHREAD, and connect to the
-		new one.   pcibr_intr_list_func expects to run at interrupt level
-		rather than in a thread.  With today's devices, this can't happen,
-		so let's punt on writing the code till we need it (probably never).
-		Instead, just ASSERT that we're a NOTHREAD xtalk_intr.
-	    */
-#ifdef IRIX
-	    ASSERT_ALWAYS(!(pcibr_intr->bi_flags & PCIIO_INTR_NOTHREAD) ||
-			xtalk_intr_flags_get(xtalk_intr) & XTALK_INTR_NOTHREAD);
-#endif
-
-	    /* Use the wrapper dispatch function to handle shared Bridge interrupts */
+	     * Use the pcibr wrapper function to handle all Bridge interrupts
+	     * regardless of whether the interrupt line is shared or not.
+	     */
 	    xtalk_intr_connect(xtalk_intr,
-			       pcibr_intr_list_func,
+				pcibr_intr_func,
 			       (intr_arg_t) intr_wrap,
 			       (xtalk_intr_setfunc_t) pcibr_setpciint,
 			       (void *) &(bridge->b_int_addr[pcibr_int_bit].addr),
 			       0);
-	    *setptr = 1;
+	    pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected = 1;
 
 #if DEBUG && INTR_DEBUG
 	    printk("%v bridge bit %d wrapper connected\n",
@@ -7001,9 +7241,9 @@
     bridge_t               *bridge = pcibr_soft->bs_base;
     unsigned                pcibr_int_bits = pcibr_intr->bi_ibits;
     unsigned                pcibr_int_bit;
-    pcibr_intr_wrap_t       intr_wrap;
+    pcibr_intr_wrap_t	    intr_wrap;
     bridgereg_t             b_int_enable;
-    unsigned                s;
+    unsigned long           s;
 
     /* Stop calling the function. Now.
      */
@@ -7021,7 +7261,7 @@
      */
     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)
 	if ((pcibr_int_bits & (1 << pcibr_int_bit)) &&
-	    (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_wrap_set))
+	    (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared))
 	    pcibr_int_bits &= ~(1 << pcibr_int_bit);
     if (!pcibr_int_bits)
 	return;
@@ -7035,26 +7275,32 @@
 
     for (pcibr_int_bit = 0; pcibr_int_bit < 8; pcibr_int_bit++)
 	if (pcibr_int_bits & (1 << pcibr_int_bit)) {
-	    /* if we have set up the share wrapper,
+	    /* if the interrupt line is now shared,
 	     * do not disconnect it.
 	     */
-	    if (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_wrap_set)
+	    if (pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared)
 		continue;
 
 	    xtalk_intr_disconnect(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr);
+	    pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_connected = 0;
+
+#if DEBUG && INTR_DEBUG
+	    printk("%s: xtalk disconnect done for Bridge bit %d\n",
+		pcibr_soft->bs_name, pcibr_int_bit);
+#endif
 
-	    /* if we have a share wrapper state,
+	    /* if we are sharing the interrupt line,
 	     * connect us up; this closes the hole
-	     * where the connection of the wrapper
+	     * where the another pcibr_intr_alloc()
 	     * was in progress as we disconnected.
 	     */
-	    intr_wrap = pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
-	    if (intr_wrap == NULL) 
+	    intr_wrap = &pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap;
+	    if (!pcibr_soft->bs_intr[pcibr_int_bit].bsi_pcibr_intr_wrap.iw_shared)
 		continue;
 
 
 	    xtalk_intr_connect(pcibr_soft->bs_intr[pcibr_int_bit].bsi_xtalk_intr,
-			       pcibr_intr_list_func,
+			       pcibr_intr_func,
 			       (intr_arg_t) intr_wrap,
 			       (xtalk_intr_setfunc_t) pcibr_setpciint,
 			       (void *) &(bridge->b_int_addr[pcibr_int_bit].addr),
@@ -7168,7 +7414,7 @@
 	bridge->b_int_enable |= ~BRIDGE_IMR_INT_MSK;
 
     } else {
-	/* routing a pci device interrupt.
+	/* routing a PCI device interrupt.
 	 * targ and low 38 bits of addr must
 	 * be the same as the already set
 	 * value for the widget error interrupt.
@@ -7187,46 +7433,71 @@
     bridge->b_wid_tflush;		/* wait until Bridge PIO complete */
 }
 
+
+/*
+ * pcibr_intr_func()
+ *
+ * This is the pcibr interrupt "wrapper" function that is called,
+ * in interrupt context, to initiate the interrupt handler(s) registered
+ * (via pcibr_intr_alloc/connect) for the occuring interrupt. Non-threaded 
+ * handlers will be called directly, and threaded handlers will have their 
+ * thread woken up.
+ */
 void
-pcibr_intr_list_func(intr_arg_t arg)
+pcibr_intr_func(intr_arg_t arg)
 {
     pcibr_intr_wrap_t       wrap = (pcibr_intr_wrap_t) arg;
-    reg_p                   statp = wrap->iw_stat;
-    bridgereg_t             mask = wrap->iw_intr;
     reg_p                   wrbf;
-    pcibr_intr_list_t       list;
-    pcibr_intr_t            intr;
     intr_func_t             func;
+    pcibr_intr_t            intr;
+    pcibr_intr_list_t       list;
     int                     clearit;
-    int                     thread_count = 0;
+#ifdef KERNEL_THREADS
+    int			    do_nonthreaded = 0;
+    int			    do_threaded = 1;
+    int			    is_threaded = 0;
+#else
+    int			    do_nonthreaded = 1;
+    int			    do_threaded = 0;
+    int			    is_threaded = 0;
+#endif
+    int			    nonthreaded_count = 0;
+    int			    x = 0;
+
+	/*
+	 * If any handler is still running from a previous interrupt
+	 * just return. If there's a need to call the handler(s) again,
+	 * another interrupt will be generated either by the device or by
+	 * pcibr_force_interrupt().
+	 */
+
+	if (wrap->iw_hdlrcnt) {
+		return;
+	}
 
     /*
-     * Loop until either
-     * 1) All interrupts have been removed by direct-called interrupt handlers OR
-     * 2) We've woken up at least one interrupt thread that will presumably clear
-     *    Bridge interrupt bits
+     * Call all interrupt handlers registered.
+     * First, the pcibr_intrd threads for any threaded handlers will be
+     * awoken, then any non-threaded handlers will be called sequentially.
      */
 	
-    while ((!thread_count) && (mask & *statp)) {
 	clearit = 1;
-	for (list = wrap->iw_list;
-	     list != NULL;
-	     list = list->il_next) {
-	    if ((intr = list->il_intr) &&
-		(intr->bi_flags & PCIIO_INTR_CONNECTED)) {
-    		int is_threaded;
+	while (do_threaded || do_nonthreaded) {
+	    for (list = wrap->iw_list; list != NULL; list = list->il_next) {
+		if ((intr = list->il_intr) &&
+		    (intr->bi_flags & PCIIO_INTR_CONNECTED)) {
 
-		ASSERT(intr->bi_func);
+		    ASSERT(intr->bi_func);
 
 		/*
 		 * This device may have initiated write
 		 * requests since the bridge last saw
 		 * an edge on this interrupt input; flushing
-		 * the buffer here should help but may not
-		 * be sufficient if we get more requests after
-		 * the flush, followed by the card deciding
-		 * it wants service, before the interrupt
-		 * handler checks to see if things need
+		 * the buffer prior to invoking the handler
+		 * should help but may not be sufficient if we 
+		 * get more requests after the flush, followed
+		 * by the card deciding it wants service, before
+		 * the interrupt handler checks to see if things need
 		 * to be done.
 		 *
 		 * There is a similar race condition if
@@ -7238,28 +7509,96 @@
 		 * has completed, but before observing the
 		 * contents of memory?
 		 */
-#ifdef IRIX
-		if (wrbf = list->il_wrbf)
+
+#ifdef KERNEL_THREADS
+		    is_threaded = !(intr->bi_flags & PCIIO_INTR_NOTHREAD);
+		    if (!is_threaded) {
+			nonthreaded_count++;
+		    }
+
+		    if ((do_threaded) && (is_threaded)) {
+			/* Only need to flush write buffers if sharing */
+
+			if ((wrap->iw_shared) && (wrbf = list->il_wrbf)) {
+			    if (x = *wrbf)	/* write request buffer flush */
+#ifdef SUPPORT_PRINTING_V_FORMAT
+				PRINT_ALERT("pcibr_intr_func %v: \n"
+				    "write buffer flush failed, wrbf=0x%x\n", 
+				    list->il_intr->bi_dev, wrbf);
 #else
-		if ((wrbf = list->il_wrbf))
+				PRINT_ALERT("pcibr_intr_func 0x%x: \n"
+				    "write buffer flush failed, wrbf=0x%x\n", 
+				    list->il_intr->bi_dev, wrbf);
 #endif
-		    (void) *wrbf;	/* write request buffer flush */
+			}
+
+			/*
+			 * Keep a running count of the number of interrupt
+			 * handlers that have yet to complete. 
+			 */
+			atomicAddInt(&(wrap->iw_hdlrcnt), 1);
+
+			/* 
+			 * Prior to waking up pcibr_intrd, a pointer to the 
+			 * wrapper struct corresponding to the interrupt taken
+			 * needs to be queued in the interrupt circular buffer.
+			 * The pcibr_intrd thread needs the wrapper pointer in
+			 * order to decrement the handler count (iw_hdlrcnt).
+			 */
+			pcibr_wrap_put(wrap, &intr->bi_ibuf);
+#ifdef ITHREAD_LATENCY
+			xthread_set_istamp(intr->bi_tinfo.thd_latstats);
+#endif /* ITHREAD_LATENCY */
+		     	up(&intr->bi_tinfo.thd_isync); 
+		    } else
+#endif	/* KERNEL_THREADS */
+			if ((do_nonthreaded) && (!is_threaded)) {
+			/* Non-threaded. 
+			 * Call the interrupt handler at interrupt level
+			 */
 
-		is_threaded = !(intr->bi_flags & PCIIO_INTR_NOTHREAD);
+			/* Only need to flush write buffers if sharing */
 
-		if (is_threaded) {
-			thread_count++;
-#ifdef IRIX
-			icvsema(&intr->bi_tinfo.thd_isync, intr->bi_tinfo.thd_pri,
-				NULL, NULL, NULL);
+			if ((wrap->iw_shared) && (wrbf = list->il_wrbf)) {
+			    if ((x = *wrbf))	/* write request buffer flush */
+#ifdef SUPPORT_PRINTING_V_FORMAT
+				PRINT_ALERT("pcibr_intr_func %v: \n"
+				    "write buffer flush failed, wrbf=0x%x\n", 
+				    list->il_intr->bi_dev, wrbf);
+#else
+				PRINT_ALERT("pcibr_intr_func %p: \n"
+				    "write buffer flush failed, wrbf=0x%x\n", 
+				    list->il_intr->bi_dev, wrbf);
 #endif
-		} else {
-			/* Non-threaded.  Call the interrupt handler at interrupt level */
+			}
+
 			func = intr->bi_func;
 			func(intr->bi_arg);
+		    }
+
+		    clearit = 0;
 		}
+	    }
+
+	    if (do_threaded) {
+		/* 
+		 * All threaded handlers have been called;
+		 * next do non-threaded, if any.
+		 */
+		do_threaded = 0;
 
-		clearit = 0;
+		if (nonthreaded_count)
+			do_nonthreaded = 1;
+	    } else {
+		do_nonthreaded = 0;
+		/*
+		 * If the non-threaded handler was the last to complete,
+		 * (i.e., no threaded handlers still running) force an
+		 * interrupt to avoid a potential deadlock situation.
+		 */
+		if (wrap->iw_hdlrcnt == 0) {
+			pcibr_force_interrupt(wrap);
+		}
 	    }
 	}
 
@@ -7275,7 +7614,8 @@
 	    pcibr_soft_t            pcibr_soft = wrap->iw_soft;
 	    bridge_t               *bridge = pcibr_soft->bs_base;
 	    bridgereg_t             b_int_enable;
-	    unsigned                s;
+	    bridgereg_t		    mask = 1 << wrap->iw_intr;
+	    unsigned long           s;
 
 	    s = pcibr_lock(pcibr_soft);
 	    b_int_enable = bridge->b_int_enable;
@@ -7285,7 +7625,6 @@
 	    pcibr_unlock(pcibr_soft, s);
 	    return;
 	}
-    }
 }
 
 /* =====================================================================
@@ -7403,7 +7742,7 @@
 		bridge->b_pci_err_lower);
     }
     if (int_status & BRIDGE_ISR_ERROR_FATAL) {
-	cmn_err_tag(14, (int)CE_PANIC, "PCI Bridge Error interrupt killed the system");
+	PRINT_PANIC("PCI Bridge Error interrupt killed the system");
 	/*NOTREACHED */
     } else {
 	PRINT_ALERT( "Non-fatal Error in Bridge..");
@@ -7491,10 +7830,8 @@
 				soft->bs_slot[slot].bss_window[win].bssw_base;
 			else if (map->bp_space == PCIIO_SPACE_ROM)
 			    base += pcibr_info->f_rbase;
-#ifdef IRIX
 			if ((pci_addr >= base) && (pci_addr < (base + size)))
-			    atomicAddInt(map->bp_toc, 1);
-#endif
+			    atomic_inc(map->bp_toc);
 		    }
 		}
 	    }
@@ -7532,34 +7869,8 @@
     bridgereg_t             err_status;
     int                     i;
 
-#if defined(SN0_HWDEBUG)
-    extern int		    la_trigger_nasid1;
-    extern int		    la_trigger_nasid2;
-    extern long		    la_trigger_val;
-#endif
-
     /* REFERENCED */
     bridgereg_t             disable_errintr_mask = 0;
-#ifdef IRIX
-    int 		    rv;
-#else
-    int                     rv = 0;
-#endif
-    int 		    error_code = IOECODE_DMA | IOECODE_READ;
-    ioerror_mode_t 	    mode = MODE_DEVERROR;
-    ioerror_t 	            ioe;
-
-#if defined(SN0_HWDEBUG)
-   /*
-    * trigger points for logic analyzer. Used to debug the DMA timeout
-    * note that 0xcafe is added to the trigger values to avoid false
-    * triggers when la_trigger_val shows up in a cacheline as data
-    */
-   if (la_trigger_nasid1 != -1) 
-	REMOTE_HUB_PI_S(la_trigger_nasid1, 0, PI_CPU_NUM, la_trigger_val + 0xcafe);
-   if (la_trigger_nasid2 != -1) 
-	REMOTE_HUB_PI_S(la_trigger_nasid2, 0, PI_CPU_NUM, la_trigger_val + 0xcafe);
-#endif
 
 #if PCIBR_SOFT_LIST
     /* IP27 seems to be handing us junk.
@@ -7635,7 +7946,7 @@
 
 		bs_estat->bs_errcount_total++;
 
-#ifdef IRIX
+#ifdef LATER
 		current_tick = lbolt;
 #else
 		current_tick = 0;
@@ -7777,7 +8088,7 @@
     if ((err_status & BRIDGE_ISR_INVLD_ADDR) &&
 	((((uint64_t) bridge->b_wid_err_upper << 32) | (bridge->b_wid_err_lower))
 	 == (BRIDGE_INT_RST_STAT & 0xff0))) {
-#ifdef IRIX
+#ifdef LATER
 	if (kdebug)
 	    PRINT_NOTICE( "%s bridge: ignoring llp/control address interrupt",
 		    pcibr_soft->bs_name);
@@ -7787,32 +8098,6 @@
     }
 #endif				/* PCIBR_LLP_CONTROL_WAR */
 
-    /* Check if this is the RESP_XTALK_ERROR interrupt. 
-     * This can happen due to a failed DMA READ operation.
-     */
-    if (err_status & BRIDGE_ISR_RESP_XTLK_ERR) {
-	/* Phase 1 : Look at the error state in the bridge and further
-	 * down in the device layers.
-	 */
-#if defined(CONFIG_SGI_IO_ERROR_HANDLING)
-	(void)error_state_set(pcibr_soft->bs_conn, ERROR_STATE_LOOKUP);
-#endif
-	IOERROR_SETVALUE(&ioe, widgetnum, pcibr_soft->bs_xid);
-	(void)pcibr_error_handler((error_handler_arg_t)pcibr_soft,
-				  error_code,
-				  mode,
-				  &ioe);
-	/* Phase 2 : Perform the action agreed upon in phase 1.
-	 */
-#if defined(CONFIG_SGI_IO_ERROR_HANDLING)
-	(void)error_state_set(pcibr_soft->bs_conn, ERROR_STATE_ACTION);
-#endif
-	rv = pcibr_error_handler((error_handler_arg_t)pcibr_soft,
-				 error_code,
-				 mode,
-				 &ioe);
-    }
-    if (rv != IOERROR_HANDLED) {
 #ifdef	DEBUG
 	if (err_status & BRIDGE_ISR_ERROR_DUMP)
 	    pcibr_error_dump(pcibr_soft);
@@ -7822,7 +8107,7 @@
 	    pcibr_error_dump(pcibr_soft);
 	}
 #endif
-    }
+
     /*
      * We can't return without re-enabling the interrupt, since
      * it would cause problems for devices like IOC3 (Lost
@@ -7853,11 +8138,7 @@
 		  iopaddr_t *offsetp,
 		  pciio_function_t *funcp)
 {
-#ifdef IRIX
-    int                     s, f, w;
-#else
     int                     s, f=0, w;
-#endif
     iopaddr_t               base;
     size_t                  size;
     pciio_piospace_t        piosp;
@@ -8082,7 +8363,7 @@
  * decodes the PCI specific portions -- we count on our
  * callers to dump the raw IOE data.
  */
-#ifdef colin
+#ifdef LATER
 #define BEM_ADD_IOE(ioe)						\
 	do {								\
 	    if (IOERROR_FIELDVALID(ioe, busspace)) {			\
@@ -8165,7 +8446,7 @@
      * and need to construct the slot/space/offset.
      */
 
-#ifdef colin
+#ifdef LATER
     bad_xaddr = IOERROR_GETVALUE(ioe, xtalkaddr);
 #else
     bad_xaddr = -1;
@@ -8207,7 +8488,7 @@
 	if (x > 1)
 	    x--;
 	/* x is which devio reg; no guarantee
-	 * pci slot x will be responding.
+	 * PCI slot x will be responding.
 	 * still need to figure out who decodes
 	 * space/offset on the bus.
 	 */
@@ -8253,7 +8534,7 @@
 
     if ((slot == PCIIO_SLOT_NONE) && (space != PCIIO_SPACE_NONE)) {
 	/* we've got a space/offset but not which
-	 * pci slot decodes it. Check through our
+	 * PCI slot decodes it. Check through our
 	 * notions of which devices decode where.
 	 *
 	 * Yes, this "duplicates" some logic in
@@ -8353,9 +8634,7 @@
 		wx = PCIIO_SPACE_MEM;
 	    wl = wb + ws;
 	    if ((wx == raw_space) && (raw_paddr >= wb) && (raw_paddr < wl)) {
-#ifdef IRIX
-		atomicAddInt(map->bp_toc, 1);
-#endif
+		atomic_inc(map->bp_toc);
 		if (slot == PCIIO_SLOT_NONE) {
 		    slot = cs;
 		    space = map->bp_space;
@@ -8369,7 +8648,7 @@
 
     if (space != PCIIO_SPACE_NONE) {
 	if (slot != PCIIO_SLOT_NONE) {
-#ifdef IRIX
+#ifdef LATER
 	    if (func != PCIIO_FUNC_NONE)
 		IOERROR_SETVALUE(ioe, widgetdev, 
 				 pciio_widgetdev_create(slot,func));
@@ -8451,10 +8730,10 @@
      * error interrupt is due to read/write error..
      */
 
-    /* We know the xtalk addr, the raw pci bus space,
-     * the raw pci bus address, the decoded pci bus
+    /* We know the xtalk addr, the raw PCI bus space,
+     * the raw PCI bus address, the decoded PCI bus
      * space, the offset within that space, and the
-     * decoded pci slot (which may be "PCIIO_SLOT_NONE" if no slot
+     * decoded PCI slot (which may be "PCIIO_SLOT_NONE" if no slot
      * is known to be involved).
      */
 
@@ -8506,7 +8785,7 @@
 	    BEM_ADD_VAR(raw_paddr);
 	    if (IOERROR_FIELDVALID(ioe, widgetdev)) {
 
-#ifdef colin
+#ifdef LATER
 		slot = pciio_widgetdev_slot_get(IOERROR_GETVALUE(ioe, 
 								 widgetdev));
 		func = pciio_widgetdev_func_get(IOERROR_GETVALUE(ioe, 
@@ -8545,7 +8824,7 @@
 	 *      Need a way to ensure we don't inadvertently clear some
 	 *      other errors.
 	 */
-#ifdef IRIX
+#ifdef LATER
 	if (IOERROR_FIELDVALID(ioe, widgetdev))
 	    pcibr_device_disable(pcibr_soft, 
 				 pciio_widgetdev_slot_get(
@@ -8586,7 +8865,7 @@
      * Look up the address, in the bridge error registers, and
      * take appropriate action
      */
-#ifdef colin
+#ifdef LATER
     ASSERT(IOERROR_GETVALUE(ioe, widgetnum) == pcibr_soft->bs_xid);
     ASSERT(bridge);
 #endif
@@ -8618,7 +8897,7 @@
 
     retval = pciio_error_handler(pcibr_vhdl, error_code, mode, ioe);
     if (retval != IOERROR_HANDLED)
-#ifdef colin
+#ifdef LATER
 	pcibr_device_disable(pcibr_soft, 
 			     pciio_widgetdev_slot_get(
 				      IOERROR_GETVALUE(ioe,widgetdev)));
@@ -8690,7 +8969,7 @@
 
     retval = pciio_error_handler(pcibr_vhdl, error_code, mode, ioe);
 
-#ifdef IRIX
+#ifdef LATER
     if (retval != IOERROR_HANDLED) {
 	pcibr_device_disable(pcibr_soft, 
 			     pciio_widgetdev_slot_get(
@@ -8722,22 +9001,8 @@
 {
     pcibr_soft_t            pcibr_soft;
     int                     retval = IOERROR_BADERRORCODE;
-    devfs_handle_t	    xconn_vhdl,pcibr_vhdl;
-#if defined(CONFIG_SGI_IO_ERROR_HANDLING)
-    error_state_t	    e_state;
-#endif
-    pcibr_soft = (pcibr_soft_t) einfo;
-
-    xconn_vhdl = pcibr_soft->bs_conn;
-    pcibr_vhdl = pcibr_soft->bs_vhdl;
 
-#if defined(CONFIG_SGI_IO_ERROR_HANDLING)
-    e_state = error_state_get(xconn_vhdl);
-    
-    if (error_state_set(pcibr_vhdl, e_state) == 
-	ERROR_RETURN_CODE_CANNOT_SET_STATE)
-	return(IOERROR_UNHANDLED);
-#endif
+    pcibr_soft = (pcibr_soft_t) einfo;
 
     /* If we are in the action handling phase clean out the error state
      * on the xswitch.
@@ -8844,7 +9109,7 @@
     bridge_t               *bridge = pcibr_soft->bs_base;
     bridgereg_t             ctlreg;
     unsigned                cfgctl[8];
-    unsigned                s;
+    unsigned long           s;
     int                     f, nf;
     pcibr_info_h            pcibr_infoh;
     pcibr_info_t            pcibr_info;
@@ -8869,11 +9134,7 @@
 	/* XXX delay? */
 
 	for (f = 0; f < nf; ++f)
-#ifdef IRIX
-	    if (pcibr_info = pcibr_infoh[f])
-#else
 	    if ((pcibr_info = pcibr_infoh[f]))
-#endif
 		for (win = 0; win < 6; ++win)
 		    if (pcibr_info->f_window[win].w_base != 0)
 			bridge->b_type0_cfg_dev[pciio_slot].f[f].l[PCI_CFG_BASE_ADDR(win) / 4] =
@@ -8901,7 +9162,7 @@
     pciio_slot_t            pciio_slot = pciio_info_slot_get(pciio_info);
     pcibr_soft_t            pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
     bridgereg_t             devreg;
-    unsigned                s;
+    unsigned long           s;
 
     /*
      * Bridge supports hardware swapping; so we can always
@@ -8944,7 +9205,7 @@
 			pciio_slot_t pciio_slot,
 			pciio_priority_t device_prio)
 {
-    int                     s;
+    unsigned long           s;
     int                    *counter;
     bridgereg_t             rtbits = 0;
     bridgereg_t             devreg;
@@ -8966,9 +9227,9 @@
      * XXX- Bug in Rev B Bridge Si:
      * Symptom: Prefetcher starts operating incorrectly. This happens
      * due to corruption of the address storage ram in the prefetcher
-     * when a non-real time pci request is pulled and a real-time one is
+     * when a non-real time PCI request is pulled and a real-time one is
      * put in it's place. Workaround: Use only a single arbitration ring
-     * on pci bus. GBR and RR can still be uniquely used per
+     * on PCI bus. GBR and RR can still be uniquely used per
      * device. NETLIST MERGE DONE, WILL BE FIXED IN REV C.
      */
 
@@ -8983,18 +9244,12 @@
     s = pcibr_lock(pcibr_soft);
     devreg = pcibr_soft->bs_slot[pciio_slot].bss_device;
     if (device_prio == PCI_PRIO_HIGH) {
-#ifdef IRIX
-	if (++*counter == 1)
-#else
 	if ((++*counter == 1)) {
-#endif
 	    if (rtbits)
 		devreg |= rtbits;
 	    else
 		rc = PRIO_FAIL;
-#ifndef IRIX
 	}
-#endif
     } else if (device_prio == PCI_PRIO_LOW) {
 	if (*counter <= 0)
 	    rc = PRIO_FAIL;
@@ -9082,15 +9337,11 @@
 
     if (set || clr) {
 	bridgereg_t             devreg;
-	unsigned                s;
+	unsigned long           s;
 
 	s = pcibr_lock(pcibr_soft);
 	devreg = pcibr_soft->bs_slot[pciio_slot].bss_device;
-#ifdef IRIX
-	devreg = devreg & ~clr | set;
-#else
 	devreg = (devreg & ~clr) | set;
-#endif
 	if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) {
 	    bridge_t               *bridge = pcibr_soft->bs_base;
 
@@ -9146,13 +9397,9 @@
 
     pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast;
 
-    if ( (pcibr_soft_t)0 != pcibr_soft ) {
-	bridge = pcibr_soft->bs_base;
-	if ( (bridge_t *)0 != bridge ) {
-		cfgbase = bridge->b_type0_cfg_dev[pciio_slot].f[pciio_func].l;
-	}
-    }
+    bridge = pcibr_soft->bs_base;
 
+    cfgbase = bridge->b_type0_cfg_dev[pciio_slot].f[pciio_func].l;
 
     return cfgbase;
 }
@@ -9215,7 +9462,7 @@
     case 3:
 	if (reg & 1) {
 	    CB(cfgbase, reg) = value;
-	    CS(cfgbase, reg + 1) = value >> 8;
+	    CS(cfgbase, (reg + 1)) = value >> 8;
 	} else {
 	    CS(cfgbase, reg) = value;
 	    CB(cfgbase, reg + 2) = value >> 16;
@@ -9266,6 +9513,16 @@
 
     (pciio_error_devenable_f *) pcibr_error_devenable,
     (pciio_error_extract_f *) pcibr_error_extract,
+
+#ifdef LATER
+    (pciio_driver_reg_callback_f *) pcibr_driver_reg_callback,
+    (pciio_driver_unreg_callback_f *) pcibr_driver_unreg_callback,
+#else
+    (pciio_driver_reg_callback_f *) 0,
+    (pciio_driver_unreg_callback_f *) 0,
+#endif
+    (pciio_device_unregister_f 	*) pcibr_device_unregister,
+    (pciio_dma_enabled_f		*) pcibr_dma_enabled,
 };
 
 LOCAL                   pcibr_hints_t
@@ -9299,7 +9556,7 @@
     return (pcibr_hints_t) ainfo;
 
 abnormal_exit:
-#ifdef IRIX
+#ifdef LATER
     printf("SHOULD NOT BE HERE\n");
 #endif
     DEL(hint);
@@ -9417,12 +9674,7 @@
 	if (ainfo == (arbitrary_info_t) subdevp)
 	    return;
 	DEL(subdevp);
-#ifdef IRIX
-	if (ainfo == NULL)
-#else
-	if (ainfo == (arbitrary_info_t) NULL)
-#endif
-	{
+	if (ainfo == (arbitrary_info_t) NULL) {
 #if DEBUG
 	    printk("pcibr_hints_subdevs: null subdevs ptr at\n"
 		    "\t%p\n", pconn_vhdl);
@@ -9438,7 +9690,7 @@
 }
 
 
-#ifdef colin
+#ifdef LATER
 
 #include <sys/idbg.h>
 #include <sys/idbgentry.h>
@@ -9531,7 +9783,7 @@
 	    pss->bss_d32_base, pss->bss_d32_flags);
     
     qprintf("\tExt ATEs active ? %s", 
-	    pss->bss_ext_ates_active ? "yes" : "no");
+	    atomic_read(&pss->bss_ext_ates_active) ? "yes" : "no");
     qprintf(" Command register : 0x%x ", pss->bss_cmd_pointer);
     qprintf(" Shadow command val : 0x%x\n", pss->bss_cmd_shadow);
 
@@ -9559,7 +9811,7 @@
 	qprintf("Invalid ips %d\n",ips);
 }
 
-#endif /* colin */
+#endif /* LATER */
 
 int
 pcibr_dma_enabled(devfs_handle_t pconn_vhdl)

FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)