| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: pci_subr.c,v 1.218 2019/12/11 07:33:55 msaitoh Exp $ */ | | 1 | /* $NetBSD: pci_subr.c,v 1.219 2020/01/17 02:08:25 msaitoh Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1997 Zubin D. Dittia. All rights reserved. | | 4 | * Copyright (c) 1997 Zubin D. Dittia. All rights reserved. |
5 | * Copyright (c) 1995, 1996, 1998, 2000 | | 5 | * Copyright (c) 1995, 1996, 1998, 2000 |
6 | * Christopher G. Demetriou. All rights reserved. | | 6 | * Christopher G. Demetriou. All rights reserved. |
7 | * Copyright (c) 1994 Charles M. Hannum. All rights reserved. | | 7 | * Copyright (c) 1994 Charles M. Hannum. All rights reserved. |
8 | * | | 8 | * |
9 | * Redistribution and use in source and binary forms, with or without | | 9 | * Redistribution and use in source and binary forms, with or without |
10 | * modification, are permitted provided that the following conditions | | 10 | * modification, are permitted provided that the following conditions |
11 | * are met: | | 11 | * are met: |
12 | * 1. Redistributions of source code must retain the above copyright | | 12 | * 1. Redistributions of source code must retain the above copyright |
13 | * notice, this list of conditions and the following disclaimer. | | 13 | * notice, this list of conditions and the following disclaimer. |
14 | * 2. Redistributions in binary form must reproduce the above copyright | | 14 | * 2. Redistributions in binary form must reproduce the above copyright |
| @@ -30,27 +30,27 @@ | | | @@ -30,27 +30,27 @@ |
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | /* | | 35 | /* |
36 | * PCI autoconfiguration support functions. | | 36 | * PCI autoconfiguration support functions. |
37 | * | | 37 | * |
38 | * Note: This file is also built into a userland library (libpci). | | 38 | * Note: This file is also built into a userland library (libpci). |
39 | * Pay attention to this when you make modifications. | | 39 | * Pay attention to this when you make modifications. |
40 | */ | | 40 | */ |
41 | | | 41 | |
42 | #include <sys/cdefs.h> | | 42 | #include <sys/cdefs.h> |
43 | __KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.218 2019/12/11 07:33:55 msaitoh Exp $"); | | 43 | __KERNEL_RCSID(0, "$NetBSD: pci_subr.c,v 1.219 2020/01/17 02:08:25 msaitoh Exp $"); |
44 | | | 44 | |
45 | #ifdef _KERNEL_OPT | | 45 | #ifdef _KERNEL_OPT |
46 | #include "opt_pci.h" | | 46 | #include "opt_pci.h" |
47 | #endif | | 47 | #endif |
48 | | | 48 | |
49 | #include <sys/param.h> | | 49 | #include <sys/param.h> |
50 | | | 50 | |
51 | #ifdef _KERNEL | | 51 | #ifdef _KERNEL |
52 | #include <sys/systm.h> | | 52 | #include <sys/systm.h> |
53 | #include <sys/intr.h> | | 53 | #include <sys/intr.h> |
54 | #include <sys/module.h> | | 54 | #include <sys/module.h> |
55 | #else | | 55 | #else |
56 | #include <pci.h> | | 56 | #include <pci.h> |
| @@ -2854,151 +2854,158 @@ pci_conf_print_aer_cap(const pcireg_t *r | | | @@ -2854,151 +2854,158 @@ pci_conf_print_aer_cap(const pcireg_t *r |
2854 | reg = regs[o2i(extcapoff + PCI_AER_ERRSRC_ID)]; | | 2854 | reg = regs[o2i(extcapoff + PCI_AER_ERRSRC_ID)]; |
2855 | printf(" Error Source Identification register: 0x%08x\n", | | 2855 | printf(" Error Source Identification register: 0x%08x\n", |
2856 | reg); | | 2856 | reg); |
2857 | pci_conf_print_aer_cap_errsrc_id(reg); | | 2857 | pci_conf_print_aer_cap_errsrc_id(reg); |
2858 | break; | | 2858 | break; |
2859 | } | | 2859 | } |
2860 | | | 2860 | |
2861 | if (tlp_prefix_log) { | | 2861 | if (tlp_prefix_log) { |
2862 | reg = regs[o2i(extcapoff + PCI_AER_TLP_PREFIX_LOG)]; | | 2862 | reg = regs[o2i(extcapoff + PCI_AER_TLP_PREFIX_LOG)]; |
2863 | printf(" TLP Prefix Log register: 0x%08x\n", reg); | | 2863 | printf(" TLP Prefix Log register: 0x%08x\n", reg); |
2864 | } | | 2864 | } |
2865 | } | | 2865 | } |
2866 | | | 2866 | |
| | | 2867 | /* |
| | | 2868 | * Helper function to print the arbitration phase register. |
| | | 2869 | * |
| | | 2870 | * phases: Number of phases in the arbitration tables. |
| | | 2871 | * arbsize: Number of bits in each phase. |
| | | 2872 | * indent: Add more two spaces if it's true. |
| | | 2873 | */ |
2867 | static void | | 2874 | static void |
2868 | pci_conf_print_vc_cap_arbtab(const pcireg_t *regs, int off, const char *name, | | 2875 | pci_conf_print_vc_cap_arbtab(const pcireg_t *regs, int off, const char *name, |
2869 | pcireg_t parbsel, int parbsize) | | 2876 | const int phases, int arbsize, bool indent) |
2870 | { | | 2877 | { |
2871 | pcireg_t reg; | | 2878 | pcireg_t reg; |
2872 | int num = 16 << parbsel; | | 2879 | int num_per_reg = 32 / arbsize; |
2873 | int num_per_reg = sizeof(pcireg_t) / parbsize; | | | |
2874 | int i, j; | | 2880 | int i, j; |
2875 | | | 2881 | |
2876 | /* First, dump the table */ | | 2882 | printf("%s %s Arbitration Table:\n", indent ? " " : "", name); |
2877 | for (i = 0; i < num; i += num_per_reg) { | | 2883 | for (i = 0; i < phases; i += num_per_reg) { |
2878 | reg = regs[o2i(off + i / num_per_reg)]; | | 2884 | reg = regs[o2i(off + (sizeof(uint32_t) * (i / num_per_reg)))]; |
2879 | printf(" %s Arbitration Table: 0x%08x\n", name, reg); | | 2885 | for (j = 0; j < num_per_reg; j++) { |
2880 | } | | 2886 | printf("%s Phase[%d]: 0x%x\n", indent ? " " : "", |
2881 | /* And then, decode each entry */ | | 2887 | i + j, |
2882 | for (i = 0; i < num; i += num_per_reg) { | | 2888 | (uint32_t)(reg & __BITS(arbsize - 1, 0))); |
2883 | reg = regs[o2i(off + i / num_per_reg)]; | | 2889 | reg >>= arbsize; |
2884 | for (j = 0; j < num_per_reg; j++) | | 2890 | } |
2885 | printf(" Phase[%d]: %d\n", j, reg); | | | |
2886 | } | | 2891 | } |
2887 | } | | 2892 | } |
2888 | | | 2893 | |
| | | 2894 | /* For VC, bit 4-7 are reserved. For Port, bit 6-7 are reserved */ |
| | | 2895 | static const int arb_phases[8] = {0, 32, 64, 128, 128, 256, 0, 0 }; |
| | | 2896 | |
2889 | static void | | 2897 | static void |
2890 | pci_conf_print_vc_cap(const pcireg_t *regs, int extcapoff) | | 2898 | pci_conf_print_vc_cap(const pcireg_t *regs, int extcapoff) |
2891 | { | | 2899 | { |
2892 | pcireg_t reg, n; | | 2900 | pcireg_t reg, n; |
2893 | int parbtab, parbsize; | | 2901 | int arbtab, parbsize; |
2894 | pcireg_t parbsel; | | 2902 | pcireg_t arbsel; |
2895 | int varbtab, varbsize; | | | |
2896 | pcireg_t varbsel; | | | |
2897 | int i, count; | | 2903 | int i, count; |
2898 | | | 2904 | |
2899 | printf("\n Virtual Channel Register\n"); | | 2905 | printf("\n Virtual Channel Register\n"); |
2900 | reg = regs[o2i(extcapoff + PCI_VC_CAP1)]; | | 2906 | reg = regs[o2i(extcapoff + PCI_VC_CAP1)]; |
2901 | printf(" Port VC Capability register 1: 0x%08x\n", reg); | | 2907 | printf(" Port VC Capability register 1: 0x%08x\n", reg); |
2902 | count = __SHIFTOUT(reg, PCI_VC_CAP1_EXT_COUNT); | | 2908 | count = __SHIFTOUT(reg, PCI_VC_CAP1_EXT_COUNT); |
2903 | printf(" Extended VC Count: %d\n", count); | | 2909 | printf(" Extended VC Count: %d\n", count); |
2904 | n = __SHIFTOUT(reg, PCI_VC_CAP1_LOWPRI_EXT_COUNT); | | 2910 | n = __SHIFTOUT(reg, PCI_VC_CAP1_LOWPRI_EXT_COUNT); |
2905 | printf(" Low Priority Extended VC Count: %u\n", n); | | 2911 | printf(" Low Priority Extended VC Count: %u\n", n); |
2906 | n = __SHIFTOUT(reg, PCI_VC_CAP1_REFCLK); | | 2912 | n = __SHIFTOUT(reg, PCI_VC_CAP1_REFCLK); |
2907 | printf(" Reference Clock: %s\n", | | 2913 | printf(" Reference Clock: %s\n", |
2908 | (n == PCI_VC_CAP1_REFCLK_100NS) ? "100ns" : "unknown"); | | 2914 | (n == PCI_VC_CAP1_REFCLK_100NS) ? "100ns" : "unknown"); |
2909 | parbsize = 1 << __SHIFTOUT(reg, PCI_VC_CAP1_PORT_ARB_TABLE_SIZE); | | 2915 | parbsize = 1 << __SHIFTOUT(reg, PCI_VC_CAP1_PORT_ARB_TABLE_SIZE); |
2910 | printf(" Port Arbitration Table Entry Size: %dbit\n", parbsize); | | 2916 | printf(" Port Arbitration Table Entry Size: %dbit\n", parbsize); |
2911 | | | 2917 | |
2912 | reg = regs[o2i(extcapoff + PCI_VC_CAP2)]; | | 2918 | reg = regs[o2i(extcapoff + PCI_VC_CAP2)]; |
2913 | printf(" Port VC Capability register 2: 0x%08x\n", reg); | | 2919 | printf(" Port VC Capability register 2: 0x%08x\n", reg); |
2914 | onoff("Hardware fixed arbitration scheme", | | 2920 | onoff("Hardware fixed arbitration scheme", |
2915 | reg, PCI_VC_CAP2_ARB_CAP_HW_FIXED_SCHEME); | | 2921 | reg, PCI_VC_CAP2_ARB_CAP_HW_FIXED_SCHEME); |
2916 | onoff("WRR arbitration with 32 phases", | | 2922 | onoff("WRR arbitration with 32 phases", |
2917 | reg, PCI_VC_CAP2_ARB_CAP_WRR_32); | | 2923 | reg, PCI_VC_CAP2_ARB_CAP_WRR_32); |
2918 | onoff("WRR arbitration with 64 phases", | | 2924 | onoff("WRR arbitration with 64 phases", |
2919 | reg, PCI_VC_CAP2_ARB_CAP_WRR_64); | | 2925 | reg, PCI_VC_CAP2_ARB_CAP_WRR_64); |
2920 | onoff("WRR arbitration with 128 phases", | | 2926 | onoff("WRR arbitration with 128 phases", |
2921 | reg, PCI_VC_CAP2_ARB_CAP_WRR_128); | | 2927 | reg, PCI_VC_CAP2_ARB_CAP_WRR_128); |
2922 | varbtab = __SHIFTOUT(reg, PCI_VC_CAP2_ARB_TABLE_OFFSET); | | 2928 | arbtab = __SHIFTOUT(reg, PCI_VC_CAP2_ARB_TABLE_OFFSET); |
2923 | printf(" VC Arbitration Table Offset: 0x%x\n", varbtab); | | 2929 | printf(" VC Arbitration Table Offset: 0x%x\n", arbtab); |
2924 | | | 2930 | |
2925 | reg = regs[o2i(extcapoff + PCI_VC_CONTROL)] & 0xffff; | | 2931 | reg = regs[o2i(extcapoff + PCI_VC_CONTROL)] & 0xffff; |
2926 | printf(" Port VC Control register: 0x%04x\n", reg); | | 2932 | printf(" Port VC Control register: 0x%04x\n", reg); |
2927 | varbsel = __SHIFTOUT(reg, PCI_VC_CONTROL_VC_ARB_SELECT); | | 2933 | arbsel = __SHIFTOUT(reg, PCI_VC_CONTROL_VC_ARB_SELECT); |
2928 | printf(" VC Arbitration Select: 0x%x\n", varbsel); | | 2934 | printf(" VC Arbitration Select: 0x%x\n", arbsel); |
2929 | | | 2935 | |
2930 | reg = regs[o2i(extcapoff + PCI_VC_STATUS)] >> 16; | | 2936 | reg = regs[o2i(extcapoff + PCI_VC_STATUS)] >> 16; |
2931 | printf(" Port VC Status register: 0x%04x\n", reg); | | 2937 | printf(" Port VC Status register: 0x%04x\n", reg); |
2932 | onoff("VC Arbitration Table Status", | | 2938 | onoff("VC Arbitration Table Status", |
2933 | reg, PCI_VC_STATUS_LOAD_VC_ARB_TABLE); | | 2939 | reg, PCI_VC_STATUS_LOAD_VC_ARB_TABLE); |
2934 | | | 2940 | |
| | | 2941 | if ((arbtab != 0) && (arbsel != 0)) |
| | | 2942 | pci_conf_print_vc_cap_arbtab(regs, extcapoff + (arbtab * 16), |
| | | 2943 | "VC", arb_phases[arbsel], 4, false); |
| | | 2944 | |
2935 | for (i = 0; i < count + 1; i++) { | | 2945 | for (i = 0; i < count + 1; i++) { |
2936 | reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_CAP(i))]; | | 2946 | reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_CAP(i))]; |
2937 | printf(" VC number %d\n", i); | | 2947 | printf(" VC number %d\n", i); |
2938 | printf(" VC Resource Capability Register: 0x%08x\n", reg); | | 2948 | printf(" VC Resource Capability Register: 0x%08x\n", reg); |
2939 | onoff(" Non-configurable Hardware fixed arbitration scheme", | | 2949 | onoff(" Non-configurable Hardware fixed arbitration scheme", |
2940 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_HW_FIXED_SCHEME); | | 2950 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_HW_FIXED_SCHEME); |
2941 | onoff(" WRR arbitration with 32 phases", | | 2951 | onoff(" WRR arbitration with 32 phases", |
2942 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_32); | | 2952 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_32); |
2943 | onoff(" WRR arbitration with 64 phases", | | 2953 | onoff(" WRR arbitration with 64 phases", |
2944 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_64); | | 2954 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_64); |
2945 | onoff(" WRR arbitration with 128 phases", | | 2955 | onoff(" WRR arbitration with 128 phases", |
2946 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_128); | | 2956 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_128); |
2947 | onoff(" Time-based WRR arbitration with 128 phases", | | 2957 | onoff(" Time-based WRR arbitration with 128 phases", |
2948 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_TWRR_128); | | 2958 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_TWRR_128); |
2949 | onoff(" WRR arbitration with 256 phases", | | 2959 | onoff(" WRR arbitration with 256 phases", |
2950 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_256); | | 2960 | reg, PCI_VC_RESOURCE_CAP_PORT_ARB_CAP_WRR_256); |
2951 | onoff(" Advanced Packet Switching", | | 2961 | onoff(" Advanced Packet Switching", |
2952 | reg, PCI_VC_RESOURCE_CAP_ADV_PKT_SWITCH); | | 2962 | reg, PCI_VC_RESOURCE_CAP_ADV_PKT_SWITCH); |
2953 | onoff(" Reject Snoop Transaction", | | 2963 | onoff(" Reject Snoop Transaction", |
2954 | reg, PCI_VC_RESOURCE_CAP_REJCT_SNOOP_TRANS); | | 2964 | reg, PCI_VC_RESOURCE_CAP_REJCT_SNOOP_TRANS); |
2955 | n = __SHIFTOUT(reg, PCI_VC_RESOURCE_CAP_MAX_TIME_SLOTS) + 1; | | 2965 | n = __SHIFTOUT(reg, PCI_VC_RESOURCE_CAP_MAX_TIME_SLOTS) + 1; |
2956 | printf(" Maximum Time Slots: %d\n", n); | | 2966 | printf(" Maximum Time Slots: %d\n", n); |
2957 | parbtab = reg >> PCI_VC_RESOURCE_CAP_PORT_ARB_TABLE_OFFSET_S; | | 2967 | arbtab = __SHIFTOUT(reg, |
| | | 2968 | PCI_VC_RESOURCE_CAP_PORT_ARB_TABLE_OFFSET); |
2958 | printf(" Port Arbitration Table offset: 0x%02x\n", | | 2969 | printf(" Port Arbitration Table offset: 0x%02x\n", |
2959 | parbtab); | | 2970 | arbtab); |
2960 | | | 2971 | |
2961 | reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_CTL(i))]; | | 2972 | reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_CTL(i))]; |
2962 | printf(" VC Resource Control Register: 0x%08x\n", reg); | | 2973 | printf(" VC Resource Control Register: 0x%08x\n", reg); |
2963 | printf(" TC/VC Map: 0x%02x\n", | | 2974 | printf(" TC/VC Map: 0x%02x\n", |
2964 | (pcireg_t)__SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_TCVC_MAP)); | | 2975 | (pcireg_t)__SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_TCVC_MAP)); |
2965 | /* | | 2976 | /* |
2966 | * The load Port Arbitration Table bit is used to update | | 2977 | * The load Port Arbitration Table bit is used to update |
2967 | * the Port Arbitration logic and it's always 0 on read, so | | 2978 | * the Port Arbitration logic and it's always 0 on read, so |
2968 | * we don't print it. | | 2979 | * we don't print it. |
2969 | */ | | 2980 | */ |
2970 | parbsel = __SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_PORT_ARB_SELECT); | | 2981 | arbsel = __SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_PORT_ARB_SELECT); |
2971 | printf(" Port Arbitration Select: 0x%x\n", parbsel); | | 2982 | printf(" Port Arbitration Select: 0x%x\n", arbsel); |
2972 | n = __SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_VC_ID); | | 2983 | n = __SHIFTOUT(reg, PCI_VC_RESOURCE_CTL_VC_ID); |
2973 | printf(" VC ID: %d\n", n); | | 2984 | printf(" VC ID: %d\n", n); |
2974 | onoff(" VC Enable", reg, PCI_VC_RESOURCE_CTL_VC_ENABLE); | | 2985 | onoff(" VC Enable", reg, PCI_VC_RESOURCE_CTL_VC_ENABLE); |
2975 | | | 2986 | |
2976 | reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_STA(i))] >> 16; | | 2987 | reg = regs[o2i(extcapoff + PCI_VC_RESOURCE_STA(i))] >> 16; |
2977 | printf(" VC Resource Status Register: 0x%08x\n", reg); | | 2988 | printf(" VC Resource Status Register: 0x%08x\n", reg); |
2978 | onoff(" Port Arbitration Table Status", | | 2989 | onoff(" Port Arbitration Table Status", |
2979 | reg, PCI_VC_RESOURCE_STA_PORT_ARB_TABLE); | | 2990 | reg, PCI_VC_RESOURCE_STA_PORT_ARB_TABLE); |
2980 | onoff(" VC Negotiation Pending", | | 2991 | onoff(" VC Negotiation Pending", |
2981 | reg, PCI_VC_RESOURCE_STA_VC_NEG_PENDING); | | 2992 | reg, PCI_VC_RESOURCE_STA_VC_NEG_PENDING); |
2982 | | | 2993 | |
2983 | if ((parbtab != 0) && (parbsel != 0)) | | 2994 | if ((arbtab != 0) && (arbsel != 0)) |
2984 | pci_conf_print_vc_cap_arbtab(regs, extcapoff + parbtab, | | 2995 | pci_conf_print_vc_cap_arbtab(regs, |
2985 | "Port", parbsel, parbsize); | | 2996 | extcapoff + (arbtab * 16), |
| | | 2997 | "Port", arb_phases[arbsel], parbsize, true); |
2986 | } | | 2998 | } |
2987 | | | | |
2988 | varbsize = 8; | | | |
2989 | if ((varbtab != 0) && (varbsel != 0)) | | | |
2990 | pci_conf_print_vc_cap_arbtab(regs, extcapoff + varbtab, | | | |
2991 | " VC", varbsel, varbsize); | | | |
2992 | } | | 2999 | } |
2993 | | | 3000 | |
2994 | /* | | 3001 | /* |
2995 | * Print Power limit. This encoding is the same among the following registers: | | 3002 | * Print Power limit. This encoding is the same among the following registers: |
2996 | * - The Captured Slot Power Limit in the PCIe Device Capability Register. | | 3003 | * - The Captured Slot Power Limit in the PCIe Device Capability Register. |
2997 | * - The Slot Power Limit in the PCIe Slot Capability Register. | | 3004 | * - The Slot Power Limit in the PCIe Slot Capability Register. |
2998 | * - The Base Power in the Data register of Power Budgeting capability. | | 3005 | * - The Base Power in the Data register of Power Budgeting capability. |
2999 | */ | | 3006 | */ |
3000 | static void | | 3007 | static void |
3001 | pci_conf_print_pcie_power(uint8_t base, unsigned int scale) | | 3008 | pci_conf_print_pcie_power(uint8_t base, unsigned int scale) |
3002 | { | | 3009 | { |
3003 | unsigned int sdiv = 1; | | 3010 | unsigned int sdiv = 1; |
3004 | | | 3011 | |