1098ca2bdSWarner Losh /*- 2717d4247SJustin T. Gibbs * Product specific probe and attach routines for: 3717d4247SJustin T. Gibbs * 3940, 2940, aic7895, aic7890, aic7880, 4717d4247SJustin T. Gibbs * aic7870, aic7860 and aic7850 SCSI controllers 5717d4247SJustin T. Gibbs * 6*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 7*718cf2ccSPedro F. Giffuni * 88f214efcSJustin T. Gibbs * Copyright (c) 1994-2001 Justin T. Gibbs. 98f214efcSJustin T. Gibbs * Copyright (c) 2000-2001 Adaptec Inc. 10717d4247SJustin T. Gibbs * All rights reserved. 11717d4247SJustin T. Gibbs * 12717d4247SJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 13717d4247SJustin T. Gibbs * modification, are permitted provided that the following conditions 14717d4247SJustin T. Gibbs * are met: 15717d4247SJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 16717d4247SJustin T. Gibbs * notice, this list of conditions, and the following disclaimer, 178f214efcSJustin T. Gibbs * without modification. 188f214efcSJustin T. Gibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer 198f214efcSJustin T. Gibbs * substantially similar to the "NO WARRANTY" disclaimer below 208f214efcSJustin T. Gibbs * ("Disclaimer") and any redistribution must be conditioned upon 218f214efcSJustin T. Gibbs * including a substantially similar Disclaimer requirement for further 228f214efcSJustin T. Gibbs * binary redistribution. 238f214efcSJustin T. Gibbs * 3. Neither the names of the above-listed copyright holders nor the names 248f214efcSJustin T. Gibbs * of any contributors may be used to endorse or promote products derived 258f214efcSJustin T. Gibbs * from this software without specific prior written permission. 26717d4247SJustin T. Gibbs * 27717d4247SJustin T. Gibbs * Alternatively, this software may be distributed under the terms of the 288f214efcSJustin T. Gibbs * GNU General Public License ("GPL") version 2 as published by the Free 298f214efcSJustin T. Gibbs * Software Foundation. 30717d4247SJustin T. Gibbs * 318f214efcSJustin T. Gibbs * NO WARRANTY 328f214efcSJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 338f214efcSJustin T. Gibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 348f214efcSJustin T. Gibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 358f214efcSJustin T. Gibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 368f214efcSJustin T. Gibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37717d4247SJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38717d4247SJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 398f214efcSJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 408f214efcSJustin T. Gibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 418f214efcSJustin T. Gibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 428f214efcSJustin T. Gibbs * POSSIBILITY OF SUCH DAMAGES. 43717d4247SJustin T. Gibbs * 44b3b25f2cSJustin T. Gibbs * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#78 $ 45717d4247SJustin T. Gibbs */ 46717d4247SJustin T. Gibbs 478f214efcSJustin T. Gibbs #include <dev/aic7xxx/aic7xxx_osm.h> 48717d4247SJustin T. Gibbs #include <dev/aic7xxx/aic7xxx_inline.h> 49717d4247SJustin T. Gibbs #include <dev/aic7xxx/aic7xxx_93cx6.h> 50717d4247SJustin T. Gibbs 51717d4247SJustin T. Gibbs static __inline uint64_t 52717d4247SJustin T. Gibbs ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) 53717d4247SJustin T. Gibbs { 54717d4247SJustin T. Gibbs uint64_t id; 55717d4247SJustin T. Gibbs 56717d4247SJustin T. Gibbs id = subvendor 57717d4247SJustin T. Gibbs | (subdevice << 16) 58717d4247SJustin T. Gibbs | ((uint64_t)vendor << 32) 59717d4247SJustin T. Gibbs | ((uint64_t)device << 48); 60717d4247SJustin T. Gibbs 61717d4247SJustin T. Gibbs return (id); 62717d4247SJustin T. Gibbs } 63717d4247SJustin T. Gibbs 64717d4247SJustin T. Gibbs #define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull 65717d4247SJustin T. Gibbs #define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull 66bfadd24dSJustin T. Gibbs #define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull 671478c711SJustin T. Gibbs #define ID_9005_SISL_MASK 0x000FFFFF00000000ull 681478c711SJustin T. Gibbs #define ID_9005_SISL_ID 0x0005900500000000ull 69717d4247SJustin T. Gibbs #define ID_AIC7850 0x5078900400000000ull 70177799b5SJustin T. Gibbs #define ID_AHA_2902_04_10_15_20C_30C 0x5078900478509004ull 71717d4247SJustin T. Gibbs #define ID_AIC7855 0x5578900400000000ull 72717d4247SJustin T. Gibbs #define ID_AIC7859 0x3860900400000000ull 73717d4247SJustin T. Gibbs #define ID_AHA_2930CU 0x3860900438699004ull 74717d4247SJustin T. Gibbs #define ID_AIC7860 0x6078900400000000ull 75717d4247SJustin T. Gibbs #define ID_AIC7860C 0x6078900478609004ull 76717d4247SJustin T. Gibbs #define ID_AHA_1480A 0x6075900400000000ull 77717d4247SJustin T. Gibbs #define ID_AHA_2940AU_0 0x6178900400000000ull 78717d4247SJustin T. Gibbs #define ID_AHA_2940AU_1 0x6178900478619004ull 79717d4247SJustin T. Gibbs #define ID_AHA_2940AU_CN 0x2178900478219004ull 80717d4247SJustin T. Gibbs #define ID_AHA_2930C_VAR 0x6038900438689004ull 81717d4247SJustin T. Gibbs 82717d4247SJustin T. Gibbs #define ID_AIC7870 0x7078900400000000ull 83717d4247SJustin T. Gibbs #define ID_AHA_2940 0x7178900400000000ull 84717d4247SJustin T. Gibbs #define ID_AHA_3940 0x7278900400000000ull 85717d4247SJustin T. Gibbs #define ID_AHA_398X 0x7378900400000000ull 86717d4247SJustin T. Gibbs #define ID_AHA_2944 0x7478900400000000ull 87717d4247SJustin T. Gibbs #define ID_AHA_3944 0x7578900400000000ull 88717d4247SJustin T. Gibbs #define ID_AHA_4944 0x7678900400000000ull 89717d4247SJustin T. Gibbs 90717d4247SJustin T. Gibbs #define ID_AIC7880 0x8078900400000000ull 91717d4247SJustin T. Gibbs #define ID_AIC7880_B 0x8078900478809004ull 92717d4247SJustin T. Gibbs #define ID_AHA_2940U 0x8178900400000000ull 93717d4247SJustin T. Gibbs #define ID_AHA_3940U 0x8278900400000000ull 94717d4247SJustin T. Gibbs #define ID_AHA_2944U 0x8478900400000000ull 95717d4247SJustin T. Gibbs #define ID_AHA_3944U 0x8578900400000000ull 96717d4247SJustin T. Gibbs #define ID_AHA_398XU 0x8378900400000000ull 97717d4247SJustin T. Gibbs #define ID_AHA_4944U 0x8678900400000000ull 98717d4247SJustin T. Gibbs #define ID_AHA_2940UB 0x8178900478819004ull 99717d4247SJustin T. Gibbs #define ID_AHA_2930U 0x8878900478889004ull 100717d4247SJustin T. Gibbs #define ID_AHA_2940U_PRO 0x8778900478879004ull 101717d4247SJustin T. Gibbs #define ID_AHA_2940U_CN 0x0078900478009004ull 102717d4247SJustin T. Gibbs 103717d4247SJustin T. Gibbs #define ID_AIC7895 0x7895900478959004ull 1041478c711SJustin T. Gibbs #define ID_AIC7895_ARO 0x7890900478939004ull 1051478c711SJustin T. Gibbs #define ID_AIC7895_ARO_MASK 0xFFF0FFFFFFFFFFFFull 106717d4247SJustin T. Gibbs #define ID_AHA_2940U_DUAL 0x7895900478919004ull 107717d4247SJustin T. Gibbs #define ID_AHA_3940AU 0x7895900478929004ull 108717d4247SJustin T. Gibbs #define ID_AHA_3944AU 0x7895900478949004ull 109717d4247SJustin T. Gibbs 110717d4247SJustin T. Gibbs #define ID_AIC7890 0x001F9005000F9005ull 1111478c711SJustin T. Gibbs #define ID_AIC7890_ARO 0x00139005000F9005ull 112717d4247SJustin T. Gibbs #define ID_AAA_131U2 0x0013900500039005ull 113717d4247SJustin T. Gibbs #define ID_AHA_2930U2 0x0011900501819005ull 114717d4247SJustin T. Gibbs #define ID_AHA_2940U2B 0x00109005A1009005ull 115717d4247SJustin T. Gibbs #define ID_AHA_2940U2_OEM 0x0010900521809005ull 116717d4247SJustin T. Gibbs #define ID_AHA_2940U2 0x00109005A1809005ull 117717d4247SJustin T. Gibbs #define ID_AHA_2950U2B 0x00109005E1009005ull 118717d4247SJustin T. Gibbs 119717d4247SJustin T. Gibbs #define ID_AIC7892 0x008F9005FFFF9005ull 1201478c711SJustin T. Gibbs #define ID_AIC7892_ARO 0x00839005FFFF9005ull 121717d4247SJustin T. Gibbs #define ID_AHA_29160 0x00809005E2A09005ull 122717d4247SJustin T. Gibbs #define ID_AHA_29160_CPQ 0x00809005E2A00E11ull 123717d4247SJustin T. Gibbs #define ID_AHA_29160N 0x0080900562A09005ull 12456a7c4a8SJustin T. Gibbs #define ID_AHA_29160C 0x0080900562209005ull 125717d4247SJustin T. Gibbs #define ID_AHA_29160B 0x00809005E2209005ull 126717d4247SJustin T. Gibbs #define ID_AHA_19160B 0x0081900562A19005ull 127b3b25f2cSJustin T. Gibbs #define ID_AHA_2915_30LP 0x0082900502109005ull 128717d4247SJustin T. Gibbs 129717d4247SJustin T. Gibbs #define ID_AIC7896 0x005F9005FFFF9005ull 1301478c711SJustin T. Gibbs #define ID_AIC7896_ARO 0x00539005FFFF9005ull 131717d4247SJustin T. Gibbs #define ID_AHA_3950U2B_0 0x00509005FFFF9005ull 132717d4247SJustin T. Gibbs #define ID_AHA_3950U2B_1 0x00509005F5009005ull 133717d4247SJustin T. Gibbs #define ID_AHA_3950U2D_0 0x00519005FFFF9005ull 134717d4247SJustin T. Gibbs #define ID_AHA_3950U2D_1 0x00519005B5009005ull 135717d4247SJustin T. Gibbs 136717d4247SJustin T. Gibbs #define ID_AIC7899 0x00CF9005FFFF9005ull 1371478c711SJustin T. Gibbs #define ID_AIC7899_ARO 0x00C39005FFFF9005ull 1386fb77fefSJustin T. Gibbs #define ID_AHA_3960D 0x00C09005F6209005ull 139717d4247SJustin T. Gibbs #define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull 140717d4247SJustin T. Gibbs 141717d4247SJustin T. Gibbs #define ID_AIC7810 0x1078900400000000ull 142717d4247SJustin T. Gibbs #define ID_AIC7815 0x7815900400000000ull 143717d4247SJustin T. Gibbs 144bfadd24dSJustin T. Gibbs #define DEVID_9005_TYPE(id) ((id) & 0xF) 145bfadd24dSJustin T. Gibbs #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ 146bfadd24dSJustin T. Gibbs #define DEVID_9005_TYPE_AAA 0x3 /* RAID Card */ 1478f214efcSJustin T. Gibbs #define DEVID_9005_TYPE_SISL 0x5 /* Container ROMB */ 148bfadd24dSJustin T. Gibbs #define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ 149bfadd24dSJustin T. Gibbs 150bfadd24dSJustin T. Gibbs #define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4) 151bfadd24dSJustin T. Gibbs #define DEVID_9005_MAXRATE_U160 0x0 152bfadd24dSJustin T. Gibbs #define DEVID_9005_MAXRATE_ULTRA2 0x1 153bfadd24dSJustin T. Gibbs #define DEVID_9005_MAXRATE_ULTRA 0x2 154bfadd24dSJustin T. Gibbs #define DEVID_9005_MAXRATE_FAST 0x3 155bfadd24dSJustin T. Gibbs 156bfadd24dSJustin T. Gibbs #define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6) 157bfadd24dSJustin T. Gibbs 158bfadd24dSJustin T. Gibbs #define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8) 159bfadd24dSJustin T. Gibbs #define DEVID_9005_CLASS_SPI 0x0 /* Parallel SCSI */ 160bfadd24dSJustin T. Gibbs 161f8838555SJustin T. Gibbs #define SUBID_9005_TYPE(id) ((id) & 0xF) 162f8838555SJustin T. Gibbs #define SUBID_9005_TYPE_MB 0xF /* On Motherboard */ 163f8838555SJustin T. Gibbs #define SUBID_9005_TYPE_CARD 0x0 /* Standard Card */ 164f8838555SJustin T. Gibbs #define SUBID_9005_TYPE_LCCARD 0x1 /* Low Cost Card */ 165f8838555SJustin T. Gibbs #define SUBID_9005_TYPE_RAID 0x3 /* Combined with Raid */ 166f8838555SJustin T. Gibbs 1671478c711SJustin T. Gibbs #define SUBID_9005_TYPE_KNOWN(id) \ 1681478c711SJustin T. Gibbs ((((id) & 0xF) == SUBID_9005_TYPE_MB) \ 1691478c711SJustin T. Gibbs || (((id) & 0xF) == SUBID_9005_TYPE_CARD) \ 1701478c711SJustin T. Gibbs || (((id) & 0xF) == SUBID_9005_TYPE_LCCARD) \ 1711478c711SJustin T. Gibbs || (((id) & 0xF) == SUBID_9005_TYPE_RAID)) 1721478c711SJustin T. Gibbs 173f8838555SJustin T. Gibbs #define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4) 174f8838555SJustin T. Gibbs #define SUBID_9005_MAXRATE_ULTRA2 0x0 175f8838555SJustin T. Gibbs #define SUBID_9005_MAXRATE_ULTRA 0x1 176f8838555SJustin T. Gibbs #define SUBID_9005_MAXRATE_U160 0x2 177f8838555SJustin T. Gibbs #define SUBID_9005_MAXRATE_RESERVED 0x3 178f8838555SJustin T. Gibbs 179f8838555SJustin T. Gibbs #define SUBID_9005_SEEPTYPE(id) \ 180f8838555SJustin T. Gibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 181f8838555SJustin T. Gibbs ? ((id) & 0xC0) >> 6 \ 182f8838555SJustin T. Gibbs : ((id) & 0x300) >> 8) 183f8838555SJustin T. Gibbs #define SUBID_9005_SEEPTYPE_NONE 0x0 184f8838555SJustin T. Gibbs #define SUBID_9005_SEEPTYPE_1K 0x1 185f8838555SJustin T. Gibbs #define SUBID_9005_SEEPTYPE_2K_4K 0x2 186f8838555SJustin T. Gibbs #define SUBID_9005_SEEPTYPE_RESERVED 0x3 187f8838555SJustin T. Gibbs #define SUBID_9005_AUTOTERM(id) \ 188f8838555SJustin T. Gibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 189f8838555SJustin T. Gibbs ? (((id) & 0x400) >> 10) == 0 \ 190f8838555SJustin T. Gibbs : (((id) & 0x40) >> 6) == 0) 191f8838555SJustin T. Gibbs 192f8838555SJustin T. Gibbs #define SUBID_9005_NUMCHAN(id) \ 193f8838555SJustin T. Gibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 194f8838555SJustin T. Gibbs ? ((id) & 0x300) >> 8 \ 195f8838555SJustin T. Gibbs : ((id) & 0xC00) >> 10) 196f8838555SJustin T. Gibbs 197f8838555SJustin T. Gibbs #define SUBID_9005_LEGACYCONN(id) \ 198f8838555SJustin T. Gibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 199f8838555SJustin T. Gibbs ? 0 \ 200f8838555SJustin T. Gibbs : ((id) & 0x80) >> 7) 201f8838555SJustin T. Gibbs 202f8838555SJustin T. Gibbs #define SUBID_9005_MFUNCENB(id) \ 203f8838555SJustin T. Gibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 204f8838555SJustin T. Gibbs ? ((id) & 0x800) >> 11 \ 205f8838555SJustin T. Gibbs : ((id) & 0x1000) >> 12) 206f8838555SJustin T. Gibbs /* 207f8838555SJustin T. Gibbs * Informational only. Should use chip register to be 2088f214efcSJustin T. Gibbs * certain, but may be use in identification strings. 209f8838555SJustin T. Gibbs */ 210f8838555SJustin T. Gibbs #define SUBID_9005_CARD_SCSIWIDTH_MASK 0x2000 211f8838555SJustin T. Gibbs #define SUBID_9005_CARD_PCIWIDTH_MASK 0x4000 212f8838555SJustin T. Gibbs #define SUBID_9005_CARD_SEDIFF_MASK 0x8000 21356a7c4a8SJustin T. Gibbs 2146fb77fefSJustin T. Gibbs static ahc_device_setup_t ahc_aic785X_setup; 215717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7860_setup; 216a5847d5cSJustin T. Gibbs static ahc_device_setup_t ahc_apa1480_setup; 217717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7870_setup; 218717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha394X_setup; 219717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha494X_setup; 220717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha398X_setup; 221717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7880_setup; 222a5847d5cSJustin T. Gibbs static ahc_device_setup_t ahc_aha2940Pro_setup; 223717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha394XU_setup; 224717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha398XU_setup; 225717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7890_setup; 226717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7892_setup; 227717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7895_setup; 228717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7896_setup; 229717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7899_setup; 230a5847d5cSJustin T. Gibbs static ahc_device_setup_t ahc_aha29160C_setup; 231717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_raid_setup; 232717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha394XX_setup; 233717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha494XX_setup; 234717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha398XX_setup; 235717d4247SJustin T. Gibbs 236717d4247SJustin T. Gibbs struct ahc_pci_identity ahc_pci_ident_table [] = 237717d4247SJustin T. Gibbs { 238717d4247SJustin T. Gibbs /* aic7850 based controllers */ 239717d4247SJustin T. Gibbs { 240177799b5SJustin T. Gibbs ID_AHA_2902_04_10_15_20C_30C, 241717d4247SJustin T. Gibbs ID_ALL_MASK, 242177799b5SJustin T. Gibbs "Adaptec 2902/04/10/15/20C/30C SCSI adapter", 2436fb77fefSJustin T. Gibbs ahc_aic785X_setup 244717d4247SJustin T. Gibbs }, 245717d4247SJustin T. Gibbs /* aic7860 based controllers */ 246717d4247SJustin T. Gibbs { 247717d4247SJustin T. Gibbs ID_AHA_2930CU, 248717d4247SJustin T. Gibbs ID_ALL_MASK, 249717d4247SJustin T. Gibbs "Adaptec 2930CU SCSI adapter", 250717d4247SJustin T. Gibbs ahc_aic7860_setup 251717d4247SJustin T. Gibbs }, 252717d4247SJustin T. Gibbs { 253717d4247SJustin T. Gibbs ID_AHA_1480A & ID_DEV_VENDOR_MASK, 254717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 255717d4247SJustin T. Gibbs "Adaptec 1480A Ultra SCSI adapter", 256a5847d5cSJustin T. Gibbs ahc_apa1480_setup 257717d4247SJustin T. Gibbs }, 258717d4247SJustin T. Gibbs { 259717d4247SJustin T. Gibbs ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK, 260717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 261717d4247SJustin T. Gibbs "Adaptec 2940A Ultra SCSI adapter", 262717d4247SJustin T. Gibbs ahc_aic7860_setup 263717d4247SJustin T. Gibbs }, 264717d4247SJustin T. Gibbs { 265717d4247SJustin T. Gibbs ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK, 266717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 267717d4247SJustin T. Gibbs "Adaptec 2940A/CN Ultra SCSI adapter", 268717d4247SJustin T. Gibbs ahc_aic7860_setup 269717d4247SJustin T. Gibbs }, 270717d4247SJustin T. Gibbs { 271717d4247SJustin T. Gibbs ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK, 272717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 27358fb7d8eSJustin T. Gibbs "Adaptec 2930C Ultra SCSI adapter (VAR)", 274717d4247SJustin T. Gibbs ahc_aic7860_setup 275717d4247SJustin T. Gibbs }, 276717d4247SJustin T. Gibbs /* aic7870 based controllers */ 277717d4247SJustin T. Gibbs { 278717d4247SJustin T. Gibbs ID_AHA_2940, 279717d4247SJustin T. Gibbs ID_ALL_MASK, 280717d4247SJustin T. Gibbs "Adaptec 2940 SCSI adapter", 281717d4247SJustin T. Gibbs ahc_aic7870_setup 282717d4247SJustin T. Gibbs }, 283717d4247SJustin T. Gibbs { 284717d4247SJustin T. Gibbs ID_AHA_3940, 285717d4247SJustin T. Gibbs ID_ALL_MASK, 286717d4247SJustin T. Gibbs "Adaptec 3940 SCSI adapter", 287717d4247SJustin T. Gibbs ahc_aha394X_setup 288717d4247SJustin T. Gibbs }, 289717d4247SJustin T. Gibbs { 290717d4247SJustin T. Gibbs ID_AHA_398X, 291717d4247SJustin T. Gibbs ID_ALL_MASK, 292717d4247SJustin T. Gibbs "Adaptec 398X SCSI RAID adapter", 293717d4247SJustin T. Gibbs ahc_aha398X_setup 294717d4247SJustin T. Gibbs }, 295717d4247SJustin T. Gibbs { 296717d4247SJustin T. Gibbs ID_AHA_2944, 297717d4247SJustin T. Gibbs ID_ALL_MASK, 298717d4247SJustin T. Gibbs "Adaptec 2944 SCSI adapter", 299717d4247SJustin T. Gibbs ahc_aic7870_setup 300717d4247SJustin T. Gibbs }, 301717d4247SJustin T. Gibbs { 302717d4247SJustin T. Gibbs ID_AHA_3944, 303717d4247SJustin T. Gibbs ID_ALL_MASK, 304717d4247SJustin T. Gibbs "Adaptec 3944 SCSI adapter", 305717d4247SJustin T. Gibbs ahc_aha394X_setup 306717d4247SJustin T. Gibbs }, 307717d4247SJustin T. Gibbs { 308717d4247SJustin T. Gibbs ID_AHA_4944, 309717d4247SJustin T. Gibbs ID_ALL_MASK, 310717d4247SJustin T. Gibbs "Adaptec 4944 SCSI adapter", 311717d4247SJustin T. Gibbs ahc_aha494X_setup 312717d4247SJustin T. Gibbs }, 313717d4247SJustin T. Gibbs /* aic7880 based controllers */ 314717d4247SJustin T. Gibbs { 315717d4247SJustin T. Gibbs ID_AHA_2940U & ID_DEV_VENDOR_MASK, 316717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 317717d4247SJustin T. Gibbs "Adaptec 2940 Ultra SCSI adapter", 318717d4247SJustin T. Gibbs ahc_aic7880_setup 319717d4247SJustin T. Gibbs }, 320717d4247SJustin T. Gibbs { 321717d4247SJustin T. Gibbs ID_AHA_3940U & ID_DEV_VENDOR_MASK, 322717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 323717d4247SJustin T. Gibbs "Adaptec 3940 Ultra SCSI adapter", 324717d4247SJustin T. Gibbs ahc_aha394XU_setup 325717d4247SJustin T. Gibbs }, 326717d4247SJustin T. Gibbs { 327717d4247SJustin T. Gibbs ID_AHA_2944U & ID_DEV_VENDOR_MASK, 328717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 329717d4247SJustin T. Gibbs "Adaptec 2944 Ultra SCSI adapter", 330717d4247SJustin T. Gibbs ahc_aic7880_setup 331717d4247SJustin T. Gibbs }, 332717d4247SJustin T. Gibbs { 333717d4247SJustin T. Gibbs ID_AHA_3944U & ID_DEV_VENDOR_MASK, 334717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 335717d4247SJustin T. Gibbs "Adaptec 3944 Ultra SCSI adapter", 336717d4247SJustin T. Gibbs ahc_aha394XU_setup 337717d4247SJustin T. Gibbs }, 338717d4247SJustin T. Gibbs { 339717d4247SJustin T. Gibbs ID_AHA_398XU & ID_DEV_VENDOR_MASK, 340717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 341717d4247SJustin T. Gibbs "Adaptec 398X Ultra SCSI RAID adapter", 342717d4247SJustin T. Gibbs ahc_aha398XU_setup 343717d4247SJustin T. Gibbs }, 344717d4247SJustin T. Gibbs { 345717d4247SJustin T. Gibbs /* 346717d4247SJustin T. Gibbs * XXX Don't know the slot numbers 347717d4247SJustin T. Gibbs * so we can't identify channels 348717d4247SJustin T. Gibbs */ 349717d4247SJustin T. Gibbs ID_AHA_4944U & ID_DEV_VENDOR_MASK, 350717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 351717d4247SJustin T. Gibbs "Adaptec 4944 Ultra SCSI adapter", 352717d4247SJustin T. Gibbs ahc_aic7880_setup 353717d4247SJustin T. Gibbs }, 354717d4247SJustin T. Gibbs { 355717d4247SJustin T. Gibbs ID_AHA_2930U & ID_DEV_VENDOR_MASK, 356717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 357717d4247SJustin T. Gibbs "Adaptec 2930 Ultra SCSI adapter", 358717d4247SJustin T. Gibbs ahc_aic7880_setup 359717d4247SJustin T. Gibbs }, 360717d4247SJustin T. Gibbs { 361717d4247SJustin T. Gibbs ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK, 362717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 363717d4247SJustin T. Gibbs "Adaptec 2940 Pro Ultra SCSI adapter", 364a5847d5cSJustin T. Gibbs ahc_aha2940Pro_setup 365717d4247SJustin T. Gibbs }, 366717d4247SJustin T. Gibbs { 367717d4247SJustin T. Gibbs ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK, 368717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 369717d4247SJustin T. Gibbs "Adaptec 2940/CN Ultra SCSI adapter", 370717d4247SJustin T. Gibbs ahc_aic7880_setup 371717d4247SJustin T. Gibbs }, 3721478c711SJustin T. Gibbs /* Ignore all SISL (AAC on MB) based controllers. */ 3731478c711SJustin T. Gibbs { 3741478c711SJustin T. Gibbs ID_9005_SISL_ID, 3751478c711SJustin T. Gibbs ID_9005_SISL_MASK, 3761478c711SJustin T. Gibbs NULL, 3771478c711SJustin T. Gibbs NULL 3781478c711SJustin T. Gibbs }, 379717d4247SJustin T. Gibbs /* aic7890 based controllers */ 380717d4247SJustin T. Gibbs { 381717d4247SJustin T. Gibbs ID_AHA_2930U2, 382717d4247SJustin T. Gibbs ID_ALL_MASK, 383717d4247SJustin T. Gibbs "Adaptec 2930 Ultra2 SCSI adapter", 384717d4247SJustin T. Gibbs ahc_aic7890_setup 385717d4247SJustin T. Gibbs }, 386717d4247SJustin T. Gibbs { 387717d4247SJustin T. Gibbs ID_AHA_2940U2B, 388717d4247SJustin T. Gibbs ID_ALL_MASK, 389717d4247SJustin T. Gibbs "Adaptec 2940B Ultra2 SCSI adapter", 390717d4247SJustin T. Gibbs ahc_aic7890_setup 391717d4247SJustin T. Gibbs }, 392717d4247SJustin T. Gibbs { 393717d4247SJustin T. Gibbs ID_AHA_2940U2_OEM, 394717d4247SJustin T. Gibbs ID_ALL_MASK, 395717d4247SJustin T. Gibbs "Adaptec 2940 Ultra2 SCSI adapter (OEM)", 396717d4247SJustin T. Gibbs ahc_aic7890_setup 397717d4247SJustin T. Gibbs }, 398717d4247SJustin T. Gibbs { 399717d4247SJustin T. Gibbs ID_AHA_2940U2, 400717d4247SJustin T. Gibbs ID_ALL_MASK, 401717d4247SJustin T. Gibbs "Adaptec 2940 Ultra2 SCSI adapter", 402717d4247SJustin T. Gibbs ahc_aic7890_setup 403717d4247SJustin T. Gibbs }, 404717d4247SJustin T. Gibbs { 405717d4247SJustin T. Gibbs ID_AHA_2950U2B, 406717d4247SJustin T. Gibbs ID_ALL_MASK, 407717d4247SJustin T. Gibbs "Adaptec 2950 Ultra2 SCSI adapter", 408717d4247SJustin T. Gibbs ahc_aic7890_setup 409717d4247SJustin T. Gibbs }, 410717d4247SJustin T. Gibbs { 4111478c711SJustin T. Gibbs ID_AIC7890_ARO, 4121478c711SJustin T. Gibbs ID_ALL_MASK, 4131478c711SJustin T. Gibbs "Adaptec aic7890/91 Ultra2 SCSI adapter (ARO)", 4141478c711SJustin T. Gibbs ahc_aic7890_setup 4151478c711SJustin T. Gibbs }, 4161478c711SJustin T. Gibbs { 417717d4247SJustin T. Gibbs ID_AAA_131U2, 418717d4247SJustin T. Gibbs ID_ALL_MASK, 419717d4247SJustin T. Gibbs "Adaptec AAA-131 Ultra2 RAID adapter", 420717d4247SJustin T. Gibbs ahc_aic7890_setup 421717d4247SJustin T. Gibbs }, 422717d4247SJustin T. Gibbs /* aic7892 based controllers */ 423717d4247SJustin T. Gibbs { 424717d4247SJustin T. Gibbs ID_AHA_29160, 425717d4247SJustin T. Gibbs ID_ALL_MASK, 426717d4247SJustin T. Gibbs "Adaptec 29160 Ultra160 SCSI adapter", 427717d4247SJustin T. Gibbs ahc_aic7892_setup 428717d4247SJustin T. Gibbs }, 429717d4247SJustin T. Gibbs { 430717d4247SJustin T. Gibbs ID_AHA_29160_CPQ, 431717d4247SJustin T. Gibbs ID_ALL_MASK, 432717d4247SJustin T. Gibbs "Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter", 433717d4247SJustin T. Gibbs ahc_aic7892_setup 434717d4247SJustin T. Gibbs }, 435717d4247SJustin T. Gibbs { 436717d4247SJustin T. Gibbs ID_AHA_29160N, 437717d4247SJustin T. Gibbs ID_ALL_MASK, 438717d4247SJustin T. Gibbs "Adaptec 29160N Ultra160 SCSI adapter", 439717d4247SJustin T. Gibbs ahc_aic7892_setup 440717d4247SJustin T. Gibbs }, 441717d4247SJustin T. Gibbs { 44256a7c4a8SJustin T. Gibbs ID_AHA_29160C, 44356a7c4a8SJustin T. Gibbs ID_ALL_MASK, 44456a7c4a8SJustin T. Gibbs "Adaptec 29160C Ultra160 SCSI adapter", 445a5847d5cSJustin T. Gibbs ahc_aha29160C_setup 44656a7c4a8SJustin T. Gibbs }, 44756a7c4a8SJustin T. Gibbs { 448717d4247SJustin T. Gibbs ID_AHA_29160B, 449717d4247SJustin T. Gibbs ID_ALL_MASK, 450717d4247SJustin T. Gibbs "Adaptec 29160B Ultra160 SCSI adapter", 451717d4247SJustin T. Gibbs ahc_aic7892_setup 452717d4247SJustin T. Gibbs }, 453717d4247SJustin T. Gibbs { 454717d4247SJustin T. Gibbs ID_AHA_19160B, 455717d4247SJustin T. Gibbs ID_ALL_MASK, 456717d4247SJustin T. Gibbs "Adaptec 19160B Ultra160 SCSI adapter", 457717d4247SJustin T. Gibbs ahc_aic7892_setup 458717d4247SJustin T. Gibbs }, 4591478c711SJustin T. Gibbs { 4601478c711SJustin T. Gibbs ID_AIC7892_ARO, 4611478c711SJustin T. Gibbs ID_ALL_MASK, 46258fb7d8eSJustin T. Gibbs "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", 4631478c711SJustin T. Gibbs ahc_aic7892_setup 4641478c711SJustin T. Gibbs }, 465b3b25f2cSJustin T. Gibbs { 466b3b25f2cSJustin T. Gibbs ID_AHA_2915_30LP, 467b3b25f2cSJustin T. Gibbs ID_ALL_MASK, 468b3b25f2cSJustin T. Gibbs "Adaptec 2915/30LP Ultra160 SCSI adapter", 469b3b25f2cSJustin T. Gibbs ahc_aic7892_setup 470b3b25f2cSJustin T. Gibbs }, 471717d4247SJustin T. Gibbs /* aic7895 based controllers */ 472717d4247SJustin T. Gibbs { 473717d4247SJustin T. Gibbs ID_AHA_2940U_DUAL, 474717d4247SJustin T. Gibbs ID_ALL_MASK, 475717d4247SJustin T. Gibbs "Adaptec 2940/DUAL Ultra SCSI adapter", 476717d4247SJustin T. Gibbs ahc_aic7895_setup 477717d4247SJustin T. Gibbs }, 478717d4247SJustin T. Gibbs { 479717d4247SJustin T. Gibbs ID_AHA_3940AU, 480717d4247SJustin T. Gibbs ID_ALL_MASK, 481717d4247SJustin T. Gibbs "Adaptec 3940A Ultra SCSI adapter", 482717d4247SJustin T. Gibbs ahc_aic7895_setup 483717d4247SJustin T. Gibbs }, 484717d4247SJustin T. Gibbs { 485717d4247SJustin T. Gibbs ID_AHA_3944AU, 486717d4247SJustin T. Gibbs ID_ALL_MASK, 487717d4247SJustin T. Gibbs "Adaptec 3944A Ultra SCSI adapter", 488717d4247SJustin T. Gibbs ahc_aic7895_setup 489717d4247SJustin T. Gibbs }, 4901478c711SJustin T. Gibbs { 4911478c711SJustin T. Gibbs ID_AIC7895_ARO, 4921478c711SJustin T. Gibbs ID_AIC7895_ARO_MASK, 4931478c711SJustin T. Gibbs "Adaptec aic7895 Ultra SCSI adapter (ARO)", 4941478c711SJustin T. Gibbs ahc_aic7895_setup 4951478c711SJustin T. Gibbs }, 496717d4247SJustin T. Gibbs /* aic7896/97 based controllers */ 497717d4247SJustin T. Gibbs { 498717d4247SJustin T. Gibbs ID_AHA_3950U2B_0, 499717d4247SJustin T. Gibbs ID_ALL_MASK, 500717d4247SJustin T. Gibbs "Adaptec 3950B Ultra2 SCSI adapter", 501717d4247SJustin T. Gibbs ahc_aic7896_setup 502717d4247SJustin T. Gibbs }, 503717d4247SJustin T. Gibbs { 504717d4247SJustin T. Gibbs ID_AHA_3950U2B_1, 505717d4247SJustin T. Gibbs ID_ALL_MASK, 506717d4247SJustin T. Gibbs "Adaptec 3950B Ultra2 SCSI adapter", 507717d4247SJustin T. Gibbs ahc_aic7896_setup 508717d4247SJustin T. Gibbs }, 509717d4247SJustin T. Gibbs { 510717d4247SJustin T. Gibbs ID_AHA_3950U2D_0, 511717d4247SJustin T. Gibbs ID_ALL_MASK, 512717d4247SJustin T. Gibbs "Adaptec 3950D Ultra2 SCSI adapter", 513717d4247SJustin T. Gibbs ahc_aic7896_setup 514717d4247SJustin T. Gibbs }, 515717d4247SJustin T. Gibbs { 516717d4247SJustin T. Gibbs ID_AHA_3950U2D_1, 517717d4247SJustin T. Gibbs ID_ALL_MASK, 518717d4247SJustin T. Gibbs "Adaptec 3950D Ultra2 SCSI adapter", 519717d4247SJustin T. Gibbs ahc_aic7896_setup 520717d4247SJustin T. Gibbs }, 5211478c711SJustin T. Gibbs { 5221478c711SJustin T. Gibbs ID_AIC7896_ARO, 5231478c711SJustin T. Gibbs ID_ALL_MASK, 5241478c711SJustin T. Gibbs "Adaptec aic7896/97 Ultra2 SCSI adapter (ARO)", 5251478c711SJustin T. Gibbs ahc_aic7896_setup 5261478c711SJustin T. Gibbs }, 527717d4247SJustin T. Gibbs /* aic7899 based controllers */ 528717d4247SJustin T. Gibbs { 529717d4247SJustin T. Gibbs ID_AHA_3960D, 530717d4247SJustin T. Gibbs ID_ALL_MASK, 531717d4247SJustin T. Gibbs "Adaptec 3960D Ultra160 SCSI adapter", 532717d4247SJustin T. Gibbs ahc_aic7899_setup 533717d4247SJustin T. Gibbs }, 534717d4247SJustin T. Gibbs { 535717d4247SJustin T. Gibbs ID_AHA_3960D_CPQ, 536717d4247SJustin T. Gibbs ID_ALL_MASK, 537717d4247SJustin T. Gibbs "Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter", 538717d4247SJustin T. Gibbs ahc_aic7899_setup 539717d4247SJustin T. Gibbs }, 5401478c711SJustin T. Gibbs { 5411478c711SJustin T. Gibbs ID_AIC7899_ARO, 5421478c711SJustin T. Gibbs ID_ALL_MASK, 5431478c711SJustin T. Gibbs "Adaptec aic7899 Ultra160 SCSI adapter (ARO)", 5441478c711SJustin T. Gibbs ahc_aic7899_setup 5451478c711SJustin T. Gibbs }, 546717d4247SJustin T. Gibbs /* Generic chip probes for devices we don't know 'exactly' */ 547717d4247SJustin T. Gibbs { 548717d4247SJustin T. Gibbs ID_AIC7850 & ID_DEV_VENDOR_MASK, 549717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 550717d4247SJustin T. Gibbs "Adaptec aic7850 SCSI adapter", 5516fb77fefSJustin T. Gibbs ahc_aic785X_setup 552717d4247SJustin T. Gibbs }, 553717d4247SJustin T. Gibbs { 554717d4247SJustin T. Gibbs ID_AIC7855 & ID_DEV_VENDOR_MASK, 555717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 556717d4247SJustin T. Gibbs "Adaptec aic7855 SCSI adapter", 5576fb77fefSJustin T. Gibbs ahc_aic785X_setup 558717d4247SJustin T. Gibbs }, 559717d4247SJustin T. Gibbs { 560717d4247SJustin T. Gibbs ID_AIC7859 & ID_DEV_VENDOR_MASK, 561717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 56258fb7d8eSJustin T. Gibbs "Adaptec aic7859 SCSI adapter", 563717d4247SJustin T. Gibbs ahc_aic7860_setup 564717d4247SJustin T. Gibbs }, 565717d4247SJustin T. Gibbs { 566717d4247SJustin T. Gibbs ID_AIC7860 & ID_DEV_VENDOR_MASK, 567717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 56858fb7d8eSJustin T. Gibbs "Adaptec aic7860 Ultra SCSI adapter", 569717d4247SJustin T. Gibbs ahc_aic7860_setup 570717d4247SJustin T. Gibbs }, 571717d4247SJustin T. Gibbs { 572717d4247SJustin T. Gibbs ID_AIC7870 & ID_DEV_VENDOR_MASK, 573717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 574717d4247SJustin T. Gibbs "Adaptec aic7870 SCSI adapter", 575717d4247SJustin T. Gibbs ahc_aic7870_setup 576717d4247SJustin T. Gibbs }, 577717d4247SJustin T. Gibbs { 578717d4247SJustin T. Gibbs ID_AIC7880 & ID_DEV_VENDOR_MASK, 579717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 580717d4247SJustin T. Gibbs "Adaptec aic7880 Ultra SCSI adapter", 581717d4247SJustin T. Gibbs ahc_aic7880_setup 582717d4247SJustin T. Gibbs }, 583717d4247SJustin T. Gibbs { 584bfadd24dSJustin T. Gibbs ID_AIC7890 & ID_9005_GENERIC_MASK, 585bfadd24dSJustin T. Gibbs ID_9005_GENERIC_MASK, 586717d4247SJustin T. Gibbs "Adaptec aic7890/91 Ultra2 SCSI adapter", 587717d4247SJustin T. Gibbs ahc_aic7890_setup 588717d4247SJustin T. Gibbs }, 589717d4247SJustin T. Gibbs { 590bfadd24dSJustin T. Gibbs ID_AIC7892 & ID_9005_GENERIC_MASK, 591bfadd24dSJustin T. Gibbs ID_9005_GENERIC_MASK, 592717d4247SJustin T. Gibbs "Adaptec aic7892 Ultra160 SCSI adapter", 593717d4247SJustin T. Gibbs ahc_aic7892_setup 594717d4247SJustin T. Gibbs }, 595717d4247SJustin T. Gibbs { 596717d4247SJustin T. Gibbs ID_AIC7895 & ID_DEV_VENDOR_MASK, 597717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 598717d4247SJustin T. Gibbs "Adaptec aic7895 Ultra SCSI adapter", 599717d4247SJustin T. Gibbs ahc_aic7895_setup 600717d4247SJustin T. Gibbs }, 601717d4247SJustin T. Gibbs { 602bfadd24dSJustin T. Gibbs ID_AIC7896 & ID_9005_GENERIC_MASK, 603bfadd24dSJustin T. Gibbs ID_9005_GENERIC_MASK, 604717d4247SJustin T. Gibbs "Adaptec aic7896/97 Ultra2 SCSI adapter", 605717d4247SJustin T. Gibbs ahc_aic7896_setup 606717d4247SJustin T. Gibbs }, 607717d4247SJustin T. Gibbs { 608bfadd24dSJustin T. Gibbs ID_AIC7899 & ID_9005_GENERIC_MASK, 609bfadd24dSJustin T. Gibbs ID_9005_GENERIC_MASK, 610717d4247SJustin T. Gibbs "Adaptec aic7899 Ultra160 SCSI adapter", 611717d4247SJustin T. Gibbs ahc_aic7899_setup 612717d4247SJustin T. Gibbs }, 613717d4247SJustin T. Gibbs { 614717d4247SJustin T. Gibbs ID_AIC7810 & ID_DEV_VENDOR_MASK, 615717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 616717d4247SJustin T. Gibbs "Adaptec aic7810 RAID memory controller", 617717d4247SJustin T. Gibbs ahc_raid_setup 618717d4247SJustin T. Gibbs }, 619717d4247SJustin T. Gibbs { 620717d4247SJustin T. Gibbs ID_AIC7815 & ID_DEV_VENDOR_MASK, 621717d4247SJustin T. Gibbs ID_DEV_VENDOR_MASK, 622717d4247SJustin T. Gibbs "Adaptec aic7815 RAID memory controller", 623717d4247SJustin T. Gibbs ahc_raid_setup 624717d4247SJustin T. Gibbs } 625717d4247SJustin T. Gibbs }; 626717d4247SJustin T. Gibbs 62756a7c4a8SJustin T. Gibbs const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table); 628717d4247SJustin T. Gibbs 629717d4247SJustin T. Gibbs #define AHC_394X_SLOT_CHANNEL_A 4 630717d4247SJustin T. Gibbs #define AHC_394X_SLOT_CHANNEL_B 5 631717d4247SJustin T. Gibbs 632717d4247SJustin T. Gibbs #define AHC_398X_SLOT_CHANNEL_A 4 633717d4247SJustin T. Gibbs #define AHC_398X_SLOT_CHANNEL_B 8 634717d4247SJustin T. Gibbs #define AHC_398X_SLOT_CHANNEL_C 12 635717d4247SJustin T. Gibbs 636717d4247SJustin T. Gibbs #define AHC_494X_SLOT_CHANNEL_A 4 637717d4247SJustin T. Gibbs #define AHC_494X_SLOT_CHANNEL_B 5 638717d4247SJustin T. Gibbs #define AHC_494X_SLOT_CHANNEL_C 6 639717d4247SJustin T. Gibbs #define AHC_494X_SLOT_CHANNEL_D 7 640717d4247SJustin T. Gibbs 641717d4247SJustin T. Gibbs #define DEVCONFIG 0x40 64270b41139SJustin T. Gibbs #define PCIERRGENDIS 0x80000000ul 643717d4247SJustin T. Gibbs #define SCBSIZE32 0x00010000ul /* aic789X only */ 6446fb77fefSJustin T. Gibbs #define REXTVALID 0x00001000ul /* ultra cards only */ 645cd036e89SJustin T. Gibbs #define MPORTMODE 0x00000400ul /* aic7870+ only */ 646cd036e89SJustin T. Gibbs #define RAMPSM 0x00000200ul /* aic7870+ only */ 647717d4247SJustin T. Gibbs #define VOLSENSE 0x00000100ul 648cd036e89SJustin T. Gibbs #define PCI64BIT 0x00000080ul /* 64Bit PCI bus (Ultra2 Only)*/ 649717d4247SJustin T. Gibbs #define SCBRAMSEL 0x00000080ul 650717d4247SJustin T. Gibbs #define MRDCEN 0x00000040ul 651717d4247SJustin T. Gibbs #define EXTSCBTIME 0x00000020ul /* aic7870 only */ 652717d4247SJustin T. Gibbs #define EXTSCBPEN 0x00000010ul /* aic7870 only */ 653717d4247SJustin T. Gibbs #define BERREN 0x00000008ul 654717d4247SJustin T. Gibbs #define DACEN 0x00000004ul 655717d4247SJustin T. Gibbs #define STPWLEVEL 0x00000002ul 656717d4247SJustin T. Gibbs #define DIFACTNEGEN 0x00000001ul /* aic7870 only */ 657717d4247SJustin T. Gibbs 658717d4247SJustin T. Gibbs #define CSIZE_LATTIME 0x0c 659717d4247SJustin T. Gibbs #define CACHESIZE 0x0000003ful /* only 5 bits */ 660717d4247SJustin T. Gibbs #define LATTIME 0x0000ff00ul 661717d4247SJustin T. Gibbs 662dc67dad8SScott Long /* PCI STATUS definitions */ 663dc67dad8SScott Long #define DPE 0x80 664dc67dad8SScott Long #define SSE 0x40 665dc67dad8SScott Long #define RMA 0x20 666dc67dad8SScott Long #define RTA 0x10 667dc67dad8SScott Long #define STA 0x08 668dc67dad8SScott Long #define DPR 0x01 669dc67dad8SScott Long 670b4d0045dSUlrich Spörlein static int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, 671b4d0045dSUlrich Spörlein uint16_t subdevice, uint16_t subvendor); 672717d4247SJustin T. Gibbs static int ahc_ext_scbram_present(struct ahc_softc *ahc); 673717d4247SJustin T. Gibbs static void ahc_scbram_config(struct ahc_softc *ahc, int enable, 674717d4247SJustin T. Gibbs int pcheck, int fast, int large); 675717d4247SJustin T. Gibbs static void ahc_probe_ext_scbram(struct ahc_softc *ahc); 676717d4247SJustin T. Gibbs static void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1); 677274c4127SJustin T. Gibbs static void ahc_parse_pci_eeprom(struct ahc_softc *ahc, 678274c4127SJustin T. Gibbs struct seeprom_config *sc); 679717d4247SJustin T. Gibbs static void configure_termination(struct ahc_softc *ahc, 680717d4247SJustin T. Gibbs struct seeprom_descriptor *sd, 681717d4247SJustin T. Gibbs u_int adapter_control, 682717d4247SJustin T. Gibbs u_int *sxfrctl1); 683717d4247SJustin T. Gibbs 684717d4247SJustin T. Gibbs static void ahc_new_term_detect(struct ahc_softc *ahc, 685717d4247SJustin T. Gibbs int *enableSEC_low, 686717d4247SJustin T. Gibbs int *enableSEC_high, 687717d4247SJustin T. Gibbs int *enablePRI_low, 688717d4247SJustin T. Gibbs int *enablePRI_high, 689717d4247SJustin T. Gibbs int *eeprom_present); 690717d4247SJustin T. Gibbs static void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 691717d4247SJustin T. Gibbs int *internal68_present, 692717d4247SJustin T. Gibbs int *externalcable_present, 693717d4247SJustin T. Gibbs int *eeprom_present); 694717d4247SJustin T. Gibbs static void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 695717d4247SJustin T. Gibbs int *externalcable_present, 696717d4247SJustin T. Gibbs int *eeprom_present); 697717d4247SJustin T. Gibbs static void write_brdctl(struct ahc_softc *ahc, uint8_t value); 698717d4247SJustin T. Gibbs static uint8_t read_brdctl(struct ahc_softc *ahc); 6999bf327a7SJustin T. Gibbs static void ahc_pci_intr(struct ahc_softc *ahc); 7009bf327a7SJustin T. Gibbs static int ahc_pci_chip_init(struct ahc_softc *ahc); 7019bf327a7SJustin T. Gibbs static int ahc_pci_suspend(struct ahc_softc *ahc); 7029bf327a7SJustin T. Gibbs static int ahc_pci_resume(struct ahc_softc *ahc); 703717d4247SJustin T. Gibbs 7048f214efcSJustin T. Gibbs static int 7058f214efcSJustin T. Gibbs ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, 7068f214efcSJustin T. Gibbs uint16_t subdevice, uint16_t subvendor) 7078f214efcSJustin T. Gibbs { 7088f214efcSJustin T. Gibbs int result; 7098f214efcSJustin T. Gibbs 7108f214efcSJustin T. Gibbs /* Default to invalid. */ 7118f214efcSJustin T. Gibbs result = 0; 7128f214efcSJustin T. Gibbs if (vendor == 0x9005 7138f214efcSJustin T. Gibbs && subvendor == 0x9005 7148f214efcSJustin T. Gibbs && subdevice != device 7158f214efcSJustin T. Gibbs && SUBID_9005_TYPE_KNOWN(subdevice) != 0) { 7168f214efcSJustin T. Gibbs switch (SUBID_9005_TYPE(subdevice)) { 7178f214efcSJustin T. Gibbs case SUBID_9005_TYPE_MB: 7188f214efcSJustin T. Gibbs break; 7198f214efcSJustin T. Gibbs case SUBID_9005_TYPE_CARD: 7208f214efcSJustin T. Gibbs case SUBID_9005_TYPE_LCCARD: 7218f214efcSJustin T. Gibbs /* 7228f214efcSJustin T. Gibbs * Currently only trust Adaptec cards to 7238f214efcSJustin T. Gibbs * get the sub device info correct. 7248f214efcSJustin T. Gibbs */ 7258f214efcSJustin T. Gibbs if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA) 7268f214efcSJustin T. Gibbs result = 1; 7278f214efcSJustin T. Gibbs break; 7288f214efcSJustin T. Gibbs case SUBID_9005_TYPE_RAID: 7298f214efcSJustin T. Gibbs break; 7308f214efcSJustin T. Gibbs default: 7318f214efcSJustin T. Gibbs break; 7328f214efcSJustin T. Gibbs } 7338f214efcSJustin T. Gibbs } 7348f214efcSJustin T. Gibbs return (result); 7358f214efcSJustin T. Gibbs } 7368f214efcSJustin T. Gibbs 737717d4247SJustin T. Gibbs struct ahc_pci_identity * 738b3b25f2cSJustin T. Gibbs ahc_find_pci_device(aic_dev_softc_t pci) 739717d4247SJustin T. Gibbs { 740717d4247SJustin T. Gibbs uint64_t full_id; 741717d4247SJustin T. Gibbs uint16_t device; 742717d4247SJustin T. Gibbs uint16_t vendor; 743717d4247SJustin T. Gibbs uint16_t subdevice; 744717d4247SJustin T. Gibbs uint16_t subvendor; 745717d4247SJustin T. Gibbs struct ahc_pci_identity *entry; 746717d4247SJustin T. Gibbs u_int i; 747717d4247SJustin T. Gibbs 748b3b25f2cSJustin T. Gibbs vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); 749b3b25f2cSJustin T. Gibbs device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); 750b3b25f2cSJustin T. Gibbs subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); 751b3b25f2cSJustin T. Gibbs subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); 7529bf327a7SJustin T. Gibbs full_id = ahc_compose_id(device, vendor, subdevice, subvendor); 753717d4247SJustin T. Gibbs 754cd036e89SJustin T. Gibbs /* 755cd036e89SJustin T. Gibbs * If the second function is not hooked up, ignore it. 756cd036e89SJustin T. Gibbs * Unfortunately, not all MB vendors implement the 757cd036e89SJustin T. Gibbs * subdevice ID as per the Adaptec spec, so do our best 758cd036e89SJustin T. Gibbs * to sanity check it prior to accepting the subdevice 759cd036e89SJustin T. Gibbs * ID as valid. 760cd036e89SJustin T. Gibbs */ 761b3b25f2cSJustin T. Gibbs if (aic_get_pci_function(pci) > 0 762b4d0045dSUlrich Spörlein && ahc_9005_subdevinfo_valid(device, vendor, subdevice, subvendor) 763f8838555SJustin T. Gibbs && SUBID_9005_MFUNCENB(subdevice) == 0) 76456a7c4a8SJustin T. Gibbs return (NULL); 76556a7c4a8SJustin T. Gibbs 766717d4247SJustin T. Gibbs for (i = 0; i < ahc_num_pci_devs; i++) { 767717d4247SJustin T. Gibbs entry = &ahc_pci_ident_table[i]; 7681478c711SJustin T. Gibbs if (entry->full_id == (full_id & entry->id_mask)) { 7691478c711SJustin T. Gibbs /* Honor exclusion entries. */ 7701478c711SJustin T. Gibbs if (entry->name == NULL) 7711478c711SJustin T. Gibbs return (NULL); 772717d4247SJustin T. Gibbs return (entry); 773717d4247SJustin T. Gibbs } 7741478c711SJustin T. Gibbs } 775717d4247SJustin T. Gibbs return (NULL); 776717d4247SJustin T. Gibbs } 777717d4247SJustin T. Gibbs 778717d4247SJustin T. Gibbs int 779717d4247SJustin T. Gibbs ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) 780717d4247SJustin T. Gibbs { 781717d4247SJustin T. Gibbs u_int command; 782274c4127SJustin T. Gibbs u_int our_id; 783717d4247SJustin T. Gibbs u_int sxfrctl1; 784717d4247SJustin T. Gibbs u_int scsiseq; 785717d4247SJustin T. Gibbs u_int dscommand0; 78670b41139SJustin T. Gibbs uint32_t devconfig; 787717d4247SJustin T. Gibbs int error; 788717d4247SJustin T. Gibbs uint8_t sblkctl; 789717d4247SJustin T. Gibbs 790274c4127SJustin T. Gibbs our_id = 0; 791cd036e89SJustin T. Gibbs error = entry->setup(ahc); 792717d4247SJustin T. Gibbs if (error != 0) 793717d4247SJustin T. Gibbs return (error); 794cd036e89SJustin T. Gibbs ahc->chip |= AHC_PCI; 795cd036e89SJustin T. Gibbs ahc->description = entry->name; 796717d4247SJustin T. Gibbs 797b3b25f2cSJustin T. Gibbs aic_power_state_change(ahc, AIC_POWER_STATE_D0); 7988f214efcSJustin T. Gibbs 799717d4247SJustin T. Gibbs error = ahc_pci_map_registers(ahc); 800717d4247SJustin T. Gibbs if (error != 0) 801717d4247SJustin T. Gibbs return (error); 802717d4247SJustin T. Gibbs 8038f214efcSJustin T. Gibbs /* 8048f214efcSJustin T. Gibbs * Before we continue probing the card, ensure that 8058f214efcSJustin T. Gibbs * its interrupts are *disabled*. We don't want 8068f214efcSJustin T. Gibbs * a misstep to hang the machine in an interrupt 8078f214efcSJustin T. Gibbs * storm. 8088f214efcSJustin T. Gibbs */ 8098f214efcSJustin T. Gibbs ahc_intr_enable(ahc, FALSE); 81056a7c4a8SJustin T. Gibbs 811b3b25f2cSJustin T. Gibbs devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 81270b41139SJustin T. Gibbs 813cd036e89SJustin T. Gibbs /* 814cd036e89SJustin T. Gibbs * If we need to support high memory, enable dual 815cd036e89SJustin T. Gibbs * address cycles. This bit must be set to enable 816cd036e89SJustin T. Gibbs * high address bit generation even if we are on a 817cd036e89SJustin T. Gibbs * 64bit bus (PCI64BIT set in devconfig). 818cd036e89SJustin T. Gibbs */ 819cd036e89SJustin T. Gibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 820cd036e89SJustin T. Gibbs if (bootverbose) 821cd036e89SJustin T. Gibbs printf("%s: Enabling 39Bit Addressing\n", 822cd036e89SJustin T. Gibbs ahc_name(ahc)); 823cd036e89SJustin T. Gibbs devconfig |= DACEN; 824cd036e89SJustin T. Gibbs } 825cd036e89SJustin T. Gibbs 82670b41139SJustin T. Gibbs /* Ensure that pci error generation, a test feature, is disabled. */ 82770b41139SJustin T. Gibbs devconfig |= PCIERRGENDIS; 82870b41139SJustin T. Gibbs 829b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 83070b41139SJustin T. Gibbs 831717d4247SJustin T. Gibbs /* Ensure busmastering is enabled */ 832b3b25f2cSJustin T. Gibbs command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); 833717d4247SJustin T. Gibbs command |= PCIM_CMD_BUSMASTEREN; 83470b41139SJustin T. Gibbs 835b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); 836717d4247SJustin T. Gibbs 837717d4247SJustin T. Gibbs /* On all PCI adapters, we allow SCB paging */ 838cd036e89SJustin T. Gibbs ahc->flags |= AHC_PAGESCBS; 839717d4247SJustin T. Gibbs 840cd036e89SJustin T. Gibbs error = ahc_softc_init(ahc); 841717d4247SJustin T. Gibbs if (error != 0) 842717d4247SJustin T. Gibbs return (error); 843717d4247SJustin T. Gibbs 8449bf327a7SJustin T. Gibbs /* 8459bf327a7SJustin T. Gibbs * Disable PCI parity error checking. Users typically 8469bf327a7SJustin T. Gibbs * do this to work around broken PCI chipsets that get 8479bf327a7SJustin T. Gibbs * the parity timing wrong and thus generate lots of spurious 8489bf327a7SJustin T. Gibbs * errors. The chip only allows us to disable *all* parity 8499bf327a7SJustin T. Gibbs * error reporting when doing this, so CIO bus, scb ram, and 8509bf327a7SJustin T. Gibbs * scratch ram parity errors will be ignored too. 8519bf327a7SJustin T. Gibbs */ 852e4e6e6d6SJustin T. Gibbs if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0) 853e4e6e6d6SJustin T. Gibbs ahc->seqctl |= FAILDIS; 8549bf327a7SJustin T. Gibbs 855b95de6daSJustin T. Gibbs ahc->bus_intr = ahc_pci_intr; 8569bf327a7SJustin T. Gibbs ahc->bus_chip_init = ahc_pci_chip_init; 8579bf327a7SJustin T. Gibbs ahc->bus_suspend = ahc_pci_suspend; 8589bf327a7SJustin T. Gibbs ahc->bus_resume = ahc_pci_resume; 859b95de6daSJustin T. Gibbs 860594c945aSPedro F. Giffuni /* Remember how the card was setup in case there is no SEEPROM */ 86156a7c4a8SJustin T. Gibbs if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { 8626fb77fefSJustin T. Gibbs ahc_pause(ahc); 863717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) 864717d4247SJustin T. Gibbs our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID; 865717d4247SJustin T. Gibbs else 866717d4247SJustin T. Gibbs our_id = ahc_inb(ahc, SCSIID) & OID; 867717d4247SJustin T. Gibbs sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN; 868717d4247SJustin T. Gibbs scsiseq = ahc_inb(ahc, SCSISEQ); 86956a7c4a8SJustin T. Gibbs } else { 87056a7c4a8SJustin T. Gibbs sxfrctl1 = STPWEN; 87156a7c4a8SJustin T. Gibbs our_id = 7; 87256a7c4a8SJustin T. Gibbs scsiseq = 0; 87356a7c4a8SJustin T. Gibbs } 874717d4247SJustin T. Gibbs 8751d528d67SJustin T. Gibbs error = ahc_reset(ahc, /*reinit*/FALSE); 876717d4247SJustin T. Gibbs if (error != 0) 877717d4247SJustin T. Gibbs return (ENXIO); 878717d4247SJustin T. Gibbs 879717d4247SJustin T. Gibbs if ((ahc->features & AHC_DT) != 0) { 880717d4247SJustin T. Gibbs u_int sfunct; 881717d4247SJustin T. Gibbs 882717d4247SJustin T. Gibbs /* Perform ALT-Mode Setup */ 883717d4247SJustin T. Gibbs sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 884717d4247SJustin T. Gibbs ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 88558fb7d8eSJustin T. Gibbs ahc_outb(ahc, OPTIONMODE, 88658fb7d8eSJustin T. Gibbs OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS); 887717d4247SJustin T. Gibbs ahc_outb(ahc, SFUNCT, sfunct); 888717d4247SJustin T. Gibbs 889717d4247SJustin T. Gibbs /* Normal mode setup */ 890717d4247SJustin T. Gibbs ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN 89156a7c4a8SJustin T. Gibbs |TARGCRCENDEN); 892717d4247SJustin T. Gibbs } 893717d4247SJustin T. Gibbs 894717d4247SJustin T. Gibbs dscommand0 = ahc_inb(ahc, DSCOMMAND0); 895a49630acSJustin T. Gibbs dscommand0 |= MPARCKEN|CACHETHEN; 896717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) { 897717d4247SJustin T. Gibbs /* 898717d4247SJustin T. Gibbs * DPARCKEN doesn't work correctly on 899717d4247SJustin T. Gibbs * some MBs so don't use it. 900717d4247SJustin T. Gibbs */ 901717d4247SJustin T. Gibbs dscommand0 &= ~DPARCKEN; 902717d4247SJustin T. Gibbs } 903717d4247SJustin T. Gibbs 904717d4247SJustin T. Gibbs /* 905717d4247SJustin T. Gibbs * Handle chips that must have cache line 906717d4247SJustin T. Gibbs * streaming (dis/en)abled. 907717d4247SJustin T. Gibbs */ 908717d4247SJustin T. Gibbs if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0) 909717d4247SJustin T. Gibbs dscommand0 |= CACHETHEN; 910717d4247SJustin T. Gibbs 911717d4247SJustin T. Gibbs if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0) 912717d4247SJustin T. Gibbs dscommand0 &= ~CACHETHEN; 913717d4247SJustin T. Gibbs 914717d4247SJustin T. Gibbs ahc_outb(ahc, DSCOMMAND0, dscommand0); 915717d4247SJustin T. Gibbs 916717d4247SJustin T. Gibbs ahc->pci_cachesize = 917b3b25f2cSJustin T. Gibbs aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, 918717d4247SJustin T. Gibbs /*bytes*/1) & CACHESIZE; 919717d4247SJustin T. Gibbs ahc->pci_cachesize *= 4; 920717d4247SJustin T. Gibbs 9219f152ec7SJustin T. Gibbs if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0 9229f152ec7SJustin T. Gibbs && ahc->pci_cachesize == 4) { 923b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 9249f152ec7SJustin T. Gibbs 0, /*bytes*/1); 9259f152ec7SJustin T. Gibbs ahc->pci_cachesize = 0; 9269f152ec7SJustin T. Gibbs } 9279f152ec7SJustin T. Gibbs 92858fb7d8eSJustin T. Gibbs /* 929594c945aSPedro F. Giffuni * We cannot perform ULTRA speeds without the presence 93058fb7d8eSJustin T. Gibbs * of the external precision resistor. 93158fb7d8eSJustin T. Gibbs */ 93258fb7d8eSJustin T. Gibbs if ((ahc->features & AHC_ULTRA) != 0) { 93358fb7d8eSJustin T. Gibbs uint32_t devconfig; 93458fb7d8eSJustin T. Gibbs 935b3b25f2cSJustin T. Gibbs devconfig = aic_pci_read_config(ahc->dev_softc, 93658fb7d8eSJustin T. Gibbs DEVCONFIG, /*bytes*/4); 93758fb7d8eSJustin T. Gibbs if ((devconfig & REXTVALID) == 0) 93858fb7d8eSJustin T. Gibbs ahc->features &= ~AHC_ULTRA; 93958fb7d8eSJustin T. Gibbs } 94058fb7d8eSJustin T. Gibbs 941717d4247SJustin T. Gibbs /* See if we have a SEEPROM and perform auto-term */ 942717d4247SJustin T. Gibbs check_extport(ahc, &sxfrctl1); 943717d4247SJustin T. Gibbs 944717d4247SJustin T. Gibbs /* 945717d4247SJustin T. Gibbs * Take the LED out of diagnostic mode 946717d4247SJustin T. Gibbs */ 947717d4247SJustin T. Gibbs sblkctl = ahc_inb(ahc, SBLKCTL); 948717d4247SJustin T. Gibbs ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON))); 949717d4247SJustin T. Gibbs 950717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) { 951dd1290f0SJustin T. Gibbs ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX); 952717d4247SJustin T. Gibbs } else { 953717d4247SJustin T. Gibbs ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100); 954717d4247SJustin T. Gibbs } 955717d4247SJustin T. Gibbs 956717d4247SJustin T. Gibbs if (ahc->flags & AHC_USEDEFAULTS) { 957717d4247SJustin T. Gibbs /* 958717d4247SJustin T. Gibbs * PCI Adapter default setup 959717d4247SJustin T. Gibbs * Should only be used if the adapter does not have 960717d4247SJustin T. Gibbs * a SEEPROM. 961717d4247SJustin T. Gibbs */ 962717d4247SJustin T. Gibbs /* See if someone else set us up already */ 96370b41139SJustin T. Gibbs if ((ahc->flags & AHC_NO_BIOS_INIT) == 0 96470b41139SJustin T. Gibbs && scsiseq != 0) { 965717d4247SJustin T. Gibbs printf("%s: Using left over BIOS settings\n", 966717d4247SJustin T. Gibbs ahc_name(ahc)); 967717d4247SJustin T. Gibbs ahc->flags &= ~AHC_USEDEFAULTS; 968bfadd24dSJustin T. Gibbs ahc->flags |= AHC_BIOS_ENABLED; 969717d4247SJustin T. Gibbs } else { 970717d4247SJustin T. Gibbs /* 971717d4247SJustin T. Gibbs * Assume only one connector and always turn 972717d4247SJustin T. Gibbs * on termination. 973717d4247SJustin T. Gibbs */ 974717d4247SJustin T. Gibbs our_id = 0x07; 975717d4247SJustin T. Gibbs sxfrctl1 = STPWEN; 976717d4247SJustin T. Gibbs } 977717d4247SJustin T. Gibbs ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI); 978717d4247SJustin T. Gibbs 979717d4247SJustin T. Gibbs ahc->our_id = our_id; 980717d4247SJustin T. Gibbs } 981717d4247SJustin T. Gibbs 982717d4247SJustin T. Gibbs /* 983717d4247SJustin T. Gibbs * Take a look to see if we have external SRAM. 984717d4247SJustin T. Gibbs * We currently do not attempt to use SRAM that is 985717d4247SJustin T. Gibbs * shared among multiple controllers. 986717d4247SJustin T. Gibbs */ 987717d4247SJustin T. Gibbs ahc_probe_ext_scbram(ahc); 988717d4247SJustin T. Gibbs 989717d4247SJustin T. Gibbs /* 990717d4247SJustin T. Gibbs * Record our termination setting for the 991717d4247SJustin T. Gibbs * generic initialization routine. 992717d4247SJustin T. Gibbs */ 993717d4247SJustin T. Gibbs if ((sxfrctl1 & STPWEN) != 0) 994717d4247SJustin T. Gibbs ahc->flags |= AHC_TERM_ENB_A; 995717d4247SJustin T. Gibbs 9969bf327a7SJustin T. Gibbs /* 9979bf327a7SJustin T. Gibbs * Save chip register configuration data for chip resets 9989bf327a7SJustin T. Gibbs * that occur during runtime and resume events. 9999bf327a7SJustin T. Gibbs */ 10009bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.devconfig = 1001b3b25f2cSJustin T. Gibbs aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 10029bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.command = 1003b3b25f2cSJustin T. Gibbs aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); 10049bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.csize_lattime = 1005b3b25f2cSJustin T. Gibbs aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1); 10069bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0); 10079bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS); 10089bf327a7SJustin T. Gibbs if ((ahc->features & AHC_DT) != 0) { 10099bf327a7SJustin T. Gibbs u_int sfunct; 10109bf327a7SJustin T. Gibbs 10119bf327a7SJustin T. Gibbs sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 10129bf327a7SJustin T. Gibbs ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 10139bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE); 10149bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT); 10159bf327a7SJustin T. Gibbs ahc_outb(ahc, SFUNCT, sfunct); 10169bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.crccontrol1 = 10179bf327a7SJustin T. Gibbs ahc_inb(ahc, CRCCONTROL1); 10189bf327a7SJustin T. Gibbs } 10199bf327a7SJustin T. Gibbs if ((ahc->features & AHC_MULTI_FUNC) != 0) 10209bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR); 10219bf327a7SJustin T. Gibbs 10229bf327a7SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) 10239bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH); 10249bf327a7SJustin T. Gibbs 1025717d4247SJustin T. Gibbs /* Core initialization */ 1026717d4247SJustin T. Gibbs error = ahc_init(ahc); 1027717d4247SJustin T. Gibbs if (error != 0) 1028717d4247SJustin T. Gibbs return (error); 1029717d4247SJustin T. Gibbs 1030717d4247SJustin T. Gibbs /* 1031b95de6daSJustin T. Gibbs * Allow interrupts now that we are completely setup. 1032b95de6daSJustin T. Gibbs */ 103358fb7d8eSJustin T. Gibbs error = ahc_pci_map_int(ahc); 103458fb7d8eSJustin T. Gibbs if (error != 0) 103558fb7d8eSJustin T. Gibbs return (error); 103658fb7d8eSJustin T. Gibbs 1037032b0a17SScott Long ahc_lock(ahc); 1038274c4127SJustin T. Gibbs /* 1039274c4127SJustin T. Gibbs * Link this softc in with all other ahc instances. 1040274c4127SJustin T. Gibbs */ 1041274c4127SJustin T. Gibbs ahc_softc_insert(ahc); 1042032b0a17SScott Long ahc_unlock(ahc); 1043717d4247SJustin T. Gibbs return (0); 1044717d4247SJustin T. Gibbs } 1045717d4247SJustin T. Gibbs 1046717d4247SJustin T. Gibbs /* 1047594c945aSPedro F. Giffuni * Test for the presence of external sram in an 1048717d4247SJustin T. Gibbs * "unshared" configuration. 1049717d4247SJustin T. Gibbs */ 1050717d4247SJustin T. Gibbs static int 1051717d4247SJustin T. Gibbs ahc_ext_scbram_present(struct ahc_softc *ahc) 1052717d4247SJustin T. Gibbs { 1053dd1290f0SJustin T. Gibbs u_int chip; 1054717d4247SJustin T. Gibbs int ramps; 1055717d4247SJustin T. Gibbs int single_user; 1056717d4247SJustin T. Gibbs uint32_t devconfig; 1057717d4247SJustin T. Gibbs 1058dd1290f0SJustin T. Gibbs chip = ahc->chip & AHC_CHIPID_MASK; 1059b3b25f2cSJustin T. Gibbs devconfig = aic_pci_read_config(ahc->dev_softc, 1060717d4247SJustin T. Gibbs DEVCONFIG, /*bytes*/4); 1061717d4247SJustin T. Gibbs single_user = (devconfig & MPORTMODE) != 0; 1062717d4247SJustin T. Gibbs 1063717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) 1064717d4247SJustin T. Gibbs ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0; 10658f214efcSJustin T. Gibbs else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C) 10668f214efcSJustin T. Gibbs /* 10678f214efcSJustin T. Gibbs * External SCBRAM arbitration is flakey 10688f214efcSJustin T. Gibbs * on these chips. Unfortunately this means 10698f214efcSJustin T. Gibbs * we don't use the extra SCB ram space on the 10708f214efcSJustin T. Gibbs * 3940AUW. 10718f214efcSJustin T. Gibbs */ 10728f214efcSJustin T. Gibbs ramps = 0; 1073dd1290f0SJustin T. Gibbs else if (chip >= AHC_AIC7870) 1074717d4247SJustin T. Gibbs ramps = (devconfig & RAMPSM) != 0; 1075717d4247SJustin T. Gibbs else 1076717d4247SJustin T. Gibbs ramps = 0; 1077717d4247SJustin T. Gibbs 1078717d4247SJustin T. Gibbs if (ramps && single_user) 1079717d4247SJustin T. Gibbs return (1); 1080717d4247SJustin T. Gibbs return (0); 1081717d4247SJustin T. Gibbs } 1082717d4247SJustin T. Gibbs 1083717d4247SJustin T. Gibbs /* 1084717d4247SJustin T. Gibbs * Enable external scbram. 1085717d4247SJustin T. Gibbs */ 1086717d4247SJustin T. Gibbs static void 1087717d4247SJustin T. Gibbs ahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck, 1088717d4247SJustin T. Gibbs int fast, int large) 1089717d4247SJustin T. Gibbs { 1090717d4247SJustin T. Gibbs uint32_t devconfig; 1091717d4247SJustin T. Gibbs 1092717d4247SJustin T. Gibbs if (ahc->features & AHC_MULTI_FUNC) { 1093717d4247SJustin T. Gibbs /* 1094717d4247SJustin T. Gibbs * Set the SCB Base addr (highest address bit) 1095717d4247SJustin T. Gibbs * depending on which channel we are. 1096717d4247SJustin T. Gibbs */ 1097b3b25f2cSJustin T. Gibbs ahc_outb(ahc, SCBBADDR, aic_get_pci_function(ahc->dev_softc)); 1098717d4247SJustin T. Gibbs } 1099717d4247SJustin T. Gibbs 1100274c4127SJustin T. Gibbs ahc->flags &= ~AHC_LSCBS_ENABLED; 1101274c4127SJustin T. Gibbs if (large) 1102274c4127SJustin T. Gibbs ahc->flags |= AHC_LSCBS_ENABLED; 1103b3b25f2cSJustin T. Gibbs devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 1104717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) { 1105717d4247SJustin T. Gibbs u_int dscommand0; 1106717d4247SJustin T. Gibbs 1107717d4247SJustin T. Gibbs dscommand0 = ahc_inb(ahc, DSCOMMAND0); 1108717d4247SJustin T. Gibbs if (enable) 1109717d4247SJustin T. Gibbs dscommand0 &= ~INTSCBRAMSEL; 1110717d4247SJustin T. Gibbs else 1111717d4247SJustin T. Gibbs dscommand0 |= INTSCBRAMSEL; 1112717d4247SJustin T. Gibbs if (large) 1113717d4247SJustin T. Gibbs dscommand0 &= ~USCBSIZE32; 1114717d4247SJustin T. Gibbs else 1115717d4247SJustin T. Gibbs dscommand0 |= USCBSIZE32; 1116717d4247SJustin T. Gibbs ahc_outb(ahc, DSCOMMAND0, dscommand0); 1117717d4247SJustin T. Gibbs } else { 1118717d4247SJustin T. Gibbs if (fast) 1119717d4247SJustin T. Gibbs devconfig &= ~EXTSCBTIME; 1120717d4247SJustin T. Gibbs else 1121717d4247SJustin T. Gibbs devconfig |= EXTSCBTIME; 1122717d4247SJustin T. Gibbs if (enable) 1123717d4247SJustin T. Gibbs devconfig &= ~SCBRAMSEL; 1124717d4247SJustin T. Gibbs else 1125717d4247SJustin T. Gibbs devconfig |= SCBRAMSEL; 1126717d4247SJustin T. Gibbs if (large) 1127717d4247SJustin T. Gibbs devconfig &= ~SCBSIZE32; 1128717d4247SJustin T. Gibbs else 1129717d4247SJustin T. Gibbs devconfig |= SCBSIZE32; 1130717d4247SJustin T. Gibbs } 1131717d4247SJustin T. Gibbs if (pcheck) 1132717d4247SJustin T. Gibbs devconfig |= EXTSCBPEN; 1133717d4247SJustin T. Gibbs else 1134717d4247SJustin T. Gibbs devconfig &= ~EXTSCBPEN; 1135717d4247SJustin T. Gibbs 1136b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 1137717d4247SJustin T. Gibbs } 1138717d4247SJustin T. Gibbs 1139717d4247SJustin T. Gibbs /* 1140717d4247SJustin T. Gibbs * Take a look to see if we have external SRAM. 1141717d4247SJustin T. Gibbs * We currently do not attempt to use SRAM that is 1142717d4247SJustin T. Gibbs * shared among multiple controllers. 1143717d4247SJustin T. Gibbs */ 1144717d4247SJustin T. Gibbs static void 1145717d4247SJustin T. Gibbs ahc_probe_ext_scbram(struct ahc_softc *ahc) 1146717d4247SJustin T. Gibbs { 1147717d4247SJustin T. Gibbs int num_scbs; 1148717d4247SJustin T. Gibbs int test_num_scbs; 1149717d4247SJustin T. Gibbs int enable; 1150717d4247SJustin T. Gibbs int pcheck; 1151717d4247SJustin T. Gibbs int fast; 1152717d4247SJustin T. Gibbs int large; 1153717d4247SJustin T. Gibbs 1154717d4247SJustin T. Gibbs enable = FALSE; 1155717d4247SJustin T. Gibbs pcheck = FALSE; 1156717d4247SJustin T. Gibbs fast = FALSE; 1157717d4247SJustin T. Gibbs large = FALSE; 1158717d4247SJustin T. Gibbs num_scbs = 0; 1159717d4247SJustin T. Gibbs 1160717d4247SJustin T. Gibbs if (ahc_ext_scbram_present(ahc) == 0) 1161717d4247SJustin T. Gibbs goto done; 1162717d4247SJustin T. Gibbs 1163717d4247SJustin T. Gibbs /* 1164717d4247SJustin T. Gibbs * Probe for the best parameters to use. 1165717d4247SJustin T. Gibbs */ 1166717d4247SJustin T. Gibbs ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large); 1167717d4247SJustin T. Gibbs num_scbs = ahc_probe_scbs(ahc); 1168717d4247SJustin T. Gibbs if (num_scbs == 0) { 1169717d4247SJustin T. Gibbs /* The SRAM wasn't really present. */ 1170717d4247SJustin T. Gibbs goto done; 1171717d4247SJustin T. Gibbs } 1172717d4247SJustin T. Gibbs enable = TRUE; 1173717d4247SJustin T. Gibbs 1174717d4247SJustin T. Gibbs /* 1175717d4247SJustin T. Gibbs * Clear any outstanding parity error 1176717d4247SJustin T. Gibbs * and ensure that parity error reporting 1177717d4247SJustin T. Gibbs * is enabled. 1178717d4247SJustin T. Gibbs */ 1179717d4247SJustin T. Gibbs ahc_outb(ahc, SEQCTL, 0); 1180717d4247SJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRPARERR); 1181717d4247SJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 1182717d4247SJustin T. Gibbs 1183717d4247SJustin T. Gibbs /* Now see if we can do parity */ 1184717d4247SJustin T. Gibbs ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large); 1185717d4247SJustin T. Gibbs num_scbs = ahc_probe_scbs(ahc); 1186717d4247SJustin T. Gibbs if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 1187717d4247SJustin T. Gibbs || (ahc_inb(ahc, ERROR) & MPARERR) == 0) 1188717d4247SJustin T. Gibbs pcheck = TRUE; 1189717d4247SJustin T. Gibbs 1190717d4247SJustin T. Gibbs /* Clear any resulting parity error */ 1191717d4247SJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRPARERR); 1192717d4247SJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 1193717d4247SJustin T. Gibbs 1194717d4247SJustin T. Gibbs /* Now see if we can do fast timing */ 1195717d4247SJustin T. Gibbs ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large); 1196717d4247SJustin T. Gibbs test_num_scbs = ahc_probe_scbs(ahc); 1197717d4247SJustin T. Gibbs if (test_num_scbs == num_scbs 1198717d4247SJustin T. Gibbs && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 1199717d4247SJustin T. Gibbs || (ahc_inb(ahc, ERROR) & MPARERR) == 0)) 1200717d4247SJustin T. Gibbs fast = TRUE; 1201717d4247SJustin T. Gibbs 1202717d4247SJustin T. Gibbs /* 1203717d4247SJustin T. Gibbs * See if we can use large SCBs and still maintain 1204717d4247SJustin T. Gibbs * the same overall count of SCBs. 1205717d4247SJustin T. Gibbs */ 1206717d4247SJustin T. Gibbs if ((ahc->features & AHC_LARGE_SCBS) != 0) { 1207717d4247SJustin T. Gibbs ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE); 1208717d4247SJustin T. Gibbs test_num_scbs = ahc_probe_scbs(ahc); 1209717d4247SJustin T. Gibbs if (test_num_scbs >= num_scbs) { 1210717d4247SJustin T. Gibbs large = TRUE; 1211717d4247SJustin T. Gibbs num_scbs = test_num_scbs; 1212717d4247SJustin T. Gibbs if (num_scbs >= 64) { 1213717d4247SJustin T. Gibbs /* 1214717d4247SJustin T. Gibbs * We have enough space to move the 1215717d4247SJustin T. Gibbs * "busy targets table" into SCB space 1216717d4247SJustin T. Gibbs * and make it qualify all the way to the 1217717d4247SJustin T. Gibbs * lun level. 1218717d4247SJustin T. Gibbs */ 1219717d4247SJustin T. Gibbs ahc->flags |= AHC_SCB_BTT; 1220717d4247SJustin T. Gibbs } 1221717d4247SJustin T. Gibbs } 1222717d4247SJustin T. Gibbs } 1223717d4247SJustin T. Gibbs done: 1224717d4247SJustin T. Gibbs /* 1225717d4247SJustin T. Gibbs * Disable parity error reporting until we 1226717d4247SJustin T. Gibbs * can load instruction ram. 1227717d4247SJustin T. Gibbs */ 1228717d4247SJustin T. Gibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); 1229717d4247SJustin T. Gibbs /* Clear any latched parity error */ 1230717d4247SJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRPARERR); 1231717d4247SJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 1232717d4247SJustin T. Gibbs if (bootverbose && enable) { 1233717d4247SJustin T. Gibbs printf("%s: External SRAM, %s access%s, %dbytes/SCB\n", 1234717d4247SJustin T. Gibbs ahc_name(ahc), fast ? "fast" : "slow", 1235717d4247SJustin T. Gibbs pcheck ? ", parity checking enabled" : "", 1236717d4247SJustin T. Gibbs large ? 64 : 32); 1237717d4247SJustin T. Gibbs } 1238717d4247SJustin T. Gibbs ahc_scbram_config(ahc, enable, pcheck, fast, large); 1239717d4247SJustin T. Gibbs } 1240717d4247SJustin T. Gibbs 1241717d4247SJustin T. Gibbs /* 1242dc67dad8SScott Long * Perform some simple tests that should catch situations where 1243dc67dad8SScott Long * our registers are invalidly mapped. 1244dc67dad8SScott Long */ 1245dc67dad8SScott Long int 1246dc67dad8SScott Long ahc_pci_test_register_access(struct ahc_softc *ahc) 1247dc67dad8SScott Long { 124897cae63dSScott Long int error; 1249dc67dad8SScott Long u_int status1; 125070b41139SJustin T. Gibbs uint32_t cmd; 125170b41139SJustin T. Gibbs uint8_t hcntrl; 125297cae63dSScott Long 125397cae63dSScott Long error = EIO; 125497cae63dSScott Long 125570b41139SJustin T. Gibbs /* 125670b41139SJustin T. Gibbs * Enable PCI error interrupt status, but suppress NMIs 125770b41139SJustin T. Gibbs * generated by SERR raised due to target aborts. 125870b41139SJustin T. Gibbs */ 1259b3b25f2cSJustin T. Gibbs cmd = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); 1260b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, 126170b41139SJustin T. Gibbs cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); 1262dc67dad8SScott Long 1263dc67dad8SScott Long /* 1264dc67dad8SScott Long * First a simple test to see if any 1265dc67dad8SScott Long * registers can be read. Reading 1266dc67dad8SScott Long * HCNTRL has no side effects and has 1267dc67dad8SScott Long * at least one bit that is guaranteed to 1268dc67dad8SScott Long * be zero so it is a good register to 1269dc67dad8SScott Long * use for this test. 1270dc67dad8SScott Long */ 127170b41139SJustin T. Gibbs hcntrl = ahc_inb(ahc, HCNTRL); 1272b3b25f2cSJustin T. Gibbs 127370b41139SJustin T. Gibbs if (hcntrl == 0xFF) 127497cae63dSScott Long goto fail; 1275dc67dad8SScott Long 1276b3b25f2cSJustin T. Gibbs if ((hcntrl & CHIPRST) != 0) { 1277b3b25f2cSJustin T. Gibbs /* 1278b3b25f2cSJustin T. Gibbs * The chip has not been initialized since 1279b3b25f2cSJustin T. Gibbs * PCI/EISA/VLB bus reset. Don't trust 1280b3b25f2cSJustin T. Gibbs * "left over BIOS data". 1281b3b25f2cSJustin T. Gibbs */ 1282b3b25f2cSJustin T. Gibbs ahc->flags |= AHC_NO_BIOS_INIT; 1283b3b25f2cSJustin T. Gibbs } 1284b3b25f2cSJustin T. Gibbs 1285dc67dad8SScott Long /* 1286dc67dad8SScott Long * Next create a situation where write combining 1287dc67dad8SScott Long * or read prefetching could be initiated by the 1288dc67dad8SScott Long * CPU or host bridge. Our device does not support 1289dc67dad8SScott Long * either, so look for data corruption and/or flagged 1290ba079c0dSScott Long * PCI errors. First pause without causing another 1291ba079c0dSScott Long * chip reset. 1292dc67dad8SScott Long */ 1293ba079c0dSScott Long hcntrl &= ~CHIPRST; 129470b41139SJustin T. Gibbs ahc_outb(ahc, HCNTRL, hcntrl|PAUSE); 129570b41139SJustin T. Gibbs while (ahc_is_paused(ahc) == 0) 129670b41139SJustin T. Gibbs ; 1297176b648eSJustin T. Gibbs 1298176b648eSJustin T. Gibbs /* Clear any PCI errors that occurred before our driver attached. */ 1299b3b25f2cSJustin T. Gibbs status1 = aic_pci_read_config(ahc->dev_softc, 1300176b648eSJustin T. Gibbs PCIR_STATUS + 1, /*bytes*/1); 1301b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 1302176b648eSJustin T. Gibbs status1, /*bytes*/1); 1303176b648eSJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRPARERR); 1304176b648eSJustin T. Gibbs 130570b41139SJustin T. Gibbs ahc_outb(ahc, SEQCTL, PERRORDIS); 130670b41139SJustin T. Gibbs ahc_outb(ahc, SCBPTR, 0); 130770b41139SJustin T. Gibbs ahc_outl(ahc, SCB_BASE, 0x5aa555aa); 130870b41139SJustin T. Gibbs if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa) 130997cae63dSScott Long goto fail; 1310dc67dad8SScott Long 1311b3b25f2cSJustin T. Gibbs status1 = aic_pci_read_config(ahc->dev_softc, 1312dc67dad8SScott Long PCIR_STATUS + 1, /*bytes*/1); 131397cae63dSScott Long if ((status1 & STA) != 0) 131497cae63dSScott Long goto fail; 1315dc67dad8SScott Long 131697cae63dSScott Long error = 0; 131797cae63dSScott Long 131897cae63dSScott Long fail: 1319dc67dad8SScott Long /* Silently clear any latched errors. */ 1320b3b25f2cSJustin T. Gibbs status1 = aic_pci_read_config(ahc->dev_softc, 132197cae63dSScott Long PCIR_STATUS + 1, /*bytes*/1); 1322b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 1323dc67dad8SScott Long status1, /*bytes*/1); 1324dc67dad8SScott Long ahc_outb(ahc, CLRINT, CLRPARERR); 132570b41139SJustin T. Gibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); 1326b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); 132797cae63dSScott Long return (error); 1328dc67dad8SScott Long } 1329dc67dad8SScott Long 1330dc67dad8SScott Long /* 1331717d4247SJustin T. Gibbs * Check the external port logic for a serial eeprom 1332717d4247SJustin T. Gibbs * and termination/cable detection contrls. 1333717d4247SJustin T. Gibbs */ 1334717d4247SJustin T. Gibbs static void 1335717d4247SJustin T. Gibbs check_extport(struct ahc_softc *ahc, u_int *sxfrctl1) 1336717d4247SJustin T. Gibbs { 1337717d4247SJustin T. Gibbs struct seeprom_descriptor sd; 1338274c4127SJustin T. Gibbs struct seeprom_config *sc; 1339717d4247SJustin T. Gibbs int have_seeprom; 1340717d4247SJustin T. Gibbs int have_autoterm; 1341717d4247SJustin T. Gibbs 1342717d4247SJustin T. Gibbs sd.sd_ahc = ahc; 1343717d4247SJustin T. Gibbs sd.sd_control_offset = SEECTL; 1344717d4247SJustin T. Gibbs sd.sd_status_offset = SEECTL; 1345717d4247SJustin T. Gibbs sd.sd_dataout_offset = SEECTL; 1346274c4127SJustin T. Gibbs sc = ahc->seep_config; 1347717d4247SJustin T. Gibbs 1348717d4247SJustin T. Gibbs /* 1349717d4247SJustin T. Gibbs * For some multi-channel devices, the c46 is simply too 1350717d4247SJustin T. Gibbs * small to work. For the other controller types, we can 1351717d4247SJustin T. Gibbs * get our information from either SEEPROM type. Set the 1352717d4247SJustin T. Gibbs * type to start our probe with accordingly. 1353717d4247SJustin T. Gibbs */ 1354717d4247SJustin T. Gibbs if (ahc->flags & AHC_LARGE_SEEPROM) 1355717d4247SJustin T. Gibbs sd.sd_chip = C56_66; 1356717d4247SJustin T. Gibbs else 1357717d4247SJustin T. Gibbs sd.sd_chip = C46; 1358717d4247SJustin T. Gibbs 1359717d4247SJustin T. Gibbs sd.sd_MS = SEEMS; 1360717d4247SJustin T. Gibbs sd.sd_RDY = SEERDY; 1361717d4247SJustin T. Gibbs sd.sd_CS = SEECS; 1362717d4247SJustin T. Gibbs sd.sd_CK = SEECK; 1363717d4247SJustin T. Gibbs sd.sd_DO = SEEDO; 1364717d4247SJustin T. Gibbs sd.sd_DI = SEEDI; 1365717d4247SJustin T. Gibbs 13668f214efcSJustin T. Gibbs have_seeprom = ahc_acquire_seeprom(ahc, &sd); 1367717d4247SJustin T. Gibbs if (have_seeprom) { 1368717d4247SJustin T. Gibbs if (bootverbose) 1369717d4247SJustin T. Gibbs printf("%s: Reading SEEPROM...", ahc_name(ahc)); 1370717d4247SJustin T. Gibbs 1371717d4247SJustin T. Gibbs for (;;) { 1372717d4247SJustin T. Gibbs u_int start_addr; 1373717d4247SJustin T. Gibbs 1374717d4247SJustin T. Gibbs start_addr = 32 * (ahc->channel - 'A'); 1375717d4247SJustin T. Gibbs 1376274c4127SJustin T. Gibbs have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc, 13778f214efcSJustin T. Gibbs start_addr, 1378274c4127SJustin T. Gibbs sizeof(*sc)/2); 1379717d4247SJustin T. Gibbs 1380717d4247SJustin T. Gibbs if (have_seeprom) 1381274c4127SJustin T. Gibbs have_seeprom = ahc_verify_cksum(sc); 1382717d4247SJustin T. Gibbs 1383717d4247SJustin T. Gibbs if (have_seeprom != 0 || sd.sd_chip == C56_66) { 1384717d4247SJustin T. Gibbs if (bootverbose) { 1385717d4247SJustin T. Gibbs if (have_seeprom == 0) 1386717d4247SJustin T. Gibbs printf ("checksum error\n"); 1387717d4247SJustin T. Gibbs else 1388717d4247SJustin T. Gibbs printf ("done.\n"); 1389717d4247SJustin T. Gibbs } 1390717d4247SJustin T. Gibbs break; 1391717d4247SJustin T. Gibbs } 1392717d4247SJustin T. Gibbs sd.sd_chip = C56_66; 1393717d4247SJustin T. Gibbs } 13948f214efcSJustin T. Gibbs ahc_release_seeprom(&sd); 1395b3b25f2cSJustin T. Gibbs 1396b3b25f2cSJustin T. Gibbs /* Remember the SEEPROM type for later */ 1397b3b25f2cSJustin T. Gibbs if (sd.sd_chip == C56_66) 1398b3b25f2cSJustin T. Gibbs ahc->flags |= AHC_LARGE_SEEPROM; 1399717d4247SJustin T. Gibbs } 1400717d4247SJustin T. Gibbs 1401717d4247SJustin T. Gibbs if (!have_seeprom) { 1402717d4247SJustin T. Gibbs /* 1403717d4247SJustin T. Gibbs * Pull scratch ram settings and treat them as 1404717d4247SJustin T. Gibbs * if they are the contents of an seeprom if 1405717d4247SJustin T. Gibbs * the 'ADPT' signature is found in SCB2. 14066fb77fefSJustin T. Gibbs * We manually compose the data as 16bit values 14076fb77fefSJustin T. Gibbs * to avoid endian issues. 1408717d4247SJustin T. Gibbs */ 1409717d4247SJustin T. Gibbs ahc_outb(ahc, SCBPTR, 2); 1410717d4247SJustin T. Gibbs if (ahc_inb(ahc, SCB_BASE) == 'A' 1411717d4247SJustin T. Gibbs && ahc_inb(ahc, SCB_BASE + 1) == 'D' 1412717d4247SJustin T. Gibbs && ahc_inb(ahc, SCB_BASE + 2) == 'P' 1413717d4247SJustin T. Gibbs && ahc_inb(ahc, SCB_BASE + 3) == 'T') { 14146fb77fefSJustin T. Gibbs uint16_t *sc_data; 1415717d4247SJustin T. Gibbs int i; 1416717d4247SJustin T. Gibbs 1417274c4127SJustin T. Gibbs sc_data = (uint16_t *)sc; 1418274c4127SJustin T. Gibbs for (i = 0; i < 32; i++, sc_data++) { 14196fb77fefSJustin T. Gibbs int j; 14206fb77fefSJustin T. Gibbs 14216fb77fefSJustin T. Gibbs j = i * 2; 1422274c4127SJustin T. Gibbs *sc_data = ahc_inb(ahc, SRAM_BASE + j) 14236fb77fefSJustin T. Gibbs | ahc_inb(ahc, SRAM_BASE + j + 1) << 8; 14246fb77fefSJustin T. Gibbs } 1425274c4127SJustin T. Gibbs have_seeprom = ahc_verify_cksum(sc); 1426274c4127SJustin T. Gibbs if (have_seeprom) 1427274c4127SJustin T. Gibbs ahc->flags |= AHC_SCB_CONFIG_USED; 1428717d4247SJustin T. Gibbs } 14298f214efcSJustin T. Gibbs /* 14308f214efcSJustin T. Gibbs * Clear any SCB parity errors in case this data and 14318f214efcSJustin T. Gibbs * its associated parity was not initialized by the BIOS 14328f214efcSJustin T. Gibbs */ 14338f214efcSJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRPARERR); 14348f214efcSJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 1435717d4247SJustin T. Gibbs } 1436717d4247SJustin T. Gibbs 1437717d4247SJustin T. Gibbs if (!have_seeprom) { 1438717d4247SJustin T. Gibbs if (bootverbose) 1439717d4247SJustin T. Gibbs printf("%s: No SEEPROM available.\n", ahc_name(ahc)); 1440717d4247SJustin T. Gibbs ahc->flags |= AHC_USEDEFAULTS; 1441274c4127SJustin T. Gibbs free(ahc->seep_config, M_DEVBUF); 1442274c4127SJustin T. Gibbs ahc->seep_config = NULL; 1443274c4127SJustin T. Gibbs sc = NULL; 1444717d4247SJustin T. Gibbs } else { 1445274c4127SJustin T. Gibbs ahc_parse_pci_eeprom(ahc, sc); 1446274c4127SJustin T. Gibbs } 1447274c4127SJustin T. Gibbs 1448274c4127SJustin T. Gibbs /* 1449274c4127SJustin T. Gibbs * Cards that have the external logic necessary to talk to 1450274c4127SJustin T. Gibbs * a SEEPROM, are almost certain to have the remaining logic 1451274c4127SJustin T. Gibbs * necessary for auto-termination control. This assumption 1452274c4127SJustin T. Gibbs * hasn't failed yet... 1453274c4127SJustin T. Gibbs */ 1454274c4127SJustin T. Gibbs have_autoterm = have_seeprom; 1455274c4127SJustin T. Gibbs 1456274c4127SJustin T. Gibbs /* 1457274c4127SJustin T. Gibbs * Some low-cost chips have SEEPROM and auto-term control built 1458274c4127SJustin T. Gibbs * in, instead of using a GAL. They can tell us directly 1459274c4127SJustin T. Gibbs * if the termination logic is enabled. 1460274c4127SJustin T. Gibbs */ 1461274c4127SJustin T. Gibbs if ((ahc->features & AHC_SPIOCAP) != 0) { 1462274c4127SJustin T. Gibbs if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0) 1463274c4127SJustin T. Gibbs have_autoterm = FALSE; 1464274c4127SJustin T. Gibbs } 1465274c4127SJustin T. Gibbs 1466274c4127SJustin T. Gibbs if (have_autoterm) { 14679bf327a7SJustin T. Gibbs ahc->flags |= AHC_HAS_TERM_LOGIC; 1468274c4127SJustin T. Gibbs ahc_acquire_seeprom(ahc, &sd); 1469274c4127SJustin T. Gibbs configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1); 1470274c4127SJustin T. Gibbs ahc_release_seeprom(&sd); 1471274c4127SJustin T. Gibbs } else if (have_seeprom) { 1472274c4127SJustin T. Gibbs *sxfrctl1 &= ~STPWEN; 1473274c4127SJustin T. Gibbs if ((sc->adapter_control & CFSTERM) != 0) 1474274c4127SJustin T. Gibbs *sxfrctl1 |= STPWEN; 1475274c4127SJustin T. Gibbs if (bootverbose) 1476274c4127SJustin T. Gibbs printf("%s: Low byte termination %sabled\n", 1477274c4127SJustin T. Gibbs ahc_name(ahc), 1478274c4127SJustin T. Gibbs (*sxfrctl1 & STPWEN) ? "en" : "dis"); 1479274c4127SJustin T. Gibbs } 1480274c4127SJustin T. Gibbs } 1481274c4127SJustin T. Gibbs 1482274c4127SJustin T. Gibbs static void 1483274c4127SJustin T. Gibbs ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc) 1484274c4127SJustin T. Gibbs { 1485717d4247SJustin T. Gibbs /* 1486717d4247SJustin T. Gibbs * Put the data we've collected down into SRAM 1487717d4247SJustin T. Gibbs * where ahc_init will find it. 1488717d4247SJustin T. Gibbs */ 1489717d4247SJustin T. Gibbs int i; 1490274c4127SJustin T. Gibbs int max_targ = sc->max_targets & CFMAXTARG; 1491274c4127SJustin T. Gibbs u_int scsi_conf; 1492717d4247SJustin T. Gibbs uint16_t discenable; 1493717d4247SJustin T. Gibbs uint16_t ultraenb; 1494717d4247SJustin T. Gibbs 1495717d4247SJustin T. Gibbs discenable = 0; 1496717d4247SJustin T. Gibbs ultraenb = 0; 1497274c4127SJustin T. Gibbs if ((sc->adapter_control & CFULTRAEN) != 0) { 1498717d4247SJustin T. Gibbs /* 1499717d4247SJustin T. Gibbs * Determine if this adapter has a "newstyle" 1500717d4247SJustin T. Gibbs * SEEPROM format. 1501717d4247SJustin T. Gibbs */ 1502717d4247SJustin T. Gibbs for (i = 0; i < max_targ; i++) { 1503274c4127SJustin T. Gibbs if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) { 1504717d4247SJustin T. Gibbs ahc->flags |= AHC_NEWEEPROM_FMT; 1505717d4247SJustin T. Gibbs break; 1506717d4247SJustin T. Gibbs } 1507717d4247SJustin T. Gibbs } 1508717d4247SJustin T. Gibbs } 1509717d4247SJustin T. Gibbs 1510717d4247SJustin T. Gibbs for (i = 0; i < max_targ; i++) { 1511717d4247SJustin T. Gibbs u_int scsirate; 1512717d4247SJustin T. Gibbs uint16_t target_mask; 1513717d4247SJustin T. Gibbs 1514717d4247SJustin T. Gibbs target_mask = 0x01 << i; 1515274c4127SJustin T. Gibbs if (sc->device_flags[i] & CFDISC) 1516717d4247SJustin T. Gibbs discenable |= target_mask; 1517717d4247SJustin T. Gibbs if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) { 1518274c4127SJustin T. Gibbs if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) 1519717d4247SJustin T. Gibbs ultraenb |= target_mask; 1520274c4127SJustin T. Gibbs } else if ((sc->adapter_control & CFULTRAEN) != 0) { 1521717d4247SJustin T. Gibbs ultraenb |= target_mask; 1522717d4247SJustin T. Gibbs } 1523274c4127SJustin T. Gibbs if ((sc->device_flags[i] & CFXFER) == 0x04 1524717d4247SJustin T. Gibbs && (ultraenb & target_mask) != 0) { 1525717d4247SJustin T. Gibbs /* Treat 10MHz as a non-ultra speed */ 1526274c4127SJustin T. Gibbs sc->device_flags[i] &= ~CFXFER; 1527717d4247SJustin T. Gibbs ultraenb &= ~target_mask; 1528717d4247SJustin T. Gibbs } 1529717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) { 1530717d4247SJustin T. Gibbs u_int offset; 1531717d4247SJustin T. Gibbs 1532274c4127SJustin T. Gibbs if (sc->device_flags[i] & CFSYNCH) 1533717d4247SJustin T. Gibbs offset = MAX_OFFSET_ULTRA2; 1534717d4247SJustin T. Gibbs else 1535717d4247SJustin T. Gibbs offset = 0; 1536717d4247SJustin T. Gibbs ahc_outb(ahc, TARG_OFFSET + i, offset); 1537717d4247SJustin T. Gibbs 1538717d4247SJustin T. Gibbs /* 1539717d4247SJustin T. Gibbs * The ultra enable bits contain the 1540717d4247SJustin T. Gibbs * high bit of the ultra2 sync rate 1541717d4247SJustin T. Gibbs * field. 1542717d4247SJustin T. Gibbs */ 1543274c4127SJustin T. Gibbs scsirate = (sc->device_flags[i] & CFXFER) 1544274c4127SJustin T. Gibbs | ((ultraenb & target_mask) ? 0x8 : 0x0); 1545274c4127SJustin T. Gibbs if (sc->device_flags[i] & CFWIDEB) 1546717d4247SJustin T. Gibbs scsirate |= WIDEXFER; 1547717d4247SJustin T. Gibbs } else { 1548274c4127SJustin T. Gibbs scsirate = (sc->device_flags[i] & CFXFER) << 4; 1549274c4127SJustin T. Gibbs if (sc->device_flags[i] & CFSYNCH) 1550717d4247SJustin T. Gibbs scsirate |= SOFS; 1551274c4127SJustin T. Gibbs if (sc->device_flags[i] & CFWIDEB) 1552717d4247SJustin T. Gibbs scsirate |= WIDEXFER; 1553717d4247SJustin T. Gibbs } 1554717d4247SJustin T. Gibbs ahc_outb(ahc, TARG_SCSIRATE + i, scsirate); 1555717d4247SJustin T. Gibbs } 1556274c4127SJustin T. Gibbs ahc->our_id = sc->brtime_id & CFSCSIID; 1557717d4247SJustin T. Gibbs 1558717d4247SJustin T. Gibbs scsi_conf = (ahc->our_id & 0x7); 1559274c4127SJustin T. Gibbs if (sc->adapter_control & CFSPARITY) 1560717d4247SJustin T. Gibbs scsi_conf |= ENSPCHK; 1561274c4127SJustin T. Gibbs if (sc->adapter_control & CFRESETB) 1562717d4247SJustin T. Gibbs scsi_conf |= RESET_SCSI; 1563717d4247SJustin T. Gibbs 1564274c4127SJustin T. Gibbs ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT; 1565bfadd24dSJustin T. Gibbs 1566274c4127SJustin T. Gibbs if (sc->bios_control & CFEXTEND) 1567717d4247SJustin T. Gibbs ahc->flags |= AHC_EXTENDED_TRANS_A; 1568bfadd24dSJustin T. Gibbs 1569274c4127SJustin T. Gibbs if (sc->bios_control & CFBIOSEN) 1570bfadd24dSJustin T. Gibbs ahc->flags |= AHC_BIOS_ENABLED; 1571717d4247SJustin T. Gibbs if (ahc->features & AHC_ULTRA 1572717d4247SJustin T. Gibbs && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) { 1573717d4247SJustin T. Gibbs /* Should we enable Ultra mode? */ 1574274c4127SJustin T. Gibbs if (!(sc->adapter_control & CFULTRAEN)) 1575717d4247SJustin T. Gibbs /* Treat us as a non-ultra card */ 1576717d4247SJustin T. Gibbs ultraenb = 0; 1577717d4247SJustin T. Gibbs } 1578717d4247SJustin T. Gibbs 1579274c4127SJustin T. Gibbs if (sc->signature == CFSIGNATURE 1580274c4127SJustin T. Gibbs || sc->signature == CFSIGNATURE2) { 1581717d4247SJustin T. Gibbs uint32_t devconfig; 1582717d4247SJustin T. Gibbs 1583717d4247SJustin T. Gibbs /* Honor the STPWLEVEL settings */ 1584b3b25f2cSJustin T. Gibbs devconfig = aic_pci_read_config(ahc->dev_softc, 1585717d4247SJustin T. Gibbs DEVCONFIG, /*bytes*/4); 1586717d4247SJustin T. Gibbs devconfig &= ~STPWLEVEL; 1587274c4127SJustin T. Gibbs if ((sc->bios_control & CFSTPWLEVEL) != 0) 1588717d4247SJustin T. Gibbs devconfig |= STPWLEVEL; 1589b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, DEVCONFIG, 1590717d4247SJustin T. Gibbs devconfig, /*bytes*/4); 1591717d4247SJustin T. Gibbs } 1592717d4247SJustin T. Gibbs /* Set SCSICONF info */ 1593717d4247SJustin T. Gibbs ahc_outb(ahc, SCSICONF, scsi_conf); 1594717d4247SJustin T. Gibbs ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); 1595717d4247SJustin T. Gibbs ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); 1596717d4247SJustin T. Gibbs ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff); 1597717d4247SJustin T. Gibbs ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff); 1598717d4247SJustin T. Gibbs } 1599717d4247SJustin T. Gibbs 1600717d4247SJustin T. Gibbs static void 1601717d4247SJustin T. Gibbs configure_termination(struct ahc_softc *ahc, 1602717d4247SJustin T. Gibbs struct seeprom_descriptor *sd, 1603717d4247SJustin T. Gibbs u_int adapter_control, 1604717d4247SJustin T. Gibbs u_int *sxfrctl1) 1605717d4247SJustin T. Gibbs { 1606717d4247SJustin T. Gibbs uint8_t brddat; 1607717d4247SJustin T. Gibbs 1608717d4247SJustin T. Gibbs brddat = 0; 1609717d4247SJustin T. Gibbs 1610717d4247SJustin T. Gibbs /* 1611717d4247SJustin T. Gibbs * Update the settings in sxfrctl1 to match the 1612717d4247SJustin T. Gibbs * termination settings 1613717d4247SJustin T. Gibbs */ 1614717d4247SJustin T. Gibbs *sxfrctl1 = 0; 1615717d4247SJustin T. Gibbs 1616717d4247SJustin T. Gibbs /* 1617717d4247SJustin T. Gibbs * SEECS must be on for the GALS to latch 1618717d4247SJustin T. Gibbs * the data properly. Be sure to leave MS 1619717d4247SJustin T. Gibbs * on or we will release the seeprom. 1620717d4247SJustin T. Gibbs */ 1621717d4247SJustin T. Gibbs SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS); 1622717d4247SJustin T. Gibbs if ((adapter_control & CFAUTOTERM) != 0 1623717d4247SJustin T. Gibbs || (ahc->features & AHC_NEW_TERMCTL) != 0) { 1624717d4247SJustin T. Gibbs int internal50_present; 1625717d4247SJustin T. Gibbs int internal68_present; 1626717d4247SJustin T. Gibbs int externalcable_present; 1627717d4247SJustin T. Gibbs int eeprom_present; 1628717d4247SJustin T. Gibbs int enableSEC_low; 1629717d4247SJustin T. Gibbs int enableSEC_high; 1630717d4247SJustin T. Gibbs int enablePRI_low; 1631717d4247SJustin T. Gibbs int enablePRI_high; 1632a5847d5cSJustin T. Gibbs int sum; 1633717d4247SJustin T. Gibbs 1634717d4247SJustin T. Gibbs enableSEC_low = 0; 1635717d4247SJustin T. Gibbs enableSEC_high = 0; 1636717d4247SJustin T. Gibbs enablePRI_low = 0; 1637717d4247SJustin T. Gibbs enablePRI_high = 0; 1638717d4247SJustin T. Gibbs if ((ahc->features & AHC_NEW_TERMCTL) != 0) { 1639717d4247SJustin T. Gibbs ahc_new_term_detect(ahc, &enableSEC_low, 1640717d4247SJustin T. Gibbs &enableSEC_high, 1641717d4247SJustin T. Gibbs &enablePRI_low, 1642717d4247SJustin T. Gibbs &enablePRI_high, 1643717d4247SJustin T. Gibbs &eeprom_present); 1644717d4247SJustin T. Gibbs if ((adapter_control & CFSEAUTOTERM) == 0) { 1645717d4247SJustin T. Gibbs if (bootverbose) 1646717d4247SJustin T. Gibbs printf("%s: Manual SE Termination\n", 1647717d4247SJustin T. Gibbs ahc_name(ahc)); 1648717d4247SJustin T. Gibbs enableSEC_low = (adapter_control & CFSELOWTERM); 1649717d4247SJustin T. Gibbs enableSEC_high = 1650717d4247SJustin T. Gibbs (adapter_control & CFSEHIGHTERM); 1651717d4247SJustin T. Gibbs } 1652717d4247SJustin T. Gibbs if ((adapter_control & CFAUTOTERM) == 0) { 1653717d4247SJustin T. Gibbs if (bootverbose) 1654717d4247SJustin T. Gibbs printf("%s: Manual LVD Termination\n", 1655717d4247SJustin T. Gibbs ahc_name(ahc)); 1656717d4247SJustin T. Gibbs enablePRI_low = (adapter_control & CFSTERM); 1657717d4247SJustin T. Gibbs enablePRI_high = (adapter_control & CFWSTERM); 1658717d4247SJustin T. Gibbs } 1659717d4247SJustin T. Gibbs /* Make the table calculations below happy */ 1660717d4247SJustin T. Gibbs internal50_present = 0; 1661717d4247SJustin T. Gibbs internal68_present = 1; 1662717d4247SJustin T. Gibbs externalcable_present = 1; 1663717d4247SJustin T. Gibbs } else if ((ahc->features & AHC_SPIOCAP) != 0) { 1664717d4247SJustin T. Gibbs aic785X_cable_detect(ahc, &internal50_present, 1665717d4247SJustin T. Gibbs &externalcable_present, 1666717d4247SJustin T. Gibbs &eeprom_present); 1667274c4127SJustin T. Gibbs /* Can never support a wide connector. */ 1668274c4127SJustin T. Gibbs internal68_present = 0; 1669717d4247SJustin T. Gibbs } else { 1670717d4247SJustin T. Gibbs aic787X_cable_detect(ahc, &internal50_present, 1671717d4247SJustin T. Gibbs &internal68_present, 1672717d4247SJustin T. Gibbs &externalcable_present, 1673717d4247SJustin T. Gibbs &eeprom_present); 1674717d4247SJustin T. Gibbs } 1675717d4247SJustin T. Gibbs 1676717d4247SJustin T. Gibbs if ((ahc->features & AHC_WIDE) == 0) 1677717d4247SJustin T. Gibbs internal68_present = 0; 1678717d4247SJustin T. Gibbs 1679a5847d5cSJustin T. Gibbs if (bootverbose 1680a5847d5cSJustin T. Gibbs && (ahc->features & AHC_ULTRA2) == 0) { 1681a5847d5cSJustin T. Gibbs printf("%s: internal 50 cable %s present", 1682717d4247SJustin T. Gibbs ahc_name(ahc), 1683a5847d5cSJustin T. Gibbs internal50_present ? "is":"not"); 1684717d4247SJustin T. Gibbs 1685a5847d5cSJustin T. Gibbs if ((ahc->features & AHC_WIDE) != 0) 1686a5847d5cSJustin T. Gibbs printf(", internal 68 cable %s present", 1687a5847d5cSJustin T. Gibbs internal68_present ? "is":"not"); 1688a5847d5cSJustin T. Gibbs printf("\n%s: external cable %s present\n", 1689717d4247SJustin T. Gibbs ahc_name(ahc), 1690717d4247SJustin T. Gibbs externalcable_present ? "is":"not"); 1691717d4247SJustin T. Gibbs } 1692a5847d5cSJustin T. Gibbs if (bootverbose) 1693717d4247SJustin T. Gibbs printf("%s: BIOS eeprom %s present\n", 1694717d4247SJustin T. Gibbs ahc_name(ahc), eeprom_present ? "is" : "not"); 1695717d4247SJustin T. Gibbs 1696717d4247SJustin T. Gibbs if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) { 1697717d4247SJustin T. Gibbs /* 1698717d4247SJustin T. Gibbs * The 50 pin connector is a separate bus, 1699717d4247SJustin T. Gibbs * so force it to always be terminated. 1700717d4247SJustin T. Gibbs * In the future, perform current sensing 1701717d4247SJustin T. Gibbs * to determine if we are in the middle of 1702717d4247SJustin T. Gibbs * a properly terminated bus. 1703717d4247SJustin T. Gibbs */ 1704717d4247SJustin T. Gibbs internal50_present = 0; 1705717d4247SJustin T. Gibbs } 1706717d4247SJustin T. Gibbs 1707717d4247SJustin T. Gibbs /* 1708717d4247SJustin T. Gibbs * Now set the termination based on what 1709717d4247SJustin T. Gibbs * we found. 1710717d4247SJustin T. Gibbs * Flash Enable = BRDDAT7 1711717d4247SJustin T. Gibbs * Secondary High Term Enable = BRDDAT6 1712717d4247SJustin T. Gibbs * Secondary Low Term Enable = BRDDAT5 (7890) 1713717d4247SJustin T. Gibbs * Primary High Term Enable = BRDDAT4 (7890) 1714717d4247SJustin T. Gibbs */ 1715717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) == 0 1716717d4247SJustin T. Gibbs && (internal50_present != 0) 1717717d4247SJustin T. Gibbs && (internal68_present != 0) 1718717d4247SJustin T. Gibbs && (externalcable_present != 0)) { 1719717d4247SJustin T. Gibbs printf("%s: Illegal cable configuration!!. " 1720717d4247SJustin T. Gibbs "Only two connectors on the " 1721717d4247SJustin T. Gibbs "adapter may be used at a " 1722717d4247SJustin T. Gibbs "time!\n", ahc_name(ahc)); 17238f214efcSJustin T. Gibbs 17248f214efcSJustin T. Gibbs /* 17258f214efcSJustin T. Gibbs * Pretend there are no cables in the hope 17268f214efcSJustin T. Gibbs * that having all of the termination on 17278f214efcSJustin T. Gibbs * gives us a more stable bus. 17288f214efcSJustin T. Gibbs */ 17298f214efcSJustin T. Gibbs internal50_present = 0; 17308f214efcSJustin T. Gibbs internal68_present = 0; 17318f214efcSJustin T. Gibbs externalcable_present = 0; 1732717d4247SJustin T. Gibbs } 1733717d4247SJustin T. Gibbs 1734717d4247SJustin T. Gibbs if ((ahc->features & AHC_WIDE) != 0 1735717d4247SJustin T. Gibbs && ((externalcable_present == 0) 1736717d4247SJustin T. Gibbs || (internal68_present == 0) 1737717d4247SJustin T. Gibbs || (enableSEC_high != 0))) { 1738717d4247SJustin T. Gibbs brddat |= BRDDAT6; 1739717d4247SJustin T. Gibbs if (bootverbose) { 1740717d4247SJustin T. Gibbs if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 1741717d4247SJustin T. Gibbs printf("%s: 68 pin termination " 1742717d4247SJustin T. Gibbs "Enabled\n", ahc_name(ahc)); 1743717d4247SJustin T. Gibbs else 1744717d4247SJustin T. Gibbs printf("%s: %sHigh byte termination " 1745717d4247SJustin T. Gibbs "Enabled\n", ahc_name(ahc), 1746717d4247SJustin T. Gibbs enableSEC_high ? "Secondary " 1747717d4247SJustin T. Gibbs : ""); 1748717d4247SJustin T. Gibbs } 1749717d4247SJustin T. Gibbs } 1750717d4247SJustin T. Gibbs 1751a5847d5cSJustin T. Gibbs sum = internal50_present + internal68_present 1752a5847d5cSJustin T. Gibbs + externalcable_present; 1753a5847d5cSJustin T. Gibbs if (sum < 2 || (enableSEC_low != 0)) { 1754717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) 1755717d4247SJustin T. Gibbs brddat |= BRDDAT5; 1756717d4247SJustin T. Gibbs else 1757717d4247SJustin T. Gibbs *sxfrctl1 |= STPWEN; 1758717d4247SJustin T. Gibbs if (bootverbose) { 1759717d4247SJustin T. Gibbs if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 1760717d4247SJustin T. Gibbs printf("%s: 50 pin termination " 1761717d4247SJustin T. Gibbs "Enabled\n", ahc_name(ahc)); 1762717d4247SJustin T. Gibbs else 1763717d4247SJustin T. Gibbs printf("%s: %sLow byte termination " 1764717d4247SJustin T. Gibbs "Enabled\n", ahc_name(ahc), 1765717d4247SJustin T. Gibbs enableSEC_low ? "Secondary " 1766717d4247SJustin T. Gibbs : ""); 1767717d4247SJustin T. Gibbs } 1768717d4247SJustin T. Gibbs } 1769717d4247SJustin T. Gibbs 1770717d4247SJustin T. Gibbs if (enablePRI_low != 0) { 1771717d4247SJustin T. Gibbs *sxfrctl1 |= STPWEN; 1772717d4247SJustin T. Gibbs if (bootverbose) 1773717d4247SJustin T. Gibbs printf("%s: Primary Low Byte termination " 1774717d4247SJustin T. Gibbs "Enabled\n", ahc_name(ahc)); 1775717d4247SJustin T. Gibbs } 1776717d4247SJustin T. Gibbs 1777717d4247SJustin T. Gibbs /* 1778717d4247SJustin T. Gibbs * Setup STPWEN before setting up the rest of 1779717d4247SJustin T. Gibbs * the termination per the tech note on the U160 cards. 1780717d4247SJustin T. Gibbs */ 1781717d4247SJustin T. Gibbs ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 1782717d4247SJustin T. Gibbs 1783717d4247SJustin T. Gibbs if (enablePRI_high != 0) { 1784717d4247SJustin T. Gibbs brddat |= BRDDAT4; 1785717d4247SJustin T. Gibbs if (bootverbose) 1786717d4247SJustin T. Gibbs printf("%s: Primary High Byte " 1787717d4247SJustin T. Gibbs "termination Enabled\n", 1788717d4247SJustin T. Gibbs ahc_name(ahc)); 1789717d4247SJustin T. Gibbs } 1790717d4247SJustin T. Gibbs 1791717d4247SJustin T. Gibbs write_brdctl(ahc, brddat); 1792717d4247SJustin T. Gibbs 1793717d4247SJustin T. Gibbs } else { 1794717d4247SJustin T. Gibbs if ((adapter_control & CFSTERM) != 0) { 1795717d4247SJustin T. Gibbs *sxfrctl1 |= STPWEN; 1796717d4247SJustin T. Gibbs 1797717d4247SJustin T. Gibbs if (bootverbose) 1798717d4247SJustin T. Gibbs printf("%s: %sLow byte termination Enabled\n", 1799717d4247SJustin T. Gibbs ahc_name(ahc), 1800717d4247SJustin T. Gibbs (ahc->features & AHC_ULTRA2) ? "Primary " 1801717d4247SJustin T. Gibbs : ""); 1802717d4247SJustin T. Gibbs } 1803717d4247SJustin T. Gibbs 1804a5847d5cSJustin T. Gibbs if ((adapter_control & CFWSTERM) != 0 1805a5847d5cSJustin T. Gibbs && (ahc->features & AHC_WIDE) != 0) { 1806717d4247SJustin T. Gibbs brddat |= BRDDAT6; 1807717d4247SJustin T. Gibbs if (bootverbose) 1808717d4247SJustin T. Gibbs printf("%s: %sHigh byte termination Enabled\n", 1809717d4247SJustin T. Gibbs ahc_name(ahc), 1810717d4247SJustin T. Gibbs (ahc->features & AHC_ULTRA2) 1811717d4247SJustin T. Gibbs ? "Secondary " : ""); 1812717d4247SJustin T. Gibbs } 1813717d4247SJustin T. Gibbs 1814717d4247SJustin T. Gibbs /* 1815717d4247SJustin T. Gibbs * Setup STPWEN before setting up the rest of 1816717d4247SJustin T. Gibbs * the termination per the tech note on the U160 cards. 1817717d4247SJustin T. Gibbs */ 1818717d4247SJustin T. Gibbs ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 1819717d4247SJustin T. Gibbs 1820a5847d5cSJustin T. Gibbs if ((ahc->features & AHC_WIDE) != 0) 1821717d4247SJustin T. Gibbs write_brdctl(ahc, brddat); 1822717d4247SJustin T. Gibbs } 1823717d4247SJustin T. Gibbs SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */ 1824717d4247SJustin T. Gibbs } 1825717d4247SJustin T. Gibbs 1826717d4247SJustin T. Gibbs static void 1827717d4247SJustin T. Gibbs ahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low, 1828717d4247SJustin T. Gibbs int *enableSEC_high, int *enablePRI_low, 1829717d4247SJustin T. Gibbs int *enablePRI_high, int *eeprom_present) 1830717d4247SJustin T. Gibbs { 1831717d4247SJustin T. Gibbs uint8_t brdctl; 1832717d4247SJustin T. Gibbs 1833717d4247SJustin T. Gibbs /* 1834717d4247SJustin T. Gibbs * BRDDAT7 = Eeprom 1835717d4247SJustin T. Gibbs * BRDDAT6 = Enable Secondary High Byte termination 1836717d4247SJustin T. Gibbs * BRDDAT5 = Enable Secondary Low Byte termination 1837717d4247SJustin T. Gibbs * BRDDAT4 = Enable Primary high byte termination 1838717d4247SJustin T. Gibbs * BRDDAT3 = Enable Primary low byte termination 1839717d4247SJustin T. Gibbs */ 1840717d4247SJustin T. Gibbs brdctl = read_brdctl(ahc); 1841717d4247SJustin T. Gibbs *eeprom_present = brdctl & BRDDAT7; 1842717d4247SJustin T. Gibbs *enableSEC_high = (brdctl & BRDDAT6); 1843717d4247SJustin T. Gibbs *enableSEC_low = (brdctl & BRDDAT5); 1844717d4247SJustin T. Gibbs *enablePRI_high = (brdctl & BRDDAT4); 1845717d4247SJustin T. Gibbs *enablePRI_low = (brdctl & BRDDAT3); 1846717d4247SJustin T. Gibbs } 1847717d4247SJustin T. Gibbs 1848717d4247SJustin T. Gibbs static void 1849717d4247SJustin T. Gibbs aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 1850717d4247SJustin T. Gibbs int *internal68_present, int *externalcable_present, 1851717d4247SJustin T. Gibbs int *eeprom_present) 1852717d4247SJustin T. Gibbs { 1853717d4247SJustin T. Gibbs uint8_t brdctl; 1854717d4247SJustin T. Gibbs 1855717d4247SJustin T. Gibbs /* 1856717d4247SJustin T. Gibbs * First read the status of our cables. 1857717d4247SJustin T. Gibbs * Set the rom bank to 0 since the 1858717d4247SJustin T. Gibbs * bank setting serves as a multiplexor 1859717d4247SJustin T. Gibbs * for the cable detection logic. 1860717d4247SJustin T. Gibbs * BRDDAT5 controls the bank switch. 1861717d4247SJustin T. Gibbs */ 1862717d4247SJustin T. Gibbs write_brdctl(ahc, 0); 1863717d4247SJustin T. Gibbs 1864717d4247SJustin T. Gibbs /* 1865717d4247SJustin T. Gibbs * Now read the state of the internal 1866717d4247SJustin T. Gibbs * connectors. BRDDAT6 is INT50 and 1867717d4247SJustin T. Gibbs * BRDDAT7 is INT68. 1868717d4247SJustin T. Gibbs */ 1869717d4247SJustin T. Gibbs brdctl = read_brdctl(ahc); 1870a5847d5cSJustin T. Gibbs *internal50_present = (brdctl & BRDDAT6) ? 0 : 1; 1871a5847d5cSJustin T. Gibbs *internal68_present = (brdctl & BRDDAT7) ? 0 : 1; 1872717d4247SJustin T. Gibbs 1873717d4247SJustin T. Gibbs /* 1874717d4247SJustin T. Gibbs * Set the rom bank to 1 and determine 1875717d4247SJustin T. Gibbs * the other signals. 1876717d4247SJustin T. Gibbs */ 1877717d4247SJustin T. Gibbs write_brdctl(ahc, BRDDAT5); 1878717d4247SJustin T. Gibbs 1879717d4247SJustin T. Gibbs /* 1880717d4247SJustin T. Gibbs * Now read the state of the external 1881717d4247SJustin T. Gibbs * connectors. BRDDAT6 is EXT68 and 1882717d4247SJustin T. Gibbs * BRDDAT7 is EPROMPS. 1883717d4247SJustin T. Gibbs */ 1884717d4247SJustin T. Gibbs brdctl = read_brdctl(ahc); 1885a5847d5cSJustin T. Gibbs *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 1886a5847d5cSJustin T. Gibbs *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0; 1887717d4247SJustin T. Gibbs } 1888717d4247SJustin T. Gibbs 1889717d4247SJustin T. Gibbs static void 1890717d4247SJustin T. Gibbs aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 1891717d4247SJustin T. Gibbs int *externalcable_present, int *eeprom_present) 1892717d4247SJustin T. Gibbs { 1893717d4247SJustin T. Gibbs uint8_t brdctl; 1894274c4127SJustin T. Gibbs uint8_t spiocap; 1895717d4247SJustin T. Gibbs 1896274c4127SJustin T. Gibbs spiocap = ahc_inb(ahc, SPIOCAP); 1897274c4127SJustin T. Gibbs spiocap &= ~SOFTCMDEN; 1898274c4127SJustin T. Gibbs spiocap |= EXT_BRDCTL; 1899274c4127SJustin T. Gibbs ahc_outb(ahc, SPIOCAP, spiocap); 1900717d4247SJustin T. Gibbs ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); 19019bf327a7SJustin T. Gibbs ahc_flush_device_writes(ahc); 1902b3b25f2cSJustin T. Gibbs aic_delay(500); 1903717d4247SJustin T. Gibbs ahc_outb(ahc, BRDCTL, 0); 19049bf327a7SJustin T. Gibbs ahc_flush_device_writes(ahc); 1905b3b25f2cSJustin T. Gibbs aic_delay(500); 1906717d4247SJustin T. Gibbs brdctl = ahc_inb(ahc, BRDCTL); 1907a5847d5cSJustin T. Gibbs *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; 1908a5847d5cSJustin T. Gibbs *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 1909a5847d5cSJustin T. Gibbs *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0; 1910717d4247SJustin T. Gibbs } 1911717d4247SJustin T. Gibbs 19128f214efcSJustin T. Gibbs int 19138f214efcSJustin T. Gibbs ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd) 1914717d4247SJustin T. Gibbs { 1915717d4247SJustin T. Gibbs int wait; 1916717d4247SJustin T. Gibbs 1917717d4247SJustin T. Gibbs if ((ahc->features & AHC_SPIOCAP) != 0 1918717d4247SJustin T. Gibbs && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0) 1919717d4247SJustin T. Gibbs return (0); 1920717d4247SJustin T. Gibbs 1921717d4247SJustin T. Gibbs /* 1922717d4247SJustin T. Gibbs * Request access of the memory port. When access is 1923717d4247SJustin T. Gibbs * granted, SEERDY will go high. We use a 1 second 1924717d4247SJustin T. Gibbs * timeout which should be near 1 second more than 1925717d4247SJustin T. Gibbs * is needed. Reason: after the chip reset, there 1926717d4247SJustin T. Gibbs * should be no contention. 1927717d4247SJustin T. Gibbs */ 1928717d4247SJustin T. Gibbs SEEPROM_OUTB(sd, sd->sd_MS); 1929717d4247SJustin T. Gibbs wait = 1000; /* 1 second timeout in msec */ 1930717d4247SJustin T. Gibbs while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { 1931b3b25f2cSJustin T. Gibbs aic_delay(1000); /* delay 1 msec */ 1932717d4247SJustin T. Gibbs } 1933717d4247SJustin T. Gibbs if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { 1934717d4247SJustin T. Gibbs SEEPROM_OUTB(sd, 0); 1935717d4247SJustin T. Gibbs return (0); 1936717d4247SJustin T. Gibbs } 1937717d4247SJustin T. Gibbs return(1); 1938717d4247SJustin T. Gibbs } 1939717d4247SJustin T. Gibbs 19408f214efcSJustin T. Gibbs void 19418f214efcSJustin T. Gibbs ahc_release_seeprom(struct seeprom_descriptor *sd) 1942717d4247SJustin T. Gibbs { 1943717d4247SJustin T. Gibbs /* Release access to the memory port and the serial EEPROM. */ 1944717d4247SJustin T. Gibbs SEEPROM_OUTB(sd, 0); 1945717d4247SJustin T. Gibbs } 1946717d4247SJustin T. Gibbs 1947717d4247SJustin T. Gibbs static void 1948717d4247SJustin T. Gibbs write_brdctl(struct ahc_softc *ahc, uint8_t value) 1949717d4247SJustin T. Gibbs { 1950717d4247SJustin T. Gibbs uint8_t brdctl; 1951717d4247SJustin T. Gibbs 1952717d4247SJustin T. Gibbs if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 1953717d4247SJustin T. Gibbs brdctl = BRDSTB; 1954717d4247SJustin T. Gibbs if (ahc->channel == 'B') 1955717d4247SJustin T. Gibbs brdctl |= BRDCS; 1956717d4247SJustin T. Gibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 1957717d4247SJustin T. Gibbs brdctl = 0; 1958717d4247SJustin T. Gibbs } else { 1959717d4247SJustin T. Gibbs brdctl = BRDSTB|BRDCS; 1960717d4247SJustin T. Gibbs } 1961717d4247SJustin T. Gibbs ahc_outb(ahc, BRDCTL, brdctl); 1962a5847d5cSJustin T. Gibbs ahc_flush_device_writes(ahc); 1963717d4247SJustin T. Gibbs brdctl |= value; 1964717d4247SJustin T. Gibbs ahc_outb(ahc, BRDCTL, brdctl); 1965a5847d5cSJustin T. Gibbs ahc_flush_device_writes(ahc); 1966717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) 1967717d4247SJustin T. Gibbs brdctl |= BRDSTB_ULTRA2; 1968717d4247SJustin T. Gibbs else 1969717d4247SJustin T. Gibbs brdctl &= ~BRDSTB; 1970717d4247SJustin T. Gibbs ahc_outb(ahc, BRDCTL, brdctl); 1971a5847d5cSJustin T. Gibbs ahc_flush_device_writes(ahc); 1972717d4247SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) 1973717d4247SJustin T. Gibbs brdctl = 0; 1974717d4247SJustin T. Gibbs else 1975717d4247SJustin T. Gibbs brdctl &= ~BRDCS; 1976717d4247SJustin T. Gibbs ahc_outb(ahc, BRDCTL, brdctl); 1977717d4247SJustin T. Gibbs } 1978717d4247SJustin T. Gibbs 1979717d4247SJustin T. Gibbs static uint8_t 19803baccea6SJustin T. Gibbs read_brdctl(struct ahc_softc *ahc) 1981717d4247SJustin T. Gibbs { 1982717d4247SJustin T. Gibbs uint8_t brdctl; 1983717d4247SJustin T. Gibbs uint8_t value; 1984717d4247SJustin T. Gibbs 1985717d4247SJustin T. Gibbs if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 1986717d4247SJustin T. Gibbs brdctl = BRDRW; 1987717d4247SJustin T. Gibbs if (ahc->channel == 'B') 1988717d4247SJustin T. Gibbs brdctl |= BRDCS; 1989717d4247SJustin T. Gibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 1990717d4247SJustin T. Gibbs brdctl = BRDRW_ULTRA2; 1991717d4247SJustin T. Gibbs } else { 1992717d4247SJustin T. Gibbs brdctl = BRDRW|BRDCS; 1993717d4247SJustin T. Gibbs } 1994717d4247SJustin T. Gibbs ahc_outb(ahc, BRDCTL, brdctl); 1995a5847d5cSJustin T. Gibbs ahc_flush_device_writes(ahc); 1996717d4247SJustin T. Gibbs value = ahc_inb(ahc, BRDCTL); 1997717d4247SJustin T. Gibbs ahc_outb(ahc, BRDCTL, 0); 1998717d4247SJustin T. Gibbs return (value); 1999717d4247SJustin T. Gibbs } 2000717d4247SJustin T. Gibbs 20019bf327a7SJustin T. Gibbs static void 2002717d4247SJustin T. Gibbs ahc_pci_intr(struct ahc_softc *ahc) 2003717d4247SJustin T. Gibbs { 2004c498406dSJustin T. Gibbs u_int error; 2005c498406dSJustin T. Gibbs u_int status1; 2006c498406dSJustin T. Gibbs 2007c498406dSJustin T. Gibbs error = ahc_inb(ahc, ERROR); 2008c498406dSJustin T. Gibbs if ((error & PCIERRSTAT) == 0) 2009c498406dSJustin T. Gibbs return; 2010717d4247SJustin T. Gibbs 2011b3b25f2cSJustin T. Gibbs status1 = aic_pci_read_config(ahc->dev_softc, 2012717d4247SJustin T. Gibbs PCIR_STATUS + 1, /*bytes*/1); 2013717d4247SJustin T. Gibbs 2014ad3d2a4dSJustin T. Gibbs if ((status1 & ~DPE) != 0 2015ad3d2a4dSJustin T. Gibbs || (ahc->flags & AHC_DISABLE_PCI_PERR) == 0) { 2016c498406dSJustin T. Gibbs printf("%s: PCI error Interrupt at seqaddr = 0x%x\n", 2017717d4247SJustin T. Gibbs ahc_name(ahc), 2018717d4247SJustin T. Gibbs ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); 2019ad3d2a4dSJustin T. Gibbs } 2020c498406dSJustin T. Gibbs 2021ad3d2a4dSJustin T. Gibbs if (status1 & DPE 2022ad3d2a4dSJustin T. Gibbs && (ahc->flags & AHC_DISABLE_PCI_PERR) == 0) { 20239bf327a7SJustin T. Gibbs ahc->pci_target_perr_count++; 2024717d4247SJustin T. Gibbs printf("%s: Data Parity Error Detected during address " 2025717d4247SJustin T. Gibbs "or write data phase\n", ahc_name(ahc)); 2026717d4247SJustin T. Gibbs } 2027717d4247SJustin T. Gibbs if (status1 & SSE) { 2028a49630acSJustin T. Gibbs printf("%s: Signal System Error Detected\n", ahc_name(ahc)); 2029717d4247SJustin T. Gibbs } 2030717d4247SJustin T. Gibbs if (status1 & RMA) { 2031a49630acSJustin T. Gibbs printf("%s: Received a Master Abort\n", ahc_name(ahc)); 2032717d4247SJustin T. Gibbs } 2033717d4247SJustin T. Gibbs if (status1 & RTA) { 2034717d4247SJustin T. Gibbs printf("%s: Received a Target Abort\n", ahc_name(ahc)); 2035717d4247SJustin T. Gibbs } 2036717d4247SJustin T. Gibbs if (status1 & STA) { 2037717d4247SJustin T. Gibbs printf("%s: Signaled a Target Abort\n", ahc_name(ahc)); 2038717d4247SJustin T. Gibbs } 2039717d4247SJustin T. Gibbs if (status1 & DPR) { 2040717d4247SJustin T. Gibbs printf("%s: Data Parity Error has been reported via PERR#\n", 2041717d4247SJustin T. Gibbs ahc_name(ahc)); 2042717d4247SJustin T. Gibbs } 2043cd036e89SJustin T. Gibbs 2044cd036e89SJustin T. Gibbs /* Clear latched errors. */ 2045b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 2046717d4247SJustin T. Gibbs status1, /*bytes*/1); 2047717d4247SJustin T. Gibbs 2048cd036e89SJustin T. Gibbs if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { 2049cd036e89SJustin T. Gibbs printf("%s: Latched PCIERR interrupt with " 2050cd036e89SJustin T. Gibbs "no status bits set\n", ahc_name(ahc)); 2051cd036e89SJustin T. Gibbs } else { 2052717d4247SJustin T. Gibbs ahc_outb(ahc, CLRINT, CLRPARERR); 2053717d4247SJustin T. Gibbs } 2054c498406dSJustin T. Gibbs 2055ad3d2a4dSJustin T. Gibbs if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH 2056ad3d2a4dSJustin T. Gibbs && (ahc->flags & AHC_DISABLE_PCI_PERR) == 0) { 20579bf327a7SJustin T. Gibbs printf( 20589bf327a7SJustin T. Gibbs "%s: WARNING WARNING WARNING WARNING\n" 20599bf327a7SJustin T. Gibbs "%s: Too many PCI parity errors observed as a target.\n" 2060ad3d2a4dSJustin T. Gibbs "%s: Some device on this PCI bus is generating bad parity.\n" 2061ad3d2a4dSJustin T. Gibbs "%s: This is an error *observed by*, not *generated by*, %s.\n" 20629bf327a7SJustin T. Gibbs "%s: PCI parity error checking has been disabled.\n" 20639bf327a7SJustin T. Gibbs "%s: WARNING WARNING WARNING WARNING\n", 20649bf327a7SJustin T. Gibbs ahc_name(ahc), ahc_name(ahc), ahc_name(ahc), 2065ad3d2a4dSJustin T. Gibbs ahc_name(ahc), ahc_name(ahc), ahc_name(ahc), 2066ad3d2a4dSJustin T. Gibbs ahc_name(ahc)); 2067e4e6e6d6SJustin T. Gibbs ahc->seqctl |= FAILDIS; 2068ad3d2a4dSJustin T. Gibbs ahc->flags |= AHC_DISABLE_PCI_PERR; 2069e4e6e6d6SJustin T. Gibbs ahc_outb(ahc, SEQCTL, ahc->seqctl); 20709bf327a7SJustin T. Gibbs } 20716fb77fefSJustin T. Gibbs ahc_unpause(ahc); 2072717d4247SJustin T. Gibbs } 2073717d4247SJustin T. Gibbs 2074717d4247SJustin T. Gibbs static int 20759bf327a7SJustin T. Gibbs ahc_pci_chip_init(struct ahc_softc *ahc) 20769bf327a7SJustin T. Gibbs { 20779bf327a7SJustin T. Gibbs ahc_outb(ahc, DSCOMMAND0, ahc->bus_softc.pci_softc.dscommand0); 20789bf327a7SJustin T. Gibbs ahc_outb(ahc, DSPCISTATUS, ahc->bus_softc.pci_softc.dspcistatus); 20799bf327a7SJustin T. Gibbs if ((ahc->features & AHC_DT) != 0) { 20809bf327a7SJustin T. Gibbs u_int sfunct; 20819bf327a7SJustin T. Gibbs 20829bf327a7SJustin T. Gibbs sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 20839bf327a7SJustin T. Gibbs ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 20849bf327a7SJustin T. Gibbs ahc_outb(ahc, OPTIONMODE, ahc->bus_softc.pci_softc.optionmode); 20859bf327a7SJustin T. Gibbs ahc_outw(ahc, TARGCRCCNT, ahc->bus_softc.pci_softc.targcrccnt); 20869bf327a7SJustin T. Gibbs ahc_outb(ahc, SFUNCT, sfunct); 20879bf327a7SJustin T. Gibbs ahc_outb(ahc, CRCCONTROL1, 20889bf327a7SJustin T. Gibbs ahc->bus_softc.pci_softc.crccontrol1); 20899bf327a7SJustin T. Gibbs } 20909bf327a7SJustin T. Gibbs if ((ahc->features & AHC_MULTI_FUNC) != 0) 20919bf327a7SJustin T. Gibbs ahc_outb(ahc, SCBBADDR, ahc->bus_softc.pci_softc.scbbaddr); 20929bf327a7SJustin T. Gibbs 20939bf327a7SJustin T. Gibbs if ((ahc->features & AHC_ULTRA2) != 0) 20949bf327a7SJustin T. Gibbs ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh); 20959bf327a7SJustin T. Gibbs 20969bf327a7SJustin T. Gibbs return (ahc_chip_init(ahc)); 20979bf327a7SJustin T. Gibbs } 20989bf327a7SJustin T. Gibbs 20999bf327a7SJustin T. Gibbs static int 21009bf327a7SJustin T. Gibbs ahc_pci_suspend(struct ahc_softc *ahc) 21019bf327a7SJustin T. Gibbs { 21029bf327a7SJustin T. Gibbs return (ahc_suspend(ahc)); 21039bf327a7SJustin T. Gibbs } 21049bf327a7SJustin T. Gibbs 21059bf327a7SJustin T. Gibbs static int 21069bf327a7SJustin T. Gibbs ahc_pci_resume(struct ahc_softc *ahc) 21079bf327a7SJustin T. Gibbs { 21089bf327a7SJustin T. Gibbs 2109b3b25f2cSJustin T. Gibbs aic_power_state_change(ahc, AIC_POWER_STATE_D0); 21109bf327a7SJustin T. Gibbs 21119bf327a7SJustin T. Gibbs /* 21129bf327a7SJustin T. Gibbs * We assume that the OS has restored our register 21139bf327a7SJustin T. Gibbs * mappings, etc. Just update the config space registers 21149bf327a7SJustin T. Gibbs * that the OS doesn't know about and rely on our chip 21159bf327a7SJustin T. Gibbs * reset handler to handle the rest. 21169bf327a7SJustin T. Gibbs */ 211725edba1eSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, DEVCONFIG, 211825edba1eSJustin T. Gibbs ahc->bus_softc.pci_softc.devconfig, /*bytes*/4); 211925edba1eSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, 212025edba1eSJustin T. Gibbs ahc->bus_softc.pci_softc.command, /*bytes*/1); 212125edba1eSJustin T. Gibbs aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 212225edba1eSJustin T. Gibbs ahc->bus_softc.pci_softc.csize_lattime, 212325edba1eSJustin T. Gibbs /*bytes*/1); 21249bf327a7SJustin T. Gibbs if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) { 21259bf327a7SJustin T. Gibbs struct seeprom_descriptor sd; 21269bf327a7SJustin T. Gibbs u_int sxfrctl1; 21279bf327a7SJustin T. Gibbs 21289bf327a7SJustin T. Gibbs sd.sd_ahc = ahc; 21299bf327a7SJustin T. Gibbs sd.sd_control_offset = SEECTL; 21309bf327a7SJustin T. Gibbs sd.sd_status_offset = SEECTL; 21319bf327a7SJustin T. Gibbs sd.sd_dataout_offset = SEECTL; 21329bf327a7SJustin T. Gibbs 21339bf327a7SJustin T. Gibbs ahc_acquire_seeprom(ahc, &sd); 21349bf327a7SJustin T. Gibbs configure_termination(ahc, &sd, 21359bf327a7SJustin T. Gibbs ahc->seep_config->adapter_control, 21369bf327a7SJustin T. Gibbs &sxfrctl1); 21379bf327a7SJustin T. Gibbs ahc_release_seeprom(&sd); 21389bf327a7SJustin T. Gibbs } 21399bf327a7SJustin T. Gibbs return (ahc_resume(ahc)); 21409bf327a7SJustin T. Gibbs } 21419bf327a7SJustin T. Gibbs 21429bf327a7SJustin T. Gibbs static int 2143cd036e89SJustin T. Gibbs ahc_aic785X_setup(struct ahc_softc *ahc) 2144717d4247SJustin T. Gibbs { 2145b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 21466fb77fefSJustin T. Gibbs uint8_t rev; 21476fb77fefSJustin T. Gibbs 2148cd036e89SJustin T. Gibbs pci = ahc->dev_softc; 2149cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2150cd036e89SJustin T. Gibbs ahc->chip = AHC_AIC7850; 2151cd036e89SJustin T. Gibbs ahc->features = AHC_AIC7850_FE; 2152cd036e89SJustin T. Gibbs ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 2153b3b25f2cSJustin T. Gibbs rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 21546fb77fefSJustin T. Gibbs if (rev >= 1) 2155cd036e89SJustin T. Gibbs ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 21569bf327a7SJustin T. Gibbs ahc->instruction_ram_size = 512; 2157717d4247SJustin T. Gibbs return (0); 2158717d4247SJustin T. Gibbs } 2159717d4247SJustin T. Gibbs 2160717d4247SJustin T. Gibbs static int 2161cd036e89SJustin T. Gibbs ahc_aic7860_setup(struct ahc_softc *ahc) 2162717d4247SJustin T. Gibbs { 2163b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 2164717d4247SJustin T. Gibbs uint8_t rev; 2165717d4247SJustin T. Gibbs 2166cd036e89SJustin T. Gibbs pci = ahc->dev_softc; 2167cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2168cd036e89SJustin T. Gibbs ahc->chip = AHC_AIC7860; 2169cd036e89SJustin T. Gibbs ahc->features = AHC_AIC7860_FE; 2170cd036e89SJustin T. Gibbs ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 2171b3b25f2cSJustin T. Gibbs rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 2172717d4247SJustin T. Gibbs if (rev >= 1) 2173cd036e89SJustin T. Gibbs ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 21749bf327a7SJustin T. Gibbs ahc->instruction_ram_size = 512; 2175717d4247SJustin T. Gibbs return (0); 2176717d4247SJustin T. Gibbs } 2177717d4247SJustin T. Gibbs 2178717d4247SJustin T. Gibbs static int 2179cd036e89SJustin T. Gibbs ahc_apa1480_setup(struct ahc_softc *ahc) 2180a5847d5cSJustin T. Gibbs { 2181a5847d5cSJustin T. Gibbs int error; 2182a5847d5cSJustin T. Gibbs 2183cd036e89SJustin T. Gibbs error = ahc_aic7860_setup(ahc); 2184a5847d5cSJustin T. Gibbs if (error != 0) 2185a5847d5cSJustin T. Gibbs return (error); 2186cd036e89SJustin T. Gibbs ahc->features |= AHC_REMOVABLE; 2187a5847d5cSJustin T. Gibbs return (0); 2188a5847d5cSJustin T. Gibbs } 2189a5847d5cSJustin T. Gibbs 2190a5847d5cSJustin T. Gibbs static int 2191cd036e89SJustin T. Gibbs ahc_aic7870_setup(struct ahc_softc *ahc) 2192717d4247SJustin T. Gibbs { 2193cd036e89SJustin T. Gibbs 2194cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2195cd036e89SJustin T. Gibbs ahc->chip = AHC_AIC7870; 2196cd036e89SJustin T. Gibbs ahc->features = AHC_AIC7870_FE; 2197cd036e89SJustin T. Gibbs ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 21989bf327a7SJustin T. Gibbs ahc->instruction_ram_size = 512; 2199717d4247SJustin T. Gibbs return (0); 2200717d4247SJustin T. Gibbs } 2201717d4247SJustin T. Gibbs 2202717d4247SJustin T. Gibbs static int 2203cd036e89SJustin T. Gibbs ahc_aha394X_setup(struct ahc_softc *ahc) 2204717d4247SJustin T. Gibbs { 2205717d4247SJustin T. Gibbs int error; 2206717d4247SJustin T. Gibbs 2207cd036e89SJustin T. Gibbs error = ahc_aic7870_setup(ahc); 2208717d4247SJustin T. Gibbs if (error == 0) 2209cd036e89SJustin T. Gibbs error = ahc_aha394XX_setup(ahc); 2210717d4247SJustin T. Gibbs return (error); 2211717d4247SJustin T. Gibbs } 2212717d4247SJustin T. Gibbs 2213717d4247SJustin T. Gibbs static int 2214cd036e89SJustin T. Gibbs ahc_aha398X_setup(struct ahc_softc *ahc) 2215717d4247SJustin T. Gibbs { 2216717d4247SJustin T. Gibbs int error; 2217717d4247SJustin T. Gibbs 2218cd036e89SJustin T. Gibbs error = ahc_aic7870_setup(ahc); 2219717d4247SJustin T. Gibbs if (error == 0) 2220cd036e89SJustin T. Gibbs error = ahc_aha398XX_setup(ahc); 2221717d4247SJustin T. Gibbs return (error); 2222717d4247SJustin T. Gibbs } 2223717d4247SJustin T. Gibbs 2224717d4247SJustin T. Gibbs static int 2225cd036e89SJustin T. Gibbs ahc_aha494X_setup(struct ahc_softc *ahc) 2226717d4247SJustin T. Gibbs { 2227717d4247SJustin T. Gibbs int error; 2228717d4247SJustin T. Gibbs 2229cd036e89SJustin T. Gibbs error = ahc_aic7870_setup(ahc); 2230717d4247SJustin T. Gibbs if (error == 0) 2231cd036e89SJustin T. Gibbs error = ahc_aha494XX_setup(ahc); 2232717d4247SJustin T. Gibbs return (error); 2233717d4247SJustin T. Gibbs } 2234717d4247SJustin T. Gibbs 2235717d4247SJustin T. Gibbs static int 2236cd036e89SJustin T. Gibbs ahc_aic7880_setup(struct ahc_softc *ahc) 2237717d4247SJustin T. Gibbs { 2238b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 2239717d4247SJustin T. Gibbs uint8_t rev; 2240717d4247SJustin T. Gibbs 2241cd036e89SJustin T. Gibbs pci = ahc->dev_softc; 2242cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2243cd036e89SJustin T. Gibbs ahc->chip = AHC_AIC7880; 2244cd036e89SJustin T. Gibbs ahc->features = AHC_AIC7880_FE; 2245cd036e89SJustin T. Gibbs ahc->bugs |= AHC_TMODE_WIDEODD_BUG; 2246b3b25f2cSJustin T. Gibbs rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 2247717d4247SJustin T. Gibbs if (rev >= 1) { 2248cd036e89SJustin T. Gibbs ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 2249717d4247SJustin T. Gibbs } else { 2250cd036e89SJustin T. Gibbs ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 2251717d4247SJustin T. Gibbs } 22529bf327a7SJustin T. Gibbs ahc->instruction_ram_size = 512; 2253717d4247SJustin T. Gibbs return (0); 2254717d4247SJustin T. Gibbs } 2255717d4247SJustin T. Gibbs 2256717d4247SJustin T. Gibbs static int 2257cd036e89SJustin T. Gibbs ahc_aha2940Pro_setup(struct ahc_softc *ahc) 2258717d4247SJustin T. Gibbs { 2259717d4247SJustin T. Gibbs 2260cd036e89SJustin T. Gibbs ahc->flags |= AHC_INT50_SPEEDFLEX; 2261274c4127SJustin T. Gibbs return (ahc_aic7880_setup(ahc)); 2262717d4247SJustin T. Gibbs } 2263717d4247SJustin T. Gibbs 2264717d4247SJustin T. Gibbs static int 2265cd036e89SJustin T. Gibbs ahc_aha394XU_setup(struct ahc_softc *ahc) 2266717d4247SJustin T. Gibbs { 2267717d4247SJustin T. Gibbs int error; 2268717d4247SJustin T. Gibbs 2269cd036e89SJustin T. Gibbs error = ahc_aic7880_setup(ahc); 2270717d4247SJustin T. Gibbs if (error == 0) 2271cd036e89SJustin T. Gibbs error = ahc_aha394XX_setup(ahc); 2272717d4247SJustin T. Gibbs return (error); 2273717d4247SJustin T. Gibbs } 2274717d4247SJustin T. Gibbs 2275717d4247SJustin T. Gibbs static int 2276cd036e89SJustin T. Gibbs ahc_aha398XU_setup(struct ahc_softc *ahc) 2277717d4247SJustin T. Gibbs { 2278717d4247SJustin T. Gibbs int error; 2279717d4247SJustin T. Gibbs 2280cd036e89SJustin T. Gibbs error = ahc_aic7880_setup(ahc); 2281717d4247SJustin T. Gibbs if (error == 0) 2282cd036e89SJustin T. Gibbs error = ahc_aha398XX_setup(ahc); 2283717d4247SJustin T. Gibbs return (error); 2284717d4247SJustin T. Gibbs } 2285717d4247SJustin T. Gibbs 2286717d4247SJustin T. Gibbs static int 2287cd036e89SJustin T. Gibbs ahc_aic7890_setup(struct ahc_softc *ahc) 2288717d4247SJustin T. Gibbs { 2289b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 2290717d4247SJustin T. Gibbs uint8_t rev; 2291717d4247SJustin T. Gibbs 2292cd036e89SJustin T. Gibbs pci = ahc->dev_softc; 2293cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2294cd036e89SJustin T. Gibbs ahc->chip = AHC_AIC7890; 2295cd036e89SJustin T. Gibbs ahc->features = AHC_AIC7890_FE; 2296cd036e89SJustin T. Gibbs ahc->flags |= AHC_NEWEEPROM_FMT; 2297b3b25f2cSJustin T. Gibbs rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 2298717d4247SJustin T. Gibbs if (rev == 0) 2299cd036e89SJustin T. Gibbs ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; 23009bf327a7SJustin T. Gibbs ahc->instruction_ram_size = 768; 2301717d4247SJustin T. Gibbs return (0); 2302717d4247SJustin T. Gibbs } 2303717d4247SJustin T. Gibbs 2304717d4247SJustin T. Gibbs static int 2305cd036e89SJustin T. Gibbs ahc_aic7892_setup(struct ahc_softc *ahc) 2306717d4247SJustin T. Gibbs { 2307cd036e89SJustin T. Gibbs 2308cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2309cd036e89SJustin T. Gibbs ahc->chip = AHC_AIC7892; 2310cd036e89SJustin T. Gibbs ahc->features = AHC_AIC7892_FE; 2311cd036e89SJustin T. Gibbs ahc->flags |= AHC_NEWEEPROM_FMT; 2312cd036e89SJustin T. Gibbs ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; 23139bf327a7SJustin T. Gibbs ahc->instruction_ram_size = 1024; 2314717d4247SJustin T. Gibbs return (0); 2315717d4247SJustin T. Gibbs } 2316717d4247SJustin T. Gibbs 2317717d4247SJustin T. Gibbs static int 2318cd036e89SJustin T. Gibbs ahc_aic7895_setup(struct ahc_softc *ahc) 2319717d4247SJustin T. Gibbs { 2320b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 2321717d4247SJustin T. Gibbs uint8_t rev; 2322717d4247SJustin T. Gibbs 2323cd036e89SJustin T. Gibbs pci = ahc->dev_softc; 2324b3b25f2cSJustin T. Gibbs ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; 2325717d4247SJustin T. Gibbs /* 2326717d4247SJustin T. Gibbs * The 'C' revision of the aic7895 has a few additional features. 2327717d4247SJustin T. Gibbs */ 2328b3b25f2cSJustin T. Gibbs rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 2329717d4247SJustin T. Gibbs if (rev >= 4) { 2330cd036e89SJustin T. Gibbs ahc->chip = AHC_AIC7895C; 2331cd036e89SJustin T. Gibbs ahc->features = AHC_AIC7895C_FE; 2332717d4247SJustin T. Gibbs } else { 2333717d4247SJustin T. Gibbs u_int command; 2334717d4247SJustin T. Gibbs 2335cd036e89SJustin T. Gibbs ahc->chip = AHC_AIC7895; 2336cd036e89SJustin T. Gibbs ahc->features = AHC_AIC7895_FE; 2337717d4247SJustin T. Gibbs 2338717d4247SJustin T. Gibbs /* 2339717d4247SJustin T. Gibbs * The BIOS disables the use of MWI transactions 2340717d4247SJustin T. Gibbs * since it does not have the MWI bug work around 2341717d4247SJustin T. Gibbs * we have. Disabling MWI reduces performance, so 2342717d4247SJustin T. Gibbs * turn it on again. 2343717d4247SJustin T. Gibbs */ 2344b3b25f2cSJustin T. Gibbs command = aic_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); 2345717d4247SJustin T. Gibbs command |= PCIM_CMD_MWRICEN; 2346b3b25f2cSJustin T. Gibbs aic_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); 2347cd036e89SJustin T. Gibbs ahc->bugs |= AHC_PCI_MWI_BUG; 2348717d4247SJustin T. Gibbs } 2349717d4247SJustin T. Gibbs /* 2350717d4247SJustin T. Gibbs * XXX Does CACHETHEN really not work??? What about PCI retry? 2351717d4247SJustin T. Gibbs * on C level chips. Need to test, but for now, play it safe. 2352717d4247SJustin T. Gibbs */ 2353cd036e89SJustin T. Gibbs ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG 2354717d4247SJustin T. Gibbs | AHC_CACHETHEN_BUG; 2355717d4247SJustin T. Gibbs 2356717d4247SJustin T. Gibbs #if 0 2357717d4247SJustin T. Gibbs uint32_t devconfig; 2358717d4247SJustin T. Gibbs 2359717d4247SJustin T. Gibbs /* 2360717d4247SJustin T. Gibbs * Cachesize must also be zero due to stray DAC 2361717d4247SJustin T. Gibbs * problem when sitting behind some bridges. 2362717d4247SJustin T. Gibbs */ 2363b3b25f2cSJustin T. Gibbs aic_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); 2364b3b25f2cSJustin T. Gibbs devconfig = aic_pci_read_config(pci, DEVCONFIG, /*bytes*/1); 2365717d4247SJustin T. Gibbs devconfig |= MRDCEN; 2366b3b25f2cSJustin T. Gibbs aic_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); 2367717d4247SJustin T. Gibbs #endif 2368cd036e89SJustin T. Gibbs ahc->flags |= AHC_NEWEEPROM_FMT; 23699bf327a7SJustin T. Gibbs ahc->instruction_ram_size = 512; 2370717d4247SJustin T. Gibbs return (0); 2371717d4247SJustin T. Gibbs } 2372717d4247SJustin T. Gibbs 2373717d4247SJustin T. Gibbs static int 2374cd036e89SJustin T. Gibbs ahc_aic7896_setup(struct ahc_softc *ahc) 2375717d4247SJustin T. Gibbs { 2376b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 2377cd036e89SJustin T. Gibbs 2378cd036e89SJustin T. Gibbs pci = ahc->dev_softc; 2379b3b25f2cSJustin T. Gibbs ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; 2380cd036e89SJustin T. Gibbs ahc->chip = AHC_AIC7896; 2381cd036e89SJustin T. Gibbs ahc->features = AHC_AIC7896_FE; 2382cd036e89SJustin T. Gibbs ahc->flags |= AHC_NEWEEPROM_FMT; 2383cd036e89SJustin T. Gibbs ahc->bugs |= AHC_CACHETHEN_DIS_BUG; 23849bf327a7SJustin T. Gibbs ahc->instruction_ram_size = 768; 2385717d4247SJustin T. Gibbs return (0); 2386717d4247SJustin T. Gibbs } 2387717d4247SJustin T. Gibbs 2388717d4247SJustin T. Gibbs static int 2389cd036e89SJustin T. Gibbs ahc_aic7899_setup(struct ahc_softc *ahc) 2390717d4247SJustin T. Gibbs { 2391b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 2392cd036e89SJustin T. Gibbs 2393cd036e89SJustin T. Gibbs pci = ahc->dev_softc; 2394b3b25f2cSJustin T. Gibbs ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A'; 2395cd036e89SJustin T. Gibbs ahc->chip = AHC_AIC7899; 2396cd036e89SJustin T. Gibbs ahc->features = AHC_AIC7899_FE; 2397cd036e89SJustin T. Gibbs ahc->flags |= AHC_NEWEEPROM_FMT; 2398cd036e89SJustin T. Gibbs ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; 23999bf327a7SJustin T. Gibbs ahc->instruction_ram_size = 1024; 2400717d4247SJustin T. Gibbs return (0); 2401717d4247SJustin T. Gibbs } 2402717d4247SJustin T. Gibbs 2403717d4247SJustin T. Gibbs static int 2404cd036e89SJustin T. Gibbs ahc_aha29160C_setup(struct ahc_softc *ahc) 2405a5847d5cSJustin T. Gibbs { 2406a5847d5cSJustin T. Gibbs int error; 2407a5847d5cSJustin T. Gibbs 2408cd036e89SJustin T. Gibbs error = ahc_aic7899_setup(ahc); 2409a5847d5cSJustin T. Gibbs if (error != 0) 2410a5847d5cSJustin T. Gibbs return (error); 2411cd036e89SJustin T. Gibbs ahc->features |= AHC_REMOVABLE; 2412a5847d5cSJustin T. Gibbs return (0); 2413a5847d5cSJustin T. Gibbs } 2414a5847d5cSJustin T. Gibbs 2415a5847d5cSJustin T. Gibbs static int 2416cd036e89SJustin T. Gibbs ahc_raid_setup(struct ahc_softc *ahc) 2417717d4247SJustin T. Gibbs { 2418717d4247SJustin T. Gibbs printf("RAID functionality unsupported\n"); 2419717d4247SJustin T. Gibbs return (ENXIO); 2420717d4247SJustin T. Gibbs } 2421717d4247SJustin T. Gibbs 2422717d4247SJustin T. Gibbs static int 2423cd036e89SJustin T. Gibbs ahc_aha394XX_setup(struct ahc_softc *ahc) 2424717d4247SJustin T. Gibbs { 2425b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 2426cd036e89SJustin T. Gibbs 2427cd036e89SJustin T. Gibbs pci = ahc->dev_softc; 2428b3b25f2cSJustin T. Gibbs switch (aic_get_pci_slot(pci)) { 2429717d4247SJustin T. Gibbs case AHC_394X_SLOT_CHANNEL_A: 2430cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2431717d4247SJustin T. Gibbs break; 2432717d4247SJustin T. Gibbs case AHC_394X_SLOT_CHANNEL_B: 2433cd036e89SJustin T. Gibbs ahc->channel = 'B'; 2434717d4247SJustin T. Gibbs break; 2435717d4247SJustin T. Gibbs default: 2436717d4247SJustin T. Gibbs printf("adapter at unexpected slot %d\n" 2437717d4247SJustin T. Gibbs "unable to map to a channel\n", 2438b3b25f2cSJustin T. Gibbs aic_get_pci_slot(pci)); 2439cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2440717d4247SJustin T. Gibbs } 2441717d4247SJustin T. Gibbs return (0); 2442717d4247SJustin T. Gibbs } 2443717d4247SJustin T. Gibbs 2444717d4247SJustin T. Gibbs static int 2445cd036e89SJustin T. Gibbs ahc_aha398XX_setup(struct ahc_softc *ahc) 2446717d4247SJustin T. Gibbs { 2447b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 2448cd036e89SJustin T. Gibbs 2449cd036e89SJustin T. Gibbs pci = ahc->dev_softc; 2450b3b25f2cSJustin T. Gibbs switch (aic_get_pci_slot(pci)) { 2451717d4247SJustin T. Gibbs case AHC_398X_SLOT_CHANNEL_A: 2452cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2453717d4247SJustin T. Gibbs break; 2454717d4247SJustin T. Gibbs case AHC_398X_SLOT_CHANNEL_B: 2455cd036e89SJustin T. Gibbs ahc->channel = 'B'; 2456717d4247SJustin T. Gibbs break; 2457717d4247SJustin T. Gibbs case AHC_398X_SLOT_CHANNEL_C: 2458cd036e89SJustin T. Gibbs ahc->channel = 'C'; 2459717d4247SJustin T. Gibbs break; 2460717d4247SJustin T. Gibbs default: 2461717d4247SJustin T. Gibbs printf("adapter at unexpected slot %d\n" 2462717d4247SJustin T. Gibbs "unable to map to a channel\n", 2463b3b25f2cSJustin T. Gibbs aic_get_pci_slot(pci)); 2464cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2465717d4247SJustin T. Gibbs break; 2466717d4247SJustin T. Gibbs } 2467cd036e89SJustin T. Gibbs ahc->flags |= AHC_LARGE_SEEPROM; 2468717d4247SJustin T. Gibbs return (0); 2469717d4247SJustin T. Gibbs } 2470717d4247SJustin T. Gibbs 2471717d4247SJustin T. Gibbs static int 2472cd036e89SJustin T. Gibbs ahc_aha494XX_setup(struct ahc_softc *ahc) 2473717d4247SJustin T. Gibbs { 2474b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 2475cd036e89SJustin T. Gibbs 2476cd036e89SJustin T. Gibbs pci = ahc->dev_softc; 2477b3b25f2cSJustin T. Gibbs switch (aic_get_pci_slot(pci)) { 2478717d4247SJustin T. Gibbs case AHC_494X_SLOT_CHANNEL_A: 2479cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2480717d4247SJustin T. Gibbs break; 2481717d4247SJustin T. Gibbs case AHC_494X_SLOT_CHANNEL_B: 2482cd036e89SJustin T. Gibbs ahc->channel = 'B'; 2483717d4247SJustin T. Gibbs break; 2484717d4247SJustin T. Gibbs case AHC_494X_SLOT_CHANNEL_C: 2485cd036e89SJustin T. Gibbs ahc->channel = 'C'; 2486717d4247SJustin T. Gibbs break; 2487717d4247SJustin T. Gibbs case AHC_494X_SLOT_CHANNEL_D: 2488cd036e89SJustin T. Gibbs ahc->channel = 'D'; 2489717d4247SJustin T. Gibbs break; 2490717d4247SJustin T. Gibbs default: 2491717d4247SJustin T. Gibbs printf("adapter at unexpected slot %d\n" 2492717d4247SJustin T. Gibbs "unable to map to a channel\n", 2493b3b25f2cSJustin T. Gibbs aic_get_pci_slot(pci)); 2494cd036e89SJustin T. Gibbs ahc->channel = 'A'; 2495717d4247SJustin T. Gibbs } 2496cd036e89SJustin T. Gibbs ahc->flags |= AHC_LARGE_SEEPROM; 2497717d4247SJustin T. Gibbs return (0); 2498717d4247SJustin T. Gibbs } 2499