📄 pcibr_dvr.c
字号:
/* * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details. * * Copyright (C) 2001-2002 Silicon Graphics, Inc. All rights reserved. */#include <linux/types.h>#include <linux/slab.h>#include <linux/module.h>#include <asm/sn/sgi.h>#include <asm/sn/sn_cpuid.h>#include <asm/sn/addrs.h>#include <asm/sn/arch.h>#include <asm/sn/iograph.h>#include <asm/sn/invent.h>#include <asm/sn/hcl.h>#include <asm/sn/labelcl.h>#include <asm/sn/xtalk/xwidget.h>#include <asm/sn/pci/bridge.h>#include <asm/sn/pci/pciio.h>#include <asm/sn/pci/pcibr.h>#include <asm/sn/pci/pcibr_private.h>#include <asm/sn/pci/pci_defs.h>#include <asm/sn/prio.h>#include <asm/sn/xtalk/xbow.h>#include <asm/sn/ioc3.h>#include <asm/sn/eeprom.h>#include <asm/sn/io.h>#include <asm/sn/sn_private.h>#ifdef __ia64#define rmallocmap atemapalloc#define rmfreemap atemapfree#define rmfree atefree#define rmalloc atealloc#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 * 1ms, so we need to set up bridges holding this part to allow at least * 1ms for pio. */#define USS302_TIMEOUT_WAR#ifdef USS302_TIMEOUT_WAR#define LUCENT_USBHC_VENDOR_ID_NUM 0x11c1#define LUCENT_USBHC302_DEVICE_ID_NUM 0x5801#define LUCENT_USBHC312_DEVICE_ID_NUM 0x5802#define USS302_BRIDGE_TIMEOUT_HLD 4#endifint pcibr_devflag = D_MP;/* * This is the file operation table for the pcibr driver. * As each of the functions are implemented, put the * appropriate function name below. */struct file_operations pcibr_fops = { owner: THIS_MODULE, llseek: NULL, read: NULL, write: NULL, readdir: NULL, poll: NULL, ioctl: NULL, mmap: NULL, open: NULL, flush: NULL, release: NULL, fsync: NULL, fasync: NULL, lock: NULL, readv: NULL, writev: NULL};/* kbrick widgetnum-to-bus layout */int p_busnum[MAX_PORT_NUM] = { /* widget# */ 0, 0, 0, 0, 0, 0, 0, 0, /* 0x0 - 0x7 */ 2, /* 0x8 */ 1, /* 0x9 */ 0, 0, /* 0xa - 0xb */ 5, /* 0xc */ 6, /* 0xd */ 4, /* 0xe */ 3, /* 0xf */};#if PCIBR_SOFT_LISTpcibr_list_p pcibr_list = 0;#endifextern int hwgraph_vertex_name_get(devfs_handle_t vhdl, char *buf, uint buflen);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 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(pcibr_soft, ate_ptr, ate_count, ate)#if PCIBR_FREEZE_TIME#define ATE_FREEZE() s = ate_freeze(pcibr_dmamap, &freeze_time, cmd_regs)#else#define ATE_FREEZE() s = ate_freeze(pcibr_dmamap, cmd_regs)#endif /* PCIBR_FREEZE_TIME */#if PCIBR_FREEZE_TIME#define ATE_THAW() ate_thaw(pcibr_dmamap, ate_index, ate, ate_total, freeze_time, cmd_regs, s)#else#define ATE_THAW() ate_thaw(pcibr_dmamap, ate_index, cmd_regs, s)#endif/* ===================================================================== * Function Table of Contents * * The order of functions in this file has stopped * making much sense. We might want to take a look * at it some time and bring back some sanity, or * perhaps bust this file into smaller chunks. */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 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_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 *);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,#if PCIBR_FREEZE_TIME unsigned *freeze_time_ptr,#endif 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,#endif unsigned *cmd_regs, unsigned s);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);pcibr_piomap_t pcibr_piomap_alloc(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, size_t, unsigned);void pcibr_piomap_free(pcibr_piomap_t);caddr_t pcibr_piomap_addr(pcibr_piomap_t, iopaddr_t, size_t);void pcibr_piomap_done(pcibr_piomap_t);caddr_t pcibr_piotrans_addr(devfs_handle_t, device_desc_t, pciio_space_t, iopaddr_t, size_t, unsigned);iopaddr_t pcibr_piospace_alloc(devfs_handle_t, device_desc_t, pciio_space_t, size_t, size_t);void pcibr_piospace_free(devfs_handle_t, pciio_space_t, iopaddr_t, size_t);static iopaddr_t pcibr_flags_to_d64(unsigned, pcibr_soft_t);extern bridge_ate_t pcibr_flags_to_ate(unsigned);pcibr_dmamap_t pcibr_dmamap_alloc(devfs_handle_t, device_desc_t, size_t, unsigned);void pcibr_dmamap_free(pcibr_dmamap_t);extern bridge_ate_p pcibr_ate_addr(pcibr_soft_t, int);static iopaddr_t pcibr_addr_xio_to_pci(pcibr_soft_t, iopaddr_t, size_t);iopaddr_t pcibr_dmamap_addr(pcibr_dmamap_t, paddr_t, size_t);alenlist_t pcibr_dmamap_list(pcibr_dmamap_t, alenlist_t, unsigned);void pcibr_dmamap_done(pcibr_dmamap_t);cnodeid_t pcibr_get_dmatrans_node(devfs_handle_t);iopaddr_t pcibr_dmatrans_addr(devfs_handle_t, device_desc_t, paddr_t, size_t, unsigned);alenlist_t pcibr_dmatrans_list(devfs_handle_t, device_desc_t, alenlist_t, unsigned);void pcibr_dmamap_drain(pcibr_dmamap_t);void pcibr_dmaaddr_drain(devfs_handle_t, paddr_t, size_t);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, 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, 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_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 void pcibr_pioerr_check(pcibr_soft_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);extern void pcibr_device_disable(pcibr_soft_t, int);extern int pcibr_pioerror(pcibr_soft_t, int, ioerror_mode_t, ioerror_t *);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_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);int pcibr_reset(devfs_handle_t);pciio_endian_t pcibr_endian_set(devfs_handle_t, pciio_endian_t, pciio_endian_t);int pcibr_priority_bits_set(pcibr_soft_t, pciio_slot_t, pciio_priority_t);pciio_priority_t pcibr_priority_set(devfs_handle_t, pciio_priority_t);int pcibr_device_flags_set(devfs_handle_t, pcibr_device_flags_t);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 pcibr_hints_t pcibr_hints_get(devfs_handle_t, int);extern void pcibr_hints_fix_rrbs(devfs_handle_t);extern void pcibr_hints_dualslot(devfs_handle_t, pciio_slot_t, pciio_slot_t);extern void pcibr_hints_intr_bits(devfs_handle_t, pcibr_intr_bits_f *);extern void pcibr_set_rrb_callback(devfs_handle_t, rrb_alloc_funct_t);extern void pcibr_hints_handsoff(devfs_handle_t);extern void pcibr_hints_subdevs(devfs_handle_t, pciio_slot_t, uint64_t);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, char *, int *);extern int pcibr_is_slot_sys_critical(devfs_handle_t, pciio_slot_t);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 *//* pcibr_try_set_device: attempt to modify Device(x) * for the specified slot on the specified bridge * as requested in flags, limited to the specified * bits. Returns which BRIDGE bits were in conflict, * or ZERO if everything went OK. * * Caller MUST hold pcibr_lock when calling this function. */static intpcibr_try_set_device(pcibr_soft_t pcibr_soft, pciio_slot_t slot, unsigned flags, bridgereg_t mask){ bridge_t *bridge; pcibr_soft_slot_t slotp; bridgereg_t old; bridgereg_t new; bridgereg_t chg; bridgereg_t bad; bridgereg_t badpmu; bridgereg_t badd32; bridgereg_t badd64; bridgereg_t fix; unsigned long s; bridgereg_t xmask; xmask = mask; 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) xmask = XBRIDGE_DEV_D64_BITS; } slotp = &pcibr_soft->bs_slot[slot]; s = pcibr_lock(pcibr_soft); bridge = pcibr_soft->bs_base; old = slotp->bss_device; /* figure out what the desired * Device(x) bits are based on * the flags specified. */ new = old; /* Currently, we inherit anything that * the new caller has not specified in * one way or another, unless we take * action here to not inherit. * * This is needed for the "swap" stuff, * since it could have been set via * pcibr_endian_set -- altho note that * any explicit PCIBR_BYTE_STREAM or * PCIBR_WORD_VALUES will freely override * the effect of that call (and vice * versa, no protection either way). * * I want to get rid of pcibr_endian_set * in favor of tracking DMA endianness * using the flags specified when DMA * channels are created. */#define BRIDGE_DEV_WRGA_BITS (BRIDGE_DEV_PMU_WRGA_EN | BRIDGE_DEV_DIR_WRGA_EN)#define BRIDGE_DEV_SWAP_BITS (BRIDGE_DEV_SWAP_PMU | BRIDGE_DEV_SWAP_DIR) /* Do not use Barrier, Write Gather, * or Prefetch unless asked. * Leave everything else as it * was from the last time. */ new = new & ~BRIDGE_DEV_BARRIER & ~BRIDGE_DEV_WRGA_BITS & ~BRIDGE_DEV_PREF ; /* Generic macro flags */ if (flags & PCIIO_DMA_DATA) { new = (new & ~BRIDGE_DEV_BARRIER) /* barrier off */ | BRIDGE_DEV_PREF; /* prefetch on */ } if (flags & PCIIO_DMA_CMD) { new = ((new & ~BRIDGE_DEV_PREF) /* prefetch off */ & ~BRIDGE_DEV_WRGA_BITS) /* write gather off */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -