📄 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/* * 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};#ifdef LATER#if PCIBR_ATE_DEBUGstatic 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 */ 2, /* 0x8 */ 1, /* 0x9 */ 0, 0, /* 0xa - 0xb */ 5, /* 0xc */ 6, /* 0xd */ 4, /* 0xe */ 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_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 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);#define ATE_WRITE() ate_write(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 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 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);void pcibr_init(void);int pcibr_attach(devfs_handle_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);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 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,#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);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 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 void pcibr_pioerr_check(pcibr_soft_t);extern void pcibr_error_intr_handler(intr_arg_t);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_devenable(devfs_handle_t, int);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 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);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);#ifdef BRIDGE_B_DATACORR_WARextern 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";#endifextern 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_addr_space_init(devfs_handle_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_is_slot_sys_critical(devfs_handle_t, pciio_slot_t);#ifdef LATERextern 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);#endifextern 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 (pcibr_soft->bs_xbridge) { 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
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -