1 1.40 andvar /* $NetBSD: ahd_pci.c,v 1.40 2022/05/28 10:36:23 andvar Exp $ */ 2 1.1 fvdl 3 1.1 fvdl /* 4 1.1 fvdl * Product specific probe and attach routines for: 5 1.1 fvdl * aic7901 and aic7902 SCSI controllers 6 1.1 fvdl * 7 1.1 fvdl * Copyright (c) 1994-2001 Justin T. Gibbs. 8 1.1 fvdl * Copyright (c) 2000-2002 Adaptec Inc. 9 1.1 fvdl * All rights reserved. 10 1.1 fvdl * 11 1.1 fvdl * Redistribution and use in source and binary forms, with or without 12 1.1 fvdl * modification, are permitted provided that the following conditions 13 1.1 fvdl * are met: 14 1.1 fvdl * 1. Redistributions of source code must retain the above copyright 15 1.1 fvdl * notice, this list of conditions, and the following disclaimer, 16 1.1 fvdl * without modification. 17 1.1 fvdl * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 1.1 fvdl * substantially similar to the "NO WARRANTY" disclaimer below 19 1.1 fvdl * ("Disclaimer") and any redistribution must be conditioned upon 20 1.1 fvdl * including a substantially similar Disclaimer requirement for further 21 1.1 fvdl * binary redistribution. 22 1.1 fvdl * 3. Neither the names of the above-listed copyright holders nor the names 23 1.1 fvdl * of any contributors may be used to endorse or promote products derived 24 1.1 fvdl * from this software without specific prior written permission. 25 1.1 fvdl * 26 1.1 fvdl * Alternatively, this software may be distributed under the terms of the 27 1.1 fvdl * GNU General Public License ("GPL") version 2 as published by the Free 28 1.1 fvdl * Software Foundation. 29 1.1 fvdl * 30 1.1 fvdl * NO WARRANTY 31 1.1 fvdl * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 1.1 fvdl * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 1.1 fvdl * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 1.1 fvdl * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 1.1 fvdl * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 1.1 fvdl * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 1.1 fvdl * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 1.1 fvdl * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 1.1 fvdl * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 1.1 fvdl * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 1.1 fvdl * POSSIBILITY OF SUCH DAMAGES. 42 1.1 fvdl * 43 1.8 fvdl * Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#80 $ 44 1.1 fvdl * 45 1.8 fvdl * $FreeBSD: src/sys/dev/aic7xxx/aic79xx_pci.c,v 1.16 2003/06/28 04:39:49 gibbs Exp $ 46 1.1 fvdl */ 47 1.1 fvdl /* 48 1.29 tsutsui * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc. 49 1.29 tsutsui * - April 2003 50 1.1 fvdl */ 51 1.3 lukem 52 1.3 lukem #include <sys/cdefs.h> 53 1.40 andvar __KERNEL_RCSID(0, "$NetBSD: ahd_pci.c,v 1.40 2022/05/28 10:36:23 andvar Exp $"); 54 1.1 fvdl 55 1.1 fvdl #define AHD_PCI_IOADDR PCI_MAPREG_START /* I/O Address */ 56 1.1 fvdl #define AHD_PCI_MEMADDR (PCI_MAPREG_START + 4) /* Mem I/O Address */ 57 1.1 fvdl 58 1.1 fvdl #include <dev/ic/aic79xx_osm.h> 59 1.1 fvdl #include <dev/ic/aic79xx_inline.h> 60 1.1 fvdl 61 1.21 perry static inline uint64_t 62 1.1 fvdl ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) 63 1.1 fvdl { 64 1.1 fvdl uint64_t id; 65 1.1 fvdl 66 1.1 fvdl id = subvendor 67 1.1 fvdl | (subdevice << 16) 68 1.1 fvdl | ((uint64_t)vendor << 32) 69 1.1 fvdl | ((uint64_t)device << 48); 70 1.1 fvdl 71 1.1 fvdl return (id); 72 1.1 fvdl } 73 1.1 fvdl 74 1.1 fvdl #define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull 75 1.16 bad #define ID_ALL_IROC_MASK 0xFF7FFFFFFFFFFFFFull 76 1.1 fvdl #define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull 77 1.1 fvdl #define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull 78 1.16 bad #define ID_9005_GENERIC_IROC_MASK 0xFF70FFFF00000000ull 79 1.1 fvdl 80 1.1 fvdl #define ID_AIC7901 0x800F9005FFFF9005ull 81 1.5 thorpej #define ID_AHA_29320A 0x8000900500609005ull 82 1.5 thorpej #define ID_AHA_29320ALP 0x8017900500449005ull 83 1.33 christos #define ID_AHA_29320LPE 0x8017900500459005ull 84 1.5 thorpej 85 1.1 fvdl #define ID_AIC7901A 0x801E9005FFFF9005ull 86 1.1 fvdl #define ID_AHA_29320LP 0x8014900500449005ull 87 1.1 fvdl 88 1.1 fvdl #define ID_AIC7902 0x801F9005FFFF9005ull 89 1.1 fvdl #define ID_AIC7902_B 0x801D9005FFFF9005ull 90 1.1 fvdl #define ID_AHA_39320 0x8010900500409005ull 91 1.16 bad #define ID_AHA_29320 0x8012900500429005ull 92 1.16 bad #define ID_AHA_29320B 0x8013900500439005ull 93 1.5 thorpej #define ID_AHA_39320_B 0x8015900500409005ull 94 1.1 fvdl #define ID_AHA_39320A 0x8016900500409005ull 95 1.1 fvdl #define ID_AHA_39320D 0x8011900500419005ull 96 1.1 fvdl #define ID_AHA_39320D_B 0x801C900500419005ull 97 1.17 bad #define ID_AHA_39320_B_DELL 0x8015900501681028ull 98 1.1 fvdl #define ID_AHA_39320D_HP 0x8011900500AC0E11ull 99 1.1 fvdl #define ID_AHA_39320D_B_HP 0x801C900500AC0E11ull 100 1.1 fvdl #define ID_AIC7902_PCI_REV_A4 0x3 101 1.1 fvdl #define ID_AIC7902_PCI_REV_B0 0x10 102 1.1 fvdl #define SUBID_HP 0x0E11 103 1.1 fvdl 104 1.16 bad #define DEVID_9005_HOSTRAID(id) ((id) & 0x80) 105 1.16 bad 106 1.1 fvdl #define DEVID_9005_TYPE(id) ((id) & 0xF) 107 1.1 fvdl #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ 108 1.1 fvdl #define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */ 109 1.1 fvdl #define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ 110 1.1 fvdl 111 1.1 fvdl #define DEVID_9005_MFUNC(id) ((id) & 0x10) 112 1.1 fvdl 113 1.1 fvdl #define DEVID_9005_PACKETIZED(id) ((id) & 0x8000) 114 1.1 fvdl 115 1.1 fvdl #define SUBID_9005_TYPE(id) ((id) & 0xF) 116 1.1 fvdl #define SUBID_9005_TYPE_HBA 0x0 /* Standard Card */ 117 1.1 fvdl #define SUBID_9005_TYPE_MB 0xF /* On Motherboard */ 118 1.1 fvdl 119 1.1 fvdl #define SUBID_9005_AUTOTERM(id) (((id) & 0x10) == 0) 120 1.1 fvdl 121 1.1 fvdl #define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20) 122 1.1 fvdl 123 1.1 fvdl #define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6) 124 1.1 fvdl #define SUBID_9005_SEEPTYPE_NONE 0x0 125 1.1 fvdl #define SUBID_9005_SEEPTYPE_4K 0x1 126 1.1 fvdl 127 1.5 thorpej static ahd_device_setup_t ahd_aic7901_setup; 128 1.1 fvdl static ahd_device_setup_t ahd_aic7901A_setup; 129 1.1 fvdl static ahd_device_setup_t ahd_aic7902_setup; 130 1.6 thorpej static ahd_device_setup_t ahd_aic790X_setup; 131 1.1 fvdl 132 1.37 maxv static const struct ahd_pci_identity ahd_pci_ident_table[] = 133 1.1 fvdl { 134 1.5 thorpej /* aic7901 based controllers */ 135 1.5 thorpej { 136 1.5 thorpej ID_AHA_29320A, 137 1.5 thorpej ID_ALL_MASK, 138 1.5 thorpej "Adaptec 29320A Ultra320 SCSI adapter", 139 1.5 thorpej ahd_aic7901_setup 140 1.5 thorpej }, 141 1.5 thorpej { 142 1.5 thorpej ID_AHA_29320ALP, 143 1.5 thorpej ID_ALL_MASK, 144 1.5 thorpej "Adaptec 29320ALP Ultra320 SCSI adapter", 145 1.5 thorpej ahd_aic7901_setup 146 1.5 thorpej }, 147 1.33 christos { 148 1.33 christos ID_AHA_29320LPE, 149 1.33 christos ID_ALL_MASK, 150 1.33 christos "Adaptec 29320LPE Ultra320 SCSI adapter", 151 1.33 christos ahd_aic7901_setup 152 1.33 christos }, 153 1.1 fvdl /* aic7901A based controllers */ 154 1.1 fvdl { 155 1.5 thorpej ID_AHA_29320LP, 156 1.1 fvdl ID_ALL_MASK, 157 1.5 thorpej "Adaptec 29320LP Ultra320 SCSI adapter", 158 1.1 fvdl ahd_aic7901A_setup 159 1.1 fvdl }, 160 1.15 perry /* aic7902 based controllers */ 161 1.1 fvdl { 162 1.1 fvdl ID_AHA_39320, 163 1.1 fvdl ID_ALL_MASK, 164 1.1 fvdl "Adaptec 39320 Ultra320 SCSI adapter", 165 1.1 fvdl ahd_aic7902_setup 166 1.1 fvdl }, 167 1.1 fvdl { 168 1.5 thorpej ID_AHA_39320_B, 169 1.5 thorpej ID_ALL_MASK, 170 1.5 thorpej "Adaptec 39320 Ultra320 SCSI adapter", 171 1.5 thorpej ahd_aic7902_setup 172 1.5 thorpej }, 173 1.5 thorpej { 174 1.17 bad ID_AHA_39320_B_DELL, 175 1.17 bad ID_ALL_IROC_MASK, 176 1.17 bad "Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter", 177 1.17 bad ahd_aic7902_setup 178 1.17 bad }, 179 1.17 bad { 180 1.1 fvdl ID_AHA_39320A, 181 1.1 fvdl ID_ALL_MASK, 182 1.1 fvdl "Adaptec 39320A Ultra320 SCSI adapter", 183 1.1 fvdl ahd_aic7902_setup 184 1.1 fvdl }, 185 1.1 fvdl { 186 1.1 fvdl ID_AHA_39320D, 187 1.1 fvdl ID_ALL_MASK, 188 1.1 fvdl "Adaptec 39320D Ultra320 SCSI adapter", 189 1.1 fvdl ahd_aic7902_setup 190 1.1 fvdl }, 191 1.1 fvdl { 192 1.1 fvdl ID_AHA_39320D_HP, 193 1.1 fvdl ID_ALL_MASK, 194 1.1 fvdl "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter", 195 1.1 fvdl ahd_aic7902_setup 196 1.1 fvdl }, 197 1.1 fvdl { 198 1.1 fvdl ID_AHA_39320D_B, 199 1.1 fvdl ID_ALL_MASK, 200 1.1 fvdl "Adaptec 39320D Ultra320 SCSI adapter", 201 1.1 fvdl ahd_aic7902_setup 202 1.1 fvdl }, 203 1.1 fvdl { 204 1.1 fvdl ID_AHA_39320D_B_HP, 205 1.1 fvdl ID_ALL_MASK, 206 1.1 fvdl "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter", 207 1.1 fvdl ahd_aic7902_setup 208 1.1 fvdl }, 209 1.1 fvdl /* Generic chip probes for devices we don't know 'exactly' */ 210 1.1 fvdl { 211 1.16 bad ID_AIC7901 & ID_9005_GENERIC_MASK, 212 1.16 bad ID_9005_GENERIC_MASK, 213 1.5 thorpej "Adaptec AIC7901 Ultra320 SCSI adapter", 214 1.5 thorpej ahd_aic7901_setup 215 1.5 thorpej }, 216 1.5 thorpej { 217 1.1 fvdl ID_AIC7901A & ID_DEV_VENDOR_MASK, 218 1.1 fvdl ID_DEV_VENDOR_MASK, 219 1.1 fvdl "Adaptec AIC7901A Ultra320 SCSI adapter", 220 1.1 fvdl ahd_aic7901A_setup 221 1.1 fvdl }, 222 1.1 fvdl { 223 1.1 fvdl ID_AIC7902 & ID_9005_GENERIC_MASK, 224 1.1 fvdl ID_9005_GENERIC_MASK, 225 1.1 fvdl "Adaptec AIC7902 Ultra320 SCSI adapter", 226 1.1 fvdl ahd_aic7902_setup 227 1.1 fvdl } 228 1.1 fvdl }; 229 1.1 fvdl 230 1.19 thorpej static const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table); 231 1.1 fvdl 232 1.1 fvdl #define DEVCONFIG 0x40 233 1.1 fvdl #define PCIXINITPAT 0x0000E000ul 234 1.1 fvdl #define PCIXINIT_PCI33_66 0x0000E000ul 235 1.1 fvdl #define PCIXINIT_PCIX50_66 0x0000C000ul 236 1.1 fvdl #define PCIXINIT_PCIX66_100 0x0000A000ul 237 1.1 fvdl #define PCIXINIT_PCIX100_133 0x00008000ul 238 1.1 fvdl #define PCI_BUS_MODES_INDEX(devconfig) \ 239 1.1 fvdl (((devconfig) & PCIXINITPAT) >> 13) 240 1.1 fvdl 241 1.1 fvdl static const char *pci_bus_modes[] = 242 1.1 fvdl { 243 1.1 fvdl "PCI bus mode unknown", 244 1.1 fvdl "PCI bus mode unknown", 245 1.1 fvdl "PCI bus mode unknown", 246 1.1 fvdl "PCI bus mode unknown", 247 1.22 lukem "PCI-X 101-133 MHz", 248 1.22 lukem "PCI-X 67-100 MHz", 249 1.22 lukem "PCI-X 50-66 MHz", 250 1.22 lukem "PCI 33 or 66 MHz" 251 1.1 fvdl }; 252 1.1 fvdl 253 1.1 fvdl #define TESTMODE 0x00000800ul 254 1.1 fvdl #define IRDY_RST 0x00000200ul 255 1.1 fvdl #define FRAME_RST 0x00000100ul 256 1.1 fvdl #define PCI64BIT 0x00000080ul 257 1.1 fvdl #define MRDCEN 0x00000040ul 258 1.1 fvdl #define ENDIANSEL 0x00000020ul 259 1.1 fvdl #define MIXQWENDIANEN 0x00000008ul 260 1.1 fvdl #define DACEN 0x00000004ul 261 1.1 fvdl #define STPWLEVEL 0x00000002ul 262 1.1 fvdl #define QWENDIANSEL 0x00000001ul 263 1.1 fvdl 264 1.1 fvdl #define DEVCONFIG1 0x44 265 1.1 fvdl #define PREQDIS 0x01 266 1.1 fvdl 267 1.1 fvdl #define LATTIME 0x0000ff00ul 268 1.1 fvdl 269 1.1 fvdl static int ahd_check_extport(struct ahd_softc *ahd); 270 1.1 fvdl static void ahd_configure_termination(struct ahd_softc *ahd, 271 1.1 fvdl u_int adapter_control); 272 1.1 fvdl static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat); 273 1.1 fvdl 274 1.19 thorpej static int ahd_pci_test_register_access(struct ahd_softc *); 275 1.19 thorpej 276 1.19 thorpej static int ahd_pci_intr(struct ahd_softc *); 277 1.19 thorpej 278 1.19 thorpej static const struct ahd_pci_identity * 279 1.19 thorpej ahd_find_pci_device(pcireg_t id, pcireg_t subid) 280 1.1 fvdl { 281 1.1 fvdl u_int64_t full_id; 282 1.1 fvdl const struct ahd_pci_identity *entry; 283 1.1 fvdl u_int i; 284 1.1 fvdl 285 1.1 fvdl full_id = ahd_compose_id(PCI_PRODUCT(id), PCI_VENDOR(id), 286 1.1 fvdl PCI_PRODUCT(subid), PCI_VENDOR(subid)); 287 1.1 fvdl 288 1.1 fvdl for (i = 0; i < ahd_num_pci_devs; i++) { 289 1.1 fvdl entry = &ahd_pci_ident_table[i]; 290 1.1 fvdl if (entry->full_id == (full_id & entry->id_mask)) 291 1.1 fvdl return (entry); 292 1.1 fvdl } 293 1.1 fvdl return (NULL); 294 1.1 fvdl } 295 1.1 fvdl 296 1.19 thorpej static int 297 1.28 cegger ahd_pci_probe(device_t parent, cfdata_t match, void *aux) 298 1.1 fvdl { 299 1.1 fvdl struct pci_attach_args *pa = aux; 300 1.1 fvdl const struct ahd_pci_identity *entry; 301 1.1 fvdl pcireg_t subid; 302 1.1 fvdl 303 1.1 fvdl subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 304 1.1 fvdl entry = ahd_find_pci_device(pa->pa_id, subid); 305 1.1 fvdl return entry != NULL ? 1 : 0; 306 1.1 fvdl } 307 1.1 fvdl 308 1.19 thorpej static void 309 1.26 dyoung ahd_pci_attach(device_t parent, device_t self, void *aux) 310 1.1 fvdl { 311 1.1 fvdl struct pci_attach_args *pa = aux; 312 1.26 dyoung struct ahd_softc *ahd = device_private(self); 313 1.1 fvdl 314 1.1 fvdl const struct ahd_pci_identity *entry; 315 1.1 fvdl 316 1.1 fvdl uint32_t devconfig; 317 1.1 fvdl pcireg_t command; 318 1.1 fvdl int error; 319 1.1 fvdl pcireg_t subid; 320 1.15 perry uint16_t subvendor; 321 1.1 fvdl pcireg_t reg; 322 1.1 fvdl int ioh_valid, ioh2_valid, memh_valid; 323 1.1 fvdl pcireg_t memtype; 324 1.1 fvdl pci_intr_handle_t ih; 325 1.1 fvdl const char *intrstr; 326 1.1 fvdl struct ahd_pci_busdata *bd; 327 1.35 christos char intrbuf[PCI_INTRSTR_LEN]; 328 1.1 fvdl 329 1.31 tsutsui ahd->sc_dev = self; 330 1.30 tsutsui ahd_set_name(ahd, device_xname(self)); 331 1.1 fvdl ahd->parent_dmat = pa->pa_dmat; 332 1.15 perry 333 1.1 fvdl command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 334 1.1 fvdl subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG); 335 1.1 fvdl entry = ahd_find_pci_device(pa->pa_id, subid); 336 1.1 fvdl if (entry == NULL) 337 1.1 fvdl return; 338 1.1 fvdl 339 1.1 fvdl /* Keep information about the PCI bus */ 340 1.39 chs bd = malloc(sizeof (struct ahd_pci_busdata), M_DEVBUF, M_WAITOK|M_ZERO); 341 1.1 fvdl bd->pc = pa->pa_pc; 342 1.1 fvdl bd->tag = pa->pa_tag; 343 1.1 fvdl bd->func = pa->pa_function; 344 1.1 fvdl bd->dev = pa->pa_device; 345 1.1 fvdl 346 1.1 fvdl ahd->bus_data = bd; 347 1.1 fvdl 348 1.1 fvdl ahd->description = entry->name; 349 1.1 fvdl 350 1.1 fvdl ahd->seep_config = malloc(sizeof(*ahd->seep_config), 351 1.39 chs M_DEVBUF, M_WAITOK|M_ZERO); 352 1.1 fvdl 353 1.1 fvdl LIST_INIT(&ahd->pending_scbs); 354 1.1 fvdl ahd_timer_init(&ahd->reset_timer); 355 1.1 fvdl ahd_timer_init(&ahd->stat_timer); 356 1.10 fvdl ahd->flags = AHD_SPCHK_ENB_A|AHD_RESET_BUS_A|AHD_TERM_ENB_A 357 1.10 fvdl | AHD_EXTENDED_TRANS_A|AHD_STPWLEVEL_A; 358 1.2 wiz ahd->int_coalescing_timer = AHD_INT_COALESCING_TIMER_DEFAULT; 359 1.2 wiz ahd->int_coalescing_maxcmds = AHD_INT_COALESCING_MAXCMDS_DEFAULT; 360 1.2 wiz ahd->int_coalescing_mincmds = AHD_INT_COALESCING_MINCMDS_DEFAULT; 361 1.2 wiz ahd->int_coalescing_threshold = AHD_INT_COALESCING_THRESHOLD_DEFAULT; 362 1.29 tsutsui ahd->int_coalescing_stop_threshold = 363 1.29 tsutsui AHD_INT_COALESCING_STOP_THRESHOLD_DEFAULT; 364 1.1 fvdl 365 1.1 fvdl if (ahd_platform_alloc(ahd, NULL) != 0) { 366 1.1 fvdl ahd_free(ahd); 367 1.1 fvdl return; 368 1.1 fvdl } 369 1.1 fvdl 370 1.1 fvdl /* 371 1.1 fvdl * Record if this is an HP board. 372 1.1 fvdl */ 373 1.1 fvdl subvendor = PCI_VENDOR(subid); 374 1.1 fvdl if (subvendor == SUBID_HP) 375 1.1 fvdl ahd->flags |= AHD_HP_BOARD; 376 1.1 fvdl 377 1.1 fvdl error = entry->setup(ahd, pa); 378 1.1 fvdl if (error != 0) 379 1.1 fvdl return; 380 1.1 fvdl 381 1.1 fvdl devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG); 382 1.8 fvdl if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { 383 1.1 fvdl ahd->chip |= AHD_PCI; 384 1.1 fvdl /* Disable PCIX workarounds when running in PCI mode. */ 385 1.1 fvdl ahd->bugs &= ~AHD_PCIX_BUG_MASK; 386 1.1 fvdl } else { 387 1.1 fvdl ahd->chip |= AHD_PCIX; 388 1.1 fvdl } 389 1.1 fvdl ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; 390 1.1 fvdl 391 1.1 fvdl memh_valid = ioh_valid = ioh2_valid = 0; 392 1.1 fvdl 393 1.1 fvdl if (!pci_get_capability(pa->pa_pc, pa->pa_tag, PCI_CAP_PCIX, 394 1.1 fvdl &bd->pcix_off, NULL)) { 395 1.1 fvdl if (ahd->chip & AHD_PCIX) 396 1.30 tsutsui aprint_error_dev(self, 397 1.27 dyoung "warning: can't find PCI-X capability\n"); 398 1.1 fvdl ahd->chip &= ~AHD_PCIX; 399 1.1 fvdl ahd->chip |= AHD_PCI; 400 1.1 fvdl ahd->bugs &= ~AHD_PCIX_BUG_MASK; 401 1.1 fvdl } 402 1.1 fvdl 403 1.1 fvdl /* 404 1.1 fvdl * Map PCI Registers 405 1.1 fvdl */ 406 1.9 thorpej if ((ahd->bugs & AHD_PCIX_MMAPIO_BUG) == 0) { 407 1.9 thorpej memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, 408 1.9 thorpej AHD_PCI_MEMADDR); 409 1.1 fvdl switch (memtype) { 410 1.1 fvdl case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT: 411 1.1 fvdl case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT: 412 1.1 fvdl memh_valid = (pci_mapreg_map(pa, AHD_PCI_MEMADDR, 413 1.15 perry memtype, 0, &ahd->tags[0], 414 1.9 thorpej &ahd->bshs[0], 415 1.9 thorpej NULL, NULL) == 0); 416 1.9 thorpej if (memh_valid) { 417 1.9 thorpej ahd->tags[1] = ahd->tags[0]; 418 1.9 thorpej bus_space_subregion(ahd->tags[0], ahd->bshs[0], 419 1.9 thorpej /*offset*/0x100, 420 1.9 thorpej /*size*/0x100, 421 1.9 thorpej &ahd->bshs[1]); 422 1.10 fvdl if (ahd_pci_test_register_access(ahd) != 0) 423 1.10 fvdl memh_valid = 0; 424 1.9 thorpej } 425 1.1 fvdl break; 426 1.15 perry default: 427 1.9 thorpej memh_valid = 0; 428 1.12 briggs aprint_error("%s: unknown memory type: 0x%x\n", 429 1.9 thorpej ahd_name(ahd), memtype); 430 1.9 thorpej break; 431 1.1 fvdl } 432 1.1 fvdl 433 1.1 fvdl if (memh_valid) { 434 1.1 fvdl command &= ~PCI_COMMAND_IO_ENABLE; 435 1.9 thorpej pci_conf_write(pa->pa_pc, pa->pa_tag, 436 1.9 thorpej PCI_COMMAND_STATUS_REG, command); 437 1.1 fvdl } 438 1.1 fvdl #ifdef AHD_DEBUG 439 1.32 dyoung printf("%s: doing memory mapping shs0 0x%lx, shs1 0x%lx\n", 440 1.32 dyoung ahd_name(ahd), ahd->bshs[0], ahd->bshs[1]); 441 1.1 fvdl #endif 442 1.1 fvdl } 443 1.1 fvdl 444 1.9 thorpej if (command & PCI_COMMAND_IO_ENABLE) { 445 1.15 perry /* First BAR */ 446 1.1 fvdl ioh_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR, 447 1.9 thorpej PCI_MAPREG_TYPE_IO, 0, 448 1.9 thorpej &ahd->tags[0], &ahd->bshs[0], 449 1.9 thorpej NULL, NULL) == 0); 450 1.1 fvdl 451 1.15 perry /* 2nd BAR */ 452 1.1 fvdl ioh2_valid = (pci_mapreg_map(pa, AHD_PCI_IOADDR1, 453 1.9 thorpej PCI_MAPREG_TYPE_IO, 0, 454 1.9 thorpej &ahd->tags[1], &ahd->bshs[1], 455 1.9 thorpej NULL, NULL) == 0); 456 1.1 fvdl 457 1.1 fvdl if (ioh_valid && ioh2_valid) { 458 1.9 thorpej KASSERT(memh_valid == 0); 459 1.1 fvdl command &= ~PCI_COMMAND_MEM_ENABLE; 460 1.9 thorpej pci_conf_write(pa->pa_pc, pa->pa_tag, 461 1.9 thorpej PCI_COMMAND_STATUS_REG, command); 462 1.15 perry } 463 1.1 fvdl #ifdef AHD_DEBUG 464 1.32 dyoung printf("%s: doing io mapping shs0 0x%lx, shs1 0x%lx\n", 465 1.32 dyoung ahd_name(ahd), ahd->bshs[0], ahd->bshs[1]); 466 1.1 fvdl #endif 467 1.1 fvdl 468 1.1 fvdl } 469 1.1 fvdl 470 1.9 thorpej if (memh_valid == 0 && (ioh_valid == 0 || ioh2_valid == 0)) { 471 1.12 briggs aprint_error("%s: unable to map registers\n", ahd_name(ahd)); 472 1.1 fvdl return; 473 1.1 fvdl } 474 1.1 fvdl 475 1.12 briggs aprint_normal("\n"); 476 1.12 briggs aprint_naive("\n"); 477 1.1 fvdl 478 1.23 christos /* power up chip */ 479 1.26 dyoung if ((error = pci_activate(pa->pa_pc, pa->pa_tag, self, 480 1.23 christos pci_activate_null)) && error != EOPNOTSUPP) { 481 1.30 tsutsui aprint_error_dev(self, "cannot activate %d\n", error); 482 1.23 christos return; 483 1.23 christos } 484 1.1 fvdl /* 485 1.1 fvdl * Should we bother disabling 39Bit addressing 486 1.1 fvdl * based on installed memory? 487 1.1 fvdl */ 488 1.1 fvdl if (sizeof(bus_addr_t) > 4) 489 1.1 fvdl ahd->flags |= AHD_39BIT_ADDRESSING; 490 1.1 fvdl 491 1.1 fvdl /* 492 1.1 fvdl * If we need to support high memory, enable dual 493 1.1 fvdl * address cycles. This bit must be set to enable 494 1.1 fvdl * high address bit generation even if we are on a 495 1.1 fvdl * 64bit bus (PCI64BIT set in devconfig). 496 1.1 fvdl */ 497 1.1 fvdl if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) { 498 1.18 christos uint32_t dvconfig; 499 1.1 fvdl 500 1.12 briggs aprint_normal("%s: Enabling 39Bit Addressing\n", ahd_name(ahd)); 501 1.18 christos dvconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG); 502 1.18 christos dvconfig |= DACEN; 503 1.18 christos pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG, dvconfig); 504 1.1 fvdl } 505 1.15 perry 506 1.1 fvdl /* Ensure busmastering is enabled */ 507 1.1 fvdl reg = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG); 508 1.1 fvdl pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, 509 1.1 fvdl reg | PCI_COMMAND_MASTER_ENABLE); 510 1.1 fvdl 511 1.1 fvdl ahd_softc_init(ahd); 512 1.15 perry 513 1.1 fvdl /* 514 1.1 fvdl * Map the interrupt routines 515 1.1 fvdl */ 516 1.1 fvdl ahd->bus_intr = ahd_pci_intr; 517 1.1 fvdl 518 1.11 fvdl error = ahd_reset(ahd, /*reinit*/FALSE); 519 1.11 fvdl if (error != 0) { 520 1.11 fvdl ahd_free(ahd); 521 1.11 fvdl return; 522 1.11 fvdl } 523 1.11 fvdl 524 1.1 fvdl if (pci_intr_map(pa, &ih)) { 525 1.12 briggs aprint_error("%s: couldn't map interrupt\n", ahd_name(ahd)); 526 1.1 fvdl ahd_free(ahd); 527 1.1 fvdl return; 528 1.1 fvdl } 529 1.35 christos intrstr = pci_intr_string(pa->pa_pc, ih, intrbuf, sizeof(intrbuf)); 530 1.38 jdolecek ahd->ih = pci_intr_establish_xname(pa->pa_pc, ih, IPL_BIO, ahd_intr, 531 1.38 jdolecek ahd, device_xname(self)); 532 1.1 fvdl if (ahd->ih == NULL) { 533 1.12 briggs aprint_error("%s: couldn't establish interrupt", 534 1.1 fvdl ahd_name(ahd)); 535 1.1 fvdl if (intrstr != NULL) 536 1.12 briggs aprint_error(" at %s", intrstr); 537 1.12 briggs aprint_error("\n"); 538 1.1 fvdl ahd_free(ahd); 539 1.1 fvdl return; 540 1.1 fvdl } 541 1.1 fvdl if (intrstr != NULL) 542 1.12 briggs aprint_normal("%s: interrupting at %s\n", ahd_name(ahd), 543 1.1 fvdl intrstr); 544 1.1 fvdl 545 1.1 fvdl /* Get the size of the cache */ 546 1.1 fvdl ahd->pci_cachesize = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_BHLC_REG); 547 1.1 fvdl ahd->pci_cachesize *= 4; 548 1.1 fvdl 549 1.1 fvdl ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 550 1.1 fvdl /* See if we have a SEEPROM and perform auto-term */ 551 1.1 fvdl error = ahd_check_extport(ahd); 552 1.1 fvdl if (error != 0) 553 1.1 fvdl return; 554 1.1 fvdl 555 1.1 fvdl /* Core initialization */ 556 1.1 fvdl error = ahd_init(ahd); 557 1.1 fvdl if (error != 0) 558 1.1 fvdl return; 559 1.1 fvdl 560 1.1 fvdl /* 561 1.1 fvdl * Link this softc in with all other ahd instances. 562 1.1 fvdl */ 563 1.1 fvdl ahd_attach(ahd); 564 1.1 fvdl } 565 1.1 fvdl 566 1.31 tsutsui CFATTACH_DECL_NEW(ahd_pci, sizeof(struct ahd_softc), 567 1.19 thorpej ahd_pci_probe, ahd_pci_attach, NULL, NULL); 568 1.19 thorpej 569 1.10 fvdl /* 570 1.10 fvdl * Perform some simple tests that should catch situations where 571 1.10 fvdl * our registers are invalidly mapped. 572 1.10 fvdl */ 573 1.19 thorpej static int 574 1.10 fvdl ahd_pci_test_register_access(struct ahd_softc *ahd) 575 1.10 fvdl { 576 1.10 fvdl uint32_t cmd; 577 1.10 fvdl struct ahd_pci_busdata *bd = ahd->bus_data; 578 1.10 fvdl u_int targpcistat; 579 1.10 fvdl uint32_t pci_status1; 580 1.10 fvdl int error; 581 1.10 fvdl uint8_t hcntrl; 582 1.10 fvdl 583 1.10 fvdl error = EIO; 584 1.10 fvdl 585 1.10 fvdl /* 586 1.10 fvdl * Enable PCI error interrupt status, but suppress NMIs 587 1.10 fvdl * generated by SERR raised due to target aborts. 588 1.10 fvdl */ 589 1.10 fvdl cmd = pci_conf_read(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG); 590 1.10 fvdl pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG, 591 1.10 fvdl cmd & ~PCI_COMMAND_SERR_ENABLE); 592 1.10 fvdl 593 1.10 fvdl /* 594 1.10 fvdl * First a simple test to see if any 595 1.10 fvdl * registers can be read. Reading 596 1.10 fvdl * HCNTRL has no side effects and has 597 1.10 fvdl * at least one bit that is guaranteed to 598 1.10 fvdl * be zero so it is a good register to 599 1.10 fvdl * use for this test. 600 1.10 fvdl */ 601 1.10 fvdl hcntrl = ahd_inb(ahd, HCNTRL); 602 1.10 fvdl if (hcntrl == 0xFF) 603 1.10 fvdl goto fail; 604 1.10 fvdl 605 1.10 fvdl /* 606 1.10 fvdl * Next create a situation where write combining 607 1.10 fvdl * or read prefetching could be initiated by the 608 1.10 fvdl * CPU or host bridge. Our device does not support 609 1.40 andvar * either, so look for data corruption and/or flagged 610 1.10 fvdl * PCI errors. First pause without causing another 611 1.10 fvdl * chip reset. 612 1.10 fvdl */ 613 1.10 fvdl hcntrl &= ~CHIPRST; 614 1.10 fvdl ahd_outb(ahd, HCNTRL, hcntrl|PAUSE); 615 1.10 fvdl while (ahd_is_paused(ahd) == 0) 616 1.10 fvdl ; 617 1.10 fvdl 618 1.10 fvdl /* Clear any PCI errors that occurred before our driver attached. */ 619 1.10 fvdl ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); 620 1.10 fvdl targpcistat = ahd_inb(ahd, TARGPCISTAT); 621 1.10 fvdl ahd_outb(ahd, TARGPCISTAT, targpcistat); 622 1.10 fvdl pci_status1 = pci_conf_read(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG); 623 1.10 fvdl pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG, pci_status1); 624 1.10 fvdl ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 625 1.10 fvdl ahd_outb(ahd, CLRINT, CLRPCIINT); 626 1.10 fvdl 627 1.10 fvdl ahd_outb(ahd, SEQCTL0, PERRORDIS); 628 1.10 fvdl ahd_outl(ahd, SRAM_BASE, 0x5aa555aa); 629 1.10 fvdl if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa) 630 1.10 fvdl goto fail; 631 1.10 fvdl 632 1.10 fvdl if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) { 633 1.18 christos u_int trgpcistat; 634 1.10 fvdl 635 1.10 fvdl ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); 636 1.18 christos trgpcistat = ahd_inb(ahd, TARGPCISTAT); 637 1.18 christos if ((trgpcistat & STA) != 0) 638 1.10 fvdl goto fail; 639 1.10 fvdl } 640 1.10 fvdl 641 1.10 fvdl error = 0; 642 1.10 fvdl 643 1.10 fvdl fail: 644 1.10 fvdl if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) { 645 1.10 fvdl 646 1.10 fvdl ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); 647 1.10 fvdl targpcistat = ahd_inb(ahd, TARGPCISTAT); 648 1.10 fvdl 649 1.10 fvdl /* Silently clear any latched errors. */ 650 1.10 fvdl ahd_outb(ahd, TARGPCISTAT, targpcistat); 651 1.10 fvdl pci_status1 = pci_conf_read(bd->pc, bd->tag, 652 1.10 fvdl PCI_COMMAND_STATUS_REG); 653 1.10 fvdl pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG, 654 1.10 fvdl pci_status1); 655 1.10 fvdl ahd_outb(ahd, CLRINT, CLRPCIINT); 656 1.10 fvdl } 657 1.10 fvdl ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS); 658 1.10 fvdl pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG, cmd); 659 1.10 fvdl return (error); 660 1.10 fvdl } 661 1.1 fvdl 662 1.1 fvdl /* 663 1.1 fvdl * Check the external port logic for a serial eeprom 664 1.1 fvdl * and termination/cable detection contrls. 665 1.1 fvdl */ 666 1.1 fvdl static int 667 1.1 fvdl ahd_check_extport(struct ahd_softc *ahd) 668 1.1 fvdl { 669 1.4 thorpej struct vpd_config vpd; 670 1.1 fvdl struct seeprom_config *sc; 671 1.1 fvdl u_int adapter_control; 672 1.1 fvdl int have_seeprom; 673 1.1 fvdl int error; 674 1.1 fvdl 675 1.1 fvdl sc = ahd->seep_config; 676 1.1 fvdl have_seeprom = ahd_acquire_seeprom(ahd); 677 1.1 fvdl if (have_seeprom) { 678 1.1 fvdl u_int start_addr; 679 1.4 thorpej 680 1.4 thorpej /* 681 1.4 thorpej * Fetch VPD for this function and parse it. 682 1.4 thorpej */ 683 1.4 thorpej #ifdef AHD_DEBUG 684 1.4 thorpej printf("%s: Reading VPD from SEEPROM...", 685 1.4 thorpej ahd_name(ahd)); 686 1.4 thorpej #endif 687 1.4 thorpej /* Address is always in units of 16bit words */ 688 1.4 thorpej start_addr = ((2 * sizeof(*sc)) 689 1.4 thorpej + (sizeof(vpd) * (ahd->channel - 'A'))) / 2; 690 1.15 perry 691 1.4 thorpej error = ahd_read_seeprom(ahd, (uint16_t *)&vpd, 692 1.4 thorpej start_addr, sizeof(vpd)/2, 693 1.4 thorpej /*bytestream*/TRUE); 694 1.4 thorpej if (error == 0) 695 1.4 thorpej error = ahd_parse_vpddata(ahd, &vpd); 696 1.4 thorpej #ifdef AHD_DEBUG 697 1.4 thorpej printf("%s: VPD parsing %s\n", 698 1.4 thorpej ahd_name(ahd), 699 1.4 thorpej error == 0 ? "successful" : "failed"); 700 1.4 thorpej #endif 701 1.4 thorpej 702 1.1 fvdl #ifdef AHD_DEBUG 703 1.1 fvdl printf("%s: Reading SEEPROM...", ahd_name(ahd)); 704 1.1 fvdl #endif 705 1.1 fvdl 706 1.1 fvdl /* Address is always in units of 16bit words */ 707 1.1 fvdl start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A'); 708 1.1 fvdl 709 1.1 fvdl error = ahd_read_seeprom(ahd, (uint16_t *)sc, 710 1.4 thorpej start_addr, sizeof(*sc)/2, 711 1.4 thorpej /*bytestream*/FALSE); 712 1.1 fvdl 713 1.1 fvdl if (error != 0) { 714 1.1 fvdl #ifdef AHD_DEBUG 715 1.1 fvdl printf("Unable to read SEEPROM\n"); 716 1.1 fvdl #endif 717 1.1 fvdl have_seeprom = 0; 718 1.1 fvdl } else { 719 1.1 fvdl have_seeprom = ahd_verify_cksum(sc); 720 1.1 fvdl #ifdef AHD_DEBUG 721 1.1 fvdl if (have_seeprom == 0) 722 1.1 fvdl printf ("checksum error\n"); 723 1.1 fvdl else 724 1.1 fvdl printf ("done.\n"); 725 1.1 fvdl #endif 726 1.1 fvdl } 727 1.1 fvdl ahd_release_seeprom(ahd); 728 1.1 fvdl } 729 1.1 fvdl 730 1.1 fvdl if (!have_seeprom) { 731 1.1 fvdl u_int nvram_scb; 732 1.1 fvdl 733 1.1 fvdl /* 734 1.1 fvdl * Pull scratch ram settings and treat them as 735 1.1 fvdl * if they are the contents of an seeprom if 736 1.1 fvdl * the 'ADPT', 'BIOS', or 'ASPI' signature is found 737 1.1 fvdl * in SCB 0xFF. We manually compose the data as 16bit 738 1.1 fvdl * values to avoid endian issues. 739 1.1 fvdl */ 740 1.1 fvdl ahd_set_scbptr(ahd, 0xFF); 741 1.1 fvdl nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET); 742 1.1 fvdl if (nvram_scb != 0xFF 743 1.1 fvdl && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A' 744 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D' 745 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P' 746 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T') 747 1.1 fvdl || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B' 748 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I' 749 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O' 750 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S') 751 1.1 fvdl || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A' 752 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S' 753 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P' 754 1.1 fvdl && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) { 755 1.1 fvdl uint16_t *sc_data; 756 1.1 fvdl int i; 757 1.1 fvdl 758 1.1 fvdl ahd_set_scbptr(ahd, nvram_scb); 759 1.1 fvdl sc_data = (uint16_t *)sc; 760 1.1 fvdl for (i = 0; i < 64; i += 2) 761 1.1 fvdl *sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i); 762 1.1 fvdl have_seeprom = ahd_verify_cksum(sc); 763 1.1 fvdl if (have_seeprom) 764 1.1 fvdl ahd->flags |= AHD_SCB_CONFIG_USED; 765 1.1 fvdl } 766 1.1 fvdl } 767 1.1 fvdl 768 1.1 fvdl #ifdef AHD_DEBUG 769 1.1 fvdl if ((have_seeprom != 0) && (ahd_debug & AHD_DUMP_SEEPROM) != 0) { 770 1.4 thorpej uint16_t *sc_data; 771 1.4 thorpej int i; 772 1.1 fvdl 773 1.1 fvdl printf("%s: Seeprom Contents:", ahd_name(ahd)); 774 1.4 thorpej sc_data = (uint16_t *)sc; 775 1.1 fvdl for (i = 0; i < (sizeof(*sc)); i += 2) 776 1.4 thorpej printf("\n\t0x%.4x", sc_data[i]); 777 1.1 fvdl printf("\n"); 778 1.1 fvdl } 779 1.1 fvdl #endif 780 1.1 fvdl 781 1.1 fvdl if (!have_seeprom) { 782 1.12 briggs aprint_error("%s: No SEEPROM available.\n", ahd_name(ahd)); 783 1.1 fvdl ahd->flags |= AHD_USEDEFAULTS; 784 1.1 fvdl error = ahd_default_config(ahd); 785 1.1 fvdl adapter_control = CFAUTOTERM|CFSEAUTOTERM; 786 1.1 fvdl free(ahd->seep_config, M_DEVBUF); 787 1.1 fvdl ahd->seep_config = NULL; 788 1.1 fvdl } else { 789 1.1 fvdl error = ahd_parse_cfgdata(ahd, sc); 790 1.1 fvdl adapter_control = sc->adapter_control; 791 1.1 fvdl } 792 1.1 fvdl if (error != 0) 793 1.1 fvdl return (error); 794 1.1 fvdl 795 1.1 fvdl ahd_configure_termination(ahd, adapter_control); 796 1.1 fvdl 797 1.1 fvdl return (0); 798 1.1 fvdl } 799 1.1 fvdl 800 1.1 fvdl static void 801 1.1 fvdl ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) 802 1.1 fvdl { 803 1.1 fvdl int error; 804 1.1 fvdl u_int sxfrctl1; 805 1.1 fvdl uint8_t termctl; 806 1.1 fvdl uint32_t devconfig; 807 1.1 fvdl struct ahd_pci_busdata *bd = ahd->bus_data; 808 1.1 fvdl 809 1.1 fvdl devconfig = pci_conf_read(bd->pc, bd->tag, DEVCONFIG); 810 1.1 fvdl devconfig &= ~STPWLEVEL; 811 1.1 fvdl if ((ahd->flags & AHD_STPWLEVEL_A) != 0) 812 1.1 fvdl devconfig |= STPWLEVEL; 813 1.1 fvdl #ifdef AHD_DEBUG 814 1.1 fvdl printf("%s: STPWLEVEL is %s\n", 815 1.1 fvdl ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off"); 816 1.1 fvdl #endif 817 1.1 fvdl pci_conf_write(bd->pc, bd->tag, DEVCONFIG, devconfig); 818 1.15 perry 819 1.1 fvdl /* Make sure current sensing is off. */ 820 1.1 fvdl if ((ahd->flags & AHD_CURRENT_SENSING) != 0) { 821 1.1 fvdl (void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0); 822 1.1 fvdl } 823 1.1 fvdl 824 1.1 fvdl /* 825 1.1 fvdl * Read to sense. Write to set. 826 1.1 fvdl */ 827 1.1 fvdl error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl); 828 1.1 fvdl if ((adapter_control & CFAUTOTERM) == 0) { 829 1.7 fvdl if (bootverbose) 830 1.7 fvdl printf("%s: Manual Primary Termination\n", 831 1.7 fvdl ahd_name(ahd)); 832 1.1 fvdl termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH); 833 1.1 fvdl if ((adapter_control & CFSTERM) != 0) 834 1.1 fvdl termctl |= FLX_TERMCTL_ENPRILOW; 835 1.1 fvdl if ((adapter_control & CFWSTERM) != 0) 836 1.1 fvdl termctl |= FLX_TERMCTL_ENPRIHIGH; 837 1.1 fvdl } else if (error != 0) { 838 1.7 fvdl if (bootverbose) 839 1.7 fvdl printf("%s: Primary Auto-Term Sensing failed! " 840 1.7 fvdl "Using Defaults.\n", ahd_name(ahd)); 841 1.1 fvdl termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH; 842 1.1 fvdl } 843 1.1 fvdl 844 1.1 fvdl if ((adapter_control & CFSEAUTOTERM) == 0) { 845 1.7 fvdl if (bootverbose) 846 1.7 fvdl printf("%s: Manual Secondary Termination\n", 847 1.7 fvdl ahd_name(ahd)); 848 1.1 fvdl termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH); 849 1.1 fvdl if ((adapter_control & CFSELOWTERM) != 0) 850 1.1 fvdl termctl |= FLX_TERMCTL_ENSECLOW; 851 1.1 fvdl if ((adapter_control & CFSEHIGHTERM) != 0) 852 1.1 fvdl termctl |= FLX_TERMCTL_ENSECHIGH; 853 1.1 fvdl } else if (error != 0) { 854 1.7 fvdl if (bootverbose) 855 1.7 fvdl printf("%s: Secondary Auto-Term Sensing failed! " 856 1.7 fvdl "Using Defaults.\n", ahd_name(ahd)); 857 1.1 fvdl termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH; 858 1.1 fvdl } 859 1.1 fvdl 860 1.1 fvdl /* 861 1.1 fvdl * Now set the termination based on what we found. 862 1.1 fvdl */ 863 1.1 fvdl sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; 864 1.1 fvdl if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { 865 1.1 fvdl ahd->flags |= AHD_TERM_ENB_A; 866 1.1 fvdl sxfrctl1 |= STPWEN; 867 1.1 fvdl } 868 1.1 fvdl /* Must set the latch once in order to be effective. */ 869 1.1 fvdl ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN); 870 1.1 fvdl ahd_outb(ahd, SXFRCTL1, sxfrctl1); 871 1.1 fvdl 872 1.1 fvdl error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl); 873 1.1 fvdl if (error != 0) { 874 1.12 briggs aprint_error("%s: Unable to set termination settings!\n", 875 1.1 fvdl ahd_name(ahd)); 876 1.1 fvdl } else { 877 1.7 fvdl if (bootverbose) { 878 1.7 fvdl printf("%s: Primary High byte termination %sabled\n", 879 1.7 fvdl ahd_name(ahd), 880 1.7 fvdl (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis"); 881 1.7 fvdl 882 1.7 fvdl printf("%s: Primary Low byte termination %sabled\n", 883 1.7 fvdl ahd_name(ahd), 884 1.7 fvdl (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis"); 885 1.7 fvdl 886 1.7 fvdl printf("%s: Secondary High byte termination %sabled\n", 887 1.7 fvdl ahd_name(ahd), 888 1.7 fvdl (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis"); 889 1.7 fvdl 890 1.7 fvdl printf("%s: Secondary Low byte termination %sabled\n", 891 1.7 fvdl ahd_name(ahd), 892 1.7 fvdl (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis"); 893 1.7 fvdl } 894 1.1 fvdl } 895 1.1 fvdl return; 896 1.1 fvdl } 897 1.1 fvdl 898 1.1 fvdl #define DPE 0x80 899 1.1 fvdl #define SSE 0x40 900 1.1 fvdl #define RMA 0x20 901 1.1 fvdl #define RTA 0x10 902 1.1 fvdl #define STA 0x08 903 1.1 fvdl #define DPR 0x01 904 1.1 fvdl 905 1.1 fvdl static const char *split_status_source[] = 906 1.1 fvdl { 907 1.1 fvdl "DFF0", 908 1.1 fvdl "DFF1", 909 1.1 fvdl "OVLY", 910 1.1 fvdl "CMC", 911 1.1 fvdl }; 912 1.1 fvdl 913 1.1 fvdl static const char *pci_status_source[] = 914 1.1 fvdl { 915 1.1 fvdl "DFF0", 916 1.1 fvdl "DFF1", 917 1.1 fvdl "SG", 918 1.1 fvdl "CMC", 919 1.1 fvdl "OVLY", 920 1.1 fvdl "NONE", 921 1.1 fvdl "MSI", 922 1.1 fvdl "TARG" 923 1.1 fvdl }; 924 1.1 fvdl 925 1.1 fvdl static const char *split_status_strings[] = 926 1.1 fvdl { 927 1.1 fvdl "%s: Received split response in %s.\n", 928 1.1 fvdl "%s: Received split completion error message in %s\n", 929 1.1 fvdl "%s: Receive overrun in %s\n", 930 1.1 fvdl "%s: Count not complete in %s\n", 931 1.1 fvdl "%s: Split completion data bucket in %s\n", 932 1.1 fvdl "%s: Split completion address error in %s\n", 933 1.1 fvdl "%s: Split completion byte count error in %s\n", 934 1.1 fvdl "%s: Signaled Target-abort to early terminate a split in %s\n" 935 1.1 fvdl }; 936 1.1 fvdl 937 1.1 fvdl static const char *pci_status_strings[] = 938 1.1 fvdl { 939 1.1 fvdl "%s: Data Parity Error has been reported via PERR# in %s\n", 940 1.1 fvdl "%s: Target initial wait state error in %s\n", 941 1.1 fvdl "%s: Split completion read data parity error in %s\n", 942 1.1 fvdl "%s: Split completion address attribute parity error in %s\n", 943 1.1 fvdl "%s: Received a Target Abort in %s\n", 944 1.1 fvdl "%s: Received a Master Abort in %s\n", 945 1.1 fvdl "%s: Signal System Error Detected in %s\n", 946 1.1 fvdl "%s: Address or Write Phase Parity Error Detected in %s.\n" 947 1.1 fvdl }; 948 1.1 fvdl 949 1.19 thorpej static int 950 1.1 fvdl ahd_pci_intr(struct ahd_softc *ahd) 951 1.1 fvdl { 952 1.1 fvdl uint8_t pci_status[8]; 953 1.1 fvdl ahd_mode_state saved_modes; 954 1.1 fvdl u_int pci_status1; 955 1.1 fvdl u_int intstat; 956 1.1 fvdl u_int i; 957 1.1 fvdl u_int reg; 958 1.1 fvdl struct ahd_pci_busdata *bd = ahd->bus_data; 959 1.15 perry 960 1.1 fvdl intstat = ahd_inb(ahd, INTSTAT); 961 1.1 fvdl 962 1.1 fvdl if ((intstat & SPLTINT) != 0) 963 1.1 fvdl ahd_pci_split_intr(ahd, intstat); 964 1.1 fvdl 965 1.1 fvdl if ((intstat & PCIINT) == 0) 966 1.1 fvdl return 0; 967 1.1 fvdl 968 1.1 fvdl printf("%s: PCI error Interrupt\n", ahd_name(ahd)); 969 1.1 fvdl saved_modes = ahd_save_modes(ahd); 970 1.1 fvdl ahd_dump_card_state(ahd); 971 1.1 fvdl ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); 972 1.1 fvdl for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) { 973 1.1 fvdl 974 1.1 fvdl if (i == 5) 975 1.1 fvdl continue; 976 1.1 fvdl pci_status[i] = ahd_inb(ahd, reg); 977 1.1 fvdl /* Clear latched errors. So our interrupt deasserts. */ 978 1.1 fvdl ahd_outb(ahd, reg, pci_status[i]); 979 1.1 fvdl } 980 1.1 fvdl 981 1.1 fvdl for (i = 0; i < 8; i++) { 982 1.1 fvdl u_int bit; 983 1.15 perry 984 1.1 fvdl if (i == 5) 985 1.1 fvdl continue; 986 1.1 fvdl 987 1.1 fvdl for (bit = 0; bit < 8; bit++) { 988 1.1 fvdl 989 1.1 fvdl if ((pci_status[i] & (0x1 << bit)) != 0) { 990 1.1 fvdl static const char *s; 991 1.1 fvdl 992 1.1 fvdl s = pci_status_strings[bit]; 993 1.1 fvdl if (i == 7/*TARG*/ && bit == 3) 994 1.1 fvdl s = "%s: Signaled Target Abort\n"; 995 1.1 fvdl printf(s, ahd_name(ahd), pci_status_source[i]); 996 1.1 fvdl } 997 1.15 perry } 998 1.1 fvdl } 999 1.1 fvdl pci_status1 = pci_conf_read(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG); 1000 1.1 fvdl pci_conf_write(bd->pc, bd->tag, PCI_COMMAND_STATUS_REG , pci_status1); 1001 1.1 fvdl 1002 1.1 fvdl ahd_restore_modes(ahd, saved_modes); 1003 1.1 fvdl ahd_outb(ahd, CLRINT, CLRPCIINT); 1004 1.1 fvdl ahd_unpause(ahd); 1005 1.1 fvdl 1006 1.1 fvdl return 1; 1007 1.1 fvdl } 1008 1.1 fvdl 1009 1.1 fvdl static void 1010 1.25 christos ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat) 1011 1.1 fvdl { 1012 1.1 fvdl uint8_t split_status[4]; 1013 1.1 fvdl uint8_t split_status1[4]; 1014 1.1 fvdl uint8_t sg_split_status[2]; 1015 1.1 fvdl uint8_t sg_split_status1[2]; 1016 1.1 fvdl ahd_mode_state saved_modes; 1017 1.1 fvdl u_int i; 1018 1.1 fvdl pcireg_t pcix_status; 1019 1.1 fvdl struct ahd_pci_busdata *bd = ahd->bus_data; 1020 1.1 fvdl 1021 1.1 fvdl /* 1022 1.1 fvdl * Check for splits in all modes. Modes 0 and 1 1023 1.1 fvdl * additionally have SG engine splits to look at. 1024 1.1 fvdl */ 1025 1.1 fvdl pcix_status = pci_conf_read(bd->pc, bd->tag, 1026 1.34 msaitoh bd->pcix_off + PCIX_STATUS); 1027 1.1 fvdl printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n", 1028 1.1 fvdl ahd_name(ahd), pcix_status); 1029 1.1 fvdl 1030 1.1 fvdl saved_modes = ahd_save_modes(ahd); 1031 1.1 fvdl for (i = 0; i < 4; i++) { 1032 1.1 fvdl ahd_set_modes(ahd, i, i); 1033 1.1 fvdl 1034 1.1 fvdl split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0); 1035 1.1 fvdl split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1); 1036 1.1 fvdl /* Clear latched errors. So our interrupt deasserts. */ 1037 1.1 fvdl ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]); 1038 1.1 fvdl ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]); 1039 1.4 thorpej if (i > 1) 1040 1.1 fvdl continue; 1041 1.1 fvdl sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0); 1042 1.1 fvdl sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1); 1043 1.1 fvdl /* Clear latched errors. So our interrupt deasserts. */ 1044 1.1 fvdl ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]); 1045 1.1 fvdl ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]); 1046 1.1 fvdl } 1047 1.1 fvdl 1048 1.1 fvdl for (i = 0; i < 4; i++) { 1049 1.1 fvdl u_int bit; 1050 1.1 fvdl 1051 1.1 fvdl for (bit = 0; bit < 8; bit++) { 1052 1.1 fvdl 1053 1.1 fvdl if ((split_status[i] & (0x1 << bit)) != 0) { 1054 1.1 fvdl static const char *s; 1055 1.1 fvdl 1056 1.1 fvdl s = split_status_strings[bit]; 1057 1.1 fvdl printf(s, ahd_name(ahd), 1058 1.1 fvdl split_status_source[i]); 1059 1.1 fvdl } 1060 1.1 fvdl 1061 1.4 thorpej if (i > 0) 1062 1.1 fvdl continue; 1063 1.1 fvdl 1064 1.1 fvdl if ((sg_split_status[i] & (0x1 << bit)) != 0) { 1065 1.1 fvdl static const char *s; 1066 1.1 fvdl 1067 1.1 fvdl s = split_status_strings[bit]; 1068 1.1 fvdl printf(s, ahd_name(ahd), "SG"); 1069 1.1 fvdl } 1070 1.1 fvdl } 1071 1.1 fvdl } 1072 1.1 fvdl /* 1073 1.1 fvdl * Clear PCI-X status bits. 1074 1.1 fvdl */ 1075 1.34 msaitoh pci_conf_write(bd->pc, bd->tag, bd->pcix_off + PCIX_STATUS, 1076 1.1 fvdl pcix_status); 1077 1.1 fvdl ahd_outb(ahd, CLRINT, CLRSPLTINT); 1078 1.1 fvdl ahd_restore_modes(ahd, saved_modes); 1079 1.5 thorpej } 1080 1.5 thorpej 1081 1.5 thorpej static int 1082 1.5 thorpej ahd_aic7901_setup(struct ahd_softc *ahd, struct pci_attach_args *pa) 1083 1.5 thorpej { 1084 1.5 thorpej 1085 1.5 thorpej ahd->chip = AHD_AIC7901; 1086 1.6 thorpej ahd->features = AHD_AIC7901_FE; 1087 1.6 thorpej return (ahd_aic790X_setup(ahd, pa)); 1088 1.1 fvdl } 1089 1.1 fvdl 1090 1.1 fvdl static int 1091 1.1 fvdl ahd_aic7901A_setup(struct ahd_softc *ahd, struct pci_attach_args *pa) 1092 1.1 fvdl { 1093 1.1 fvdl 1094 1.1 fvdl ahd->chip = AHD_AIC7901A; 1095 1.6 thorpej ahd->features = AHD_AIC7901A_FE; 1096 1.6 thorpej return (ahd_aic790X_setup(ahd, pa)); 1097 1.6 thorpej } 1098 1.6 thorpej 1099 1.6 thorpej static int 1100 1.6 thorpej ahd_aic7902_setup(struct ahd_softc *ahd, struct pci_attach_args *pa) 1101 1.6 thorpej { 1102 1.6 thorpej 1103 1.6 thorpej ahd->chip = AHD_AIC7902; 1104 1.6 thorpej ahd->features = AHD_AIC7902_FE; 1105 1.6 thorpej return (ahd_aic790X_setup(ahd, pa)); 1106 1.1 fvdl } 1107 1.1 fvdl 1108 1.1 fvdl static int 1109 1.6 thorpej ahd_aic790X_setup(struct ahd_softc *ahd, struct pci_attach_args *pa) 1110 1.1 fvdl { 1111 1.1 fvdl u_int rev; 1112 1.1 fvdl 1113 1.1 fvdl rev = PCI_REVISION(pa->pa_class); 1114 1.1 fvdl #ifdef AHD_DEBUG 1115 1.1 fvdl printf("\n%s: aic7902 chip revision 0x%x\n", ahd_name(ahd), rev); 1116 1.1 fvdl #endif 1117 1.1 fvdl if (rev < ID_AIC7902_PCI_REV_A4) { 1118 1.29 tsutsui aprint_error("%s: Unable to attach to " 1119 1.29 tsutsui "unsupported chip revision %d\n", ahd_name(ahd), rev); 1120 1.29 tsutsui pci_conf_write(pa->pa_pc, pa->pa_tag, 1121 1.29 tsutsui PCI_COMMAND_STATUS_REG, 0); 1122 1.1 fvdl return (ENXIO); 1123 1.1 fvdl } 1124 1.1 fvdl 1125 1.1 fvdl ahd->channel = (pa->pa_function == 1) ? 'B' : 'A'; 1126 1.1 fvdl if (rev < ID_AIC7902_PCI_REV_B0) { 1127 1.1 fvdl /* 1128 1.1 fvdl * Enable A series workarounds. 1129 1.1 fvdl */ 1130 1.1 fvdl ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG 1131 1.1 fvdl | AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG 1132 1.1 fvdl | AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG 1133 1.1 fvdl | AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG 1134 1.1 fvdl | AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG 1135 1.1 fvdl | AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG 1136 1.1 fvdl | AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG 1137 1.1 fvdl | AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG 1138 1.1 fvdl | AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG 1139 1.4 thorpej | AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG 1140 1.4 thorpej | AHD_FAINT_LED_BUG; 1141 1.1 fvdl 1142 1.1 fvdl 1143 1.1 fvdl /* 1144 1.13 wiz * IO Cell parameter setup. 1145 1.1 fvdl */ 1146 1.1 fvdl AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29); 1147 1.1 fvdl 1148 1.1 fvdl if ((ahd->flags & AHD_HP_BOARD) == 0) 1149 1.1 fvdl AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA); 1150 1.1 fvdl } else { 1151 1.1 fvdl u_int devconfig1; 1152 1.1 fvdl 1153 1.1 fvdl ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS 1154 1.1 fvdl | AHD_NEW_DFCNTRL_OPTS; 1155 1.6 thorpej ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG; 1156 1.6 thorpej 1157 1.6 thorpej /* 1158 1.6 thorpej * Some issues have been resolved in the 7901B. 1159 1.6 thorpej */ 1160 1.6 thorpej if ((ahd->features & AHD_MULTI_FUNC) != 0) 1161 1.6 thorpej ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG; 1162 1.1 fvdl 1163 1.1 fvdl /* 1164 1.13 wiz * IO Cell parameter setup. 1165 1.1 fvdl */ 1166 1.1 fvdl AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29); 1167 1.1 fvdl AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB); 1168 1.1 fvdl AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF); 1169 1.1 fvdl 1170 1.1 fvdl /* 1171 1.1 fvdl * Set the PREQDIS bit for H2B which disables some workaround 1172 1.1 fvdl * that doesn't work on regular PCI busses. 1173 1.1 fvdl * XXX - Find out exactly what this does from the hardware 1174 1.1 fvdl * folks! 1175 1.1 fvdl */ 1176 1.1 fvdl devconfig1 = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG1); 1177 1.29 tsutsui pci_conf_write(pa->pa_pc, pa->pa_tag, 1178 1.29 tsutsui DEVCONFIG1, devconfig1|PREQDIS); 1179 1.1 fvdl devconfig1 = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG1); 1180 1.1 fvdl } 1181 1.1 fvdl 1182 1.1 fvdl return (0); 1183 1.1 fvdl } 1184