📄 pcibr_slot.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 <linux/pci.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>#include <asm/sn/ate_utils.h>#ifdef __ia64#define rmallocmap atemapalloc#define rmfreemap atemapfree#define rmfree atefree#define rmalloc atealloc#endifextern pcibr_info_t pcibr_info_get(devfs_handle_t);extern int pcibr_widget_to_bus(devfs_handle_t pcibr_vhdl);extern pcibr_info_t pcibr_device_info_new(pcibr_soft_t, pciio_slot_t, pciio_function_t, pciio_vendor_id_t, pciio_device_id_t);extern int pcibr_slot_initial_rrb_alloc(devfs_handle_t,pciio_slot_t);extern int pcibr_pcix_rbars_calc(pcibr_soft_t);int pcibr_slot_info_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot);int pcibr_slot_info_free(devfs_handle_t pcibr_vhdl, pciio_slot_t slot);int pcibr_slot_addr_space_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot);int pcibr_slot_pcix_rbar_init(pcibr_soft_t pcibr_soft, pciio_slot_t slot);int pcibr_slot_device_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot);int pcibr_slot_guest_info_init(devfs_handle_t pcibr_vhdl, pciio_slot_t slot);int pcibr_slot_call_device_attach(devfs_handle_t pcibr_vhdl, pciio_slot_t slot, int drv_flags);int pcibr_slot_call_device_detach(devfs_handle_t pcibr_vhdl, pciio_slot_t slot, int drv_flags);int pcibr_slot_detach(devfs_handle_t pcibr_vhdl, pciio_slot_t slot, int drv_flags, char *l1_msg, int *sub_errorp);int pcibr_is_slot_sys_critical(devfs_handle_t pcibr_vhdl, pciio_slot_t slot);static int pcibr_probe_slot(bridge_t *, cfg_p, unsigned int *);void pcibr_device_info_free(devfs_handle_t, pciio_slot_t);iopaddr_t pcibr_bus_addr_alloc(pcibr_soft_t, pciio_win_info_t, pciio_space_t, int, int, int);void pciibr_bus_addr_free(pcibr_soft_t, pciio_win_info_t);cfg_p pcibr_find_capability(cfg_p, unsigned);extern uint64_t do_pcibr_config_get(int, cfg_p, unsigned, unsigned);void do_pcibr_config_set(int, cfg_p, unsigned, unsigned, uint64_t); int pcibr_slot_attach(devfs_handle_t pcibr_vhdl, pciio_slot_t slot, int drv_flags, char *l1_msg, int *sub_errorp);int pcibr_slot_info_return(pcibr_soft_t pcibr_soft, pciio_slot_t slot, pcibr_slot_info_resp_t respp);extern devfs_handle_t baseio_pci_vhdl;int scsi_ctlr_nums_add(devfs_handle_t, devfs_handle_t);/* For now .... *//* * PCI Hot-Plug Capability Flags */#define D_PCI_HOT_PLUG_ATTACH 0x200 /* Driver supports PCI hot-plug attach */#define D_PCI_HOT_PLUG_DETACH 0x400 /* Driver supports PCI hot-plug detach *//* * PCI-X Max Outstanding Split Transactions translation array and Max Memory * Read Byte Count translation array, as defined in the PCI-X Specification. * Section 7.2.3 & 7.2.4 of PCI-X Specification - rev 1.0 */#define MAX_SPLIT_TABLE 8#define MAX_READCNT_TABLE 4int max_splittrans_to_numbuf[MAX_SPLIT_TABLE] = {1, 2, 3, 4, 8, 12, 16, 32};int max_readcount_to_bufsize[MAX_READCNT_TABLE] = {512, 1024, 2048, 4096 };/*========================================================================== * BRIDGE PCI SLOT RELATED IOCTLs *//* * pcibr_slot_startup * Software start-up the PCI slot. */#ifdef PIC_LATERintpcibr_slot_startup(devfs_handle_t pcibr_vhdl, pcibr_slot_req_t reqp){ pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); pciio_slot_t slot; int error = 0; char l1_msg[BRL1_QSIZE+1]; struct pcibr_slot_up_resp_s tmp_up_resp; /* Make sure that we are dealing with a bridge device vertex */ if (!pcibr_soft) { return(PCI_NOT_A_BRIDGE); } /* req_slot is the 'external' slot number, convert for internal use */ slot = PCIBR_SLOT_TO_DEVICE(pcibr_soft, reqp->req_slot); /* Do not allow start-up of a slot in a shoehorn */ if(nic_vertex_info_match(pcibr_soft->bs_conn, XTALK_PCI_PART_NUM)) { return(PCI_SLOT_IN_SHOEHORN); } /* Check for the valid slot */ if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) return(PCI_NOT_A_SLOT);#ifdef PIC_LATER /* Acquire update access to the bus */ mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO);#endif if (pcibr_soft->bs_slot[slot].slot_status & SLOT_STARTUP_CMPLT) { error = PCI_SLOT_ALREADY_UP; goto startup_unlock; } error = pcibr_slot_attach(pcibr_vhdl, slot, D_PCI_HOT_PLUG_ATTACH, l1_msg, &tmp_up_resp.resp_sub_errno); strncpy(tmp_up_resp.resp_l1_msg, l1_msg, L1_QSIZE); tmp_up_resp.resp_l1_msg[L1_QSIZE] = '\0'; if (COPYOUT(&tmp_up_resp, reqp->req_respp.up, reqp->req_size)) { return(EFAULT); } startup_unlock:#ifdef PIC_LATER /* Release the bus lock */ mrunlock(pcibr_soft->bs_bus_lock);#endif return(error);}/* * pcibr_slot_shutdown * Software shut-down the PCI slot */intpcibr_slot_shutdown(devfs_handle_t pcibr_vhdl, pcibr_slot_req_t reqp){ pcibr_soft_t pcibr_soft = pcibr_soft_get(pcibr_vhdl); bridge_t *bridge; pciio_slot_t slot; int error = 0; char l1_msg[BRL1_QSIZE+1]; struct pcibr_slot_down_resp_s tmp_down_resp; pciio_slot_t tmp_slot; /* Make sure that we are dealing with a bridge device vertex */ if (!pcibr_soft) { return(PCI_NOT_A_BRIDGE); } /* req_slot is the 'external' slot number, convert for internal use */ slot = PCIBR_SLOT_TO_DEVICE(pcibr_soft, reqp->req_slot); bridge = pcibr_soft->bs_base; /* Check for valid slot */ if (!PCIBR_VALID_SLOT(pcibr_soft, slot)) return(PCI_NOT_A_SLOT); /* Do not allow shut-down of a slot in a shoehorn */ if(nic_vertex_info_match(pcibr_soft->bs_conn, XTALK_PCI_PART_NUM)) { return(PCI_SLOT_IN_SHOEHORN); }#ifdef PIC_LATER /* Acquire update access to the bus */ mrlock(pcibr_soft->bs_bus_lock, MR_UPDATE, PZERO);#endif if ((pcibr_soft->bs_slot[slot].slot_status & SLOT_SHUTDOWN_CMPLT) || ((pcibr_soft->bs_slot[slot].slot_status & SLOT_STATUS_MASK) == 0)) { error = PCI_SLOT_ALREADY_DOWN; /* * RJR - Should we invoke an L1 slot power-down command just in case * a previous shut-down failed to power-down the slot? */ goto shutdown_unlock; } /* Do not allow a multi-function card to be hot-plug removed */ if (pcibr_soft->bs_slot[slot].bss_ninfo > 1) { tmp_down_resp.resp_sub_errno = EPERM; error = PCI_MULTI_FUNC_ERR; goto shutdown_copyout; } /* Do not allow the last 33 MHz card to be removed */ if ((bridge->b_wid_control & BRIDGE_CTRL_BUS_SPEED_MASK) == BRIDGE_CTRL_BUS_SPEED_33) { for (tmp_slot = pcibr_soft->bs_first_slot; tmp_slot <= pcibr_soft->bs_last_slot; tmp_slot++) if (tmp_slot != slot) if (pcibr_soft->bs_slot[tmp_slot].slot_status & SLOT_POWER_UP) { error++; break; } if (!error) { error = PCI_EMPTY_33MHZ; goto shutdown_unlock; } } error = pcibr_slot_detach(pcibr_vhdl, slot, D_PCI_HOT_PLUG_DETACH, l1_msg, &tmp_down_resp.resp_sub_errno); strncpy(tmp_down_resp.resp_l1_msg, l1_msg, L1_QSIZE); tmp_down_resp.resp_l1_msg[L1_QSIZE] = '\0'; shutdown_copyout: if (COPYOUT(&tmp_down_resp, reqp->req_respp.down, reqp->req_size)) { return(EFAULT); } shutdown_unlock:#ifdef PIC_LATER /* Release the bus lock */ mrunlock(pcibr_soft->bs_bus_lock);#endif return(error);}#endif /* PIC_LATER */char *pci_space_name[] = {"NONE", "ROM", "IO", "", "MEM", "MEM32", "MEM64", "CFG", "WIN0", "WIN1", "WIN2", "WIN3", "WIN4", "WIN5", "", "BAD"};voidpcibr_slot_func_info_return(pcibr_info_h pcibr_infoh, int func, pcibr_slot_func_info_resp_t funcp){ pcibr_info_t pcibr_info = pcibr_infoh[func]; int win; boolean_t is_sys_critical_vertex(devfs_handle_t); funcp->resp_f_status = 0; if (!pcibr_info) { return; } funcp->resp_f_status |= FUNC_IS_VALID;#if defined(SUPPORT_PRINTING_V_FORMAT) sprintf(funcp->resp_f_slot_name, "%v", pcibr_info->f_vertex);#endif if(is_sys_critical_vertex(pcibr_info->f_vertex)) { funcp->resp_f_status |= FUNC_IS_SYS_CRITICAL; } funcp->resp_f_bus = pcibr_info->f_bus; funcp->resp_f_slot = PCIBR_INFO_SLOT_GET_EXT(pcibr_info); funcp->resp_f_func = pcibr_info->f_func;#if defined(SUPPORT_PRINTING_V_FORMAT) sprintf(funcp->resp_f_master_name, "%v", pcibr_info->f_master);#endif funcp->resp_f_pops = pcibr_info->f_pops; funcp->resp_f_efunc = pcibr_info->f_efunc; funcp->resp_f_einfo = pcibr_info->f_einfo; funcp->resp_f_vendor = pcibr_info->f_vendor; funcp->resp_f_device = pcibr_info->f_device; for(win = 0 ; win < 6 ; win++) { funcp->resp_f_window[win].resp_w_base = pcibr_info->f_window[win].w_base; funcp->resp_f_window[win].resp_w_size = pcibr_info->f_window[win].w_size; sprintf(funcp->resp_f_window[win].resp_w_space, "%s", pci_space_name[pcibr_info->f_window[win].w_space]); } funcp->resp_f_rbase = pcibr_info->f_rbase; funcp->resp_f_rsize = pcibr_info->f_rsize; for (win = 0 ; win < 4; win++) { funcp->resp_f_ibit[win] = pcibr_info->f_ibit[win]; } funcp->resp_f_att_det_error = pcibr_info->f_att_det_error;}intpcibr_slot_info_return(pcibr_soft_t pcibr_soft, pciio_slot_t slot, pcibr_slot_info_resp_t respp){ pcibr_soft_slot_t pss; int func; bridge_t *bridge = pcibr_soft->bs_base; reg_p b_respp; pcibr_slot_info_resp_t slotp; pcibr_slot_func_info_resp_t funcp; boolean_t is_sys_critical_vertex(devfs_handle_t); extern void snia_kmem_free(void *, int); slotp = snia_kmem_zalloc(sizeof(*slotp), 0); if (slotp == NULL) { return(ENOMEM); } pss = &pcibr_soft->bs_slot[slot]; slotp->resp_bs_bridge_mode = pcibr_soft->bs_bridge_mode; slotp->resp_bs_bridge_type = pcibr_soft->bs_bridge_type; slotp->resp_has_host = pss->has_host; slotp->resp_host_slot = pss->host_slot;#if defined(SUPPORT_PRINTING_V_FORMAT) sprintf(slotp->resp_slot_conn_name, "%v", pss->slot_conn);#else sprintf(slotp->resp_slot_conn_name, "%p", (void *)pss->slot_conn);#endif slotp->resp_slot_status = pss->slot_status; slotp->resp_l1_bus_num = pcibr_widget_to_bus(pcibr_soft->bs_vhdl); if (is_sys_critical_vertex(pss->slot_conn)) { slotp->resp_slot_status |= SLOT_IS_SYS_CRITICAL; } slotp->resp_bss_ninfo = pss->bss_ninfo; for (func = 0; func < pss->bss_ninfo; func++) { funcp = &(slotp->resp_func[func]); pcibr_slot_func_info_return(pss->bss_infos, func, funcp); } sprintf(slotp->resp_bss_devio_bssd_space, "%s", pci_space_name[pss->bss_devio.bssd_space]); slotp->resp_bss_devio_bssd_base = pss->bss_devio.bssd_base; slotp->resp_bss_device = pss->bss_device; slotp->resp_bss_pmu_uctr = pss->bss_pmu_uctr; slotp->resp_bss_d32_uctr = pss->bss_d32_uctr; slotp->resp_bss_d64_uctr = pss->bss_d64_uctr; slotp->resp_bss_d64_base = pss->bss_d64_base; slotp->resp_bss_d64_flags = pss->bss_d64_flags; slotp->resp_bss_d32_base = pss->bss_d32_base; slotp->resp_bss_d32_flags = pss->bss_d32_flags; slotp->resp_bss_ext_ates_active = pss->bss_ext_ates_active; slotp->resp_bss_cmd_pointer = pss->bss_cmd_pointer; slotp->resp_bss_cmd_shadow = pss->bss_cmd_shadow; slotp->resp_bs_rrb_valid = pcibr_soft->bs_rrb_valid[slot][VCHAN0]; slotp->resp_bs_rrb_valid_v1 = pcibr_soft->bs_rrb_valid[slot][VCHAN1]; slotp->resp_bs_rrb_valid_v2 = pcibr_soft->bs_rrb_valid[slot][VCHAN2]; slotp->resp_bs_rrb_valid_v3 = pcibr_soft->bs_rrb_valid[slot][VCHAN3]; slotp->resp_bs_rrb_res = pcibr_soft->bs_rrb_res[slot]; if (slot & 1) { b_respp = &bridge->b_odd_resp; } else { b_respp = &bridge->b_even_resp; } slotp->resp_b_resp = *b_respp; slotp->resp_b_int_device = bridge->b_int_device; if (IS_PIC_SOFT(pcibr_soft)) { slotp->resp_p_int_enable = bridge->p_int_enable_64;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -