1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved. 24 * Copyright 2022 Oxide Computer Company 25 */ 26 27 #ifndef _SYS_PCI_CFGSPACE_IMPL_H 28 #define _SYS_PCI_CFGSPACE_IMPL_H 29 30 /* 31 * Routines to support particular PCI chipsets and the PCI BIOS. 32 */ 33 34 #include <sys/plat/pci_prd.h> 35 36 #ifdef __cplusplus 37 extern "C" { 38 #endif 39 40 /* 41 * Generic Mechanism 1 routines 42 * XX64 putb -> put8, putw -> put16 etc. 43 */ 44 extern uint8_t pci_mech1_getb(int bus, int dev, int func, int reg); 45 extern uint16_t pci_mech1_getw(int bus, int dev, int func, int reg); 46 extern uint32_t pci_mech1_getl(int bus, int dev, int func, int reg); 47 extern void pci_mech1_putb(int bus, int dev, int func, int reg, uint8_t val); 48 extern void pci_mech1_putw(int bus, int dev, int func, int reg, uint16_t val); 49 extern void pci_mech1_putl(int bus, int dev, int func, int reg, uint32_t val); 50 51 /* 52 * AMD family >= 0x10 Mechanism 1 routines with ECS support 53 */ 54 extern boolean_t pci_check_amd_ioecs(void); 55 extern uint8_t pci_mech1_amd_getb(int bus, int dev, int func, int reg); 56 extern uint16_t pci_mech1_amd_getw(int bus, int dev, int func, int reg); 57 extern uint32_t pci_mech1_amd_getl(int bus, int dev, int func, int reg); 58 extern void pci_mech1_amd_putb(int bus, int dev, int func, int reg, 59 uint8_t val); 60 extern void pci_mech1_amd_putw(int bus, int dev, int func, int reg, 61 uint16_t val); 62 extern void pci_mech1_amd_putl(int bus, int dev, int func, int reg, 63 uint32_t val); 64 65 /* 66 * Generic Mechanism 2 routines 67 */ 68 extern uint8_t pci_mech2_getb(int bus, int dev, int func, int reg); 69 extern uint16_t pci_mech2_getw(int bus, int dev, int func, int reg); 70 extern uint32_t pci_mech2_getl(int bus, int dev, int func, int reg); 71 extern void pci_mech2_putb(int bus, int dev, int func, int reg, uint8_t val); 72 extern void pci_mech2_putw(int bus, int dev, int func, int reg, uint16_t val); 73 extern void pci_mech2_putl(int bus, int dev, int func, int reg, uint32_t val); 74 75 /* 76 * Intel Neptune routines. Neptune is Mech 1, except that BIOSes 77 * often initialize it into Mech 2 so we dynamically switch it to 78 * Mech 1. The chipset's buggy, so we have to do it carefully. 79 */ 80 extern boolean_t pci_check_neptune(void); 81 extern uint8_t pci_neptune_getb(int bus, int dev, int func, int reg); 82 extern uint16_t pci_neptune_getw(int bus, int dev, int func, int reg); 83 extern uint32_t pci_neptune_getl(int bus, int dev, int func, int reg); 84 extern void pci_neptune_putb(int bus, int dev, int func, int reg, uint8_t val); 85 extern void pci_neptune_putw(int bus, int dev, int func, int reg, uint16_t val); 86 extern void pci_neptune_putl(int bus, int dev, int func, int reg, uint32_t val); 87 88 /* 89 * Intel Orion routines. Orion is Mech 1, except that there's a bug 90 * in the peer bridge that requires that it be tweaked specially 91 * around accesses to config space. 92 */ 93 extern boolean_t pci_is_broken_orion(void); 94 extern uint8_t pci_orion_getb(int bus, int dev, int func, int reg); 95 extern uint16_t pci_orion_getw(int bus, int dev, int func, int reg); 96 extern uint32_t pci_orion_getl(int bus, int dev, int func, int reg); 97 extern void pci_orion_putb(int bus, int dev, int func, int reg, uint8_t val); 98 extern void pci_orion_putw(int bus, int dev, int func, int reg, uint16_t val); 99 extern void pci_orion_putl(int bus, int dev, int func, int reg, uint32_t val); 100 101 /* 102 * Generic PCI constants. Probably these should be in pci.h. 103 */ 104 #define PCI_MAX_BUSSES 256 105 #define PCI_MAX_DEVS 32 106 #define PCI_MAX_FUNCS 8 107 /* 108 * PCI access mechanism constants. Probably these should be in pci_impl.h. 109 */ 110 #define PCI_MECH2_CONFIG_ENABLE 0x10 /* any nonzero high nibble works */ 111 112 #define PCI_MECH1_SPEC_CYCLE_DEV 0x1f /* dev to request spec cyc */ 113 #define PCI_MECH1_SPEC_CYCLE_FUNC 0x07 /* func to request spec cyc */ 114 115 extern uint64_t mcfg_mem_base; 116 extern uint8_t mcfg_bus_start; 117 extern uint8_t mcfg_bus_end; 118 119 /* 120 * Mutexes for pci config space routines 121 */ 122 extern kmutex_t pcicfg_mutex; 123 extern kmutex_t pcicfg_mmio_mutex; 124 125 /* 126 * The maximum offset that these I/O space mechanisms can read. Generally either 127 * 0xff to indicate that PCIe extended configuration space is not available or 128 * 0xfff to indicate that it is. 129 */ 130 extern uint_t pci_iocfg_max_offset; 131 132 /* 133 * Orion/Neptune cfg access wraps mech1 cfg access, so needs a separate mutex 134 */ 135 136 extern kmutex_t pcicfg_chipset_mutex; 137 138 /* 139 * pci get irq routing information support 140 */ 141 #define PCI_GET_IRQ_ROUTING 0x0e 142 143 #define PCI_FUNCTION_ID (0xb1) 144 #define PCI_BIOS_PRESENT (0x1) 145 146 /* 147 * low-mem addresses for irq routing bios operations 148 * We set up the initial request for up to 32 table entries, and will 149 * re-issue for up to 255 entries if the bios indicates it requires 150 * a larger table. 255 entries plus the header would consume the 151 * memory between 0x7000-0x7fff. 152 */ 153 #define BIOS_IRQ_ROUTING_HDR 0x7000 154 #define BIOS_IRQ_ROUTING_DATA 0x7010 155 156 #define N_PCI_IRQ_ROUTES 32 157 #define N_PCI_IRQ_ROUTES_MAX 255 158 159 #define MCFG_PROPNAME "ecfg" 160 161 #define FP_OFF(fp) (((uintptr_t)(fp)) & 0xFFFF) 162 #define FP_SEG(fp) ((((uintptr_t)(fp)) >> 16) & 0xFFFF) 163 164 #pragma pack(1) 165 typedef struct pci_irq_route { 166 uchar_t pir_bus; 167 uchar_t pir_dev; 168 uchar_t pir_inta_link; 169 uint16_t pir_inta_irq_map; 170 uchar_t pir_intb_link; 171 uint16_t pir_intb_irq_map; 172 uchar_t pir_intc_link; 173 uint16_t pir_intc_irq_map; 174 uchar_t pir_intd_link; 175 uint16_t pir_intd_irq_map; 176 uchar_t pir_slot; 177 uchar_t pir_reserved; 178 } pci_irq_route_t; 179 #pragma pack() 180 181 #pragma pack(1) 182 typedef struct pci_irq_route_hdr { 183 uint16_t pir_size; 184 uint32_t pir_addr; 185 } pci_irq_route_hdr_t; 186 #pragma pack() 187 188 extern int pci_irq_nroutes; 189 190 extern int pci_slot_names_prop(int, char *, int); 191 extern void pci_bios_bus_iter(pci_prd_root_complex_f, void *); 192 193 #ifdef __cplusplus 194 } 195 #endif 196 197 #endif /* _SYS_PCI_CFGSPACE_IMPL_H */ 198