patch-2.4.21 linux-2.4.21/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
Next file: linux-2.4.21/arch/ia64/sn/io/sn2/pcibr/pcibr_error.c
Previous file: linux-2.4.21/arch/ia64/sn/io/sn2/pcibr/pcibr_config.c
Back to the patch index
Back to the overall index
- Lines: 3886
- Date:
2003-06-13 07:51:31.000000000 -0700
- Orig file:
linux-2.4.20/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
- Orig date:
2002-08-02 17:39:43.000000000 -0700
diff -urN linux-2.4.20/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c linux-2.4.21/arch/ia64/sn/io/sn2/pcibr/pcibr_dvr.c
@@ -7,7 +7,6 @@
* Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved.
*/
-
#include <linux/types.h>
#include <linux/slab.h>
#include <linux/module.h>
@@ -40,6 +39,25 @@
#endif
/*
+ * global variables to toggle the different levels of pcibr debugging.
+ * -pcibr_debug_mask is the mask of the different types of debugging
+ * you want to enable. See sys/PCI/pcibr_private.h
+ * -pcibr_debug_module is the module you want to trace. By default
+ * all modules are trace. For IP35 this value has the format of
+ * something like "001c10". For IP27 this value is a node number,
+ * i.e. "1", "2"... For IP30 this is undefined and should be set to
+ * 'all'.
+ * -pcibr_debug_widget is the widget you want to trace. For IP27
+ * the widget isn't exposed in the hwpath so use the xio slot num.
+ * i.e. for 'io2' set pcibr_debug_widget to "2".
+ * -pcibr_debug_slot is the pci slot you want to trace.
+ */
+uint32_t pcibr_debug_mask = 0x0; /* 0x00000000 to disable */
+char *pcibr_debug_module = "all"; /* 'all' for all modules */
+int pcibr_debug_widget = -1; /* '-1' for all widgets */
+int pcibr_debug_slot = -1; /* '-1' for all slots */
+
+/*
* 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
@@ -82,44 +100,6 @@
writev: NULL
};
-#ifdef LATER
-
-#if PCIBR_ATE_DEBUG
-static struct reg_values ssram_sizes[] =
-{
- {BRIDGE_CTRL_SSRAM_512K, "512k"},
- {BRIDGE_CTRL_SSRAM_128K, "128k"},
- {BRIDGE_CTRL_SSRAM_64K, "64k"},
- {BRIDGE_CTRL_SSRAM_1K, "1k"},
- {0}
-};
-
-static struct reg_desc control_bits[] =
-{
- {BRIDGE_CTRL_FLASH_WR_EN, 0, "FLASH_WR_EN"},
- {BRIDGE_CTRL_EN_CLK50, 0, "EN_CLK50"},
- {BRIDGE_CTRL_EN_CLK40, 0, "EN_CLK40"},
- {BRIDGE_CTRL_EN_CLK33, 0, "EN_CLK33"},
- {BRIDGE_CTRL_RST_MASK, -24, "RST", "%x"},
- {BRIDGE_CTRL_IO_SWAP, 0, "IO_SWAP"},
- {BRIDGE_CTRL_MEM_SWAP, 0, "MEM_SWAP"},
- {BRIDGE_CTRL_PAGE_SIZE, 0, "PAGE_SIZE"},
- {BRIDGE_CTRL_SS_PAR_BAD, 0, "SS_PAR_BAD"},
- {BRIDGE_CTRL_SS_PAR_EN, 0, "SS_PAR_EN"},
- {BRIDGE_CTRL_SSRAM_SIZE_MASK, 0, "SSRAM_SIZE", 0, ssram_sizes},
- {BRIDGE_CTRL_F_BAD_PKT, 0, "F_BAD_PKT"},
- {BRIDGE_CTRL_LLP_XBAR_CRD_MASK, -12, "LLP_XBAR_CRD", "%d"},
- {BRIDGE_CTRL_CLR_RLLP_CNT, 0, "CLR_RLLP_CNT"},
- {BRIDGE_CTRL_CLR_TLLP_CNT, 0, "CLR_TLLP_CNT"},
- {BRIDGE_CTRL_SYS_END, 0, "SYS_END"},
-
- {BRIDGE_CTRL_BUS_SPEED_MASK, -4, "BUS_SPEED", "%d"},
- {BRIDGE_CTRL_WIDGET_ID_MASK, 0, "WIDGET_ID", "%x"},
- {0}
-};
-#endif
-#endif /* LATER */
-
/* kbrick widgetnum-to-bus layout */
int p_busnum[MAX_PORT_NUM] = { /* widget# */
0, 0, 0, 0, 0, 0, 0, 0, /* 0x0 - 0x7 */
@@ -132,18 +112,6 @@
3, /* 0xf */
};
-/*
- * Additional PIO spaces per slot are
- * recorded in this structure.
- */
-struct pciio_piospace_s {
- pciio_piospace_t next; /* another space for this device */
- char free; /* 1 if free, 0 if in use */
- pciio_space_t space; /* Which space is in use */
- iopaddr_t start; /* Starting address of the PIO space */
- size_t count; /* size of PIO space */
-};
-
#if PCIBR_SOFT_LIST
pcibr_list_p pcibr_list = 0;
#endif
@@ -152,15 +120,15 @@
extern int hub_device_flags_set(devfs_handle_t widget_dev, hub_widget_flags_t flags);
extern long atoi(register char *p);
extern cnodeid_t nodevertex_to_cnodeid(devfs_handle_t vhdl);
-extern void *swap_ptr(void **loc, void *new);
extern char *dev_to_name(devfs_handle_t dev, char *buf, uint buflen);
extern struct map *atemapalloc(uint64_t);
extern void atefree(struct map *, size_t, uint64_t);
extern void atemapfree(struct map *);
extern pciio_dmamap_t get_free_pciio_dmamap(devfs_handle_t);
extern void free_pciio_dmamap(pcibr_dmamap_t);
+extern void xwidget_error_register(devfs_handle_t, error_handler_f *, error_handler_arg_t);
-#define ATE_WRITE() ate_write(ate_ptr, ate_count, ate)
+#define ATE_WRITE() ate_write(pcibr_soft, ate_ptr, ate_count, ate)
#if PCIBR_FREEZE_TIME
#define ATE_FREEZE() s = ate_freeze(pcibr_dmamap, &freeze_time, cmd_regs)
#else
@@ -173,7 +141,6 @@
#define ATE_THAW() ate_thaw(pcibr_dmamap, ate_index, cmd_regs, s)
#endif
-
/* =====================================================================
* Function Table of Contents
*
@@ -183,58 +150,54 @@
* perhaps bust this file into smaller chunks.
*/
-extern void do_pcibr_rrb_clear(bridge_t *, int);
-extern void do_pcibr_rrb_flush(bridge_t *, int);
-extern int do_pcibr_rrb_count_valid(bridge_t *, pciio_slot_t);
-extern int do_pcibr_rrb_count_avail(bridge_t *, pciio_slot_t);
-extern int do_pcibr_rrb_alloc(bridge_t *, pciio_slot_t, int);
-extern int do_pcibr_rrb_free(bridge_t *, pciio_slot_t, int);
-
-extern void do_pcibr_rrb_autoalloc(pcibr_soft_t, int, int);
+extern int do_pcibr_rrb_free_all(pcibr_soft_t, bridge_t *, pciio_slot_t);
+extern void do_pcibr_rrb_autoalloc(pcibr_soft_t, int, int, int);
extern int pcibr_wrb_flush(devfs_handle_t);
extern int pcibr_rrb_alloc(devfs_handle_t, int *, int *);
-extern int pcibr_rrb_check(devfs_handle_t, int *, int *, int *, int *);
-extern int pcibr_alloc_all_rrbs(devfs_handle_t, int, int, int, int, int, int, int, int, int);
extern void pcibr_rrb_flush(devfs_handle_t);
static int pcibr_try_set_device(pcibr_soft_t, pciio_slot_t, unsigned, bridgereg_t);
void pcibr_release_device(pcibr_soft_t, pciio_slot_t, bridgereg_t);
-extern void pcibr_clearwidint(bridge_t *);
extern void pcibr_setwidint(xtalk_intr_t);
+extern void pcibr_clearwidint(bridge_t *);
+
+extern iopaddr_t pcibr_bus_addr_alloc(pcibr_soft_t, pciio_win_info_t,
+ pciio_space_t, int, int, int);
void pcibr_init(void);
int pcibr_attach(devfs_handle_t);
+int pcibr_attach2(devfs_handle_t, bridge_t *, devfs_handle_t,
+ int, pcibr_soft_t *);
int pcibr_detach(devfs_handle_t);
int pcibr_open(devfs_handle_t *, int, int, cred_t *);
int pcibr_close(devfs_handle_t, int, int, cred_t *);
int pcibr_map(devfs_handle_t, vhandl_t *, off_t, size_t, uint);
int pcibr_unmap(devfs_handle_t, vhandl_t *);
int pcibr_ioctl(devfs_handle_t, int, void *, int, struct cred *, int *);
-
-void pcibr_freeblock_sub(iopaddr_t *, iopaddr_t *, iopaddr_t, size_t);
-
+int pcibr_pcix_rbars_calc(pcibr_soft_t);
extern int pcibr_init_ext_ate_ram(bridge_t *);
extern int pcibr_ate_alloc(pcibr_soft_t, int);
extern void pcibr_ate_free(pcibr_soft_t, int, int);
+extern int pcibr_widget_to_bus(devfs_handle_t pcibr_vhdl);
-extern unsigned ate_freeze(pcibr_dmamap_t pcibr_dmamap,
+extern unsigned ate_freeze(pcibr_dmamap_t pcibr_dmamap,
#if PCIBR_FREEZE_TIME
unsigned *freeze_time_ptr,
#endif
- unsigned *cmd_regs);
-extern void ate_write(bridge_ate_p ate_ptr, int ate_count, bridge_ate_t ate);
-extern void ate_thaw(pcibr_dmamap_t pcibr_dmamap, int ate_index,
+ unsigned *cmd_regs);
+extern void ate_write(pcibr_soft_t pcibr_soft, bridge_ate_p ate_ptr, int ate_count, bridge_ate_t ate);
+extern void ate_thaw(pcibr_dmamap_t pcibr_dmamap, int ate_index,
#if PCIBR_FREEZE_TIME
- bridge_ate_t ate,
- int ate_total,
- unsigned freeze_time_start,
+ bridge_ate_t ate,
+ int ate_total,
+ unsigned freeze_time_start,
#endif
- unsigned *cmd_regs,
- unsigned s);
+ unsigned *cmd_regs,
+ unsigned s);
-pcibr_info_t pcibr_info_get(devfs_handle_t);
+pcibr_info_t pcibr_info_get(devfs_handle_t);
static iopaddr_t pcibr_addr_pci_to_xio(devfs_handle_t, pciio_slot_t, pciio_space_t, iopaddr_t, size_t, unsigned);
@@ -264,23 +227,23 @@
void pcibr_dmalist_drain(devfs_handle_t, alenlist_t);
iopaddr_t pcibr_dmamap_pciaddr_get(pcibr_dmamap_t);
-extern unsigned pcibr_intr_bits(pciio_info_t info, pciio_intr_line_t lines);
+extern unsigned pcibr_intr_bits(pciio_info_t info,
+ pciio_intr_line_t lines, int nslots);
extern pcibr_intr_t pcibr_intr_alloc(devfs_handle_t, device_desc_t, pciio_intr_line_t, devfs_handle_t);
extern void pcibr_intr_free(pcibr_intr_t);
extern void pcibr_setpciint(xtalk_intr_t);
-extern int pcibr_intr_connect(pcibr_intr_t);
+extern int pcibr_intr_connect(pcibr_intr_t, intr_func_t, intr_arg_t);
extern void pcibr_intr_disconnect(pcibr_intr_t);
extern devfs_handle_t pcibr_intr_cpu_get(pcibr_intr_t);
-extern void pcibr_xintr_preset(void *, int, xwidgetnum_t, iopaddr_t, xtalk_intr_vector_t);
extern void pcibr_intr_func(intr_arg_t);
extern void print_bridge_errcmd(uint32_t, char *);
extern void pcibr_error_dump(pcibr_soft_t);
-extern uint32_t pcibr_errintr_group(uint32_t);
+extern uint32_t pcibr_errintr_group(uint32_t);
extern void pcibr_pioerr_check(pcibr_soft_t);
-extern void pcibr_error_intr_handler(intr_arg_t);
+extern void pcibr_error_intr_handler(int, void *, struct pt_regs *);
extern int pcibr_addr_toslot(pcibr_soft_t, iopaddr_t, pciio_space_t *, iopaddr_t *, pciio_function_t *);
extern void pcibr_error_cleanup(pcibr_soft_t, int);
@@ -289,8 +252,7 @@
extern int pcibr_dmard_error(pcibr_soft_t, int, ioerror_mode_t, ioerror_t *);
extern int pcibr_dmawr_error(pcibr_soft_t, int, ioerror_mode_t, ioerror_t *);
extern int pcibr_error_handler(error_handler_arg_t, int, ioerror_mode_t, ioerror_t *);
-extern int pcibr_error_devenable(devfs_handle_t, int);
-
+extern int pcibr_error_handler_wrapper(error_handler_arg_t, int, ioerror_mode_t, ioerror_t *);
void pcibr_provider_startup(devfs_handle_t);
void pcibr_provider_shutdown(devfs_handle_t);
@@ -303,7 +265,6 @@
extern cfg_p pcibr_config_addr(devfs_handle_t, unsigned);
extern uint64_t pcibr_config_get(devfs_handle_t, unsigned, unsigned);
extern void pcibr_config_set(devfs_handle_t, unsigned, unsigned, uint64_t);
-extern void do_pcibr_config_set(cfg_p, unsigned, unsigned, uint64_t);
extern pcibr_hints_t pcibr_hints_get(devfs_handle_t, int);
extern void pcibr_hints_fix_rrbs(devfs_handle_t);
@@ -313,38 +274,31 @@
extern void pcibr_hints_handsoff(devfs_handle_t);
extern void pcibr_hints_subdevs(devfs_handle_t, pciio_slot_t, uint64_t);
-#ifdef BRIDGE_B_DATACORR_WAR
-extern int ql_bridge_rev_b_war(devfs_handle_t);
-extern int bridge_rev_b_data_check_disable;
-char *rev_b_datacorr_warning =
-"***************************** WARNING! ******************************\n";
-char *rev_b_datacorr_mesg =
-"UNRECOVERABLE IO LINK ERROR. CONTACT SERVICE PROVIDER\n";
-#endif
-
extern int pcibr_slot_reset(devfs_handle_t,pciio_slot_t);
extern int pcibr_slot_info_init(devfs_handle_t,pciio_slot_t);
extern int pcibr_slot_info_free(devfs_handle_t,pciio_slot_t);
+extern int pcibr_slot_info_return(pcibr_soft_t, pciio_slot_t,
+ pcibr_slot_info_resp_t);
+extern void pcibr_slot_func_info_return(pcibr_info_h, int,
+ pcibr_slot_func_info_resp_t);
extern int pcibr_slot_addr_space_init(devfs_handle_t,pciio_slot_t);
+extern int pcibr_slot_pcix_rbar_init(pcibr_soft_t, pciio_slot_t);
extern int pcibr_slot_device_init(devfs_handle_t, pciio_slot_t);
extern int pcibr_slot_guest_info_init(devfs_handle_t,pciio_slot_t);
-extern int pcibr_slot_call_device_attach(devfs_handle_t, pciio_slot_t, int);
-extern int pcibr_slot_call_device_detach(devfs_handle_t, pciio_slot_t, int);
-extern int pcibr_slot_attach(devfs_handle_t, pciio_slot_t, int, char *, int *);
-extern int pcibr_slot_detach(devfs_handle_t, pciio_slot_t, int);
+extern int pcibr_slot_call_device_attach(devfs_handle_t,
+ pciio_slot_t, int);
+extern int pcibr_slot_call_device_detach(devfs_handle_t,
+ pciio_slot_t, int);
+extern int pcibr_slot_attach(devfs_handle_t, pciio_slot_t, int,
+ char *, int *);
+extern int pcibr_slot_detach(devfs_handle_t, pciio_slot_t, int,
+ char *, int *);
extern int pcibr_is_slot_sys_critical(devfs_handle_t, pciio_slot_t);
-#ifdef LATER
-extern int pcibr_slot_startup(devfs_handle_t, pcibr_slot_req_t);
-extern int pcibr_slot_shutdown(devfs_handle_t, pcibr_slot_req_t);
-extern int pcibr_slot_query(devfs_handle_t, pcibr_slot_req_t);
-#endif
-
extern int pcibr_slot_initial_rrb_alloc(devfs_handle_t, pciio_slot_t);
extern int pcibr_initial_rrb(devfs_handle_t, pciio_slot_t, pciio_slot_t);
-
/* =====================================================================
* Device(x) register management
*/
@@ -377,7 +331,7 @@
bridgereg_t xmask;
xmask = mask;
- if (pcibr_soft->bs_xbridge) {
+ if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) {
if (mask == BRIDGE_DEV_PMU_BITS)
xmask = XBRIDGE_DEV_PMU_BITS;
if (mask == BRIDGE_DEV_D64_BITS)
@@ -464,10 +418,10 @@
new &= ~BRIDGE_DEV_WRGA_BITS;
if (flags & PCIIO_BYTE_STREAM)
- new |= (pcibr_soft->bs_xbridge) ?
+ new |= (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) ?
BRIDGE_DEV_SWAP_DIR : BRIDGE_DEV_SWAP_BITS;
if (flags & PCIIO_WORD_VALUES)
- new &= (pcibr_soft->bs_xbridge) ?
+ new &= (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) ?
~BRIDGE_DEV_SWAP_DIR : ~BRIDGE_DEV_SWAP_BITS;
/* Provider-specific flags
@@ -492,13 +446,28 @@
if (flags & PCIBR_NO64BIT)
new &= ~BRIDGE_DEV_DEV_SIZE;
+ /*
+ * PIC BRINGUP WAR (PV# 855271):
+ * Allow setting BRIDGE_DEV_VIRTUAL_EN on PIC iff we're a 64-bit
+ * device. The bit is only intended for 64-bit devices and, on
+ * PIC, can cause problems for 32-bit devices.
+ */
+ if (IS_PIC_SOFT(pcibr_soft) && mask == BRIDGE_DEV_D64_BITS &&
+ PCIBR_WAR_ENABLED(PV855271, pcibr_soft)) {
+ if (flags & PCIBR_VCHAN1) {
+ new |= BRIDGE_DEV_VIRTUAL_EN;
+ xmask |= BRIDGE_DEV_VIRTUAL_EN;
+ }
+ }
+
+
chg = old ^ new; /* what are we changing, */
chg &= xmask; /* of the interesting bits */
if (chg) {
badd32 = slotp->bss_d32_uctr ? (BRIDGE_DEV_D32_BITS & chg) : 0;
- if (pcibr_soft->bs_xbridge) {
+ if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) {
badpmu = slotp->bss_pmu_uctr ? (XBRIDGE_DEV_PMU_BITS & chg) : 0;
badd64 = slotp->bss_d64_uctr ? (XBRIDGE_DEV_D64_BITS & chg) : 0;
} else {
@@ -517,7 +486,7 @@
* the new stream at all.
*/
if ( (fix = bad & (BRIDGE_DEV_PRECISE |
- BRIDGE_DEV_BARRIER)) ){
+ BRIDGE_DEV_BARRIER)) ) {
bad &= ~fix;
/* don't change these bits if
* they are already set in "old"
@@ -546,8 +515,10 @@
*/
if (bad) {
pcibr_unlock(pcibr_soft, s);
-#if (DEBUG && PCIBR_DEV_DEBUG)
- printk("pcibr_try_set_device: mod blocked by %R\n", bad, device_bits);
+#ifdef PIC_LATER
+ PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pcibr_soft->bs_vhdl,
+ "pcibr_try_set_device: mod blocked by %x\n",
+ bad, device_bits));
#endif
return bad;
}
@@ -571,14 +542,31 @@
pcibr_unlock(pcibr_soft, s);
return 0;
}
- bridge->b_device[slot].reg = new;
- slotp->bss_device = new;
- bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ bridge->b_device[slot].reg = new;
+ slotp->bss_device = new;
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ BRIDGE_REG_SET32((&bridge->b_device[slot].reg)) = __swab32(new);
+ slotp->bss_device = new;
+ BRIDGE_REG_GET32((&bridge->b_wid_tflush)); /* wait until Bridge PIO complete */
+ } else {
+ bridge->b_device[slot].reg = new;
+ slotp->bss_device = new;
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ }
pcibr_unlock(pcibr_soft, s);
-#if DEBUG && PCIBR_DEV_DEBUG
- printk("pcibr Device(%d): 0x%p\n", slot, bridge->b_device[slot].reg);
-#endif
+#ifdef PIC_LATER
+ PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pcibr_soft->bs_vhdl,
+ "pcibr_try_set_device: Device(%d): %x\n",
+ slot, new, device_bits));
+#else
+ printk("pcibr_try_set_device: Device(%d): %x\n", slot, new);
+#endif
return 0;
}
@@ -616,7 +604,17 @@
volatile uint32_t wrf;
s = pcibr_lock(pcibr_soft);
bridge = pcibr_soft->bs_base;
- wrf = bridge->b_wr_req_buf[slot].reg;
+
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ wrf = bridge->b_wr_req_buf[slot].reg;
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ wrf = BRIDGE_REG_GET32((&bridge->b_wr_req_buf[slot].reg));
+ } else {
+ wrf = bridge->b_wr_req_buf[slot].reg;
+ }
+ }
pcibr_unlock(pcibr_soft, s);
}
@@ -637,9 +635,7 @@
void
pcibr_init(void)
{
-#if DEBUG && ATTACH_DEBUG
- printk("pcibr_init\n");
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INIT, NULL, "pcibr_init()\n"));
xwidget_driver_register(XBRIDGE_WIDGET_PART_NUM,
XBRIDGE_WIDGET_MFGR_NUM,
@@ -700,7 +696,7 @@
* XXX- deprecate this in favor of using the
* real flash driver ...
*/
- if (!error &&
+ if (IS_BRIDGE_SOFT(pcibr_soft) && !error &&
((off == BRIDGE_EXTERNAL_FLASH) ||
(len > BRIDGE_EXTERNAL_FLASH))) {
int s;
@@ -710,11 +706,16 @@
* The read following the write is required for the Bridge war
*/
s = splhi();
- bridge->b_wid_control |= BRIDGE_CTRL_FLASH_WR_EN;
- bridge->b_wid_control; /* inval addr bug war */
+
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ BRIDGE_REG_SET32((&bridge->b_wid_control)) |= __swab32(BRIDGE_CTRL_FLASH_WR_EN);
+ BRIDGE_REG_GET32((&bridge->b_wid_control)); /* inval addr bug war */
+ } else {
+ bridge->b_wid_control |= BRIDGE_CTRL_FLASH_WR_EN;
+ bridge->b_wid_control; /* inval addr bug war */
+ }
splx(s);
}
-
return error;
}
@@ -728,21 +729,53 @@
hwgraph_vertex_unref(pcibr_vhdl);
- /*
- * If flashprom write was enabled, disable it, as
- * this is the last unmap.
- */
- if (bridge->b_wid_control & BRIDGE_CTRL_FLASH_WR_EN) {
- int s;
-
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
/*
- * ensure that we write and read without any interruption.
- * The read following the write is required for the Bridge war
+ * If flashprom write was enabled, disable it, as
+ * this is the last unmap.
*/
- s = splhi();
- bridge->b_wid_control &= ~BRIDGE_CTRL_FLASH_WR_EN;
- bridge->b_wid_control; /* inval addr bug war */
- splx(s);
+ if (IS_BRIDGE_SOFT(pcibr_soft) &&
+ (bridge->b_wid_control & BRIDGE_CTRL_FLASH_WR_EN)) {
+ int s;
+
+ /*
+ * ensure that we write and read without any interruption.
+ * The read following the write is required for the Bridge war
+ */
+ s = splhi();
+ bridge->b_wid_control &= ~BRIDGE_CTRL_FLASH_WR_EN;
+ bridge->b_wid_control; /* inval addr bug war */
+ splx(s);
+ }
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ if (BRIDGE_REG_GET32((&bridge->b_wid_control)) & BRIDGE_CTRL_FLASH_WR_EN) {
+ int s;
+
+ /*
+ * ensure that we write and read without any interruption.
+ * The read following the write is required for the Bridge war
+ */
+ s = splhi();
+ BRIDGE_REG_SET32((&bridge->b_wid_control)) &= __swab32((unsigned int)~BRIDGE_CTRL_FLASH_WR_EN);
+ BRIDGE_REG_GET32((&bridge->b_wid_control)); /* inval addr bug war */
+ splx(s);
+ } else {
+ if (bridge->b_wid_control & BRIDGE_CTRL_FLASH_WR_EN) {
+ int s;
+
+ /*
+ * ensure that we write and read without any interruption.
+ * The read following the write is required for the Bridge war
+ */
+ s = splhi();
+ bridge->b_wid_control &= ~BRIDGE_CTRL_FLASH_WR_EN;
+ bridge->b_wid_control; /* inval addr bug war */
+ splx(s);
+ }
+ }
+ }
}
return 0;
}
@@ -768,7 +801,7 @@
while (tdev != GRAPH_VERTEX_NONE) {
pciio_info = pciio_info_chk(tdev);
if (pciio_info) {
- slot = pciio_info_slot_get(pciio_info);
+ slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
break;
}
hwgraph_vertex_unref(tdev);
@@ -788,167 +821,7 @@
struct cred *cr,
int *rvalp)
{
- devfs_handle_t pcibr_vhdl = hwgraph_connectpt_get((devfs_handle_t)dev);
-#ifdef LATER
- pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl);
-#endif
- int error = 0;
-
- hwgraph_vertex_unref(pcibr_vhdl);
-
- switch (cmd) {
-#ifdef LATER
- case GIOCSETBW:
- {
- grio_ioctl_info_t info;
- pciio_slot_t slot = 0;
-
- if (!cap_able((uint64_t)CAP_DEVICE_MGT)) {
- error = EPERM;
- break;
- }
- if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) {
- error = EFAULT;
- break;
- }
-#ifdef GRIO_DEBUG
- printk("pcibr:: prev_vhdl: %d reqbw: %lld\n",
- info.prev_vhdl, info.reqbw);
-#endif /* GRIO_DEBUG */
-
- if ((slot = pcibr_device_slot_get(info.prev_vhdl)) ==
- PCIIO_SLOT_NONE) {
- error = EIO;
- break;
- }
- if (info.reqbw)
- pcibr_priority_bits_set(pcibr_soft, slot, PCI_PRIO_HIGH);
- break;
- }
-
- case GIOCRELEASEBW:
- {
- grio_ioctl_info_t info;
- pciio_slot_t slot = 0;
-
- if (!cap_able(CAP_DEVICE_MGT)) {
- error = EPERM;
- break;
- }
- if (COPYIN(arg, &info, sizeof(grio_ioctl_info_t))) {
- error = EFAULT;
- break;
- }
-#ifdef GRIO_DEBUG
- printk("pcibr:: prev_vhdl: %d reqbw: %lld\n",
- info.prev_vhdl, info.reqbw);
-#endif /* GRIO_DEBUG */
-
- if ((slot = pcibr_device_slot_get(info.prev_vhdl)) ==
- PCIIO_SLOT_NONE) {
- error = EIO;
- break;
- }
- if (info.reqbw)
- pcibr_priority_bits_set(pcibr_soft, slot, PCI_PRIO_LOW);
- break;
- }
-
- case PCIBR_SLOT_STARTUP:
- {
- struct pcibr_slot_req_s req;
-
- if (!cap_able(CAP_DEVICE_MGT)) {
- error = EPERM;
- break;
- }
-
- if (COPYIN(arg, &req, sizeof(req))) {
- error = EFAULT;
- break;
- }
-
- error = pcibr_slot_startup(pcibr_vhdl, &req);
- break;
- }
- case PCIBR_SLOT_SHUTDOWN:
- {
- struct pcibr_slot_req_s req;
-
- if (!cap_able(CAP_DEVICE_MGT)) {
- error = EPERM;
- break;
- }
-
- if (COPYIN(arg, &req, sizeof(req))) {
- error = EFAULT;
- break;
- }
-
- error = pcibr_slot_shutdown(pcibr_vhdl, &req);
- break;
- }
- case PCIBR_SLOT_QUERY:
- {
- struct pcibr_slot_req_s req;
-
- if (!cap_able(CAP_DEVICE_MGT)) {
- error = EPERM;
- break;
- }
-
- if (COPYIN(arg, &req, sizeof(req))) {
- error = EFAULT;
- break;
- }
-
- error = pcibr_slot_query(pcibr_vhdl, &req);
- break;
- }
-#endif /* LATER */
- default:
- break;
-
- }
-
- return error;
-}
-
-void
-pcibr_freeblock_sub(iopaddr_t *free_basep,
- iopaddr_t *free_lastp,
- iopaddr_t base,
- size_t size)
-{
- iopaddr_t free_base = *free_basep;
- iopaddr_t free_last = *free_lastp;
- iopaddr_t last = base + size - 1;
-
- if ((last < free_base) || (base > free_last)); /* free block outside arena */
-
- else if ((base <= free_base) && (last >= free_last))
- /* free block contains entire arena */
- *free_basep = *free_lastp = 0;
-
- else if (base <= free_base)
- /* free block is head of arena */
- *free_basep = last + 1;
-
- else if (last >= free_last)
- /* free block is tail of arena */
- *free_lastp = base - 1;
-
- /*
- * We are left with two regions: the free area
- * in the arena "below" the block, and the free
- * area in the arena "above" the block. Keep
- * the one that is bigger.
- */
-
- else if ((base - free_base) > (free_last - last))
- *free_lastp = base - 1; /* keep lower chunk */
- else
- *free_basep = last + 1; /* keep upper chunk */
+ return 0;
}
pcibr_info_t
@@ -971,16 +844,22 @@
func = (rfunc == PCIIO_FUNC_NONE) ? 0 : rfunc;
+ /*
+ * Create a pciio_info_s for this device. pciio_device_info_new()
+ * will set the c_slot (which is suppose to represent the external
+ * slot (i.e the slot number silk screened on the back of the I/O
+ * brick)). So for PIC we need to adjust this "internal slot" num
+ * passed into us, into it's external representation. See comment
+ * for the PCIBR_DEVICE_TO_SLOT macro for more information.
+ */
NEW(pcibr_info);
+ pciio_device_info_new(&pcibr_info->f_c, pcibr_soft->bs_vhdl,
+ PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot),
+ rfunc, vendor, device);
+ pcibr_info->f_dev = slot;
- pciio_device_info_new(&pcibr_info->f_c,
- pcibr_soft->bs_vhdl,
- slot, rfunc,
- vendor, device);
-
-/* pfg - this is new ..... */
/* Set PCI bus number */
- pcibr_info->f_bus = io_path_map_widget(pcibr_soft->bs_vhdl);
+ pcibr_info->f_bus = pcibr_widget_to_bus(pcibr_soft->bs_vhdl);
if (slot != PCIIO_SLOT_NONE) {
@@ -1016,30 +895,6 @@
}
-/* FIXME: for now this is needed by both pcibr.c and
- * pcibr_slot.c. Need to find a better way, the least
- * of which would be to move it to pcibr_private.h
- */
-
-/*
- * PCI_ADDR_SPACE_LIMITS_STORE
- * Sets the current values of
- * pci io base,
- * pci io last,
- * pci low memory base,
- * pci low memory last,
- * pci high memory base,
- * pci high memory last
- */
-#define PCI_ADDR_SPACE_LIMITS_STORE() \
- pcibr_soft->bs_spinfo.pci_io_base = pci_io_fb; \
- pcibr_soft->bs_spinfo.pci_io_last = pci_io_fl; \
- pcibr_soft->bs_spinfo.pci_swin_base = pci_lo_fb; \
- pcibr_soft->bs_spinfo.pci_swin_last = pci_lo_fl; \
- pcibr_soft->bs_spinfo.pci_mem_base = pci_hi_fb; \
- pcibr_soft->bs_spinfo.pci_mem_last = pci_hi_fl;
-
-
/*
* pcibr_device_unregister
* This frees up any hardware resources reserved for this PCI device
@@ -1062,7 +917,7 @@
pciio_info = pciio_info_get(pconn_vhdl);
pcibr_vhdl = pciio_info_master_get(pciio_info);
- slot = pciio_info_slot_get(pciio_info);
+ slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft = pcibr_soft_get(pcibr_vhdl);
bridge = pcibr_soft->bs_base;
@@ -1077,27 +932,24 @@
* If the RRB configuration for this slot has changed, set it
* back to the boot-time default
*/
- if (pcibr_soft->bs_rrb_valid_dflt[slot] >= 0) {
+ if (pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN0] >= 0) {
s = pcibr_lock(pcibr_soft);
- /* Free the rrbs allocated to this slot */
- 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_res[slot] = pcibr_soft->bs_rrb_res[slot] +
- pcibr_soft->bs_rrb_valid[slot] +
- pcibr_soft->bs_rrb_valid[slot +
- PCIBR_RRB_SLOT_VIRTUAL];
-
- count_vchan0 = pcibr_soft->bs_rrb_valid_dflt[slot];
- count_vchan1 = pcibr_soft->bs_rrb_valid_dflt[slot +
- PCIBR_RRB_SLOT_VIRTUAL];
+ /* PIC NOTE: If this is a BRIDGE, VCHAN2 & VCHAN3 will be zero so
+ * no need to conditionalize this (ie. "if (IS_PIC_SOFT())" ).
+ */
+ pcibr_soft->bs_rrb_res[slot] = pcibr_soft->bs_rrb_res[slot] +
+ pcibr_soft->bs_rrb_valid[slot][VCHAN0] +
+ pcibr_soft->bs_rrb_valid[slot][VCHAN1] +
+ pcibr_soft->bs_rrb_valid[slot][VCHAN2] +
+ pcibr_soft->bs_rrb_valid[slot][VCHAN3];
+
+ /* Free the rrbs allocated to this slot, both the normal & virtual */
+ do_pcibr_rrb_free_all(pcibr_soft, bridge, slot);
+
+ count_vchan0 = pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN0];
+ count_vchan1 = pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN1];
pcibr_unlock(pcibr_soft, s);
@@ -1147,12 +999,14 @@
pcibr_info = pcibr_info_get(pconn_vhdl);
pcibr_vhdl = pciio_info_master_get(pciio_info);
- slot = pciio_info_slot_get(pciio_info);
+ slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+#ifdef PIC_LATER
/* This may be a loadable driver so lock out any pciconfig actions */
mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO);
+#endif
pcibr_info->f_att_det_error = error;
@@ -1164,9 +1018,10 @@
pcibr_soft->bs_slot[slot].slot_status |= SLOT_STARTUP_CMPLT;
}
+#ifdef PIC_LATER
/* Release the bus lock */
mrunlock(pcibr_soft->bs_bus_lock);
-
+#endif
}
/*
@@ -1195,12 +1050,14 @@
pcibr_info = pcibr_info_get(pconn_vhdl);
pcibr_vhdl = pciio_info_master_get(pciio_info);
- slot = pciio_info_slot_get(pciio_info);
+ slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft = pcibr_soft_get(pcibr_vhdl);
+#ifdef PIC_LATER
/* This may be a loadable driver so lock out any pciconfig actions */
mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO);
+#endif
pcibr_info->f_att_det_error = error;
@@ -1211,10 +1068,11 @@
} else {
pcibr_soft->bs_slot[slot].slot_status |= SLOT_SHUTDOWN_CMPLT;
}
-
+
+#ifdef PIC_LATER
/* Release the bus lock */
mrunlock(pcibr_soft->bs_bus_lock);
-
+#endif
}
/*
@@ -1226,7 +1084,7 @@
* depends on hwgraph separator == '/'
*/
int
-pcibr_bus_cnvlink(devfs_handle_t f_c, int slot)
+pcibr_bus_cnvlink(devfs_handle_t f_c)
{
char dst[MAXDEVNAME];
char *dp = dst;
@@ -1236,16 +1094,7 @@
devfs_handle_t nvtx, svtx;
int rv;
-#if DEBUG
- printk("pcibr_bus_cnvlink: slot= %d f_c= %p\n",
- slot, f_c);
- {
- int pos;
- char dname[256];
- pos = devfs_generate_path(f_c, dname, 256);
- printk("%s : path= %s\n", __FUNCTION__, &dname[pos]);
- }
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, f_c, "pcibr_bus_cnvlink\n"));
if (GRAPH_SUCCESS != hwgraph_vertex_name_get(f_c, dst, MAXDEVNAME))
return 0;
@@ -1261,7 +1110,7 @@
return 0;
/* remove "/pci/direct" from path */
- cp = strstr(dst, "/" EDGE_LBL_PCI "/" "direct");
+ cp = strstr(dst, "/" EDGE_LBL_PCI "/" EDGE_LBL_DIRECT);
if (cp == NULL)
return 0;
*cp = (char)NULL;
@@ -1275,7 +1124,8 @@
/* dst example now == /hw/module/001c02/Pbrick */
/* get the bus number */
- strcat(dst, "/bus");
+ strcat(dst, "/");
+ strcat(dst, EDGE_LBL_BUS);
sprintf(pcibus, "%d", p_busnum[widgetnum]);
/* link to bus to widget */
@@ -1300,75 +1150,74 @@
/* REFERENCED */
graph_error_t rc;
devfs_handle_t pcibr_vhdl;
+ bridge_t *bridge;
+
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, xconn_vhdl, "pcibr_attach\n"));
+
+ bridge = (bridge_t *)
+ xtalk_piotrans_addr(xconn_vhdl, NULL,
+ 0, sizeof(bridge_t), 0);
+ /*
+ * Create the vertex for the PCI bus, which we
+ * will also use to hold the pcibr_soft and
+ * which will be the "master" vertex for all the
+ * pciio connection points we will hang off it.
+ * This needs to happen before we call nic_bridge_vertex_info
+ * as we are some of the *_vmc functions need access to the edges.
+ *
+ * Opening this vertex will provide access to
+ * the Bridge registers themselves.
+ */
+ rc = hwgraph_path_add(xconn_vhdl, EDGE_LBL_PCI, &pcibr_vhdl);
+ ASSERT(rc == GRAPH_SUCCESS);
+
+ pciio_provider_register(pcibr_vhdl, &pcibr_provider);
+ pciio_provider_startup(pcibr_vhdl);
+
+ return pcibr_attach2(xconn_vhdl, bridge, pcibr_vhdl, 0, NULL);
+}
+
+
+/*ARGSUSED */
+int
+pcibr_attach2(devfs_handle_t xconn_vhdl, bridge_t *bridge,
+ devfs_handle_t pcibr_vhdl, int busnum, pcibr_soft_t *ret_softp)
+{
+ /* REFERENCED */
devfs_handle_t ctlr_vhdl;
- bridge_t *bridge = NULL;
bridgereg_t id;
int rev;
pcibr_soft_t pcibr_soft;
pcibr_info_t pcibr_info;
xwidget_info_t info;
xtalk_intr_t xtalk_intr;
- device_desc_t dev_desc = (device_desc_t)0;
int slot;
int ibit;
devfs_handle_t noslot_conn;
char devnm[MAXDEVNAME], *s;
pcibr_hints_t pcibr_hints;
- bridgereg_t b_int_enable;
+ uint64_t int_enable;
+ bridgereg_t int_enable_32;
+ picreg_t int_enable_64;
unsigned rrb_fixed = 0;
- iopaddr_t pci_io_fb, pci_io_fl;
- iopaddr_t pci_lo_fb, pci_lo_fl;
- 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;
+ int iobrick_type_get_nasid(nasid_t nasid);
+ int iobrick_module_get_nasid(nasid_t nasid);
+ extern unsigned char Is_pic_on_this_nasid[512];
- async_attach_t aa = NULL;
-
- aa = async_attach_get_info(xconn_vhdl);
-#if DEBUG && ATTACH_DEBUG
- printk("pcibr_attach: xconn_vhdl= %p\n", xconn_vhdl);
- {
- int pos;
- char dname[256];
- pos = devfs_generate_path(xconn_vhdl, dname, 256);
- printk("%s : path= %s \n", __FUNCTION__, &dname[pos]);
- }
-#endif
-
- /* Setup the PRB for the bridge in CONVEYOR BELT
- * mode. PRBs are setup in default FIRE-AND-FORGET
- * mode during the initialization.
- */
- hub_device_flags_set(xconn_vhdl, HUB_PIO_CONVEYOR);
+ async_attach_t aa = NULL;
- bridge = (bridge_t *)
- xtalk_piotrans_addr(xconn_vhdl, NULL,
- 0, sizeof(bridge_t), 0);
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,
+ "pcibr_attach2: bridge=0x%p, busnum=%d\n", bridge, busnum));
- /*
- * Create the vertex for the PCI bus, which we
- * will also use to hold the pcibr_soft and
- * which will be the "master" vertex for all the
- * pciio connection points we will hang off it.
- * This needs to happen before we call nic_bridge_vertex_info
- * as we are some of the *_vmc functions need access to the edges.
- *
- * Opening this vertex will provide access to
- * the Bridge registers themselves.
- */
- rc = hwgraph_path_add(xconn_vhdl, EDGE_LBL_PCI, &pcibr_vhdl);
- ASSERT(rc == GRAPH_SUCCESS);
+ aa = async_attach_get_info(xconn_vhdl);
ctlr_vhdl = NULL;
ctlr_vhdl = hwgraph_register(pcibr_vhdl, EDGE_LBL_CONTROLLER,
@@ -1380,15 +1229,6 @@
ASSERT(ctlr_vhdl != NULL);
/*
- * decode the nic, and hang its stuff off our
- * connection point where other drivers can get
- * at it.
- */
-#ifdef LATER
- nicinfo = BRIDGE_VERTEX_MFG_INFO(xconn_vhdl, (nic_data_t) & bridge->b_nic);
-#endif
-
- /*
* Get the hint structure; if some NIC callback
* marked this vertex as "hands-off" then we
* just return here, before doing anything else.
@@ -1408,26 +1248,63 @@
* fields, and hook it up to our vertex.
*/
NEW(pcibr_soft);
+ if (ret_softp)
+ *ret_softp = pcibr_soft;
BZERO(pcibr_soft, sizeof *pcibr_soft);
pcibr_soft_set(pcibr_vhdl, pcibr_soft);
-
pcibr_soft->bs_conn = xconn_vhdl;
pcibr_soft->bs_vhdl = pcibr_vhdl;
pcibr_soft->bs_base = bridge;
pcibr_soft->bs_rev_num = rev;
- pcibr_soft->bs_intr_bits = pcibr_intr_bits;
+ pcibr_soft->bs_intr_bits = (pcibr_intr_bits_f *)pcibr_intr_bits;
+
+ pcibr_soft->bs_min_slot = 0; /* lowest possible slot# */
+ pcibr_soft->bs_max_slot = 7; /* highest possible slot# */
+ pcibr_soft->bs_busnum = busnum;
if (is_xbridge(bridge)) {
- pcibr_soft->bs_int_ate_size = XBRIDGE_INTERNAL_ATES;
- pcibr_soft->bs_xbridge = 1;
+ pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_XBRIDGE;
+ } else if (is_pic(bridge)) {
+ pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_PIC;
} else {
+ pcibr_soft->bs_bridge_type = PCIBR_BRIDGETYPE_BRIDGE;
+ }
+ switch(pcibr_soft->bs_bridge_type) {
+ case PCIBR_BRIDGETYPE_BRIDGE:
pcibr_soft->bs_int_ate_size = BRIDGE_INTERNAL_ATES;
- pcibr_soft->bs_xbridge = 0;
+ pcibr_soft->bs_bridge_mode = 0; /* speed is not available in bridge */
+ break;
+ case PCIBR_BRIDGETYPE_PIC:
+ pcibr_soft->bs_min_slot = 0;
+ pcibr_soft->bs_max_slot = 3;
+ pcibr_soft->bs_int_ate_size = XBRIDGE_INTERNAL_ATES;
+ pcibr_soft->bs_bridge_mode =
+ (((bridge->p_wid_stat_64 & PIC_STAT_PCIX_SPEED) >> 33) |
+ ((bridge->p_wid_stat_64 & PIC_STAT_PCIX_ACTIVE) >> 33));
+
+ /* We have to clear PIC's write request buffer to avoid parity
+ * errors. See PV#854845.
+ */
+ {
+ int i;
+
+ for (i=0; i < PIC_WR_REQ_BUFSIZE; i++) {
+ bridge->p_wr_req_lower[i] = 0;
+ bridge->p_wr_req_upper[i] = 0;
+ bridge->p_wr_req_parity[i] = 0;
+ }
+ }
+
+ break;
+ case PCIBR_BRIDGETYPE_XBRIDGE:
+ pcibr_soft->bs_int_ate_size = XBRIDGE_INTERNAL_ATES;
+ pcibr_soft->bs_bridge_mode =
+ ((bridge->b_wid_control & BRIDGE_CTRL_PCI_SPEED) >> 3);
+ break;
}
- 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_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,
+ "pcibr_attach2: pcibr_soft=0x%x, mode=0x%x\n",
+ pcibr_soft, pcibr_soft->bs_bridge_mode));
pcibr_soft->bsi_err_intr = 0;
/* Bridges up through REV C
@@ -1439,6 +1316,9 @@
pcibr_soft->bs_pio_end_mem = PCIIO_WORD_VALUES;
}
#if PCIBR_SOFT_LIST
+ /*
+ * link all the pcibr_soft structs
+ */
{
pcibr_list_p self;
@@ -1446,9 +1326,9 @@
self->bl_soft = pcibr_soft;
self->bl_vhdl = pcibr_vhdl;
self->bl_next = pcibr_list;
- self->bl_next = swap_ptr((void **) &pcibr_list, (void *)self);
+ pcibr_list = self;
}
-#endif
+#endif /* PCIBR_SOFT_LIST */
/*
* get the name of this bridge vertex and keep the info. Use this
@@ -1458,45 +1338,114 @@
pcibr_soft->bs_name = kmalloc(strlen(s) + 1, GFP_KERNEL);
strcpy(pcibr_soft->bs_name, s);
-#if SHOW_REVS || DEBUG
-#if !DEBUG
- if (kdebug)
-#endif
- printk("%sBridge ASIC: rev %s (code=0x%x) at %s\n",
- is_xbridge(bridge) ? "X" : "",
- (rev == BRIDGE_PART_REV_A) ? "A" :
- (rev == BRIDGE_PART_REV_B) ? "B" :
- (rev == BRIDGE_PART_REV_C) ? "C" :
- (rev == BRIDGE_PART_REV_D) ? "D" :
- (rev == XBRIDGE_PART_REV_A) ? "A" :
- (rev == XBRIDGE_PART_REV_B) ? "B" :
- "unknown",
- rev, pcibr_soft->bs_name);
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,
+ "pcibr_attach2: %s ASIC: rev %s (code=0x%x)\n",
+ IS_XBRIDGE_SOFT(pcibr_soft) ? "XBridge" :
+ IS_PIC_SOFT(pcibr_soft) ? "PIC" : "Bridge",
+ (rev == BRIDGE_PART_REV_A) ? "A" :
+ (rev == BRIDGE_PART_REV_B) ? "B" :
+ (rev == BRIDGE_PART_REV_C) ? "C" :
+ (rev == BRIDGE_PART_REV_D) ? "D" :
+ (rev == XBRIDGE_PART_REV_A) ? "A" :
+ (rev == XBRIDGE_PART_REV_B) ? "B" :
+ (IS_PIC_PART_REV_A(rev)) ? "A" :
+ "unknown", rev, pcibr_soft->bs_name));
info = xwidget_info_get(xconn_vhdl);
pcibr_soft->bs_xid = xwidget_info_id_get(info);
pcibr_soft->bs_master = xwidget_info_master_get(info);
pcibr_soft->bs_mxid = xwidget_info_masterid_get(info);
+ pcibr_soft->bs_first_slot = pcibr_soft->bs_min_slot;
+ pcibr_soft->bs_last_slot = pcibr_soft->bs_max_slot;
/*
- * Init bridge lock.
+ * Bridge can only reset slots 0, 1, 2, and 3. Ibrick internal
+ * slots 4, 5, 6, and 7 must be reset as a group, so do not
+ * reset them.
*/
- spin_lock_init(&pcibr_soft->bs_lock);
+ pcibr_soft->bs_last_reset = 3;
+
+ nasid = NASID_GET(bridge);
+
+ /* set whether it is a PIC or not */
+ Is_pic_on_this_nasid[nasid] = (IS_PIC_SOFT(pcibr_soft)) ? 1 : 0;
+
+
+ if ((pcibr_soft->bs_bricktype = iobrick_type_get_nasid(nasid)) < 0)
+ printk(KERN_WARNING "0x%p: Unknown bricktype : 0x%x\n", (void *)xconn_vhdl,
+ (unsigned int)pcibr_soft->bs_bricktype);
+
+ pcibr_soft->bs_moduleid = iobrick_module_get_nasid(nasid);
+
+ if (pcibr_soft->bs_bricktype > 0) {
+ switch (pcibr_soft->bs_bricktype) {
+ case MODULE_PXBRICK:
+ pcibr_soft->bs_first_slot = 0;
+ pcibr_soft->bs_last_slot = 1;
+ pcibr_soft->bs_last_reset = 1;
+ break;
+ case MODULE_PEBRICK:
+ case MODULE_PBRICK:
+ pcibr_soft->bs_first_slot = 1;
+ pcibr_soft->bs_last_slot = 2;
+ pcibr_soft->bs_last_reset = 2;
+ break;
+
+ case MODULE_IBRICK:
+ /*
+ * Here's the current baseio layout for SN1 style systems:
+ *
+ * 0 1 2 3 4 5 6 7 slot#
+ *
+ * x scsi x x ioc3 usb x x O300 Ibrick
+ *
+ * x == never occupied
+ * E == external (add-in) slot
+ *
+ */
+ pcibr_soft->bs_first_slot = 1; /* Ibrick first slot == 1 */
+ if (pcibr_soft->bs_xid == 0xe) {
+ pcibr_soft->bs_last_slot = 2;
+ pcibr_soft->bs_last_reset = 2;
+ } else {
+ pcibr_soft->bs_last_slot = 6;
+ }
+ break;
+ default:
+ break;
+ }
+
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,
+ "pcibr_attach2: %cbrick, slots %d-%d\n",
+ MODULE_GET_BTCHAR(pcibr_soft->bs_moduleid),
+ pcibr_soft->bs_first_slot, pcibr_soft->bs_last_slot));
+ }
/*
+ * Initialize bridge and bus locks
+ */
+ spin_lock_init(&pcibr_soft->bs_lock);
+#ifdef PIC_LATER
+ mrinit(pcibr_soft->bs_bus_lock, "bus_lock");
+#endif
+ /*
* If we have one, process the hints structure.
*/
if (pcibr_hints) {
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_HINTS, pcibr_vhdl,
+ "pcibr_attach2: pcibr_hints=0x%x\n", pcibr_hints));
+
rrb_fixed = pcibr_hints->ph_rrb_fixed;
pcibr_soft->bs_rrb_fixed = rrb_fixed;
- if (pcibr_hints->ph_intr_bits)
+ if (pcibr_hints->ph_intr_bits) {
pcibr_soft->bs_intr_bits = pcibr_hints->ph_intr_bits;
+ }
- for (slot = 0; slot < 8; ++slot) {
- int hslot = pcibr_hints->ph_host_slot[slot] - 1;
+ for (slot = pcibr_soft->bs_min_slot;
+ slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
+ int hslot = pcibr_hints->ph_host_slot[slot] - 1;
if (hslot < 0) {
pcibr_soft->bs_slot[slot].host_slot = slot;
@@ -1507,13 +1456,16 @@
}
}
/*
- * set up initial values for state fields
+ * Set-up initial values for state fields
*/
- for (slot = 0; slot < 8; ++slot) {
+ for (slot = pcibr_soft->bs_min_slot;
+ slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
pcibr_soft->bs_slot[slot].bss_devio.bssd_space = PCIIO_SPACE_NONE;
+ pcibr_soft->bs_slot[slot].bss_devio.bssd_ref_cnt = 0;
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 = ATOMIC_INIT(0);
+ pcibr_soft->bs_rrb_valid_dflt[slot][VCHAN0] = -1;
}
for (ibit = 0; ibit < 8; ++ibit) {
@@ -1522,15 +1474,31 @@
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_ibit = ibit;
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;
}
/*
+ * connect up our error handler. PIC has 2 busses (thus resulting in 2
+ * pcibr_soft structs under 1 widget), so only register a xwidget error
+ * handler for PIC's bus0. NOTE: for PIC pcibr_error_handler_wrapper()
+ * is a wrapper routine we register that will call the real error handler
+ * pcibr_error_handler() with the correct pcibr_soft struct.
+ */
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ if (busnum == 0) {
+ xwidget_error_register(xconn_vhdl, pcibr_error_handler_wrapper, pcibr_soft);
+ }
+ } else {
+ xwidget_error_register(xconn_vhdl, pcibr_error_handler, pcibr_soft);
+ }
+
+ /*
* Initialize various Bridge registers.
*/
-
+
/*
* On pre-Rev.D bridges, set the PCI_RETRY_CNT
* to zero to avoid dropping stores. (#475347)
@@ -1543,12 +1511,43 @@
*/
bridge->b_int_rst_stat = (BRIDGE_IRR_ALL_CLR);
+ /* Initialize some PIC specific registers. */
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ picreg_t pic_ctrl_reg = bridge->p_wid_control_64;
+
+ /* Bridges Requester ID: bus = busnum, dev = 0, func = 0 */
+ pic_ctrl_reg &= ~PIC_CTRL_BUS_NUM_MASK;
+ pic_ctrl_reg |= PIC_CTRL_BUS_NUM(busnum);
+ pic_ctrl_reg &= ~PIC_CTRL_DEV_NUM_MASK;
+ pic_ctrl_reg &= ~PIC_CTRL_FUN_NUM_MASK;
+
+ pic_ctrl_reg &= ~PIC_CTRL_NO_SNOOP;
+ pic_ctrl_reg &= ~PIC_CTRL_RELAX_ORDER;
+
+ /* enable parity checking on PICs internal RAM */
+ pic_ctrl_reg |= PIC_CTRL_PAR_EN_RESP;
+ pic_ctrl_reg |= PIC_CTRL_PAR_EN_ATE;
+ /* PIC BRINGUP WAR (PV# 862253): dont enable write request
+ * parity checking.
+ */
+ if (!PCIBR_WAR_ENABLED(PV862253, pcibr_soft)) {
+ pic_ctrl_reg |= PIC_CTRL_PAR_EN_REQ;
+ }
+
+ bridge->p_wid_control_64 = pic_ctrl_reg;
+ }
+
/*
* Until otherwise set up,
* assume all interrupts are
- * from slot 7.
+ * from slot 7(Bridge/Xbridge) or 3(PIC).
+ * XXX. Not sure why we're doing this, made change for PIC
+ * just to avoid setting reserved bits.
*/
- bridge->b_int_device = (uint32_t) 0xffffffff;
+ if (IS_PIC_SOFT(pcibr_soft))
+ bridge->b_int_device = (uint32_t) 0x006db6db;
+ else
+ bridge->b_int_device = (uint32_t) 0xffffffff;
{
bridgereg_t dirmap;
@@ -1560,6 +1559,11 @@
int entry;
cnodeid_t cnodeid;
nasid_t nasid;
+#ifdef PIC_LATER
+ char *node_val;
+ devfs_handle_t node_vhdl;
+ char vname[MAXDEVNAME];
+#endif
/* Set the Bridge's 32-bit PCI to XTalk
* Direct Map register to the most useful
@@ -1578,6 +1582,30 @@
*/
cnodeid = 0; /* default node id */
+ /*
+ * Determine the base address node id to be used for all 32-bit
+ * Direct Mapping I/O. The default is node 0, but this can be changed
+ * via a DEVICE_ADMIN directive and the PCIBUS_DMATRANS_NODE
+ * attribute in the irix.sm config file. A device driver can obtain
+ * this node value via a call to pcibr_get_dmatrans_node().
+ */
+#ifdef PIC_LATER
+// This probably needs to be addressed - pfg
+ node_val = device_admin_info_get(pcibr_vhdl, ADMIN_LBL_DMATRANS_NODE);
+ if (node_val != NULL) {
+ node_vhdl = hwgraph_path_to_vertex(node_val);
+ if (node_vhdl != GRAPH_VERTEX_NONE) {
+ cnodeid = nodevertex_to_cnodeid(node_vhdl);
+ }
+ if ((node_vhdl == GRAPH_VERTEX_NONE) || (cnodeid == CNODEID_NONE)) {
+ cnodeid = 0;
+ vertex_to_name(pcibr_vhdl, vname, sizeof(vname));
+ printk(KERN_WARNING "Invalid hwgraph node path specified:\n"
+ " DEVICE_ADMIN: %s %s=%s\n",
+ vname, ADMIN_LBL_DMATRANS_NODE, node_val);
+ }
+ }
+#endif /* PIC_LATER */
nasid = COMPACT_TO_NASID_NODEID(cnodeid);
paddr = NODE_OFFSET(nasid) + 0;
@@ -1619,9 +1647,17 @@
*/
spl_level = splhi();
#if IOPGSIZE == 4096
- bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE;
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ bridge->p_wid_control_64 &= ~BRIDGE_CTRL_PAGE_SIZE;
+ } else {
+ bridge->b_wid_control &= ~BRIDGE_CTRL_PAGE_SIZE;
+ }
#elif IOPGSIZE == 16384
- bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE;
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ bridge->p_wid_control_64 |= BRIDGE_CTRL_PAGE_SIZE;
+ } else {
+ bridge->b_wid_control |= BRIDGE_CTRL_PAGE_SIZE;
+ }
#else
<<<Unable to deal with IOPGSIZE >>>;
#endif
@@ -1652,7 +1688,8 @@
* recomparing against BRIDGE_INTERNAL_ATES every
* time.
*/
- if (is_xbridge(bridge))
+
+ if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft))
num_entries = 0;
else
num_entries = pcibr_init_ext_ate_ram(bridge);
@@ -1662,9 +1699,6 @@
*/
pcibr_soft->bs_int_ate_map = rmallocmap(pcibr_soft->bs_int_ate_size);
pcibr_ate_free(pcibr_soft, 0, pcibr_soft->bs_int_ate_size);
-#if PCIBR_ATE_DEBUG
- printk("pcibr_attach: %d INTERNAL ATEs\n", pcibr_soft->bs_int_ate_size);
-#endif
if (num_entries > pcibr_soft->bs_int_ate_size) {
#if PCIBR_ATE_NOTBOTH /* for debug -- forces us to use external ates */
@@ -1674,11 +1708,12 @@
pcibr_soft->bs_ext_ate_map = rmallocmap(num_entries);
pcibr_ate_free(pcibr_soft, pcibr_soft->bs_int_ate_size,
num_entries - pcibr_soft->bs_int_ate_size);
-#if PCIBR_ATE_DEBUG
- printk("pcibr_attach: %d EXTERNAL ATEs\n",
- num_entries - pcibr_soft->bs_int_ate_size);
-#endif
}
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATE, pcibr_vhdl,
+ "pcibr_attach2: %d ATEs, %d internal & %d external\n",
+ num_entries ? num_entries : pcibr_soft->bs_int_ate_size,
+ pcibr_soft->bs_int_ate_size,
+ num_entries ? num_entries-pcibr_soft->bs_int_ate_size : 0));
}
{
@@ -1727,7 +1762,7 @@
* knows to do this.
*/
- xtalk_intr = xtalk_intr_alloc(xconn_vhdl, dev_desc, pcibr_vhdl);
+ xtalk_intr = xtalk_intr_alloc(xconn_vhdl, (device_desc_t)0, pcibr_vhdl);
ASSERT(xtalk_intr != NULL);
pcibr_soft->bsi_err_intr = xtalk_intr;
@@ -1740,17 +1775,124 @@
*/
pcibr_clearwidint(bridge);
- xtalk_intr_connect(xtalk_intr, (xtalk_intr_setfunc_t)pcibr_setwidint, (void *)bridge);
+ xtalk_intr_connect(xtalk_intr, (intr_func_t) pcibr_error_intr_handler,
+ (intr_arg_t) pcibr_soft, (xtalk_intr_setfunc_t)pcibr_setwidint, (void *)bridge);
+
+#ifdef BUS_INT_WAR_NOT_YET
+ request_irq(CPU_VECTOR_TO_IRQ(((hub_intr_t)xtalk_intr)->i_cpuid,
+ ((hub_intr_t)xtalk_intr)->i_bit),
+ (intr_func_t)pcibr_error_intr_handler, 0, "PCIBR error",
+ (intr_arg_t) pcibr_soft);
+#endif
+
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_INTR_ALLOC, pcibr_vhdl,
+ "pcibr_setwidint: b_wid_int_upper=0x%x, b_wid_int_lower=0x%x\n",
+ bridge->b_wid_int_upper, bridge->b_wid_int_lower));
/*
* now we can start handling error interrupts;
* enable all of them.
* NOTE: some PCI ints may already be enabled.
*/
- b_int_enable = bridge->b_int_enable | BRIDGE_ISR_ERRORS;
+ /* We read the INT_ENABLE register as a 64bit picreg_t for PIC and a
+ * 32bit bridgereg_t for BRIDGE, but always process the result as a
+ * 64bit value so the code can be "common" for both PIC and BRIDGE...
+ */
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ int_enable_64 = bridge->p_int_enable_64 | BRIDGE_ISR_ERRORS;
+ int_enable = (uint64_t)int_enable_64;
+ } else {
+ int_enable_32 = bridge->b_int_enable | (BRIDGE_ISR_ERRORS & 0xffffffff);
+ int_enable = ((uint64_t)int_enable_32 & 0xffffffff);
+ }
+#ifdef BUS_INT_WAR_NOT_YET
+ {
+ extern void sn_add_polled_interrupt(int irq, int interval);
+
+ sn_add_polled_interrupt(CPU_VECTOR_TO_IRQ(((hub_intr_t)xtalk_intr)->i_cpuid,
+ ((hub_intr_t)xtalk_intr)->i_bit), 20000);
+ }
+#endif
+
+
+#if BRIDGE_ERROR_INTR_WAR
+ if (pcibr_soft->bs_rev_num == BRIDGE_PART_REV_A) {
+ /*
+ * We commonly get master timeouts when talking to ql.
+ * We also see RESP_XTALK_ERROR and LLP_TX_RETRY interrupts.
+ * Insure that these are all disabled for now.
+ */
+ int_enable &= ~(BRIDGE_IMR_PCI_MST_TIMEOUT |
+ BRIDGE_ISR_RESP_XTLK_ERR |
+ BRIDGE_ISR_LLP_TX_RETRY);
+ }
+ if (pcibr_soft->bs_rev_num < BRIDGE_PART_REV_C) {
+ int_enable &= ~BRIDGE_ISR_BAD_XRESP_PKT;
+ }
+#endif /* BRIDGE_ERROR_INTR_WAR */
+
+#ifdef QL_SCSI_CTRL_WAR /* for IP30 only */
+ /* Really a QL rev A issue, but all newer hearts have newer QLs.
+ * Forces all IO6/MSCSI to be new.
+ */
+ if (heart_rev() == HEART_REV_A)
+ int_enable &= ~BRIDGE_IMR_PCI_MST_TIMEOUT;
+#endif
+
+#ifdef BRIDGE1_TIMEOUT_WAR
+ if (pcibr_soft->bs_rev_num == BRIDGE_PART_REV_A) {
+ /*
+ * Turn off these interrupts. They can't be trusted in bridge 1
+ */
+ int_enable &= ~(BRIDGE_IMR_XREAD_REQ_TIMEOUT |
+ BRIDGE_IMR_UNEXP_RESP);
+ }
+#endif
+
+#ifdef BRIDGE_B_DATACORR_WAR
+
+ /* WAR panic for Rev B silent data corruption.
+ * PIOERR turned off here because there is a problem
+ * with not re-arming it in pcibr_error_intr_handler.
+ * We don't get LLP error interrupts if we don't
+ * re-arm PIOERR interrupts! Just disable them here
+ */
+ if (pcibr_soft->bs_rev_num == BRIDGE_PART_REV_B) {
+ int_enable |= BRIDGE_IMR_LLP_REC_CBERR;
+ int_enable &= ~BRIDGE_ISR_PCIBUS_PIOERR;
- bridge->b_int_enable = b_int_enable;
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATTACH, pcibr_vhdl,
+ "Turning on LLP_REC_CBERR for Rev B Bridge.\n"));
+ }
+#endif
+
+ /* PIC BRINGUP WAR (PV# 856864 & 856865): allow the tnums that are
+ * locked out to be freed up sooner (by timing out) so that the
+ * read tnums are never completely used up.
+ */
+ if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV856864, pcibr_soft)) {
+ int_enable &= ~PIC_ISR_PCIX_REQ_TOUT;
+ int_enable &= ~BRIDGE_ISR_XREAD_REQ_TIMEOUT;
+
+ bridge->b_wid_req_timeout = 0x750;
+ }
+
+ /*
+ * PIC BRINGUP WAR (PV# 856866, 859504, 861476, 861478): Don't use
+ * RRB0, RRB8, RRB1, and RRB9. Assign them to DEVICE[2|3]--VCHAN3
+ * so they are not used
+ */
+ if (IS_PIC_SOFT(pcibr_soft) && PCIBR_WAR_ENABLED(PV856866, pcibr_soft)) {
+ bridge->b_even_resp |= 0x000f000f;
+ bridge->b_odd_resp |= 0x000f000f;
+ }
+
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ bridge->p_int_enable_64 = (picreg_t)int_enable;
+ } else {
+ bridge->b_int_enable = (bridgereg_t)int_enable;
+ }
bridge->b_int_mode = 0; /* do not send "clear interrupt" packets */
bridge->b_wid_tflush; /* wait until Bridge PIO complete */
@@ -1788,20 +1930,59 @@
(BRIDGE_WIDGET_PART_NUM << 4 | pcibr_wg_enable_rev))
pcibr_soft->bs_dma_flags |= PCIBR_NOWRITE_GATHER;
- pciio_provider_register(pcibr_vhdl, &pcibr_provider);
- pciio_provider_startup(pcibr_vhdl);
-
- pci_io_fb = 0x00000004; /* I/O FreeBlock Base */
- pci_io_fl = 0xFFFFFFFF; /* I/O FreeBlock Last */
-
- pci_lo_fb = 0x00000010; /* Low Memory FreeBlock Base */
- pci_lo_fl = 0x001FFFFF; /* Low Memory FreeBlock Last */
+ /* PIC only supports 64-bit direct mapping in PCI-X mode. Since
+ * all PCI-X devices that initiate memory transactions must be
+ * capable of generating 64-bit addressed, we force 64-bit DMAs.
+ */
+ if (IS_PCIX(pcibr_soft)) {
+ pcibr_soft->bs_dma_flags |= PCIIO_DMA_A64;
+ }
- pci_hi_fb = 0x00200000; /* High Memory FreeBlock Base */
- pci_hi_fl = 0x3FFFFFFF; /* High Memory FreeBlock Last */
+ {
+ pciio_win_map_t win_map_p;
+ iopaddr_t prom_base_addr = pcibr_soft->bs_xid << 24;
+ int prom_base_size = 0x1000000;
+ iopaddr_t prom_base_limit = prom_base_addr + prom_base_size;
+
+ /* Allocate resource maps based on bus page size; for I/O and memory
+ * space, free all pages except those in the base area and in the
+ * range set by the PROM.
+ *
+ * PROM creates BAR addresses in this format: 0x0ws00000 where w is
+ * the widget number and s is the device register offset for the slot.
+ */
- PCI_ADDR_SPACE_LIMITS_STORE();
+ win_map_p = &pcibr_soft->bs_io_win_map;
+ pciio_device_win_map_new(win_map_p,
+ PCIBR_BUS_IO_MAX + 1,
+ PCIBR_BUS_IO_PAGE);
+ pciio_device_win_populate(win_map_p,
+ PCIBR_BUS_IO_BASE,
+ prom_base_addr - PCIBR_BUS_IO_BASE);
+ pciio_device_win_populate(win_map_p,
+ prom_base_limit,
+ (PCIBR_BUS_IO_MAX + 1) - prom_base_limit);
+
+ win_map_p = &pcibr_soft->bs_swin_map;
+ pciio_device_win_map_new(win_map_p,
+ PCIBR_BUS_SWIN_MAX + 1,
+ PCIBR_BUS_SWIN_PAGE);
+ pciio_device_win_populate(win_map_p,
+ PCIBR_BUS_SWIN_BASE,
+ (PCIBR_BUS_SWIN_MAX + 1) - PCIBR_BUS_SWIN_PAGE);
+
+ win_map_p = &pcibr_soft->bs_mem_win_map;
+ pciio_device_win_map_new(win_map_p,
+ PCIBR_BUS_MEM_MAX + 1,
+ PCIBR_BUS_MEM_PAGE);
+ pciio_device_win_populate(win_map_p,
+ PCIBR_BUS_MEM_BASE,
+ prom_base_addr - PCIBR_BUS_MEM_BASE);
+ pciio_device_win_populate(win_map_p,
+ prom_base_limit,
+ (PCIBR_BUS_MEM_MAX + 1) - prom_base_limit);
+ }
/* build "no-slot" connection point
*/
@@ -1830,59 +2011,91 @@
}
#endif
-#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);
-#endif
-
- for (slot = 0; slot < 8; ++slot)
+ for (slot = pcibr_soft->bs_min_slot;
+ slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
/* Find out what is out there */
(void)pcibr_slot_info_init(pcibr_vhdl,slot);
+ }
+ for (slot = pcibr_soft->bs_min_slot;
+ slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot)
+ /* Set up the address space for this slot in the PCI land */
+ (void)pcibr_slot_addr_space_init(pcibr_vhdl, slot);
- for (slot = 0; slot < 8; ++slot)
- /* Set up the address space for this slot in the pci land */
- (void)pcibr_slot_addr_space_init(pcibr_vhdl,slot);
-
- for (slot = 0; slot < 8; ++slot)
+ for (slot = pcibr_soft->bs_min_slot;
+ slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot)
/* Setup the device register */
(void)pcibr_slot_device_init(pcibr_vhdl, slot);
- for (slot = 0; slot < 8; ++slot)
- /* Setup host/guest relations */
- (void)pcibr_slot_guest_info_init(pcibr_vhdl,slot);
-
- for (slot = 0; slot < 8; ++slot)
- /* Initial RRB management */
- (void)pcibr_slot_initial_rrb_alloc(pcibr_vhdl,slot);
+ if (IS_PCIX(pcibr_soft)) {
+ pcibr_soft->bs_pcix_rbar_inuse = 0;
+ pcibr_soft->bs_pcix_rbar_avail = NUM_RBAR;
+ pcibr_soft->bs_pcix_rbar_percent_allowed =
+ pcibr_pcix_rbars_calc(pcibr_soft);
+
+ for (slot = pcibr_soft->bs_min_slot;
+ slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot)
+ /* Setup the PCI-X Read Buffer Attribute Registers (RBARs) */
+ (void)pcibr_slot_pcix_rbar_init(pcibr_soft, slot);
+ }
+
+ /* Set up convenience links */
+ if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft))
+ pcibr_bus_cnvlink(pcibr_soft->bs_vhdl);
- /* 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, 0);
+ for (slot = pcibr_soft->bs_min_slot;
+ slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot)
+ /* Setup host/guest relations */
+ (void)pcibr_slot_guest_info_init(pcibr_vhdl, slot);
+ /* Handle initial RRB management for Bridge and Xbridge */
+ pcibr_initial_rrb(pcibr_vhdl,
+ pcibr_soft->bs_first_slot, pcibr_soft->bs_last_slot);
+
+{ /* Before any drivers get called that may want to re-allocate
+ * RRB's, let's get some special cases pre-allocated. Drivers
+ * may override these pre-allocations, but by doing pre-allocations
+ * now we're assured not to step all over what the driver intended.
+ *
+ * Note: Someday this should probably be moved over to pcibr_rrb.c
+ */
/*
* 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);
+ if (pcibr_soft->bs_bricktype > 0) {
+ switch (pcibr_soft->bs_bricktype) {
+ case MODULE_PXBRICK:
+ /*
+ * If the IO9 is in the PXBrick (bus1, slot1) allocate
+ * RRBs to all the devices
+ */
+ if ((pcibr_widget_to_bus(pcibr_vhdl) == 1) &&
+ (pcibr_soft->bs_slot[0].bss_vendor_id == 0x10A9) &&
+ (pcibr_soft->bs_slot[0].bss_device_id == 0x100A)) {
+ do_pcibr_rrb_autoalloc(pcibr_soft, 0, VCHAN0, 4);
+ do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 4);
+ do_pcibr_rrb_autoalloc(pcibr_soft, 2, VCHAN0, 4);
+ do_pcibr_rrb_autoalloc(pcibr_soft, 3, VCHAN0, 4);
+ } else {
+ do_pcibr_rrb_autoalloc(pcibr_soft, 0, VCHAN0, 8);
+ do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8);
+ }
+
+ break;
+ case MODULE_PEBRICK:
+ case MODULE_PBRICK:
+ do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8);
+ do_pcibr_rrb_autoalloc(pcibr_soft, 2, VCHAN0, 8);
break;
- case 'i': /* Ibrick */
+ case MODULE_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);
+ do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8);
+ do_pcibr_rrb_autoalloc(pcibr_soft, 2, VCHAN0, 8);
}
else {
/* allocate one RRB for the serial port */
- do_pcibr_rrb_autoalloc(pcibr_soft, 0, 1);
+ do_pcibr_rrb_autoalloc(pcibr_soft, 0, VCHAN0, 1);
}
break;
} /* switch */
@@ -1890,33 +2103,80 @@
#ifdef LATER
if (strstr(nicinfo, XTALK_PCI_PART_NUM)) {
- do_pcibr_rrb_autoalloc(pcibr_soft, 1, 8);
-#if PCIBR_RRB_DEBUG
- printf("\n\nFound XTALK_PCI (030-1275) at %v\n", xconn_vhdl);
-
- printf("pcibr_attach: %v Shoebox RRB MANAGEMENT: %d+%d free\n",
- pcibr_vhdl,
- pcibr_soft->bs_rrb_avail[0],
- pcibr_soft->bs_rrb_avail[1]);
-
- for (slot = 0; slot < 8; ++slot)
- printf("\t%d+%d+%d",
- 0xFFF & pcibr_soft->bs_rrb_valid[slot],
- 0xFFF & pcibr_soft->bs_rrb_valid[slot + PCIBR_RRB_SLOT_VIRTUAL],
- pcibr_soft->bs_rrb_res[slot]);
-
- printf("\n");
+ do_pcibr_rrb_autoalloc(pcibr_soft, 1, VCHAN0, 8);
+ }
#endif
+} /* OK Special RRB allocations are done. */
+
+ for (slot = pcibr_soft->bs_min_slot;
+ slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot)
+ /* Call the device attach */
+ (void)pcibr_slot_call_device_attach(pcibr_vhdl, slot, 0);
+
+#ifdef PIC_LATER
+#if (defined(USS302_TIMEOUT_WAR))
+ /*
+ * If this bridge holds a Lucent USS-302 or USS-312 pci/usb controller,
+ * increase the Bridge PCI retry backoff interval. This part seems
+ * to go away for long periods of time if a DAC appears on the bus during
+ * a read command that is being retried.
+ */
+
+{
+ ii_ixtt_u_t ixtt;
+
+ for (slot = pcibr_soft->bs_min_slot;
+ slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
+ if (pcibr_soft->bs_slot[slot].bss_vendor_id ==
+ LUCENT_USBHC_VENDOR_ID_NUM &&
+ (pcibr_soft->bs_slot[slot].bss_device_id ==
+ LUCENT_USBHC302_DEVICE_ID_NUM ||
+ pcibr_soft->bs_slot[slot].bss_device_id ==
+ LUCENT_USBHC312_DEVICE_ID_NUM)) {
+ printk(KERN_NOTICE
+ "pcibr_attach: %x Bus holds a usb part - setting"
+ "bridge PCI_RETRY_HLD to %d\n",
+ pcibr_vhdl, USS302_BRIDGE_TIMEOUT_HLD);
+
+ bridge->b_bus_timeout &= ~BRIDGE_BUS_PCI_RETRY_HLD_MASK;
+ bridge->b_bus_timeout |=
+ BRIDGE_BUS_PCI_RETRY_HLD(USS302_BRIDGE_TIMEOUT_HLD);
+
+ /*
+ * Have to consider the read response timer in the hub II as well
+ */
+
+ hubii_ixtt_get(xconn_vhdl, &ixtt);
+
+ /*
+ * bump rrsp_ps to allow at least 1ms for read
+ * responses from this widget
+ */
+
+ ixtt.ii_ixtt_fld_s.i_rrsp_ps = 20000;
+ hubii_ixtt_set(xconn_vhdl, &ixtt);
+
+ /*
+ * print the current setting
+ */
+
+ hubii_ixtt_get(xconn_vhdl, &ixtt);
+ printk( "Setting hub ixtt.rrsp_ps field to 0x%x\n",
+ ixtt.ii_ixtt_fld_s.i_rrsp_ps);
+
+ break; /* only need to do it once */
+ }
}
+}
+#endif /* (defined(USS302_TIMEOUT_WAR)) */
#else
FIXME("pcibr_attach: Call do_pcibr_rrb_autoalloc nicinfo\n");
-#endif
+#endif /* PIC_LATER */
if (aa)
async_attach_add_info(noslot_conn, aa);
- pciio_device_attach(noslot_conn, 0);
-
+ pciio_device_attach(noslot_conn, (int)0);
/*
* Tear down pointer to async attach info -- async threads for
@@ -1927,11 +2187,13 @@
return 0;
}
+
/*
* pcibr_detach:
* Detach the bridge device from the hwgraph after cleaning out all the
* underlying vertices.
*/
+
int
pcibr_detach(devfs_handle_t xconn)
{
@@ -1939,6 +2201,9 @@
devfs_handle_t pcibr_vhdl;
pcibr_soft_t pcibr_soft;
bridge_t *bridge;
+ unsigned s;
+
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DETACH, xconn, "pcibr_detach\n"));
/* Get the bridge vertex from its xtalk connection point */
if (hwgraph_traverse(xconn, EDGE_LBL_PCI, &pcibr_vhdl) != GRAPH_SUCCESS)
@@ -1947,16 +2212,20 @@
pcibr_soft = pcibr_soft_get(pcibr_vhdl);
bridge = pcibr_soft->bs_base;
+
+ s = pcibr_lock(pcibr_soft);
/* Disable the interrupts from the bridge */
- bridge->b_int_enable = 0;
+ if (IS_PIC_SOFT(pcibr_soft)) {
+ bridge->p_int_enable_64 = 0;
+ } else {
+ bridge->b_int_enable = 0;
+ }
+ pcibr_unlock(pcibr_soft, s);
/* Detach all the PCI devices talking to this bridge */
- for(slot = 0; slot < 8; slot++) {
-#ifdef DEBUG
- printk("pcibr_device_detach called for %p/%d\n",
- pcibr_vhdl,slot);
-#endif
- pcibr_slot_detach(pcibr_vhdl, slot, 0);
+ for (slot = pcibr_soft->bs_min_slot;
+ slot < PCIBR_NUM_SLOTS(pcibr_soft); ++slot) {
+ pcibr_slot_detach(pcibr_vhdl, slot, 0, (char *)NULL, (int *)NULL);
}
/* Unregister the no-slot connection point */
@@ -1998,17 +2267,29 @@
int
pcibr_asic_rev(devfs_handle_t pconn_vhdl)
{
- devfs_handle_t pcibr_vhdl;
+ devfs_handle_t pcibr_vhdl;
+ int tmp_vhdl;
arbitrary_info_t ainfo;
if (GRAPH_SUCCESS !=
hwgraph_traverse(pconn_vhdl, EDGE_LBL_MASTER, &pcibr_vhdl))
return -1;
- if (GRAPH_SUCCESS !=
- hwgraph_info_get_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, &ainfo))
- return -1;
+ tmp_vhdl = hwgraph_info_get_LBL(pcibr_vhdl, INFO_LBL_PCIBR_ASIC_REV, &ainfo);
+
+ /*
+ * Any hwgraph function that returns a vertex handle will implicity
+ * increment that vertex's reference count. The caller must explicity
+ * decrement the vertex's referece count after the last reference to
+ * that vertex.
+ *
+ * Decrement reference count incremented by call to hwgraph_traverse().
+ *
+ */
+ hwgraph_vertex_unref(pcibr_vhdl);
+ if (tmp_vhdl != GRAPH_SUCCESS)
+ return -1;
return (int) ainfo;
}
@@ -2018,7 +2299,7 @@
pciio_info_t pciio_info = pciio_info_get(pconn_vhdl);
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
pciio_slot_t slot;
- slot = pciio_info_slot_get(pciio_info);
+ slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_device_write_gather_flush(pcibr_soft, slot);
return 0;
}
@@ -2048,11 +2329,13 @@
size_t wsize; /* size of device decode on PCI */
int try; /* DevIO(x) window scanning order control */
+ int maxtry, halftry;
int win; /* which DevIO(x) window is being used */
pciio_space_t mspace; /* target space for devio(x) register */
iopaddr_t mbase; /* base of devio(x) mapped area on PCI */
size_t msize; /* size of devio(x) mapped area on PCI */
size_t mmask; /* addr bits stored in Device(x) */
+ char tmp_str[512];
unsigned long s;
@@ -2061,6 +2344,17 @@
if (pcibr_soft->bs_slot[slot].has_host) {
slot = pcibr_soft->bs_slot[slot].host_slot;
pcibr_info = pcibr_soft->bs_slot[slot].bss_infos[0];
+
+ /*
+ * Special case for dual-slot pci devices such as ioc3 on IP27
+ * baseio. In these cases, pconn_vhdl should never be for a pci
+ * function on a subordiate PCI bus, so we can safely reset pciio_info
+ * to be the info struct embedded in pcibr_info. Failure to do this
+ * results in using a bogus pciio_info_t for calculations done later
+ * in this routine.
+ */
+
+ pciio_info = &pcibr_info->f_c;
}
if (space == PCIIO_SPACE_NONE)
goto done;
@@ -2080,7 +2374,7 @@
*/
if (((flags & PCIIO_BYTE_STREAM) == 0) &&
((pci_addr + req_size) <= BRIDGE_TYPE0_CFG_FUNC_OFF))
- xio_addr = pci_addr + BRIDGE_TYPE0_CFG_DEV(slot);
+ xio_addr = pci_addr + PCIBR_TYPE0_CFG_DEV(pcibr_soft, slot);
goto done;
}
@@ -2090,8 +2384,8 @@
* enabling and disabling
* decodes properly.
*/
- wbase = pcibr_info->f_rbase;
- wsize = pcibr_info->f_rsize;
+ wbase = pciio_info->c_rbase;
+ wsize = pciio_info->c_rsize;
/*
* While the driver should know better
@@ -2113,13 +2407,13 @@
*/
bar = space - PCIIO_SPACE_WIN0;
if (bar < 6) {
- wspace = pcibr_info->f_window[bar].w_space;
+ wspace = pciio_info->c_window[bar].w_space;
if (wspace == PCIIO_SPACE_NONE)
goto done;
/* get PCI base and size */
- wbase = pcibr_info->f_window[bar].w_base;
- wsize = pcibr_info->f_window[bar].w_size;
+ wbase = pciio_info->c_window[bar].w_base;
+ wsize = pciio_info->c_window[bar].w_size;
/*
* While the driver should know better
@@ -2147,11 +2441,15 @@
* We will not attempt to satisfy a single request
* by concatinating multiple windows.
*/
- for (try = 0; try < 16; ++try) {
+ maxtry = PCIBR_NUM_SLOTS(pcibr_soft) * 2;
+ halftry = PCIBR_NUM_SLOTS(pcibr_soft) - 1;
+ for (try = 0; try < maxtry; ++try) {
bridgereg_t devreg;
unsigned offset;
- win = (try + slot) % 8;
+ /* calculate win based on slot, attempt, and max possible
+ devices on bus */
+ win = (try + slot) % PCIBR_NUM_SLOTS(pcibr_soft);
/* If this DevIO(x) mapping area can provide
* a mapping to this address, use it.
@@ -2176,7 +2474,7 @@
* (only check this the second time through)
*/
mspace = pcibr_soft->bs_slot[win].bss_devio.bssd_space;
- if ((try > 7) && (mspace == PCIIO_SPACE_NONE)) {
+ if ((try > halftry) && (mspace == PCIIO_SPACE_NONE)) {
/* If this is the primary DevIO(x) window
* for some other device, skip it.
@@ -2214,25 +2512,61 @@
devreg &= ~BRIDGE_DEV_DEV_SWAP;
if (pcibr_soft->bs_slot[win].bss_device != devreg) {
- bridge->b_device[win].reg = devreg;
- pcibr_soft->bs_slot[win].bss_device = devreg;
- bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ bridge->b_device[win].reg = devreg;
+ pcibr_soft->bs_slot[win].bss_device = devreg;
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ BRIDGE_REG_SET32((&bridge->b_device[win].reg)) = __swab32(devreg);
+ pcibr_soft->bs_slot[win].bss_device = devreg;
+ BRIDGE_REG_GET32((&bridge->b_wid_tflush)); /* wait until Bridge PIO complete */
+ } else {
+ bridge->b_device[win].reg = devreg;
+ pcibr_soft->bs_slot[win].bss_device = devreg;
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ }
-#if DEBUG && PCI_DEBUG
- printk("pcibr Device(%d): 0x%lx\n", win, bridge->b_device[win].reg);
+#ifdef PCI_LATER
+ PCIBR_DEBUG((PCIBR_DEBUG_DEVREG, pconn_vhdl,
+ "pcibr_addr_pci_to_xio: Device(%d): %x\n",
+ win, devreg, device_bits));
+#else
+ printk("pcibr_addr_pci_to_xio: Device(%d): %x\n", win, devreg);
#endif
}
pcibr_soft->bs_slot[win].bss_devio.bssd_space = space;
pcibr_soft->bs_slot[win].bss_devio.bssd_base = mbase;
- xio_addr = BRIDGE_DEVIO(win) + (pci_addr - mbase);
+ xio_addr = PCIBR_BRIDGE_DEVIO(pcibr_soft, win) + (pci_addr - mbase);
-#if DEBUG && PCI_DEBUG
- printk("%s LINE %d map to space %d space desc 0x%x[%lx..%lx] for slot %d allocates DevIO(%d) devreg 0x%x\n",
- __FUNCTION__, __LINE__, space, space_desc,
- pci_addr, pci_addr + req_size - 1,
- slot, win, devreg);
-#endif
+ /* Increment this DevIO's use count */
+ pcibr_soft->bs_slot[win].bss_devio.bssd_ref_cnt++;
+
+ /* Save the DevIO register index used to access this BAR */
+ if (bar != -1)
+ pcibr_info->f_window[bar].w_devio_index = win;
+ /*
+ * The kernel only allows functions to have so many variable args,
+ * attempting to call PCIBR_DEBUG_ALWAYS() with more than 5 printk
+ * arguments fails so sprintf() it into a temporary string.
+ */
+ if (pcibr_debug_mask & PCIBR_DEBUG_PIOMAP) {
+#ifdef PIC_LATER
+ sprintf(tmp_str, "pcibr_addr_pci_to_xio: map to %x[%x..%x] for "
+ "slot %d allocates DevIO(%d) Device(%d) set to %x\n",
+ space, space_desc, pci_addr, pci_addr + req_size - 1,
+ slot, win, win, devreg, device_bits);
+#else
+ sprintf(tmp_str, "pcibr_addr_pci_to_xio: map to [%lx..%lx] for "
+ "slot %d allocates DevIO(%d) Device(%d) set to %lx\n",
+ (unsigned long)pci_addr, (unsigned long)(pci_addr + req_size - 1),
+ (unsigned int)slot, win, win, (unsigned long)devreg);
+#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, "%s", tmp_str));
+ }
goto done;
} /* endif DevIO(x) not pointed */
mbase = pcibr_soft->bs_slot[win].bss_devio.bssd_base;
@@ -2251,12 +2585,23 @@
* final XIO address, release the lock and
* return.
*/
- xio_addr = BRIDGE_DEVIO(win) + (pci_addr - mbase);
+ xio_addr = PCIBR_BRIDGE_DEVIO(pcibr_soft, win) + (pci_addr - mbase);
+
+ /* Increment this DevIO's use count */
+ pcibr_soft->bs_slot[win].bss_devio.bssd_ref_cnt++;
-#if DEBUG && PCI_DEBUG
- printk("%s LINE %d map to space %d [0x%p..0x%p] for slot %d uses DevIO(%d)\n",
- __FUNCTION__, __LINE__, space, pci_addr, pci_addr + req_size - 1, slot, win);
+ /* Save the DevIO register index used to access this BAR */
+ if (bar != -1)
+ pcibr_info->f_window[bar].w_devio_index = win;
+
+ if (pcibr_debug_mask & PCIBR_DEBUG_PIOMAP) {
+#ifdef PIC_LATER
+ sprintf(tmp_str, "pcibr_addr_pci_to_xio: map to %x[%x..%x] for "
+ "slot %d uses DevIO(%d)\n", space, space_desc, pci_addr,
+ pci_addr + req_size - 1, slot, win);
#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, "%s", tmp_str));
+ }
goto done;
}
@@ -2322,33 +2667,55 @@
if (bfn == bfo) { /* we already match. */
;
} else if (bfo != 0) { /* we have a conflict. */
-#if DEBUG && PCI_DEBUG
- printk("pcibr_addr_pci_to_xio: swap conflict in space %d , was%s%s, want%s%s\n",
- space,
- bfo & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "",
- bfo & PCIIO_WORD_VALUES ? " WORD_VALUES" : "",
- bfn & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "",
- bfn & PCIIO_WORD_VALUES ? " WORD_VALUES" : "");
+ if (pcibr_debug_mask & PCIBR_DEBUG_PIOMAP) {
+#ifdef PIC_LATER
+ sprintf(tmp_str, "pcibr_addr_pci_to_xio: swap conflict in %x, "
+ "was%s%s, want%s%s\n", space, space_desc,
+ bfo & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "",
+ bfo & PCIIO_WORD_VALUES ? " WORD_VALUES" : "",
+ bfn & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "",
+ bfn & PCIIO_WORD_VALUES ? " WORD_VALUES" : "");
#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, "%s", tmp_str));
+ }
xio_addr = XIO_NOWHERE;
} else { /* OK to make the change. */
- bridgereg_t octl, nctl;
-
swb = (space == PCIIO_SPACE_IO) ? BRIDGE_CTRL_IO_SWAP : BRIDGE_CTRL_MEM_SWAP;
- octl = bridge->b_wid_control;
- nctl = bst ? octl | swb : octl & ~swb;
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ picreg_t octl, nctl;
+ octl = bridge->p_wid_control_64;
+ nctl = bst ? octl | (uint64_t)swb : octl & ((uint64_t)~swb);
- if (octl != nctl) /* make the change if any */
- bridge->b_wid_control = nctl;
+ if (octl != nctl) /* make the change if any */
+ bridge->b_wid_control = nctl;
+ }
+ else {
+ picreg_t octl, nctl;
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ octl = BRIDGE_REG_GET32((&bridge->b_wid_control));
+ nctl = bst ? octl | swb : octl & ~swb;
+
+ if (octl != nctl) /* make the change if any */
+ BRIDGE_REG_SET32((&bridge->b_wid_control)) = __swab32(nctl);
+ } else {
+ octl = bridge->b_wid_control;
+ nctl = bst ? octl | swb : octl & ~swb;
+ if (octl != nctl) /* make the change if any */
+ bridge->b_wid_control = nctl;
+ }
+ }
*bfp = bfn; /* record the assignment */
-#if DEBUG && PCI_DEBUG
- printk("pcibr_addr_pci_to_xio: swap for space %d set to%s%s\n",
- space,
- bfn & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "",
- bfn & PCIIO_WORD_VALUES ? " WORD_VALUES" : "");
+ if (pcibr_debug_mask & PCIBR_DEBUG_PIOMAP) {
+#ifdef PIC_LATER
+ sprintf(tmp_str, "pcibr_addr_pci_to_xio: swap for %x set "
+ "to%s%s\n", space, space_desc,
+ bfn & PCIIO_BYTE_STREAM ? " BYTE_STREAM" : "",
+ bfn & PCIIO_WORD_VALUES ? " WORD_VALUES" : "");
#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl, "%s", tmp_str));
+ }
}
}
done:
@@ -2368,7 +2735,7 @@
{
pcibr_info_t pcibr_info = pcibr_info_get(pconn_vhdl);
pciio_info_t pciio_info = &pcibr_info->f_c;
- pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+ pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn;
@@ -2380,8 +2747,11 @@
unsigned long s;
/* Make sure that the req sizes are non-zero */
- if ((req_size < 1) || (req_size_max < 1))
+ if ((req_size < 1) || (req_size_max < 1)) {
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_PIOMAP, pconn_vhdl,
+ "pcibr_piomap_alloc: req_size | req_size_max < 1\n"));
return NULL;
+ }
/*
* Code to translate slot/space/addr
@@ -2390,8 +2760,11 @@
*/
xio_addr = pcibr_addr_pci_to_xio(pconn_vhdl, pciio_slot, space, pci_addr, req_size, flags);
- if (xio_addr == XIO_NOWHERE)
+ if (xio_addr == XIO_NOWHERE) {
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_PIOMAP, pconn_vhdl,
+ "pcibr_piomap_alloc: xio_addr == XIO_NOWHERE\n"));
return NULL;
+ }
/* Check the piomap list to see if there is already an allocated
* piomap entry but not in use. If so use that one. Otherwise
@@ -2415,7 +2788,7 @@
}
pcibr_piomap->bp_dev = pconn_vhdl;
- pcibr_piomap->bp_slot = pciio_slot;
+ pcibr_piomap->bp_slot = PCIBR_DEVICE_TO_SLOT(pcibr_soft, pciio_slot);
pcibr_piomap->bp_flags = flags;
pcibr_piomap->bp_space = space;
pcibr_piomap->bp_pciaddr = pci_addr;
@@ -2446,6 +2819,10 @@
pcibr_piomap = 0;
}
}
+
+ PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl,
+ "pcibr_piomap_alloc: map=0x%x\n", pcibr_piomap));
+
return pcibr_piomap;
}
@@ -2453,6 +2830,9 @@
void
pcibr_piomap_free(pcibr_piomap_t pcibr_piomap)
{
+ PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pcibr_piomap->bp_dev,
+ "pcibr_piomap_free: map=0x%x\n", pcibr_piomap));
+
xtalk_piomap_free(pcibr_piomap->bp_xtalk_pio);
pcibr_piomap->bp_xtalk_pio = 0;
pcibr_piomap->bp_mapsz = 0;
@@ -2464,16 +2844,24 @@
iopaddr_t pci_addr,
size_t req_size)
{
- return xtalk_piomap_addr(pcibr_piomap->bp_xtalk_pio,
+ caddr_t addr;
+ addr = xtalk_piomap_addr(pcibr_piomap->bp_xtalk_pio,
pcibr_piomap->bp_xtalk_addr +
pci_addr - pcibr_piomap->bp_pciaddr,
req_size);
+ PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pcibr_piomap->bp_dev,
+ "pcibr_piomap_free: map=0x%x, addr=0x%x\n",
+ pcibr_piomap, addr));
+
+ return(addr);
}
/*ARGSUSED */
void
pcibr_piomap_done(pcibr_piomap_t pcibr_piomap)
{
+ PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pcibr_piomap->bp_dev,
+ "pcibr_piomap_done: map=0x%x\n", pcibr_piomap));
xtalk_piomap_done(pcibr_piomap->bp_xtalk_pio);
}
@@ -2487,26 +2875,34 @@
unsigned flags)
{
pciio_info_t pciio_info = pciio_info_get(pconn_vhdl);
- pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+ pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn;
iopaddr_t xio_addr;
+ caddr_t addr;
xio_addr = pcibr_addr_pci_to_xio(pconn_vhdl, pciio_slot, space, pci_addr, req_size, flags);
- if (xio_addr == XIO_NOWHERE)
+ if (xio_addr == XIO_NOWHERE) {
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_PIODIR, pconn_vhdl,
+ "pcibr_piotrans_addr: xio_addr == XIO_NOWHERE\n"));
return NULL;
+ }
- return xtalk_piotrans_addr(xconn_vhdl, 0, xio_addr, req_size, flags & PIOMAP_FLAGS);
+ addr = xtalk_piotrans_addr(xconn_vhdl, 0, xio_addr, req_size, flags & PIOMAP_FLAGS);
+ PCIBR_DEBUG((PCIBR_DEBUG_PIODIR, pconn_vhdl,
+ "pcibr_piotrans_addr: xio_addr=0x%x, addr=0x%x\n",
+ xio_addr, addr));
+ return(addr);
}
/*
* PIO Space allocation and management.
* Allocate and Manage the PCI PIO space (mem and io space)
* This routine is pretty simplistic at this time, and
- * does pretty trivial management of allocation and freeing..
- * The current scheme is prone for fragmentation..
+ * does pretty trivial management of allocation and freeing.
+ * The current scheme is prone for fragmentation.
* Change the scheme to use bitmaps.
*/
@@ -2525,7 +2921,6 @@
pciio_piospace_t piosp;
unsigned long s;
- iopaddr_t *pciaddr, *pcilast;
iopaddr_t start_addr;
size_t align_mask;
@@ -2559,38 +2954,43 @@
}
ASSERT(!piosp);
+ /*
+ * Allocate PCI bus address, usually for the Universe chip driver;
+ * do not pass window info since the actual PCI bus address
+ * space will never be freed. The space may be reused after it
+ * is logically released by pcibr_piospace_free().
+ */
switch (space) {
case PCIIO_SPACE_IO:
- pciaddr = &pcibr_soft->bs_spinfo.pci_io_base;
- pcilast = &pcibr_soft->bs_spinfo.pci_io_last;
+ start_addr = pcibr_bus_addr_alloc(pcibr_soft, NULL,
+ PCIIO_SPACE_IO,
+ 0, req_size, alignment);
break;
+
case PCIIO_SPACE_MEM:
case PCIIO_SPACE_MEM32:
- pciaddr = &pcibr_soft->bs_spinfo.pci_mem_base;
- pcilast = &pcibr_soft->bs_spinfo.pci_mem_last;
+ start_addr = pcibr_bus_addr_alloc(pcibr_soft, NULL,
+ PCIIO_SPACE_MEM32,
+ 0, req_size, alignment);
break;
+
default:
ASSERT(0);
pcibr_unlock(pcibr_soft, s);
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_PIOMAP, pconn_vhdl,
+ "pcibr_piospace_alloc: unknown space %d\n", space));
return 0;
}
- start_addr = *pciaddr;
-
/*
- * Align start_addr.
+ * If too big a request, reject it.
*/
- if (start_addr & align_mask)
- start_addr = (start_addr + align_mask) & ~align_mask;
-
- if ((start_addr + req_size) > *pcilast) {
- /*
- * If too big a request, reject it.
- */
+ if (!start_addr) {
pcibr_unlock(pcibr_soft, s);
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_PIOMAP, pconn_vhdl,
+ "pcibr_piospace_alloc: request 0x%x to big\n", req_size));
return 0;
}
- *pciaddr = (start_addr + req_size);
NEW(piosp);
piosp->free = 0;
@@ -2601,6 +3001,10 @@
pcibr_info->f_piospace = piosp;
pcibr_unlock(pcibr_soft, s);
+
+ PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl,
+ "pcibr_piospace_alloc: piosp=0x%x\n", piosp));
+
return start_addr;
}
@@ -2612,7 +3016,9 @@
size_t req_size)
{
pcibr_info_t pcibr_info = pcibr_info_get(pconn_vhdl);
+#ifdef PIC_LATER
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pcibr_info->f_mfast;
+#endif
pciio_piospace_t piosp;
unsigned long s;
@@ -2655,6 +3061,9 @@
}
piosp->free = 1;
pcibr_unlock(pcibr_soft, s);
+
+ PCIBR_DEBUG((PCIBR_DEBUG_PIOMAP, pconn_vhdl,
+ "pcibr_piospace_free: piosp=0x%x\n", piosp));
return;
}
@@ -2713,7 +3122,7 @@
attributes &= ~PCI64_ATTR_PREF;
/* the swap bit is in the address attributes for xbridge */
- if (pcibr_soft->bs_xbridge) {
+ if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) {
if (flags & PCIIO_BYTE_STREAM)
attributes |= PCI64_ATTR_SWAP;
if (flags & PCIIO_WORD_VALUES)
@@ -2742,6 +3151,11 @@
if (flags & PCIBR_VCHAN0)
attributes &= ~PCI64_ATTR_VIRTUAL;
+ /* PIC in PCI-X mode only supports barrier & swap */
+ if (IS_PCIX(pcibr_soft)) {
+ attributes &= (PCI64_ATTR_BAR | PCI64_ATTR_SWAP);
+ }
+
return (attributes);
}
@@ -2762,6 +3176,7 @@
pcibr_dmamap_t pcibr_dmamap;
int ate_count;
int ate_index;
+ int vchan = VCHAN0;
/* merge in forced flags */
flags |= pcibr_soft->bs_dma_flags;
@@ -2778,17 +3193,16 @@
xtalk_dmamap = xtalk_dmamap_alloc(xconn_vhdl, dev_desc, req_size_max,
flags & DMAMAP_FLAGS);
if (!xtalk_dmamap) {
-#if PCIBR_ATE_DEBUG
- printk("pcibr_attach: xtalk_dmamap_alloc failed\n");
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pconn_vhdl,
+ "pcibr_dmamap_alloc: xtalk_dmamap_alloc failed\n"));
free_pciio_dmamap(pcibr_dmamap);
return 0;
}
xio_port = pcibr_soft->bs_mxid;
- slot = pciio_info_slot_get(pciio_info);
+ slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_dmamap->bd_dev = pconn_vhdl;
- pcibr_dmamap->bd_slot = slot;
+ pcibr_dmamap->bd_slot = PCIBR_DEVICE_TO_SLOT(pcibr_soft, slot);
pcibr_dmamap->bd_soft = pcibr_soft;
pcibr_dmamap->bd_xtalk = xtalk_dmamap;
pcibr_dmamap->bd_max_size = req_size_max;
@@ -2812,29 +3226,37 @@
pcibr_dmamap->bd_xio_addr = 0;
pcibr_dmamap->bd_pci_addr = pci_addr;
- /* Make sure we have an RRB (or two).
+ /* If in PCI mode, make sure we have an RRB (or two).
*/
- if (!(pcibr_soft->bs_rrb_fixed & (1 << slot))) {
+ if (IS_PCI(pcibr_soft) &&
+ !(pcibr_soft->bs_rrb_fixed & (1 << slot))) {
if (flags & PCIBR_VCHAN1)
- slot += PCIBR_RRB_SLOT_VIRTUAL;
- have_rrbs = pcibr_soft->bs_rrb_valid[slot];
+ vchan = VCHAN1;
+ have_rrbs = pcibr_soft->bs_rrb_valid[slot][vchan];
if (have_rrbs < 2) {
if (pci_addr & PCI64_ATTR_PREF)
min_rrbs = 2;
else
min_rrbs = 1;
if (have_rrbs < min_rrbs)
- do_pcibr_rrb_autoalloc(pcibr_soft, slot, min_rrbs - have_rrbs);
+ do_pcibr_rrb_autoalloc(pcibr_soft, slot, vchan,
+ min_rrbs - have_rrbs);
}
}
-#if PCIBR_ATE_DEBUG
- printk("pcibr_dmamap_alloc: using direct64\n");
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmamap_alloc: using direct64, map=0x%x\n",
+ pcibr_dmamap));
return pcibr_dmamap;
}
-#if PCIBR_ATE_DEBUG
- printk("pcibr_dmamap_alloc: unable to use direct64\n");
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmamap_alloc: unable to use direct64\n"));
+
+ /* PIC only supports 64-bit direct mapping in PCI-X mode. */
+ if (IS_PCIX(pcibr_soft)) {
+ DEL(pcibr_dmamap);
+ return 0;
+ }
+
flags &= ~PCIIO_DMA_A64;
}
if (flags & PCIIO_FIXED) {
@@ -2849,17 +3271,17 @@
* Mapping calls may fail if target
* is outside the direct32 range.
*/
-#if PCIBR_ATE_DEBUG
- printk("pcibr_dmamap_alloc: using direct32\n");
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmamap_alloc: using direct32, map=0x%x\n",
+ pcibr_dmamap));
pcibr_dmamap->bd_flags = flags;
pcibr_dmamap->bd_xio_addr = pcibr_soft->bs_dir_xbase;
pcibr_dmamap->bd_pci_addr = PCI32_DIRECT_BASE;
return pcibr_dmamap;
}
-#if PCIBR_ATE_DEBUG
- printk("pcibr_dmamap_alloc: unable to use direct32\n");
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmamap_alloc: unable to use direct32\n"));
+
/* If the user demands FIXED and we can't
* give it to him, fail.
*/
@@ -2892,9 +3314,9 @@
int have_rrbs;
int min_rrbs;
-#if PCIBR_ATE_DEBUG
- printk("pcibr_dmamap_alloc: using PMU\n");
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pconn_vhdl,
+ "pcibr_dmamap_alloc: using PMU, ate_index=%d, "
+ "pcibr_dmamap=0x%x\n", ate_index, pcibr_dmamap));
ate_proto = pcibr_flags_to_ate(flags);
@@ -2904,7 +3326,7 @@
/*
* for xbridge the byte-swap bit == bit 29 of PCI address
*/
- if (pcibr_soft->bs_xbridge) {
+ if (IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) {
if (flags & PCIIO_BYTE_STREAM)
ATE_SWAP_ON(pcibr_dmamap->bd_pci_addr);
/*
@@ -2926,18 +3348,19 @@
/* Make sure we have an RRB (or two).
*/
if (!(pcibr_soft->bs_rrb_fixed & (1 << slot))) {
- have_rrbs = pcibr_soft->bs_rrb_valid[slot];
+ have_rrbs = pcibr_soft->bs_rrb_valid[slot][vchan];
if (have_rrbs < 2) {
if (ate_proto & ATE_PREF)
min_rrbs = 2;
else
min_rrbs = 1;
if (have_rrbs < min_rrbs)
- do_pcibr_rrb_autoalloc(pcibr_soft, slot, min_rrbs - have_rrbs);
+ do_pcibr_rrb_autoalloc(pcibr_soft, slot, vchan,
+ min_rrbs - have_rrbs);
}
}
if (ate_index >= pcibr_soft->bs_int_ate_size &&
- !pcibr_soft->bs_xbridge) {
+ !IS_XBRIDGE_OR_PIC_SOFT(pcibr_soft)) {
bridge_t *bridge = pcibr_soft->bs_base;
volatile unsigned *cmd_regp;
unsigned cmd_reg;
@@ -2946,27 +3369,35 @@
pcibr_dmamap->bd_flags |= PCIBR_DMAMAP_SSRAM;
s = pcibr_lock(pcibr_soft);
- cmd_regp = &(bridge->
- b_type0_cfg_dev[slot].
- l[PCI_CFG_COMMAND / 4]);
- cmd_reg = *cmd_regp;
+ cmd_regp = pcibr_slot_config_addr(bridge, slot,
+ PCI_CFG_COMMAND/4);
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ cmd_reg = pcibr_slot_config_get(bridge, slot, PCI_CFG_COMMAND/4);
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ BRIDGE_REG_SET32((&cmd_reg)) = __swab32(*cmd_regp);
+ } else {
+ cmd_reg = pcibr_slot_config_get(bridge, slot, PCI_CFG_COMMAND/4);
+ }
+ }
pcibr_soft->bs_slot[slot].bss_cmd_pointer = cmd_regp;
pcibr_soft->bs_slot[slot].bss_cmd_shadow = cmd_reg;
pcibr_unlock(pcibr_soft, s);
}
return pcibr_dmamap;
}
-#if PCIBR_ATE_DEBUG
- printk("pcibr_dmamap_alloc: unable to use PMU\n");
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pconn_vhdl,
+ "pcibr_dmamap_alloc: PMU use failed, ate_index=%d\n",
+ ate_index));
+
pcibr_ate_free(pcibr_soft, ate_index, ate_count);
}
/* total failure: sorry, you just can't
* get from here to there that way.
*/
-#if PCIBR_ATE_DEBUG
- printk("pcibr_dmamap_alloc: complete failure.\n");
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pconn_vhdl,
+ "pcibr_dmamap_alloc: complete failure.\n"));
xtalk_dmamap_free(xtalk_dmamap);
free_pciio_dmamap(pcibr_dmamap);
return 0;
@@ -2977,7 +3408,8 @@
pcibr_dmamap_free(pcibr_dmamap_t pcibr_dmamap)
{
pcibr_soft_t pcibr_soft = pcibr_dmamap->bd_soft;
- pciio_slot_t slot = pcibr_dmamap->bd_slot;
+ pciio_slot_t slot = PCIBR_SLOT_TO_DEVICE(pcibr_soft,
+ pcibr_dmamap->bd_slot);
unsigned flags = pcibr_dmamap->bd_flags;
@@ -3001,6 +3433,9 @@
pcibr_release_device(pcibr_soft, slot, BRIDGE_DEV_PMU_BITS);
}
+ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_free: pcibr_dmamap=0x%x\n", pcibr_dmamap));
+
free_pciio_dmamap(pcibr_dmamap);
}
@@ -3029,15 +3464,15 @@
pci_addr = xio_addr - BRIDGE_PCI_MEM64_BASE;
return pci_addr;
}
- for (slot = 0; slot < 8; ++slot)
- if ((xio_addr >= BRIDGE_DEVIO(slot)) &&
- (xio_lim < BRIDGE_DEVIO(slot + 1))) {
+ for (slot = soft->bs_min_slot; slot < PCIBR_NUM_SLOTS(soft); ++slot)
+ if ((xio_addr >= PCIBR_BRIDGE_DEVIO(soft, slot)) &&
+ (xio_lim < PCIBR_BRIDGE_DEVIO(soft, slot + 1))) {
bridgereg_t dev;
dev = soft->bs_slot[slot].bss_device;
pci_addr = dev & BRIDGE_DEV_OFF_MASK;
pci_addr <<= BRIDGE_DEV_OFF_ADDR_SHFT;
- pci_addr += xio_addr - BRIDGE_DEVIO(slot);
+ pci_addr += xio_addr - PCIBR_BRIDGE_DEVIO(soft, slot);
return (dev & BRIDGE_DEV_DEV_IO_MEM) ? pci_addr : PCI_NOWHERE;
}
return 0;
@@ -3070,7 +3505,7 @@
} else
xio_port = pcibr_dmamap->bd_xio_port;
- /* If this DMA is to an address that
+ /* If this DMA is to an addres that
* refers back to this Bridge chip,
* reduce it back to the correct
* PCI MEM address.
@@ -3099,14 +3534,12 @@
if (flags & PCIBR_NOPREFETCH)
pci_addr &= ~PCI64_ATTR_PREF;
-#if DEBUG && PCIBR_DMA_DEBUG
- printk("pcibr_dmamap_addr (direct64):\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\tXIO port 0x%x offset 0x%x\n"
- "\treturning PCI 0x%x\n",
- paddr, paddr + req_size - 1,
- xio_port, xio_addr, pci_addr);
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR,
+ pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_addr: (direct64): wanted paddr [0x%x..0x%x] "
+ "XIO port 0x%x offset 0x%x, returning PCI 0x%x\n",
+ paddr, paddr + req_size - 1, xio_port, xio_addr, pci_addr));
+
} else if (flags & PCIIO_FIXED) {
/* A32 direct DMA:
* always use 32-bit direct mapping,
@@ -3126,14 +3559,12 @@
pci_addr = pcibr_dmamap->bd_pci_addr +
xio_addr - pcibr_dmamap->bd_xio_addr;
-#if DEBUG && PCIBR_DMA_DEBUG
- printk("pcibr_dmamap_addr (direct32):\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\tXIO port 0x%x offset 0x%x\n"
- "\treturning PCI 0x%x\n",
- paddr, paddr + req_size - 1,
- xio_port, xio_addr, pci_addr);
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP | PCIBR_DEBUG_DMADIR,
+ pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_addr (direct32): wanted paddr [0x%x..0x%x] "
+ "XIO port 0x%x offset 0x%x, returning PCI 0x%x\n",
+ paddr, paddr + req_size - 1, xio_port, xio_addr, pci_addr));
+
} else {
bridge_t *bridge = pcibr_soft->bs_base;
iopaddr_t offset = IOPGOFF(xio_addr);
@@ -3148,14 +3579,6 @@
int ate_total = ate_count;
unsigned freeze_time;
#endif
-
-#if PCIBR_ATE_DEBUG
- bridge_ate_t ate_cmp;
- bridge_ate_p ate_cptr;
- unsigned ate_lo, ate_hi;
- int ate_bad = 0;
- int ate_rbc = 0;
-#endif
bridge_ate_p ate_ptr = pcibr_dmamap->bd_ate_ptr;
bridge_ate_t ate;
@@ -3183,7 +3606,21 @@
ATE_FREEZE();
ATE_WRITE();
ATE_THAW();
- bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ BRIDGE_REG_GET32((&bridge->b_wid_tflush));
+ } else {
+ bridge->b_wid_tflush;
+ }
+ }
+ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_addr (PMU) : wanted paddr "
+ "[0x%x..0x%x] returning PCI 0x%x\n",
+ paddr, paddr + req_size - 1, pci_addr));
+
} else {
/* The number of ATE's required is greater than the number
* allocated for this map. One way this can happen is if
@@ -3193,14 +3630,12 @@
* The other possibility is that the map is just plain too
* small to handle the requested target area.
*/
-#if PCIBR_ATE_DEBUG
- printk(KERN_WARNING "pcibr_dmamap_addr :\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\tate_count 0x%x bd_ate_count 0x%x\n"
- "\tATE's required > number allocated\n",
- paddr, paddr + req_size - 1,
- ate_count, pcibr_dmamap->bd_ate_count);
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_addr (PMU) : wanted paddr "
+ "[0x%x..0x%x] ate_count 0x%x bd_ate_count 0x%x "
+ "ATE's required > number allocated\n",
+ paddr, paddr + req_size - 1,
+ ate_count, pcibr_dmamap->bd_ate_count));
pci_addr = 0;
}
@@ -3250,17 +3685,24 @@
xtalk_alenlist = xtalk_dmamap_list(pcibr_dmamap->bd_xtalk, palenlist,
flags & DMAMAP_FLAGS);
- if (!xtalk_alenlist)
+ if (!xtalk_alenlist) {
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_list: xtalk_dmamap_list() failed, "
+ "pcibr_dmamap=0x%x\n", pcibr_dmamap));
goto fail;
-
+ }
alenlist_cursor_init(xtalk_alenlist, 0, NULL);
if (inplace) {
pciio_alenlist = xtalk_alenlist;
} else {
pciio_alenlist = alenlist_create(al_flags);
- if (!pciio_alenlist)
+ if (!pciio_alenlist) {
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_list: alenlist_create() failed, "
+ "pcibr_dmamap=0x%lx\n", (unsigned long)pcibr_dmamap));
goto fail;
+ }
}
direct64 = pcibr_dmamap->bd_flags & PCIIO_DMA_A64;
@@ -3286,8 +3728,12 @@
if (xio_port == pcibr_soft->bs_xid) {
new_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, length);
- if (new_addr == PCI_NOWHERE)
+ if (new_addr == PCI_NOWHERE) {
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_list: pcibr_addr_xio_to_pci failed, "
+ "pcibr_dmamap=0x%x\n", pcibr_dmamap));
goto fail;
+ }
} else if (direct64) {
new_addr = pci_addr | xio_addr
| ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT);
@@ -3318,9 +3764,8 @@
| (xio_port << ATE_TIDSHIFT)
| (xio_addr - offset);
if (ate == ate_prev) {
-#if PCIBR_ATE_DEBUG
- printk("pcibr_dmamap_list: ATE share\n");
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_ATE, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_list: ATE share\n"));
ate_ptr--;
ate_index--;
pci_addr -= IOPGSIZE;
@@ -3335,14 +3780,13 @@
/* Ensure that this map contains enough ATE's */
if (ate_total > pcibr_dmamap->bd_ate_count) {
-#if PCIBR_ATE_DEBUG
- printk(KERN_WARNING "pcibr_dmamap_list :\n"
- "\twanted xio_addr [0x%x..0x%x]\n"
- "\tate_total 0x%x bd_ate_count 0x%x\n"
- "\tATE's required > number allocated\n",
- xio_addr, xio_addr + length - 1,
- ate_total, pcibr_dmamap->bd_ate_count);
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_ATE, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_list :\n"
+ "\twanted xio_addr [0x%x..0x%x]\n"
+ "\tate_total 0x%x bd_ate_count 0x%x\n"
+ "\tATE's required > number allocated\n",
+ xio_addr, xio_addr + length - 1,
+ ate_total, pcibr_dmamap->bd_ate_count));
goto fail;
}
@@ -3362,13 +3806,22 @@
if (inplace) {
if (ALENLIST_SUCCESS !=
alenlist_replace(pciio_alenlist, NULL,
- &new_addr, &length, al_flags))
+ &new_addr, &length, al_flags)) {
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_list: alenlist_replace() failed, "
+ "pcibr_dmamap=0x%x\n", pcibr_dmamap));
+
goto fail;
+ }
} else {
if (ALENLIST_SUCCESS !=
alenlist_append(pciio_alenlist,
- new_addr, length, al_flags))
+ new_addr, length, al_flags)) {
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_list: alenlist_append() failed, "
+ "pcibr_dmamap=0x%x\n", pcibr_dmamap));
goto fail;
+ }
}
}
if (!inplace)
@@ -3386,8 +3839,21 @@
*/
if (ate_freeze_done) {
ATE_THAW();
- bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ BRIDGE_REG_GET32((&bridge->b_wid_tflush));
+ } else {
+ bridge->b_wid_tflush;
+ }
+ }
}
+ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_list: pcibr_dmamap=0x%x, pciio_alenlist=0x%x\n",
+ pcibr_dmamap, pciio_alenlist));
+
return pciio_alenlist;
fail:
@@ -3398,7 +3864,16 @@
*/
if (ate_freeze_done) {
ATE_THAW();
- bridge->b_wid_tflush;
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ bridge->b_wid_tflush;
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ BRIDGE_REG_GET32((&bridge->b_wid_tflush));
+ } else {
+ bridge->b_wid_tflush;
+ }
+ }
}
if (pciio_alenlist && !inplace)
alenlist_destroy(pciio_alenlist);
@@ -3409,6 +3884,10 @@
void
pcibr_dmamap_done(pcibr_dmamap_t pcibr_dmamap)
{
+#ifdef PIC_LATER
+ pcibr_soft_t pcibr_soft = pcibr_dmamap->bd_soft;
+ pciio_slot_t slot = PCIBR_SLOT_TO_DEVICE(pcibr_soft,
+#endif
/*
* We could go through and invalidate ATEs here;
* for performance reasons, we don't.
@@ -3423,6 +3902,9 @@
atomic_dec(&(pcibr_dmamap->bd_soft->bs_slot[pcibr_dmamap->bd_slot]. bss_ext_ates_active));
}
xtalk_dmamap_done(pcibr_dmamap->bd_xtalk);
+
+ PCIBR_DEBUG((PCIBR_DEBUG_DMAMAP, pcibr_dmamap->bd_dev,
+ "pcibr_dmamap_done: pcibr_dmamap=0x%x\n", pcibr_dmamap));
}
@@ -3455,7 +3937,7 @@
pciio_info_t pciio_info = pciio_info_get(pconn_vhdl);
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn;
- pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+ pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft_slot_t slotp = &pcibr_soft->bs_slot[pciio_slot];
xwidgetnum_t xio_port;
@@ -3464,6 +3946,7 @@
int have_rrbs;
int min_rrbs;
+ int vchan = VCHAN0;
/* merge in forced flags */
flags |= pcibr_soft->bs_dma_flags;
@@ -3471,16 +3954,10 @@
xio_addr = xtalk_dmatrans_addr(xconn_vhdl, 0, paddr, req_size,
flags & DMAMAP_FLAGS);
if (!xio_addr) {
-#if PCIBR_DMA_DEBUG
- printk("pcibr_dmatrans_addr:\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr);
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xtalk_dmatrans_addr failed with 0x%x\n",
+ paddr, paddr + req_size - 1, xio_addr));
return 0;
}
/*
@@ -3488,16 +3965,10 @@
*/
if (XIO_PACKED(xio_addr)) {
if (xio_addr == XIO_NOWHERE) {
-#if PCIBR_DMA_DEBUG
- printk("pcibr_dmatrans_addr:\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr);
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xtalk_dmatrans_addr failed with XIO_NOWHERE\n",
+ paddr, paddr + req_size - 1));
return 0;
}
xio_port = XIO_PORT(xio_addr);
@@ -3515,6 +3986,10 @@
*/
if (xio_port == pcibr_soft->bs_xid) {
pci_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, req_size);
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xio_port=0x%x, pci_addr=0x%x\n",
+ paddr, paddr + req_size - 1, xio_port, pci_addr));
return pci_addr;
}
/* If the caller can use A64, try to
@@ -3531,92 +4006,65 @@
if ((pci_addr != PCIBR_D64_BASE_UNSET) &&
(flags == slotp->bss_d64_flags)) {
-#ifdef CONFIG_IA64_SGI_SN2
- pci_addr |= (PHYS_TO_DMA(xio_addr))
- | ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT);
-#else
pci_addr |= xio_addr
| ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT);
-#endif
-#if DEBUG && PCIBR_DMA_DEBUG
#if HWG_PERF_CHECK
if (xio_addr != 0x20000000)
#endif
- printk("pcibr_dmatrans_addr: [reuse]\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n"
- "\tdirect 64bit address is 0x%x\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr, pci_addr);
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xio_port=0x%x, direct64: pci_addr=0x%x\n",
+ paddr, paddr + req_size - 1, xio_addr, pci_addr));
return (pci_addr);
}
if (!pcibr_try_set_device(pcibr_soft, pciio_slot, flags, BRIDGE_DEV_D64_BITS)) {
pci_addr = pcibr_flags_to_d64(flags, pcibr_soft);
slotp->bss_d64_flags = flags;
slotp->bss_d64_base = pci_addr;
-#ifdef CONFIG_IA64_SGI_SN2
- pci_addr |= (PHYS_TO_DMA(xio_addr))
- | ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT);
-#else
pci_addr |= xio_addr
| ((uint64_t) xio_port << PCI64_ATTR_TARG_SHFT);
-#endif
- /* Make sure we have an RRB (or two).
+ /* If in PCI mode, make sure we have an RRB (or two).
*/
- if (!(pcibr_soft->bs_rrb_fixed & (1 << pciio_slot))) {
+ if (IS_PCI(pcibr_soft) &&
+ !(pcibr_soft->bs_rrb_fixed & (1 << pciio_slot))) {
if (flags & PCIBR_VCHAN1)
- pciio_slot += PCIBR_RRB_SLOT_VIRTUAL;
- have_rrbs = pcibr_soft->bs_rrb_valid[pciio_slot];
+ vchan = VCHAN1;
+ have_rrbs = pcibr_soft->bs_rrb_valid[pciio_slot][vchan];
if (have_rrbs < 2) {
if (pci_addr & PCI64_ATTR_PREF)
min_rrbs = 2;
else
min_rrbs = 1;
if (have_rrbs < min_rrbs)
- do_pcibr_rrb_autoalloc(pcibr_soft, pciio_slot, min_rrbs - have_rrbs);
+ do_pcibr_rrb_autoalloc(pcibr_soft, pciio_slot, vchan,
+ min_rrbs - have_rrbs);
}
}
-#if PCIBR_DMA_DEBUG
#if HWG_PERF_CHECK
if (xio_addr != 0x20000000)
#endif
- printk("pcibr_dmatrans_addr:\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n"
- "\tdirect 64bit address is 0x%x\n"
- "\tnew flags: 0x%x\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr, pci_addr, (uint64_t) flags);
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xio_port=0x%x, direct64: pci_addr=0x%x, "
+ "new flags: 0x%x\n", paddr, paddr + req_size - 1,
+ xio_addr, pci_addr, (uint64_t) flags));
return (pci_addr);
}
- /* our flags conflict with Device(x).
- */
- flags = flags
- & ~PCIIO_DMA_A64
- & ~PCIBR_VCHAN0
- ;
-#if PCIBR_DMA_DEBUG
- printk("pcibr_dmatrans_addr:\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n"
- "\tUnable to set Device(x) bits for Direct-64\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr);
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xio_port=0x%x, Unable to set direct64 Device(x) bits\n",
+ paddr, paddr + req_size - 1, xio_addr));
+
+ /* PIC only supports 64-bit direct mapping in PCI-X mode */
+ if (IS_PCIX(pcibr_soft)) {
+ return 0;
+ }
+
+ /* our flags conflict with Device(x). try direct32*/
+ flags = flags & ~(PCIIO_DMA_A64 | PCIBR_VCHAN0);
}
/* Try to satisfy the request with the 32-bit direct
* map. This can fail if the configuration bits in
@@ -3633,17 +4081,11 @@
(xio_addr < xio_base) ||
(xio_port != pcibr_soft->bs_dir_xport) ||
(endoff > map_size)) {
-#if PCIBR_DMA_DEBUG
- printk("pcibr_dmatrans_addr:\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n"
- "\txio region outside direct32 target\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr);
-#endif
+
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xio_port=0x%x, xio region outside direct32 target\n",
+ paddr, paddr + req_size - 1, xio_addr));
} else {
pci_addr = slotp->bss_d32_base;
if ((pci_addr != PCIBR_D32_BASE_UNSET) &&
@@ -3651,18 +4093,11 @@
pci_addr |= offset;
-#if DEBUG && PCIBR_DMA_DEBUG
- printk("pcibr_dmatrans_addr: [reuse]\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n"
- "\tmapped via direct32 offset 0x%x\n"
- "\twill DMA via pci addr 0x%x\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr, offset, pci_addr);
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xio_port=0x%x, direct32: pci_addr=0x%x\n",
+ paddr, paddr + req_size - 1, xio_addr, pci_addr));
+
return (pci_addr);
}
if (!pcibr_try_set_device(pcibr_soft, pciio_slot, flags, BRIDGE_DEV_D32_BITS)) {
@@ -3675,61 +4110,41 @@
/* Make sure we have an RRB (or two).
*/
if (!(pcibr_soft->bs_rrb_fixed & (1 << pciio_slot))) {
- have_rrbs = pcibr_soft->bs_rrb_valid[pciio_slot];
+ have_rrbs = pcibr_soft->bs_rrb_valid[pciio_slot][vchan];
if (have_rrbs < 2) {
if (slotp->bss_device & BRIDGE_DEV_PREF)
min_rrbs = 2;
else
min_rrbs = 1;
if (have_rrbs < min_rrbs)
- do_pcibr_rrb_autoalloc(pcibr_soft, pciio_slot, min_rrbs - have_rrbs);
+ do_pcibr_rrb_autoalloc(pcibr_soft, pciio_slot,
+ vchan, min_rrbs - have_rrbs);
}
}
-#if PCIBR_DMA_DEBUG
#if HWG_PERF_CHECK
if (xio_addr != 0x20000000)
#endif
- printk("pcibr_dmatrans_addr:\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n"
- "\tmapped via direct32 offset 0x%x\n"
- "\twill DMA via pci addr 0x%x\n"
- "\tnew flags: 0x%x\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr, offset, pci_addr, (uint64_t) flags);
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xio_port=0x%x, direct32: pci_addr=0x%x, "
+ "new flags: 0x%x\n", paddr, paddr + req_size - 1,
+ xio_addr, pci_addr, (uint64_t) flags));
+
return (pci_addr);
}
/* our flags conflict with Device(x).
*/
-#if PCIBR_DMA_DEBUG
- printk("pcibr_dmatrans_addr:\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n"
- "\tUnable to set Device(x) bits for Direct-32\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr);
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xio_port=0x%x, Unable to set direct32 Device(x) bits\n",
+ paddr, paddr + req_size - 1, xio_port));
}
}
-#if PCIBR_DMA_DEBUG
- printk("pcibr_dmatrans_addr:\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n"
- "\tno acceptable PCI address found or constructable\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr);
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_addr: wanted paddr [0x%x..0x%x], "
+ "xio_port=0x%x, No acceptable PCI address found\n",
+ paddr, paddr + req_size - 1, xio_port));
return 0;
}
@@ -3744,7 +4159,7 @@
pciio_info_t pciio_info = pciio_info_get(pconn_vhdl);
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
devfs_handle_t xconn_vhdl = pcibr_soft->bs_conn;
- pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+ pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft_slot_t slotp = &pcibr_soft->bs_slot[pciio_slot];
xwidgetnum_t xio_port;
@@ -3781,6 +4196,9 @@
/* reuse previous base info */
} else if (pcibr_try_set_device(pcibr_soft, pciio_slot, flags, BRIDGE_DEV_D64_BITS) < 0) {
/* DMA configuration conflict */
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_list: DMA configuration conflict "
+ "for direct64, flags=0x%x\n", flags));
goto fail;
} else {
relbits = BRIDGE_DEV_D64_BITS;
@@ -3796,6 +4214,9 @@
/* reuse previous base info */
} else if (pcibr_try_set_device(pcibr_soft, pciio_slot, flags, BRIDGE_DEV_D32_BITS) < 0) {
/* DMA configuration conflict */
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_list: DMA configuration conflict "
+ "for direct32, flags=0x%x\n", flags));
goto fail;
} else {
relbits = BRIDGE_DEV_D32_BITS;
@@ -3805,8 +4226,12 @@
xtalk_alenlist = xtalk_dmatrans_list(xconn_vhdl, 0, palenlist,
flags & DMAMAP_FLAGS);
- if (!xtalk_alenlist)
+ if (!xtalk_alenlist) {
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_list: xtalk_dmatrans_list failed "
+ "xtalk_alenlist=0x%x\n", xtalk_alenlist));
goto fail;
+ }
alenlist_cursor_init(xtalk_alenlist, 0, NULL);
@@ -3814,8 +4239,12 @@
pciio_alenlist = xtalk_alenlist;
} else {
pciio_alenlist = alenlist_create(al_flags);
- if (!pciio_alenlist)
+ if (!pciio_alenlist) {
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_list: alenlist_create failed with "
+ " 0x%x\n", pciio_alenlist));
goto fail;
+ }
}
while (ALENLIST_SUCCESS ==
@@ -3827,16 +4256,8 @@
*/
if (XIO_PACKED(xio_addr)) {
if (xio_addr == XIO_NOWHERE) {
-#if PCIBR_DMA_DEBUG
- printk("pcibr_dmatrans_addr:\n"
- "\tpciio connection point %v\n"
- "\txtalk connection point %v\n"
- "\twanted paddr [0x%x..0x%x]\n"
- "\txtalk_dmatrans_addr returned 0x%x\n",
- pconn_vhdl, xconn_vhdl,
- paddr, paddr + req_size - 1,
- xio_addr);
-#endif
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_list: xio_addr == XIO_NOWHERE\n"));
return 0;
}
xio_port = XIO_PORT(xio_addr);
@@ -3853,8 +4274,12 @@
*/
if (xio_port == pcibr_soft->bs_xid) {
pci_addr = pcibr_addr_xio_to_pci(pcibr_soft, xio_addr, xio_size);
- if ( (pci_addr == (alenaddr_t)NULL) )
+ if (pci_addr == (alenaddr_t)NULL) {
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_list: pcibr_addr_xio_to_pci failed "
+ "xio_addr=0x%x, xio_size=0x%x\n", xio_addr, xio_size));
goto fail;
+ }
} else if (direct64) {
ASSERT(xio_port != 0);
pci_addr = pci_base | xio_addr
@@ -3866,8 +4291,14 @@
if ((xio_size > map_size) ||
(xio_addr < xio_base) ||
(xio_port != pcibr_soft->bs_dir_xport) ||
- (endoff > map_size))
+ (endoff > map_size)) {
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_list: xio_size > map_size fail\n"
+ "xio_addr=0x%x, xio_size=0x%x. map_size=0x%x, "
+ "xio_port=0x%x, endoff=0x%x\n",
+ xio_addr, xio_size, map_size, xio_port, endoff));
goto fail;
+ }
pci_addr = pci_base + (xio_addr - xio_base);
}
@@ -3878,13 +4309,19 @@
if (inplace) {
if (ALENLIST_SUCCESS !=
alenlist_replace(pciio_alenlist, NULL,
- &pci_addr, &xio_size, al_flags))
+ &pci_addr, &xio_size, al_flags)) {
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_list: alenlist_replace failed\n"));
goto fail;
+ }
} else {
if (ALENLIST_SUCCESS !=
alenlist_append(pciio_alenlist,
- pci_addr, xio_size, al_flags))
+ pci_addr, xio_size, al_flags)) {
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_list: alenlist_append failed\n"));
goto fail;
+ }
}
}
@@ -3904,6 +4341,11 @@
* to the caller.
*/
alenlist_cursor_init(pciio_alenlist, 0, NULL);
+
+ PCIBR_DEBUG((PCIBR_DEBUG_DMADIR, pconn_vhdl,
+ "pcibr_dmatrans_list: pciio_alenlist=0x%x\n",
+ pciio_alenlist));
+
return pciio_alenlist;
fail:
@@ -3973,8 +4415,9 @@
int
pcibr_reset(devfs_handle_t conn)
{
+#ifdef PIC_LATER
pciio_info_t pciio_info = pciio_info_get(conn);
- pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+ pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
bridge_t *bridge = pcibr_soft->bs_base;
bridgereg_t ctlreg;
@@ -3984,42 +4427,59 @@
pcibr_info_h pcibr_infoh;
pcibr_info_t pcibr_info;
int win;
+ int error = 0;
+#endif /* PIC_LATER */
+ BUG();
+#ifdef PIC_LATER
if (pcibr_soft->bs_slot[pciio_slot].has_host) {
pciio_slot = pcibr_soft->bs_slot[pciio_slot].host_slot;
pcibr_info = pcibr_soft->bs_slot[pciio_slot].bss_infos[0];
}
- if (pciio_slot < 4) {
+
+ if ((pciio_slot >= pcibr_soft->bs_first_slot) &&
+ (pciio_slot <= pcibr_soft->bs_last_reset)) {
s = pcibr_lock(pcibr_soft);
nf = pcibr_soft->bs_slot[pciio_slot].bss_ninfo;
pcibr_infoh = pcibr_soft->bs_slot[pciio_slot].bss_infos;
for (f = 0; f < nf; ++f)
if (pcibr_infoh[f])
- cfgctl[f] = bridge->b_type0_cfg_dev[pciio_slot].f[f].l[PCI_CFG_COMMAND / 4];
+ cfgctl[f] = pcibr_func_config_get(bridge, pciio_slot, f,
+ PCI_CFG_COMMAND/4);
+
+ error = iobrick_pci_slot_rst(pcibr_soft->bs_l1sc,
+ pcibr_widget_to_bus(pcibr_soft->bs_vhdl),
+ PCIBR_DEVICE_TO_SLOT(pcibr_soft,pciio_slot),
+ NULL);
ctlreg = bridge->b_wid_control;
- bridge->b_wid_control = ctlreg | BRIDGE_CTRL_RST(pciio_slot);
- /* XXX delay? */
- bridge->b_wid_control = ctlreg;
- /* XXX delay? */
+ bridge->b_wid_control = ctlreg & ~BRIDGE_CTRL_RST_PIN(pciio_slot);
+ nano_delay(&ts);
+ bridge->b_wid_control = ctlreg | BRIDGE_CTRL_RST_PIN(pciio_slot);
+ nano_delay(&ts);
for (f = 0; f < nf; ++f)
if ((pcibr_info = pcibr_infoh[f]))
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] =
- pcibr_info->f_window[win].w_base;
+ pcibr_func_config_set(bridge, pciio_slot, f,
+ PCI_CFG_BASE_ADDR(win) / 4,
+ pcibr_info->f_window[win].w_base);
for (f = 0; f < nf; ++f)
if (pcibr_infoh[f])
- bridge->b_type0_cfg_dev[pciio_slot].f[f].l[PCI_CFG_COMMAND / 4] = cfgctl[f];
+ pcibr_func_config_set(bridge, pciio_slot, f,
+ PCI_CFG_COMMAND / 4,
+ cfgctl[f]);
pcibr_unlock(pcibr_soft, s);
+ if (error)
+ return(-1);
+
return 0;
}
-#ifdef SUPPORT_PRINTING_V_FORMAT
- printk(KERN_WARNING "%v: pcibr_reset unimplemented for slot %d\n",
- conn, pciio_slot);
-#endif
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DETACH, conn,
+ "pcibr_reset unimplemented for slot %d\n", conn, pciio_slot));
+#endif /* PIC_LATER */
return -1;
}
@@ -4029,7 +4489,7 @@
pciio_endian_t desired_end)
{
pciio_info_t pciio_info = pciio_info_get(pconn_vhdl);
- pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+ pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
bridgereg_t devreg;
unsigned long s;
@@ -4053,16 +4513,32 @@
if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) {
bridge_t *bridge = pcibr_soft->bs_base;
- bridge->b_device[pciio_slot].reg = devreg;
- pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
- bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ bridge->b_device[pciio_slot].reg = devreg;
+ pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ BRIDGE_REG_SET32((&bridge->b_device[pciio_slot].reg)) = __swab32(devreg);
+ pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
+ BRIDGE_REG_GET32((&bridge->b_wid_tflush));/* wait until Bridge PIO complete */
+ } else {
+ bridge->b_device[pciio_slot].reg = devreg;
+ pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ }
}
pcibr_unlock(pcibr_soft, s);
-#if DEBUG && PCIBR_DEV_DEBUG
- printk("pcibr Device(%d): 0x%p\n", pciio_slot, bridge->b_device[pciio_slot].reg);
+#ifdef PIC_LATER
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DEVREG, pconn_vhdl,
+ "pcibr_endian_set: Device(%d): %x\n",
+ pciio_slot, devreg, device_bits));
+#else
+ printk("pcibr_endian_set: Device(%d): %x\n", pciio_slot, devreg);
#endif
-
return desired_end;
}
@@ -4130,9 +4606,22 @@
if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) {
bridge_t *bridge = pcibr_soft->bs_base;
- bridge->b_device[pciio_slot].reg = devreg;
- pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
- bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ bridge->b_device[pciio_slot].reg = devreg;
+ pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ BRIDGE_REG_SET32((&bridge->b_device[pciio_slot].reg)) = __swab32(devreg);
+ pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
+ BRIDGE_REG_GET32((&bridge->b_wid_tflush));/* wait until Bridge PIO complete */
+ } else {
+ bridge->b_device[pciio_slot].reg = devreg;
+ pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ }
}
pcibr_unlock(pcibr_soft, s);
@@ -4144,7 +4633,7 @@
pciio_priority_t device_prio)
{
pciio_info_t pciio_info = pciio_info_get(pconn_vhdl);
- pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+ pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
(void) pcibr_priority_bits_set(pcibr_soft, pciio_slot, device_prio);
@@ -4168,7 +4657,7 @@
pcibr_device_flags_t flags)
{
pciio_info_t pciio_info = pciio_info_get(pconn_vhdl);
- pciio_slot_t pciio_slot = pciio_info_slot_get(pciio_info);
+ pciio_slot_t pciio_slot = PCIBR_INFO_SLOT_GET_INT(pciio_info);
pcibr_soft_t pcibr_soft = (pcibr_soft_t) pciio_info_mfast_get(pciio_info);
bridgereg_t set = 0;
bridgereg_t clr = 0;
@@ -4215,18 +4704,81 @@
if (pcibr_soft->bs_slot[pciio_slot].bss_device != devreg) {
bridge_t *bridge = pcibr_soft->bs_base;
- bridge->b_device[pciio_slot].reg = devreg;
- pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
- bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ if ( IS_PIC_SOFT(pcibr_soft) ) {
+ bridge->b_device[pciio_slot].reg = devreg;
+ pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ else {
+ if (io_get_sh_swapper(NASID_GET(bridge))) {
+ BRIDGE_REG_SET32((&bridge->b_device[pciio_slot].reg)) = __swab32(devreg);
+ pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
+ BRIDGE_REG_GET32((&bridge->b_wid_tflush));/* wait until Bridge PIO complete */
+ } else {
+ bridge->b_device[pciio_slot].reg = devreg;
+ pcibr_soft->bs_slot[pciio_slot].bss_device = devreg;
+ bridge->b_wid_tflush; /* wait until Bridge PIO complete */
+ }
+ }
}
pcibr_unlock(pcibr_soft, s);
-#if DEBUG && PCIBR_DEV_DEBUG
- printk("pcibr Device(%d): %R\n", pciio_slot, bridge->b_device[pciio_slot].regbridge->b_device[pciio_slot].reg, device_bits);
+#ifdef PIC_LATER
+ PCIBR_DEBUG_ALWAYS((PCIBR_DEBUG_DEVREG, pconn_vhdl,
+ "pcibr_device_flags_set: Device(%d): %x\n",
+ pciio_slot, devreg, device_bits));
+#else
+ printk("pcibr_device_flags_set: Device(%d): %x\n", pciio_slot, devreg);
#endif
}
return (1);
}
+/*
+ * PIC has 16 RBARs per bus; meaning it can have a total of 16 outstanding
+ * split transactions. If the functions on the bus have requested a total
+ * of 16 or less, then we can give them what they requested (ie. 100%).
+ * Otherwise we have make sure each function can get at least one buffer
+ * and then divide the rest of the buffers up among the functions as ``A
+ * PERCENTAGE OF WHAT THEY REQUESTED'' (i.e. 0% - 100% of a function's
+ * pcix_type0_status.max_out_split). This percentage does not include the
+ * one RBAR that all functions get by default.
+ */
+int
+pcibr_pcix_rbars_calc(pcibr_soft_t pcibr_soft)
+{
+ /* 'percent_allowed' is the percentage of requested RBARs that functions
+ * are allowed, ***less the 1 RBAR that all functions get by default***
+ */
+ int percent_allowed;
+
+ if (pcibr_soft->bs_pcix_num_funcs) {
+ if (pcibr_soft->bs_pcix_num_funcs > NUM_RBAR) {
+ printk(KERN_WARNING
+ "%lx: Must oversubscribe Read Buffer Attribute Registers"
+ "(RBAR). Bus has %d RBARs but %d funcs need them.\n",
+ (unsigned long)pcibr_soft->bs_vhdl, NUM_RBAR, pcibr_soft->bs_pcix_num_funcs);
+ percent_allowed = 0;
+ } else {
+ percent_allowed = (((NUM_RBAR-pcibr_soft->bs_pcix_num_funcs)*100) /
+ pcibr_soft->bs_pcix_split_tot);
+
+ /* +1 to percentage to solve rounding errors that occur because
+ * we're not doing fractional math. (ie. ((3 * 66%) / 100) = 1)
+ * but should be "2" if doing true fractional math. NOTE: Since
+ * the greatest number of outstanding transactions a function
+ * can request is 32, this "+1" will always work (i.e. we won't
+ * accidentally oversubscribe the RBARs because of this rounding
+ * of the percentage).
+ */
+ percent_allowed=(percent_allowed > 100) ? 100 : percent_allowed+1;
+ }
+ } else {
+ return(ENODEV);
+ }
+
+ return(percent_allowed);
+}
+
pciio_provider_t pcibr_provider =
{
(pciio_piomap_alloc_f *) pcibr_piomap_alloc,
@@ -4262,17 +4814,17 @@
(pciio_priority_set_f *) pcibr_priority_set,
(pciio_config_get_f *) pcibr_config_get,
(pciio_config_set_f *) pcibr_config_set,
-
- (pciio_error_devenable_f *) 0,
- (pciio_error_extract_f *) 0,
-
-#ifdef LATER
+#ifdef PIC_LATER
+ (pciio_error_devenable_f *) pcibr_error_devenable,
+ (pciio_error_extract_f *) pcibr_error_extract,
(pciio_driver_reg_callback_f *) pcibr_driver_reg_callback,
(pciio_driver_unreg_callback_f *) pcibr_driver_unreg_callback,
#else
+ (pciio_error_devenable_f *) 0,
+ (pciio_error_extract_f *) 0,
(pciio_driver_reg_callback_f *) 0,
(pciio_driver_unreg_callback_f *) 0,
-#endif
+#endif /* PIC_LATER */
(pciio_device_unregister_f *) pcibr_device_unregister,
(pciio_dma_enabled_f *) pcibr_dma_enabled,
};
@@ -4286,3 +4838,83 @@
return xtalk_dma_enabled(pcibr_soft->bs_conn);
}
+
+
+/*
+ * pcibr_debug() is used to print pcibr debug messages to the console. A
+ * user enables tracing by setting the following global variables:
+ *
+ * pcibr_debug_mask -Bitmask of what to trace. see pcibr_private.h
+ * pcibr_debug_module -Module to trace. 'all' means trace all modules
+ * pcibr_debug_widget -Widget to trace. '-1' means trace all widgets
+ * pcibr_debug_slot -Slot to trace. '-1' means trace all slots
+ *
+ * 'type' is the type of debugging that the current PCIBR_DEBUG macro is
+ * tracing. 'vhdl' (which can be NULL) is the vhdl associated with the
+ * debug statement. If there is a 'vhdl' associated with this debug
+ * statement, it is parsed to obtain the module, widget, and slot. If the
+ * globals above match the PCIBR_DEBUG params, then the debug info in the
+ * parameter 'format' is sent to the console.
+ */
+void
+pcibr_debug(uint32_t type, devfs_handle_t vhdl, char *format, ...)
+{
+ char hwpath[MAXDEVNAME] = "\0";
+ char copy_of_hwpath[MAXDEVNAME];
+ char *module = "all";
+ short widget = -1;
+ short slot = -1;
+ va_list ap;
+ char *strtok_r(char *string, const char *sepset, char **lasts);
+
+ if (pcibr_debug_mask & type) {
+ if (vhdl) {
+ if (!hwgraph_vertex_name_get(vhdl, hwpath, MAXDEVNAME)) {
+ char *cp;
+
+ if (strcmp(module, pcibr_debug_module)) {
+ /* strtok_r() wipes out string, use a copy */
+ (void)strcpy(copy_of_hwpath, hwpath);
+ cp = strstr(copy_of_hwpath, "/module/");
+ if (cp) {
+ char *last = NULL;
+ cp += strlen("/module");
+ module = strtok_r(cp, "/", &last);
+ }
+ }
+ if (pcibr_debug_widget != -1) {
+ cp = strstr(hwpath, "/xtalk/");
+ if (cp) {
+ cp += strlen("/xtalk/");
+ widget = atoi(cp);
+ }
+ }
+ if (pcibr_debug_slot != -1) {
+ cp = strstr(hwpath, "/pci/");
+ if (cp) {
+ cp += strlen("/pci/");
+ slot = atoi(cp);
+ }
+ }
+ }
+ }
+ if ((vhdl == NULL) ||
+ (!strcmp(module, pcibr_debug_module) &&
+ (widget == pcibr_debug_widget) &&
+ (slot == pcibr_debug_slot))) {
+#ifdef LATER
+ printk("PCIBR_DEBUG<%d>\t: %s :", cpuid(), hwpath);
+#else
+ printk("PCIBR_DEBUG\t: %s :", hwpath);
+#endif
+ /*
+ * Kernel printk translates to this 3 line sequence.
+ * Since we have a variable length argument list, we
+ * need to call printk this way rather than directly
+ */
+ va_start(ap, format);
+ printk(format, ap);
+ va_end(ap);
+ }
+ }
+}
FUNET's LINUX-ADM group, linux-adm@nic.funet.fi
TCL-scripts by Sam Shen (who was at: slshen@lbl.gov)