162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Product specific probe and attach routines for: 362306a36Sopenharmony_ci * 3940, 2940, aic7895, aic7890, aic7880, 462306a36Sopenharmony_ci * aic7870, aic7860 and aic7850 SCSI controllers 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (c) 1994-2001 Justin T. Gibbs. 762306a36Sopenharmony_ci * Copyright (c) 2000-2001 Adaptec Inc. 862306a36Sopenharmony_ci * All rights reserved. 962306a36Sopenharmony_ci * 1062306a36Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 1162306a36Sopenharmony_ci * modification, are permitted provided that the following conditions 1262306a36Sopenharmony_ci * are met: 1362306a36Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 1462306a36Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 1562306a36Sopenharmony_ci * without modification. 1662306a36Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1762306a36Sopenharmony_ci * substantially similar to the "NO WARRANTY" disclaimer below 1862306a36Sopenharmony_ci * ("Disclaimer") and any redistribution must be conditioned upon 1962306a36Sopenharmony_ci * including a substantially similar Disclaimer requirement for further 2062306a36Sopenharmony_ci * binary redistribution. 2162306a36Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 2262306a36Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 2362306a36Sopenharmony_ci * from this software without specific prior written permission. 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 2662306a36Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 2762306a36Sopenharmony_ci * Software Foundation. 2862306a36Sopenharmony_ci * 2962306a36Sopenharmony_ci * NO WARRANTY 3062306a36Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3162306a36Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3262306a36Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3362306a36Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3462306a36Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3562306a36Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3662306a36Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3762306a36Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3862306a36Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 3962306a36Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4062306a36Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES. 4162306a36Sopenharmony_ci * 4262306a36Sopenharmony_ci * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $ 4362306a36Sopenharmony_ci */ 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci#include "aic7xxx_osm.h" 4662306a36Sopenharmony_ci#include "aic7xxx_inline.h" 4762306a36Sopenharmony_ci#include "aic7xxx_93cx6.h" 4862306a36Sopenharmony_ci#include "aic7xxx_pci.h" 4962306a36Sopenharmony_ci 5062306a36Sopenharmony_cistatic inline uint64_t 5162306a36Sopenharmony_ciahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci uint64_t id; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci id = subvendor 5662306a36Sopenharmony_ci | (subdevice << 16) 5762306a36Sopenharmony_ci | ((uint64_t)vendor << 32) 5862306a36Sopenharmony_ci | ((uint64_t)device << 48); 5962306a36Sopenharmony_ci 6062306a36Sopenharmony_ci return (id); 6162306a36Sopenharmony_ci} 6262306a36Sopenharmony_ci 6362306a36Sopenharmony_ci#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */ 6462306a36Sopenharmony_ci#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */ 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci#define DEVID_9005_TYPE(id) ((id) & 0xF) 6762306a36Sopenharmony_ci#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ 6862306a36Sopenharmony_ci#define DEVID_9005_TYPE_AAA 0x3 /* RAID Card */ 6962306a36Sopenharmony_ci#define DEVID_9005_TYPE_SISL 0x5 /* Container ROMB */ 7062306a36Sopenharmony_ci#define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci#define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4) 7362306a36Sopenharmony_ci#define DEVID_9005_MAXRATE_U160 0x0 7462306a36Sopenharmony_ci#define DEVID_9005_MAXRATE_ULTRA2 0x1 7562306a36Sopenharmony_ci#define DEVID_9005_MAXRATE_ULTRA 0x2 7662306a36Sopenharmony_ci#define DEVID_9005_MAXRATE_FAST 0x3 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci#define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6) 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci#define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8) 8162306a36Sopenharmony_ci#define DEVID_9005_CLASS_SPI 0x0 /* Parallel SCSI */ 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci#define SUBID_9005_TYPE(id) ((id) & 0xF) 8462306a36Sopenharmony_ci#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */ 8562306a36Sopenharmony_ci#define SUBID_9005_TYPE_CARD 0x0 /* Standard Card */ 8662306a36Sopenharmony_ci#define SUBID_9005_TYPE_LCCARD 0x1 /* Low Cost Card */ 8762306a36Sopenharmony_ci#define SUBID_9005_TYPE_RAID 0x3 /* Combined with Raid */ 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci#define SUBID_9005_TYPE_KNOWN(id) \ 9062306a36Sopenharmony_ci ((((id) & 0xF) == SUBID_9005_TYPE_MB) \ 9162306a36Sopenharmony_ci || (((id) & 0xF) == SUBID_9005_TYPE_CARD) \ 9262306a36Sopenharmony_ci || (((id) & 0xF) == SUBID_9005_TYPE_LCCARD) \ 9362306a36Sopenharmony_ci || (((id) & 0xF) == SUBID_9005_TYPE_RAID)) 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci#define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4) 9662306a36Sopenharmony_ci#define SUBID_9005_MAXRATE_ULTRA2 0x0 9762306a36Sopenharmony_ci#define SUBID_9005_MAXRATE_ULTRA 0x1 9862306a36Sopenharmony_ci#define SUBID_9005_MAXRATE_U160 0x2 9962306a36Sopenharmony_ci#define SUBID_9005_MAXRATE_RESERVED 0x3 10062306a36Sopenharmony_ci 10162306a36Sopenharmony_ci#define SUBID_9005_SEEPTYPE(id) \ 10262306a36Sopenharmony_ci ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 10362306a36Sopenharmony_ci ? ((id) & 0xC0) >> 6 \ 10462306a36Sopenharmony_ci : ((id) & 0x300) >> 8) 10562306a36Sopenharmony_ci#define SUBID_9005_SEEPTYPE_NONE 0x0 10662306a36Sopenharmony_ci#define SUBID_9005_SEEPTYPE_1K 0x1 10762306a36Sopenharmony_ci#define SUBID_9005_SEEPTYPE_2K_4K 0x2 10862306a36Sopenharmony_ci#define SUBID_9005_SEEPTYPE_RESERVED 0x3 10962306a36Sopenharmony_ci#define SUBID_9005_AUTOTERM(id) \ 11062306a36Sopenharmony_ci ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 11162306a36Sopenharmony_ci ? (((id) & 0x400) >> 10) == 0 \ 11262306a36Sopenharmony_ci : (((id) & 0x40) >> 6) == 0) 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci#define SUBID_9005_NUMCHAN(id) \ 11562306a36Sopenharmony_ci ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 11662306a36Sopenharmony_ci ? ((id) & 0x300) >> 8 \ 11762306a36Sopenharmony_ci : ((id) & 0xC00) >> 10) 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci#define SUBID_9005_LEGACYCONN(id) \ 12062306a36Sopenharmony_ci ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 12162306a36Sopenharmony_ci ? 0 \ 12262306a36Sopenharmony_ci : ((id) & 0x80) >> 7) 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci#define SUBID_9005_MFUNCENB(id) \ 12562306a36Sopenharmony_ci ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 12662306a36Sopenharmony_ci ? ((id) & 0x800) >> 11 \ 12762306a36Sopenharmony_ci : ((id) & 0x1000) >> 12) 12862306a36Sopenharmony_ci/* 12962306a36Sopenharmony_ci * Informational only. Should use chip register to be 13062306a36Sopenharmony_ci * certain, but may be use in identification strings. 13162306a36Sopenharmony_ci */ 13262306a36Sopenharmony_ci#define SUBID_9005_CARD_SCSIWIDTH_MASK 0x2000 13362306a36Sopenharmony_ci#define SUBID_9005_CARD_PCIWIDTH_MASK 0x4000 13462306a36Sopenharmony_ci#define SUBID_9005_CARD_SEDIFF_MASK 0x8000 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic785X_setup; 13762306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7860_setup; 13862306a36Sopenharmony_cistatic ahc_device_setup_t ahc_apa1480_setup; 13962306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7870_setup; 14062306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7870h_setup; 14162306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha394X_setup; 14262306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha394Xh_setup; 14362306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha494X_setup; 14462306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha494Xh_setup; 14562306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha398X_setup; 14662306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7880_setup; 14762306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7880h_setup; 14862306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha2940Pro_setup; 14962306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha394XU_setup; 15062306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha394XUh_setup; 15162306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha398XU_setup; 15262306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7890_setup; 15362306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7892_setup; 15462306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7895_setup; 15562306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7895h_setup; 15662306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7896_setup; 15762306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aic7899_setup; 15862306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha29160C_setup; 15962306a36Sopenharmony_cistatic ahc_device_setup_t ahc_raid_setup; 16062306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha394XX_setup; 16162306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha494XX_setup; 16262306a36Sopenharmony_cistatic ahc_device_setup_t ahc_aha398XX_setup; 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_cistatic const struct ahc_pci_identity ahc_pci_ident_table[] = { 16562306a36Sopenharmony_ci /* aic7850 based controllers */ 16662306a36Sopenharmony_ci { 16762306a36Sopenharmony_ci ID_AHA_2902_04_10_15_20C_30C, 16862306a36Sopenharmony_ci ID_ALL_MASK, 16962306a36Sopenharmony_ci "Adaptec 2902/04/10/15/20C/30C SCSI adapter", 17062306a36Sopenharmony_ci ahc_aic785X_setup 17162306a36Sopenharmony_ci }, 17262306a36Sopenharmony_ci /* aic7860 based controllers */ 17362306a36Sopenharmony_ci { 17462306a36Sopenharmony_ci ID_AHA_2930CU, 17562306a36Sopenharmony_ci ID_ALL_MASK, 17662306a36Sopenharmony_ci "Adaptec 2930CU SCSI adapter", 17762306a36Sopenharmony_ci ahc_aic7860_setup 17862306a36Sopenharmony_ci }, 17962306a36Sopenharmony_ci { 18062306a36Sopenharmony_ci ID_AHA_1480A & ID_DEV_VENDOR_MASK, 18162306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 18262306a36Sopenharmony_ci "Adaptec 1480A Ultra SCSI adapter", 18362306a36Sopenharmony_ci ahc_apa1480_setup 18462306a36Sopenharmony_ci }, 18562306a36Sopenharmony_ci { 18662306a36Sopenharmony_ci ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK, 18762306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 18862306a36Sopenharmony_ci "Adaptec 2940A Ultra SCSI adapter", 18962306a36Sopenharmony_ci ahc_aic7860_setup 19062306a36Sopenharmony_ci }, 19162306a36Sopenharmony_ci { 19262306a36Sopenharmony_ci ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK, 19362306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 19462306a36Sopenharmony_ci "Adaptec 2940A/CN Ultra SCSI adapter", 19562306a36Sopenharmony_ci ahc_aic7860_setup 19662306a36Sopenharmony_ci }, 19762306a36Sopenharmony_ci { 19862306a36Sopenharmony_ci ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK, 19962306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 20062306a36Sopenharmony_ci "Adaptec 2930C Ultra SCSI adapter (VAR)", 20162306a36Sopenharmony_ci ahc_aic7860_setup 20262306a36Sopenharmony_ci }, 20362306a36Sopenharmony_ci /* aic7870 based controllers */ 20462306a36Sopenharmony_ci { 20562306a36Sopenharmony_ci ID_AHA_2940, 20662306a36Sopenharmony_ci ID_ALL_MASK, 20762306a36Sopenharmony_ci "Adaptec 2940 SCSI adapter", 20862306a36Sopenharmony_ci ahc_aic7870_setup 20962306a36Sopenharmony_ci }, 21062306a36Sopenharmony_ci { 21162306a36Sopenharmony_ci ID_AHA_3940, 21262306a36Sopenharmony_ci ID_ALL_MASK, 21362306a36Sopenharmony_ci "Adaptec 3940 SCSI adapter", 21462306a36Sopenharmony_ci ahc_aha394X_setup 21562306a36Sopenharmony_ci }, 21662306a36Sopenharmony_ci { 21762306a36Sopenharmony_ci ID_AHA_398X, 21862306a36Sopenharmony_ci ID_ALL_MASK, 21962306a36Sopenharmony_ci "Adaptec 398X SCSI RAID adapter", 22062306a36Sopenharmony_ci ahc_aha398X_setup 22162306a36Sopenharmony_ci }, 22262306a36Sopenharmony_ci { 22362306a36Sopenharmony_ci ID_AHA_2944, 22462306a36Sopenharmony_ci ID_ALL_MASK, 22562306a36Sopenharmony_ci "Adaptec 2944 SCSI adapter", 22662306a36Sopenharmony_ci ahc_aic7870h_setup 22762306a36Sopenharmony_ci }, 22862306a36Sopenharmony_ci { 22962306a36Sopenharmony_ci ID_AHA_3944, 23062306a36Sopenharmony_ci ID_ALL_MASK, 23162306a36Sopenharmony_ci "Adaptec 3944 SCSI adapter", 23262306a36Sopenharmony_ci ahc_aha394Xh_setup 23362306a36Sopenharmony_ci }, 23462306a36Sopenharmony_ci { 23562306a36Sopenharmony_ci ID_AHA_4944, 23662306a36Sopenharmony_ci ID_ALL_MASK, 23762306a36Sopenharmony_ci "Adaptec 4944 SCSI adapter", 23862306a36Sopenharmony_ci ahc_aha494Xh_setup 23962306a36Sopenharmony_ci }, 24062306a36Sopenharmony_ci /* aic7880 based controllers */ 24162306a36Sopenharmony_ci { 24262306a36Sopenharmony_ci ID_AHA_2940U & ID_DEV_VENDOR_MASK, 24362306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 24462306a36Sopenharmony_ci "Adaptec 2940 Ultra SCSI adapter", 24562306a36Sopenharmony_ci ahc_aic7880_setup 24662306a36Sopenharmony_ci }, 24762306a36Sopenharmony_ci { 24862306a36Sopenharmony_ci ID_AHA_3940U & ID_DEV_VENDOR_MASK, 24962306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 25062306a36Sopenharmony_ci "Adaptec 3940 Ultra SCSI adapter", 25162306a36Sopenharmony_ci ahc_aha394XU_setup 25262306a36Sopenharmony_ci }, 25362306a36Sopenharmony_ci { 25462306a36Sopenharmony_ci ID_AHA_2944U & ID_DEV_VENDOR_MASK, 25562306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 25662306a36Sopenharmony_ci "Adaptec 2944 Ultra SCSI adapter", 25762306a36Sopenharmony_ci ahc_aic7880h_setup 25862306a36Sopenharmony_ci }, 25962306a36Sopenharmony_ci { 26062306a36Sopenharmony_ci ID_AHA_3944U & ID_DEV_VENDOR_MASK, 26162306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 26262306a36Sopenharmony_ci "Adaptec 3944 Ultra SCSI adapter", 26362306a36Sopenharmony_ci ahc_aha394XUh_setup 26462306a36Sopenharmony_ci }, 26562306a36Sopenharmony_ci { 26662306a36Sopenharmony_ci ID_AHA_398XU & ID_DEV_VENDOR_MASK, 26762306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 26862306a36Sopenharmony_ci "Adaptec 398X Ultra SCSI RAID adapter", 26962306a36Sopenharmony_ci ahc_aha398XU_setup 27062306a36Sopenharmony_ci }, 27162306a36Sopenharmony_ci { 27262306a36Sopenharmony_ci /* 27362306a36Sopenharmony_ci * XXX Don't know the slot numbers 27462306a36Sopenharmony_ci * so we can't identify channels 27562306a36Sopenharmony_ci */ 27662306a36Sopenharmony_ci ID_AHA_4944U & ID_DEV_VENDOR_MASK, 27762306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 27862306a36Sopenharmony_ci "Adaptec 4944 Ultra SCSI adapter", 27962306a36Sopenharmony_ci ahc_aic7880h_setup 28062306a36Sopenharmony_ci }, 28162306a36Sopenharmony_ci { 28262306a36Sopenharmony_ci ID_AHA_2930U & ID_DEV_VENDOR_MASK, 28362306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 28462306a36Sopenharmony_ci "Adaptec 2930 Ultra SCSI adapter", 28562306a36Sopenharmony_ci ahc_aic7880_setup 28662306a36Sopenharmony_ci }, 28762306a36Sopenharmony_ci { 28862306a36Sopenharmony_ci ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK, 28962306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 29062306a36Sopenharmony_ci "Adaptec 2940 Pro Ultra SCSI adapter", 29162306a36Sopenharmony_ci ahc_aha2940Pro_setup 29262306a36Sopenharmony_ci }, 29362306a36Sopenharmony_ci { 29462306a36Sopenharmony_ci ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK, 29562306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 29662306a36Sopenharmony_ci "Adaptec 2940/CN Ultra SCSI adapter", 29762306a36Sopenharmony_ci ahc_aic7880_setup 29862306a36Sopenharmony_ci }, 29962306a36Sopenharmony_ci /* Ignore all SISL (AAC on MB) based controllers. */ 30062306a36Sopenharmony_ci { 30162306a36Sopenharmony_ci ID_9005_SISL_ID, 30262306a36Sopenharmony_ci ID_9005_SISL_MASK, 30362306a36Sopenharmony_ci NULL, 30462306a36Sopenharmony_ci NULL 30562306a36Sopenharmony_ci }, 30662306a36Sopenharmony_ci /* aic7890 based controllers */ 30762306a36Sopenharmony_ci { 30862306a36Sopenharmony_ci ID_AHA_2930U2, 30962306a36Sopenharmony_ci ID_ALL_MASK, 31062306a36Sopenharmony_ci "Adaptec 2930 Ultra2 SCSI adapter", 31162306a36Sopenharmony_ci ahc_aic7890_setup 31262306a36Sopenharmony_ci }, 31362306a36Sopenharmony_ci { 31462306a36Sopenharmony_ci ID_AHA_2940U2B, 31562306a36Sopenharmony_ci ID_ALL_MASK, 31662306a36Sopenharmony_ci "Adaptec 2940B Ultra2 SCSI adapter", 31762306a36Sopenharmony_ci ahc_aic7890_setup 31862306a36Sopenharmony_ci }, 31962306a36Sopenharmony_ci { 32062306a36Sopenharmony_ci ID_AHA_2940U2_OEM, 32162306a36Sopenharmony_ci ID_ALL_MASK, 32262306a36Sopenharmony_ci "Adaptec 2940 Ultra2 SCSI adapter (OEM)", 32362306a36Sopenharmony_ci ahc_aic7890_setup 32462306a36Sopenharmony_ci }, 32562306a36Sopenharmony_ci { 32662306a36Sopenharmony_ci ID_AHA_2940U2, 32762306a36Sopenharmony_ci ID_ALL_MASK, 32862306a36Sopenharmony_ci "Adaptec 2940 Ultra2 SCSI adapter", 32962306a36Sopenharmony_ci ahc_aic7890_setup 33062306a36Sopenharmony_ci }, 33162306a36Sopenharmony_ci { 33262306a36Sopenharmony_ci ID_AHA_2950U2B, 33362306a36Sopenharmony_ci ID_ALL_MASK, 33462306a36Sopenharmony_ci "Adaptec 2950 Ultra2 SCSI adapter", 33562306a36Sopenharmony_ci ahc_aic7890_setup 33662306a36Sopenharmony_ci }, 33762306a36Sopenharmony_ci { 33862306a36Sopenharmony_ci ID_AIC7890_ARO, 33962306a36Sopenharmony_ci ID_ALL_MASK, 34062306a36Sopenharmony_ci "Adaptec aic7890/91 Ultra2 SCSI adapter (ARO)", 34162306a36Sopenharmony_ci ahc_aic7890_setup 34262306a36Sopenharmony_ci }, 34362306a36Sopenharmony_ci { 34462306a36Sopenharmony_ci ID_AAA_131U2, 34562306a36Sopenharmony_ci ID_ALL_MASK, 34662306a36Sopenharmony_ci "Adaptec AAA-131 Ultra2 RAID adapter", 34762306a36Sopenharmony_ci ahc_aic7890_setup 34862306a36Sopenharmony_ci }, 34962306a36Sopenharmony_ci /* aic7892 based controllers */ 35062306a36Sopenharmony_ci { 35162306a36Sopenharmony_ci ID_AHA_29160, 35262306a36Sopenharmony_ci ID_ALL_MASK, 35362306a36Sopenharmony_ci "Adaptec 29160 Ultra160 SCSI adapter", 35462306a36Sopenharmony_ci ahc_aic7892_setup 35562306a36Sopenharmony_ci }, 35662306a36Sopenharmony_ci { 35762306a36Sopenharmony_ci ID_AHA_29160_CPQ, 35862306a36Sopenharmony_ci ID_ALL_MASK, 35962306a36Sopenharmony_ci "Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter", 36062306a36Sopenharmony_ci ahc_aic7892_setup 36162306a36Sopenharmony_ci }, 36262306a36Sopenharmony_ci { 36362306a36Sopenharmony_ci ID_AHA_29160N, 36462306a36Sopenharmony_ci ID_ALL_MASK, 36562306a36Sopenharmony_ci "Adaptec 29160N Ultra160 SCSI adapter", 36662306a36Sopenharmony_ci ahc_aic7892_setup 36762306a36Sopenharmony_ci }, 36862306a36Sopenharmony_ci { 36962306a36Sopenharmony_ci ID_AHA_29160C, 37062306a36Sopenharmony_ci ID_ALL_MASK, 37162306a36Sopenharmony_ci "Adaptec 29160C Ultra160 SCSI adapter", 37262306a36Sopenharmony_ci ahc_aha29160C_setup 37362306a36Sopenharmony_ci }, 37462306a36Sopenharmony_ci { 37562306a36Sopenharmony_ci ID_AHA_29160B, 37662306a36Sopenharmony_ci ID_ALL_MASK, 37762306a36Sopenharmony_ci "Adaptec 29160B Ultra160 SCSI adapter", 37862306a36Sopenharmony_ci ahc_aic7892_setup 37962306a36Sopenharmony_ci }, 38062306a36Sopenharmony_ci { 38162306a36Sopenharmony_ci ID_AHA_19160B, 38262306a36Sopenharmony_ci ID_ALL_MASK, 38362306a36Sopenharmony_ci "Adaptec 19160B Ultra160 SCSI adapter", 38462306a36Sopenharmony_ci ahc_aic7892_setup 38562306a36Sopenharmony_ci }, 38662306a36Sopenharmony_ci { 38762306a36Sopenharmony_ci ID_AIC7892_ARO, 38862306a36Sopenharmony_ci ID_ALL_MASK, 38962306a36Sopenharmony_ci "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", 39062306a36Sopenharmony_ci ahc_aic7892_setup 39162306a36Sopenharmony_ci }, 39262306a36Sopenharmony_ci { 39362306a36Sopenharmony_ci ID_AHA_2915_30LP, 39462306a36Sopenharmony_ci ID_ALL_MASK, 39562306a36Sopenharmony_ci "Adaptec 2915/30LP Ultra160 SCSI adapter", 39662306a36Sopenharmony_ci ahc_aic7892_setup 39762306a36Sopenharmony_ci }, 39862306a36Sopenharmony_ci /* aic7895 based controllers */ 39962306a36Sopenharmony_ci { 40062306a36Sopenharmony_ci ID_AHA_2940U_DUAL, 40162306a36Sopenharmony_ci ID_ALL_MASK, 40262306a36Sopenharmony_ci "Adaptec 2940/DUAL Ultra SCSI adapter", 40362306a36Sopenharmony_ci ahc_aic7895_setup 40462306a36Sopenharmony_ci }, 40562306a36Sopenharmony_ci { 40662306a36Sopenharmony_ci ID_AHA_3940AU, 40762306a36Sopenharmony_ci ID_ALL_MASK, 40862306a36Sopenharmony_ci "Adaptec 3940A Ultra SCSI adapter", 40962306a36Sopenharmony_ci ahc_aic7895_setup 41062306a36Sopenharmony_ci }, 41162306a36Sopenharmony_ci { 41262306a36Sopenharmony_ci ID_AHA_3944AU, 41362306a36Sopenharmony_ci ID_ALL_MASK, 41462306a36Sopenharmony_ci "Adaptec 3944A Ultra SCSI adapter", 41562306a36Sopenharmony_ci ahc_aic7895h_setup 41662306a36Sopenharmony_ci }, 41762306a36Sopenharmony_ci { 41862306a36Sopenharmony_ci ID_AIC7895_ARO, 41962306a36Sopenharmony_ci ID_AIC7895_ARO_MASK, 42062306a36Sopenharmony_ci "Adaptec aic7895 Ultra SCSI adapter (ARO)", 42162306a36Sopenharmony_ci ahc_aic7895_setup 42262306a36Sopenharmony_ci }, 42362306a36Sopenharmony_ci /* aic7896/97 based controllers */ 42462306a36Sopenharmony_ci { 42562306a36Sopenharmony_ci ID_AHA_3950U2B_0, 42662306a36Sopenharmony_ci ID_ALL_MASK, 42762306a36Sopenharmony_ci "Adaptec 3950B Ultra2 SCSI adapter", 42862306a36Sopenharmony_ci ahc_aic7896_setup 42962306a36Sopenharmony_ci }, 43062306a36Sopenharmony_ci { 43162306a36Sopenharmony_ci ID_AHA_3950U2B_1, 43262306a36Sopenharmony_ci ID_ALL_MASK, 43362306a36Sopenharmony_ci "Adaptec 3950B Ultra2 SCSI adapter", 43462306a36Sopenharmony_ci ahc_aic7896_setup 43562306a36Sopenharmony_ci }, 43662306a36Sopenharmony_ci { 43762306a36Sopenharmony_ci ID_AHA_3950U2D_0, 43862306a36Sopenharmony_ci ID_ALL_MASK, 43962306a36Sopenharmony_ci "Adaptec 3950D Ultra2 SCSI adapter", 44062306a36Sopenharmony_ci ahc_aic7896_setup 44162306a36Sopenharmony_ci }, 44262306a36Sopenharmony_ci { 44362306a36Sopenharmony_ci ID_AHA_3950U2D_1, 44462306a36Sopenharmony_ci ID_ALL_MASK, 44562306a36Sopenharmony_ci "Adaptec 3950D Ultra2 SCSI adapter", 44662306a36Sopenharmony_ci ahc_aic7896_setup 44762306a36Sopenharmony_ci }, 44862306a36Sopenharmony_ci { 44962306a36Sopenharmony_ci ID_AIC7896_ARO, 45062306a36Sopenharmony_ci ID_ALL_MASK, 45162306a36Sopenharmony_ci "Adaptec aic7896/97 Ultra2 SCSI adapter (ARO)", 45262306a36Sopenharmony_ci ahc_aic7896_setup 45362306a36Sopenharmony_ci }, 45462306a36Sopenharmony_ci /* aic7899 based controllers */ 45562306a36Sopenharmony_ci { 45662306a36Sopenharmony_ci ID_AHA_3960D, 45762306a36Sopenharmony_ci ID_ALL_MASK, 45862306a36Sopenharmony_ci "Adaptec 3960D Ultra160 SCSI adapter", 45962306a36Sopenharmony_ci ahc_aic7899_setup 46062306a36Sopenharmony_ci }, 46162306a36Sopenharmony_ci { 46262306a36Sopenharmony_ci ID_AHA_3960D_CPQ, 46362306a36Sopenharmony_ci ID_ALL_MASK, 46462306a36Sopenharmony_ci "Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter", 46562306a36Sopenharmony_ci ahc_aic7899_setup 46662306a36Sopenharmony_ci }, 46762306a36Sopenharmony_ci { 46862306a36Sopenharmony_ci ID_AIC7899_ARO, 46962306a36Sopenharmony_ci ID_ALL_MASK, 47062306a36Sopenharmony_ci "Adaptec aic7899 Ultra160 SCSI adapter (ARO)", 47162306a36Sopenharmony_ci ahc_aic7899_setup 47262306a36Sopenharmony_ci }, 47362306a36Sopenharmony_ci /* Generic chip probes for devices we don't know 'exactly' */ 47462306a36Sopenharmony_ci { 47562306a36Sopenharmony_ci ID_AIC7850 & ID_DEV_VENDOR_MASK, 47662306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 47762306a36Sopenharmony_ci "Adaptec aic7850 SCSI adapter", 47862306a36Sopenharmony_ci ahc_aic785X_setup 47962306a36Sopenharmony_ci }, 48062306a36Sopenharmony_ci { 48162306a36Sopenharmony_ci ID_AIC7855 & ID_DEV_VENDOR_MASK, 48262306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 48362306a36Sopenharmony_ci "Adaptec aic7855 SCSI adapter", 48462306a36Sopenharmony_ci ahc_aic785X_setup 48562306a36Sopenharmony_ci }, 48662306a36Sopenharmony_ci { 48762306a36Sopenharmony_ci ID_AIC7859 & ID_DEV_VENDOR_MASK, 48862306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 48962306a36Sopenharmony_ci "Adaptec aic7859 SCSI adapter", 49062306a36Sopenharmony_ci ahc_aic7860_setup 49162306a36Sopenharmony_ci }, 49262306a36Sopenharmony_ci { 49362306a36Sopenharmony_ci ID_AIC7860 & ID_DEV_VENDOR_MASK, 49462306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 49562306a36Sopenharmony_ci "Adaptec aic7860 Ultra SCSI adapter", 49662306a36Sopenharmony_ci ahc_aic7860_setup 49762306a36Sopenharmony_ci }, 49862306a36Sopenharmony_ci { 49962306a36Sopenharmony_ci ID_AIC7870 & ID_DEV_VENDOR_MASK, 50062306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 50162306a36Sopenharmony_ci "Adaptec aic7870 SCSI adapter", 50262306a36Sopenharmony_ci ahc_aic7870_setup 50362306a36Sopenharmony_ci }, 50462306a36Sopenharmony_ci { 50562306a36Sopenharmony_ci ID_AIC7880 & ID_DEV_VENDOR_MASK, 50662306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 50762306a36Sopenharmony_ci "Adaptec aic7880 Ultra SCSI adapter", 50862306a36Sopenharmony_ci ahc_aic7880_setup 50962306a36Sopenharmony_ci }, 51062306a36Sopenharmony_ci { 51162306a36Sopenharmony_ci ID_AIC7890 & ID_9005_GENERIC_MASK, 51262306a36Sopenharmony_ci ID_9005_GENERIC_MASK, 51362306a36Sopenharmony_ci "Adaptec aic7890/91 Ultra2 SCSI adapter", 51462306a36Sopenharmony_ci ahc_aic7890_setup 51562306a36Sopenharmony_ci }, 51662306a36Sopenharmony_ci { 51762306a36Sopenharmony_ci ID_AIC7892 & ID_9005_GENERIC_MASK, 51862306a36Sopenharmony_ci ID_9005_GENERIC_MASK, 51962306a36Sopenharmony_ci "Adaptec aic7892 Ultra160 SCSI adapter", 52062306a36Sopenharmony_ci ahc_aic7892_setup 52162306a36Sopenharmony_ci }, 52262306a36Sopenharmony_ci { 52362306a36Sopenharmony_ci ID_AIC7895 & ID_DEV_VENDOR_MASK, 52462306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 52562306a36Sopenharmony_ci "Adaptec aic7895 Ultra SCSI adapter", 52662306a36Sopenharmony_ci ahc_aic7895_setup 52762306a36Sopenharmony_ci }, 52862306a36Sopenharmony_ci { 52962306a36Sopenharmony_ci ID_AIC7896 & ID_9005_GENERIC_MASK, 53062306a36Sopenharmony_ci ID_9005_GENERIC_MASK, 53162306a36Sopenharmony_ci "Adaptec aic7896/97 Ultra2 SCSI adapter", 53262306a36Sopenharmony_ci ahc_aic7896_setup 53362306a36Sopenharmony_ci }, 53462306a36Sopenharmony_ci { 53562306a36Sopenharmony_ci ID_AIC7899 & ID_9005_GENERIC_MASK, 53662306a36Sopenharmony_ci ID_9005_GENERIC_MASK, 53762306a36Sopenharmony_ci "Adaptec aic7899 Ultra160 SCSI adapter", 53862306a36Sopenharmony_ci ahc_aic7899_setup 53962306a36Sopenharmony_ci }, 54062306a36Sopenharmony_ci { 54162306a36Sopenharmony_ci ID_AIC7810 & ID_DEV_VENDOR_MASK, 54262306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 54362306a36Sopenharmony_ci "Adaptec aic7810 RAID memory controller", 54462306a36Sopenharmony_ci ahc_raid_setup 54562306a36Sopenharmony_ci }, 54662306a36Sopenharmony_ci { 54762306a36Sopenharmony_ci ID_AIC7815 & ID_DEV_VENDOR_MASK, 54862306a36Sopenharmony_ci ID_DEV_VENDOR_MASK, 54962306a36Sopenharmony_ci "Adaptec aic7815 RAID memory controller", 55062306a36Sopenharmony_ci ahc_raid_setup 55162306a36Sopenharmony_ci } 55262306a36Sopenharmony_ci}; 55362306a36Sopenharmony_ci 55462306a36Sopenharmony_cistatic const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table); 55562306a36Sopenharmony_ci 55662306a36Sopenharmony_ci#define AHC_394X_SLOT_CHANNEL_A 4 55762306a36Sopenharmony_ci#define AHC_394X_SLOT_CHANNEL_B 5 55862306a36Sopenharmony_ci 55962306a36Sopenharmony_ci#define AHC_398X_SLOT_CHANNEL_A 4 56062306a36Sopenharmony_ci#define AHC_398X_SLOT_CHANNEL_B 8 56162306a36Sopenharmony_ci#define AHC_398X_SLOT_CHANNEL_C 12 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_ci#define AHC_494X_SLOT_CHANNEL_A 4 56462306a36Sopenharmony_ci#define AHC_494X_SLOT_CHANNEL_B 5 56562306a36Sopenharmony_ci#define AHC_494X_SLOT_CHANNEL_C 6 56662306a36Sopenharmony_ci#define AHC_494X_SLOT_CHANNEL_D 7 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_ci#define DEVCONFIG 0x40 56962306a36Sopenharmony_ci#define PCIERRGENDIS 0x80000000ul 57062306a36Sopenharmony_ci#define SCBSIZE32 0x00010000ul /* aic789X only */ 57162306a36Sopenharmony_ci#define REXTVALID 0x00001000ul /* ultra cards only */ 57262306a36Sopenharmony_ci#define MPORTMODE 0x00000400ul /* aic7870+ only */ 57362306a36Sopenharmony_ci#define RAMPSM 0x00000200ul /* aic7870+ only */ 57462306a36Sopenharmony_ci#define VOLSENSE 0x00000100ul 57562306a36Sopenharmony_ci#define PCI64BIT 0x00000080ul /* 64Bit PCI bus (Ultra2 Only)*/ 57662306a36Sopenharmony_ci#define SCBRAMSEL 0x00000080ul 57762306a36Sopenharmony_ci#define MRDCEN 0x00000040ul 57862306a36Sopenharmony_ci#define EXTSCBTIME 0x00000020ul /* aic7870 only */ 57962306a36Sopenharmony_ci#define EXTSCBPEN 0x00000010ul /* aic7870 only */ 58062306a36Sopenharmony_ci#define BERREN 0x00000008ul 58162306a36Sopenharmony_ci#define DACEN 0x00000004ul 58262306a36Sopenharmony_ci#define STPWLEVEL 0x00000002ul 58362306a36Sopenharmony_ci#define DIFACTNEGEN 0x00000001ul /* aic7870 only */ 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_ci#define CSIZE_LATTIME 0x0c 58662306a36Sopenharmony_ci#define CACHESIZE 0x0000003ful /* only 5 bits */ 58762306a36Sopenharmony_ci#define LATTIME 0x0000ff00ul 58862306a36Sopenharmony_ci 58962306a36Sopenharmony_ci/* PCI STATUS definitions */ 59062306a36Sopenharmony_ci#define DPE 0x80 59162306a36Sopenharmony_ci#define SSE 0x40 59262306a36Sopenharmony_ci#define RMA 0x20 59362306a36Sopenharmony_ci#define RTA 0x10 59462306a36Sopenharmony_ci#define STA 0x08 59562306a36Sopenharmony_ci#define DPR 0x01 59662306a36Sopenharmony_ci 59762306a36Sopenharmony_cistatic int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, 59862306a36Sopenharmony_ci uint16_t subdevice, uint16_t subvendor); 59962306a36Sopenharmony_cistatic int ahc_ext_scbram_present(struct ahc_softc *ahc); 60062306a36Sopenharmony_cistatic void ahc_scbram_config(struct ahc_softc *ahc, int enable, 60162306a36Sopenharmony_ci int pcheck, int fast, int large); 60262306a36Sopenharmony_cistatic void ahc_probe_ext_scbram(struct ahc_softc *ahc); 60362306a36Sopenharmony_cistatic void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1); 60462306a36Sopenharmony_cistatic void ahc_parse_pci_eeprom(struct ahc_softc *ahc, 60562306a36Sopenharmony_ci struct seeprom_config *sc); 60662306a36Sopenharmony_cistatic void configure_termination(struct ahc_softc *ahc, 60762306a36Sopenharmony_ci struct seeprom_descriptor *sd, 60862306a36Sopenharmony_ci u_int adapter_control, 60962306a36Sopenharmony_ci u_int *sxfrctl1); 61062306a36Sopenharmony_ci 61162306a36Sopenharmony_cistatic void ahc_new_term_detect(struct ahc_softc *ahc, 61262306a36Sopenharmony_ci int *enableSEC_low, 61362306a36Sopenharmony_ci int *enableSEC_high, 61462306a36Sopenharmony_ci int *enablePRI_low, 61562306a36Sopenharmony_ci int *enablePRI_high, 61662306a36Sopenharmony_ci int *eeprom_present); 61762306a36Sopenharmony_cistatic void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 61862306a36Sopenharmony_ci int *internal68_present, 61962306a36Sopenharmony_ci int *externalcable_present, 62062306a36Sopenharmony_ci int *eeprom_present); 62162306a36Sopenharmony_cistatic void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 62262306a36Sopenharmony_ci int *externalcable_present, 62362306a36Sopenharmony_ci int *eeprom_present); 62462306a36Sopenharmony_cistatic void write_brdctl(struct ahc_softc *ahc, uint8_t value); 62562306a36Sopenharmony_cistatic uint8_t read_brdctl(struct ahc_softc *ahc); 62662306a36Sopenharmony_cistatic void ahc_pci_intr(struct ahc_softc *ahc); 62762306a36Sopenharmony_cistatic int ahc_pci_chip_init(struct ahc_softc *ahc); 62862306a36Sopenharmony_ci 62962306a36Sopenharmony_cistatic int 63062306a36Sopenharmony_ciahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, 63162306a36Sopenharmony_ci uint16_t subdevice, uint16_t subvendor) 63262306a36Sopenharmony_ci{ 63362306a36Sopenharmony_ci int result; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci /* Default to invalid. */ 63662306a36Sopenharmony_ci result = 0; 63762306a36Sopenharmony_ci if (vendor == 0x9005 63862306a36Sopenharmony_ci && subvendor == 0x9005 63962306a36Sopenharmony_ci && subdevice != device 64062306a36Sopenharmony_ci && SUBID_9005_TYPE_KNOWN(subdevice) != 0) { 64162306a36Sopenharmony_ci 64262306a36Sopenharmony_ci switch (SUBID_9005_TYPE(subdevice)) { 64362306a36Sopenharmony_ci case SUBID_9005_TYPE_MB: 64462306a36Sopenharmony_ci break; 64562306a36Sopenharmony_ci case SUBID_9005_TYPE_CARD: 64662306a36Sopenharmony_ci case SUBID_9005_TYPE_LCCARD: 64762306a36Sopenharmony_ci /* 64862306a36Sopenharmony_ci * Currently only trust Adaptec cards to 64962306a36Sopenharmony_ci * get the sub device info correct. 65062306a36Sopenharmony_ci */ 65162306a36Sopenharmony_ci if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA) 65262306a36Sopenharmony_ci result = 1; 65362306a36Sopenharmony_ci break; 65462306a36Sopenharmony_ci case SUBID_9005_TYPE_RAID: 65562306a36Sopenharmony_ci break; 65662306a36Sopenharmony_ci default: 65762306a36Sopenharmony_ci break; 65862306a36Sopenharmony_ci } 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci return (result); 66162306a36Sopenharmony_ci} 66262306a36Sopenharmony_ci 66362306a36Sopenharmony_ciconst struct ahc_pci_identity * 66462306a36Sopenharmony_ciahc_find_pci_device(ahc_dev_softc_t pci) 66562306a36Sopenharmony_ci{ 66662306a36Sopenharmony_ci uint64_t full_id; 66762306a36Sopenharmony_ci uint16_t device; 66862306a36Sopenharmony_ci uint16_t vendor; 66962306a36Sopenharmony_ci uint16_t subdevice; 67062306a36Sopenharmony_ci uint16_t subvendor; 67162306a36Sopenharmony_ci const struct ahc_pci_identity *entry; 67262306a36Sopenharmony_ci u_int i; 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); 67562306a36Sopenharmony_ci device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); 67662306a36Sopenharmony_ci subvendor = ahc_pci_read_config(pci, PCI_SUBSYSTEM_VENDOR_ID, /*bytes*/2); 67762306a36Sopenharmony_ci subdevice = ahc_pci_read_config(pci, PCI_SUBSYSTEM_ID, /*bytes*/2); 67862306a36Sopenharmony_ci full_id = ahc_compose_id(device, vendor, subdevice, subvendor); 67962306a36Sopenharmony_ci 68062306a36Sopenharmony_ci /* 68162306a36Sopenharmony_ci * If the second function is not hooked up, ignore it. 68262306a36Sopenharmony_ci * Unfortunately, not all MB vendors implement the 68362306a36Sopenharmony_ci * subdevice ID as per the Adaptec spec, so do our best 68462306a36Sopenharmony_ci * to sanity check it prior to accepting the subdevice 68562306a36Sopenharmony_ci * ID as valid. 68662306a36Sopenharmony_ci */ 68762306a36Sopenharmony_ci if (ahc_get_pci_function(pci) > 0 68862306a36Sopenharmony_ci && ahc_9005_subdevinfo_valid(device, vendor, subdevice, subvendor) 68962306a36Sopenharmony_ci && SUBID_9005_MFUNCENB(subdevice) == 0) 69062306a36Sopenharmony_ci return (NULL); 69162306a36Sopenharmony_ci 69262306a36Sopenharmony_ci for (i = 0; i < ahc_num_pci_devs; i++) { 69362306a36Sopenharmony_ci entry = &ahc_pci_ident_table[i]; 69462306a36Sopenharmony_ci if (entry->full_id == (full_id & entry->id_mask)) { 69562306a36Sopenharmony_ci /* Honor exclusion entries. */ 69662306a36Sopenharmony_ci if (entry->name == NULL) 69762306a36Sopenharmony_ci return (NULL); 69862306a36Sopenharmony_ci return (entry); 69962306a36Sopenharmony_ci } 70062306a36Sopenharmony_ci } 70162306a36Sopenharmony_ci return (NULL); 70262306a36Sopenharmony_ci} 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ciint 70562306a36Sopenharmony_ciahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry) 70662306a36Sopenharmony_ci{ 70762306a36Sopenharmony_ci u_int command; 70862306a36Sopenharmony_ci u_int our_id; 70962306a36Sopenharmony_ci u_int sxfrctl1; 71062306a36Sopenharmony_ci u_int scsiseq; 71162306a36Sopenharmony_ci u_int dscommand0; 71262306a36Sopenharmony_ci uint32_t devconfig; 71362306a36Sopenharmony_ci int error; 71462306a36Sopenharmony_ci uint8_t sblkctl; 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci our_id = 0; 71762306a36Sopenharmony_ci error = entry->setup(ahc); 71862306a36Sopenharmony_ci if (error != 0) 71962306a36Sopenharmony_ci return (error); 72062306a36Sopenharmony_ci ahc->chip |= AHC_PCI; 72162306a36Sopenharmony_ci ahc->description = entry->name; 72262306a36Sopenharmony_ci 72362306a36Sopenharmony_ci pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0); 72462306a36Sopenharmony_ci 72562306a36Sopenharmony_ci error = ahc_pci_map_registers(ahc); 72662306a36Sopenharmony_ci if (error != 0) 72762306a36Sopenharmony_ci return (error); 72862306a36Sopenharmony_ci 72962306a36Sopenharmony_ci /* 73062306a36Sopenharmony_ci * Before we continue probing the card, ensure that 73162306a36Sopenharmony_ci * its interrupts are *disabled*. We don't want 73262306a36Sopenharmony_ci * a misstep to hang the machine in an interrupt 73362306a36Sopenharmony_ci * storm. 73462306a36Sopenharmony_ci */ 73562306a36Sopenharmony_ci ahc_intr_enable(ahc, FALSE); 73662306a36Sopenharmony_ci 73762306a36Sopenharmony_ci devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 73862306a36Sopenharmony_ci 73962306a36Sopenharmony_ci /* 74062306a36Sopenharmony_ci * If we need to support high memory, enable dual 74162306a36Sopenharmony_ci * address cycles. This bit must be set to enable 74262306a36Sopenharmony_ci * high address bit generation even if we are on a 74362306a36Sopenharmony_ci * 64bit bus (PCI64BIT set in devconfig). 74462306a36Sopenharmony_ci */ 74562306a36Sopenharmony_ci if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (bootverbose) 74862306a36Sopenharmony_ci printk("%s: Enabling 39Bit Addressing\n", 74962306a36Sopenharmony_ci ahc_name(ahc)); 75062306a36Sopenharmony_ci devconfig |= DACEN; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci /* Ensure that pci error generation, a test feature, is disabled. */ 75462306a36Sopenharmony_ci devconfig |= PCIERRGENDIS; 75562306a36Sopenharmony_ci 75662306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_ci /* Ensure busmastering is enabled */ 75962306a36Sopenharmony_ci command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); 76062306a36Sopenharmony_ci command |= PCIM_CMD_BUSMASTEREN; 76162306a36Sopenharmony_ci 76262306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci /* On all PCI adapters, we allow SCB paging */ 76562306a36Sopenharmony_ci ahc->flags |= AHC_PAGESCBS; 76662306a36Sopenharmony_ci 76762306a36Sopenharmony_ci error = ahc_softc_init(ahc); 76862306a36Sopenharmony_ci if (error != 0) 76962306a36Sopenharmony_ci return (error); 77062306a36Sopenharmony_ci 77162306a36Sopenharmony_ci /* 77262306a36Sopenharmony_ci * Disable PCI parity error checking. Users typically 77362306a36Sopenharmony_ci * do this to work around broken PCI chipsets that get 77462306a36Sopenharmony_ci * the parity timing wrong and thus generate lots of spurious 77562306a36Sopenharmony_ci * errors. The chip only allows us to disable *all* parity 77662306a36Sopenharmony_ci * error reporting when doing this, so CIO bus, scb ram, and 77762306a36Sopenharmony_ci * scratch ram parity errors will be ignored too. 77862306a36Sopenharmony_ci */ 77962306a36Sopenharmony_ci if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0) 78062306a36Sopenharmony_ci ahc->seqctl |= FAILDIS; 78162306a36Sopenharmony_ci 78262306a36Sopenharmony_ci ahc->bus_intr = ahc_pci_intr; 78362306a36Sopenharmony_ci ahc->bus_chip_init = ahc_pci_chip_init; 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci /* Remember how the card was setup in case there is no SEEPROM */ 78662306a36Sopenharmony_ci if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { 78762306a36Sopenharmony_ci ahc_pause(ahc); 78862306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 78962306a36Sopenharmony_ci our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID; 79062306a36Sopenharmony_ci else 79162306a36Sopenharmony_ci our_id = ahc_inb(ahc, SCSIID) & OID; 79262306a36Sopenharmony_ci sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN; 79362306a36Sopenharmony_ci scsiseq = ahc_inb(ahc, SCSISEQ); 79462306a36Sopenharmony_ci } else { 79562306a36Sopenharmony_ci sxfrctl1 = STPWEN; 79662306a36Sopenharmony_ci our_id = 7; 79762306a36Sopenharmony_ci scsiseq = 0; 79862306a36Sopenharmony_ci } 79962306a36Sopenharmony_ci 80062306a36Sopenharmony_ci error = ahc_reset(ahc, /*reinit*/FALSE); 80162306a36Sopenharmony_ci if (error != 0) 80262306a36Sopenharmony_ci return (ENXIO); 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci if ((ahc->features & AHC_DT) != 0) { 80562306a36Sopenharmony_ci u_int sfunct; 80662306a36Sopenharmony_ci 80762306a36Sopenharmony_ci /* Perform ALT-Mode Setup */ 80862306a36Sopenharmony_ci sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 80962306a36Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 81062306a36Sopenharmony_ci ahc_outb(ahc, OPTIONMODE, 81162306a36Sopenharmony_ci OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS); 81262306a36Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct); 81362306a36Sopenharmony_ci 81462306a36Sopenharmony_ci /* Normal mode setup */ 81562306a36Sopenharmony_ci ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN 81662306a36Sopenharmony_ci |TARGCRCENDEN); 81762306a36Sopenharmony_ci } 81862306a36Sopenharmony_ci 81962306a36Sopenharmony_ci dscommand0 = ahc_inb(ahc, DSCOMMAND0); 82062306a36Sopenharmony_ci dscommand0 |= MPARCKEN|CACHETHEN; 82162306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) { 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci /* 82462306a36Sopenharmony_ci * DPARCKEN doesn't work correctly on 82562306a36Sopenharmony_ci * some MBs so don't use it. 82662306a36Sopenharmony_ci */ 82762306a36Sopenharmony_ci dscommand0 &= ~DPARCKEN; 82862306a36Sopenharmony_ci } 82962306a36Sopenharmony_ci 83062306a36Sopenharmony_ci /* 83162306a36Sopenharmony_ci * Handle chips that must have cache line 83262306a36Sopenharmony_ci * streaming (dis/en)abled. 83362306a36Sopenharmony_ci */ 83462306a36Sopenharmony_ci if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0) 83562306a36Sopenharmony_ci dscommand0 |= CACHETHEN; 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_ci if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0) 83862306a36Sopenharmony_ci dscommand0 &= ~CACHETHEN; 83962306a36Sopenharmony_ci 84062306a36Sopenharmony_ci ahc_outb(ahc, DSCOMMAND0, dscommand0); 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci ahc->pci_cachesize = 84362306a36Sopenharmony_ci ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, 84462306a36Sopenharmony_ci /*bytes*/1) & CACHESIZE; 84562306a36Sopenharmony_ci ahc->pci_cachesize *= 4; 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0 84862306a36Sopenharmony_ci && ahc->pci_cachesize == 4) { 84962306a36Sopenharmony_ci 85062306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 85162306a36Sopenharmony_ci 0, /*bytes*/1); 85262306a36Sopenharmony_ci ahc->pci_cachesize = 0; 85362306a36Sopenharmony_ci } 85462306a36Sopenharmony_ci 85562306a36Sopenharmony_ci /* 85662306a36Sopenharmony_ci * We cannot perform ULTRA speeds without the presence 85762306a36Sopenharmony_ci * of the external precision resistor. 85862306a36Sopenharmony_ci */ 85962306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA) != 0) { 86062306a36Sopenharmony_ci uint32_t devconfig; 86162306a36Sopenharmony_ci 86262306a36Sopenharmony_ci devconfig = ahc_pci_read_config(ahc->dev_softc, 86362306a36Sopenharmony_ci DEVCONFIG, /*bytes*/4); 86462306a36Sopenharmony_ci if ((devconfig & REXTVALID) == 0) 86562306a36Sopenharmony_ci ahc->features &= ~AHC_ULTRA; 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci 86862306a36Sopenharmony_ci /* See if we have a SEEPROM and perform auto-term */ 86962306a36Sopenharmony_ci check_extport(ahc, &sxfrctl1); 87062306a36Sopenharmony_ci 87162306a36Sopenharmony_ci /* 87262306a36Sopenharmony_ci * Take the LED out of diagnostic mode 87362306a36Sopenharmony_ci */ 87462306a36Sopenharmony_ci sblkctl = ahc_inb(ahc, SBLKCTL); 87562306a36Sopenharmony_ci ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON))); 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) { 87862306a36Sopenharmony_ci ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX); 87962306a36Sopenharmony_ci } else { 88062306a36Sopenharmony_ci ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100); 88162306a36Sopenharmony_ci } 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci if (ahc->flags & AHC_USEDEFAULTS) { 88462306a36Sopenharmony_ci /* 88562306a36Sopenharmony_ci * PCI Adapter default setup 88662306a36Sopenharmony_ci * Should only be used if the adapter does not have 88762306a36Sopenharmony_ci * a SEEPROM. 88862306a36Sopenharmony_ci */ 88962306a36Sopenharmony_ci /* See if someone else set us up already */ 89062306a36Sopenharmony_ci if ((ahc->flags & AHC_NO_BIOS_INIT) == 0 89162306a36Sopenharmony_ci && scsiseq != 0) { 89262306a36Sopenharmony_ci printk("%s: Using left over BIOS settings\n", 89362306a36Sopenharmony_ci ahc_name(ahc)); 89462306a36Sopenharmony_ci ahc->flags &= ~AHC_USEDEFAULTS; 89562306a36Sopenharmony_ci ahc->flags |= AHC_BIOS_ENABLED; 89662306a36Sopenharmony_ci } else { 89762306a36Sopenharmony_ci /* 89862306a36Sopenharmony_ci * Assume only one connector and always turn 89962306a36Sopenharmony_ci * on termination. 90062306a36Sopenharmony_ci */ 90162306a36Sopenharmony_ci our_id = 0x07; 90262306a36Sopenharmony_ci sxfrctl1 = STPWEN; 90362306a36Sopenharmony_ci } 90462306a36Sopenharmony_ci ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI); 90562306a36Sopenharmony_ci 90662306a36Sopenharmony_ci ahc->our_id = our_id; 90762306a36Sopenharmony_ci } 90862306a36Sopenharmony_ci 90962306a36Sopenharmony_ci /* 91062306a36Sopenharmony_ci * Take a look to see if we have external SRAM. 91162306a36Sopenharmony_ci * We currently do not attempt to use SRAM that is 91262306a36Sopenharmony_ci * shared among multiple controllers. 91362306a36Sopenharmony_ci */ 91462306a36Sopenharmony_ci ahc_probe_ext_scbram(ahc); 91562306a36Sopenharmony_ci 91662306a36Sopenharmony_ci /* 91762306a36Sopenharmony_ci * Record our termination setting for the 91862306a36Sopenharmony_ci * generic initialization routine. 91962306a36Sopenharmony_ci */ 92062306a36Sopenharmony_ci if ((sxfrctl1 & STPWEN) != 0) 92162306a36Sopenharmony_ci ahc->flags |= AHC_TERM_ENB_A; 92262306a36Sopenharmony_ci 92362306a36Sopenharmony_ci /* 92462306a36Sopenharmony_ci * Save chip register configuration data for chip resets 92562306a36Sopenharmony_ci * that occur during runtime and resume events. 92662306a36Sopenharmony_ci */ 92762306a36Sopenharmony_ci ahc->bus_softc.pci_softc.devconfig = 92862306a36Sopenharmony_ci ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 92962306a36Sopenharmony_ci ahc->bus_softc.pci_softc.command = 93062306a36Sopenharmony_ci ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); 93162306a36Sopenharmony_ci ahc->bus_softc.pci_softc.csize_lattime = 93262306a36Sopenharmony_ci ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1); 93362306a36Sopenharmony_ci ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0); 93462306a36Sopenharmony_ci ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS); 93562306a36Sopenharmony_ci if ((ahc->features & AHC_DT) != 0) { 93662306a36Sopenharmony_ci u_int sfunct; 93762306a36Sopenharmony_ci 93862306a36Sopenharmony_ci sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 93962306a36Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 94062306a36Sopenharmony_ci ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE); 94162306a36Sopenharmony_ci ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT); 94262306a36Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct); 94362306a36Sopenharmony_ci ahc->bus_softc.pci_softc.crccontrol1 = 94462306a36Sopenharmony_ci ahc_inb(ahc, CRCCONTROL1); 94562306a36Sopenharmony_ci } 94662306a36Sopenharmony_ci if ((ahc->features & AHC_MULTI_FUNC) != 0) 94762306a36Sopenharmony_ci ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR); 94862306a36Sopenharmony_ci 94962306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 95062306a36Sopenharmony_ci ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH); 95162306a36Sopenharmony_ci 95262306a36Sopenharmony_ci /* Core initialization */ 95362306a36Sopenharmony_ci error = ahc_init(ahc); 95462306a36Sopenharmony_ci if (error != 0) 95562306a36Sopenharmony_ci return (error); 95662306a36Sopenharmony_ci ahc->init_level++; 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci /* 95962306a36Sopenharmony_ci * Allow interrupts now that we are completely setup. 96062306a36Sopenharmony_ci */ 96162306a36Sopenharmony_ci return ahc_pci_map_int(ahc); 96262306a36Sopenharmony_ci} 96362306a36Sopenharmony_ci 96462306a36Sopenharmony_ci/* 96562306a36Sopenharmony_ci * Test for the presence of external sram in an 96662306a36Sopenharmony_ci * "unshared" configuration. 96762306a36Sopenharmony_ci */ 96862306a36Sopenharmony_cistatic int 96962306a36Sopenharmony_ciahc_ext_scbram_present(struct ahc_softc *ahc) 97062306a36Sopenharmony_ci{ 97162306a36Sopenharmony_ci u_int chip; 97262306a36Sopenharmony_ci int ramps; 97362306a36Sopenharmony_ci int single_user; 97462306a36Sopenharmony_ci uint32_t devconfig; 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci chip = ahc->chip & AHC_CHIPID_MASK; 97762306a36Sopenharmony_ci devconfig = ahc_pci_read_config(ahc->dev_softc, 97862306a36Sopenharmony_ci DEVCONFIG, /*bytes*/4); 97962306a36Sopenharmony_ci single_user = (devconfig & MPORTMODE) != 0; 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 98262306a36Sopenharmony_ci ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0; 98362306a36Sopenharmony_ci else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C) 98462306a36Sopenharmony_ci /* 98562306a36Sopenharmony_ci * External SCBRAM arbitration is flakey 98662306a36Sopenharmony_ci * on these chips. Unfortunately this means 98762306a36Sopenharmony_ci * we don't use the extra SCB ram space on the 98862306a36Sopenharmony_ci * 3940AUW. 98962306a36Sopenharmony_ci */ 99062306a36Sopenharmony_ci ramps = 0; 99162306a36Sopenharmony_ci else if (chip >= AHC_AIC7870) 99262306a36Sopenharmony_ci ramps = (devconfig & RAMPSM) != 0; 99362306a36Sopenharmony_ci else 99462306a36Sopenharmony_ci ramps = 0; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci if (ramps && single_user) 99762306a36Sopenharmony_ci return (1); 99862306a36Sopenharmony_ci return (0); 99962306a36Sopenharmony_ci} 100062306a36Sopenharmony_ci 100162306a36Sopenharmony_ci/* 100262306a36Sopenharmony_ci * Enable external scbram. 100362306a36Sopenharmony_ci */ 100462306a36Sopenharmony_cistatic void 100562306a36Sopenharmony_ciahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck, 100662306a36Sopenharmony_ci int fast, int large) 100762306a36Sopenharmony_ci{ 100862306a36Sopenharmony_ci uint32_t devconfig; 100962306a36Sopenharmony_ci 101062306a36Sopenharmony_ci if (ahc->features & AHC_MULTI_FUNC) { 101162306a36Sopenharmony_ci /* 101262306a36Sopenharmony_ci * Set the SCB Base addr (highest address bit) 101362306a36Sopenharmony_ci * depending on which channel we are. 101462306a36Sopenharmony_ci */ 101562306a36Sopenharmony_ci ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc)); 101662306a36Sopenharmony_ci } 101762306a36Sopenharmony_ci 101862306a36Sopenharmony_ci ahc->flags &= ~AHC_LSCBS_ENABLED; 101962306a36Sopenharmony_ci if (large) 102062306a36Sopenharmony_ci ahc->flags |= AHC_LSCBS_ENABLED; 102162306a36Sopenharmony_ci devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 102262306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) { 102362306a36Sopenharmony_ci u_int dscommand0; 102462306a36Sopenharmony_ci 102562306a36Sopenharmony_ci dscommand0 = ahc_inb(ahc, DSCOMMAND0); 102662306a36Sopenharmony_ci if (enable) 102762306a36Sopenharmony_ci dscommand0 &= ~INTSCBRAMSEL; 102862306a36Sopenharmony_ci else 102962306a36Sopenharmony_ci dscommand0 |= INTSCBRAMSEL; 103062306a36Sopenharmony_ci if (large) 103162306a36Sopenharmony_ci dscommand0 &= ~USCBSIZE32; 103262306a36Sopenharmony_ci else 103362306a36Sopenharmony_ci dscommand0 |= USCBSIZE32; 103462306a36Sopenharmony_ci ahc_outb(ahc, DSCOMMAND0, dscommand0); 103562306a36Sopenharmony_ci } else { 103662306a36Sopenharmony_ci if (fast) 103762306a36Sopenharmony_ci devconfig &= ~EXTSCBTIME; 103862306a36Sopenharmony_ci else 103962306a36Sopenharmony_ci devconfig |= EXTSCBTIME; 104062306a36Sopenharmony_ci if (enable) 104162306a36Sopenharmony_ci devconfig &= ~SCBRAMSEL; 104262306a36Sopenharmony_ci else 104362306a36Sopenharmony_ci devconfig |= SCBRAMSEL; 104462306a36Sopenharmony_ci if (large) 104562306a36Sopenharmony_ci devconfig &= ~SCBSIZE32; 104662306a36Sopenharmony_ci else 104762306a36Sopenharmony_ci devconfig |= SCBSIZE32; 104862306a36Sopenharmony_ci } 104962306a36Sopenharmony_ci if (pcheck) 105062306a36Sopenharmony_ci devconfig |= EXTSCBPEN; 105162306a36Sopenharmony_ci else 105262306a36Sopenharmony_ci devconfig &= ~EXTSCBPEN; 105362306a36Sopenharmony_ci 105462306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 105562306a36Sopenharmony_ci} 105662306a36Sopenharmony_ci 105762306a36Sopenharmony_ci/* 105862306a36Sopenharmony_ci * Take a look to see if we have external SRAM. 105962306a36Sopenharmony_ci * We currently do not attempt to use SRAM that is 106062306a36Sopenharmony_ci * shared among multiple controllers. 106162306a36Sopenharmony_ci */ 106262306a36Sopenharmony_cistatic void 106362306a36Sopenharmony_ciahc_probe_ext_scbram(struct ahc_softc *ahc) 106462306a36Sopenharmony_ci{ 106562306a36Sopenharmony_ci int num_scbs; 106662306a36Sopenharmony_ci int test_num_scbs; 106762306a36Sopenharmony_ci int enable; 106862306a36Sopenharmony_ci int pcheck; 106962306a36Sopenharmony_ci int fast; 107062306a36Sopenharmony_ci int large; 107162306a36Sopenharmony_ci 107262306a36Sopenharmony_ci enable = FALSE; 107362306a36Sopenharmony_ci pcheck = FALSE; 107462306a36Sopenharmony_ci fast = FALSE; 107562306a36Sopenharmony_ci large = FALSE; 107662306a36Sopenharmony_ci num_scbs = 0; 107762306a36Sopenharmony_ci 107862306a36Sopenharmony_ci if (ahc_ext_scbram_present(ahc) == 0) 107962306a36Sopenharmony_ci goto done; 108062306a36Sopenharmony_ci 108162306a36Sopenharmony_ci /* 108262306a36Sopenharmony_ci * Probe for the best parameters to use. 108362306a36Sopenharmony_ci */ 108462306a36Sopenharmony_ci ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large); 108562306a36Sopenharmony_ci num_scbs = ahc_probe_scbs(ahc); 108662306a36Sopenharmony_ci if (num_scbs == 0) { 108762306a36Sopenharmony_ci /* The SRAM wasn't really present. */ 108862306a36Sopenharmony_ci goto done; 108962306a36Sopenharmony_ci } 109062306a36Sopenharmony_ci enable = TRUE; 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci /* 109362306a36Sopenharmony_ci * Clear any outstanding parity error 109462306a36Sopenharmony_ci * and ensure that parity error reporting 109562306a36Sopenharmony_ci * is enabled. 109662306a36Sopenharmony_ci */ 109762306a36Sopenharmony_ci ahc_outb(ahc, SEQCTL, 0); 109862306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 109962306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRBRKADRINT); 110062306a36Sopenharmony_ci 110162306a36Sopenharmony_ci /* Now see if we can do parity */ 110262306a36Sopenharmony_ci ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large); 110362306a36Sopenharmony_ci num_scbs = ahc_probe_scbs(ahc); 110462306a36Sopenharmony_ci if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 110562306a36Sopenharmony_ci || (ahc_inb(ahc, ERROR) & MPARERR) == 0) 110662306a36Sopenharmony_ci pcheck = TRUE; 110762306a36Sopenharmony_ci 110862306a36Sopenharmony_ci /* Clear any resulting parity error */ 110962306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 111062306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRBRKADRINT); 111162306a36Sopenharmony_ci 111262306a36Sopenharmony_ci /* Now see if we can do fast timing */ 111362306a36Sopenharmony_ci ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large); 111462306a36Sopenharmony_ci test_num_scbs = ahc_probe_scbs(ahc); 111562306a36Sopenharmony_ci if (test_num_scbs == num_scbs 111662306a36Sopenharmony_ci && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 111762306a36Sopenharmony_ci || (ahc_inb(ahc, ERROR) & MPARERR) == 0)) 111862306a36Sopenharmony_ci fast = TRUE; 111962306a36Sopenharmony_ci 112062306a36Sopenharmony_ci /* 112162306a36Sopenharmony_ci * See if we can use large SCBs and still maintain 112262306a36Sopenharmony_ci * the same overall count of SCBs. 112362306a36Sopenharmony_ci */ 112462306a36Sopenharmony_ci if ((ahc->features & AHC_LARGE_SCBS) != 0) { 112562306a36Sopenharmony_ci ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE); 112662306a36Sopenharmony_ci test_num_scbs = ahc_probe_scbs(ahc); 112762306a36Sopenharmony_ci if (test_num_scbs >= num_scbs) { 112862306a36Sopenharmony_ci large = TRUE; 112962306a36Sopenharmony_ci num_scbs = test_num_scbs; 113062306a36Sopenharmony_ci if (num_scbs >= 64) { 113162306a36Sopenharmony_ci /* 113262306a36Sopenharmony_ci * We have enough space to move the 113362306a36Sopenharmony_ci * "busy targets table" into SCB space 113462306a36Sopenharmony_ci * and make it qualify all the way to the 113562306a36Sopenharmony_ci * lun level. 113662306a36Sopenharmony_ci */ 113762306a36Sopenharmony_ci ahc->flags |= AHC_SCB_BTT; 113862306a36Sopenharmony_ci } 113962306a36Sopenharmony_ci } 114062306a36Sopenharmony_ci } 114162306a36Sopenharmony_cidone: 114262306a36Sopenharmony_ci /* 114362306a36Sopenharmony_ci * Disable parity error reporting until we 114462306a36Sopenharmony_ci * can load instruction ram. 114562306a36Sopenharmony_ci */ 114662306a36Sopenharmony_ci ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); 114762306a36Sopenharmony_ci /* Clear any latched parity error */ 114862306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 114962306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRBRKADRINT); 115062306a36Sopenharmony_ci if (bootverbose && enable) { 115162306a36Sopenharmony_ci printk("%s: External SRAM, %s access%s, %dbytes/SCB\n", 115262306a36Sopenharmony_ci ahc_name(ahc), fast ? "fast" : "slow", 115362306a36Sopenharmony_ci pcheck ? ", parity checking enabled" : "", 115462306a36Sopenharmony_ci large ? 64 : 32); 115562306a36Sopenharmony_ci } 115662306a36Sopenharmony_ci ahc_scbram_config(ahc, enable, pcheck, fast, large); 115762306a36Sopenharmony_ci} 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci/* 116062306a36Sopenharmony_ci * Perform some simple tests that should catch situations where 116162306a36Sopenharmony_ci * our registers are invalidly mapped. 116262306a36Sopenharmony_ci */ 116362306a36Sopenharmony_ciint 116462306a36Sopenharmony_ciahc_pci_test_register_access(struct ahc_softc *ahc) 116562306a36Sopenharmony_ci{ 116662306a36Sopenharmony_ci int error; 116762306a36Sopenharmony_ci u_int status1; 116862306a36Sopenharmony_ci uint32_t cmd; 116962306a36Sopenharmony_ci uint8_t hcntrl; 117062306a36Sopenharmony_ci 117162306a36Sopenharmony_ci error = EIO; 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci /* 117462306a36Sopenharmony_ci * Enable PCI error interrupt status, but suppress NMIs 117562306a36Sopenharmony_ci * generated by SERR raised due to target aborts. 117662306a36Sopenharmony_ci */ 117762306a36Sopenharmony_ci cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); 117862306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, 117962306a36Sopenharmony_ci cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci /* 118262306a36Sopenharmony_ci * First a simple test to see if any 118362306a36Sopenharmony_ci * registers can be read. Reading 118462306a36Sopenharmony_ci * HCNTRL has no side effects and has 118562306a36Sopenharmony_ci * at least one bit that is guaranteed to 118662306a36Sopenharmony_ci * be zero so it is a good register to 118762306a36Sopenharmony_ci * use for this test. 118862306a36Sopenharmony_ci */ 118962306a36Sopenharmony_ci hcntrl = ahc_inb(ahc, HCNTRL); 119062306a36Sopenharmony_ci 119162306a36Sopenharmony_ci if (hcntrl == 0xFF) 119262306a36Sopenharmony_ci goto fail; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci if ((hcntrl & CHIPRST) != 0) { 119562306a36Sopenharmony_ci /* 119662306a36Sopenharmony_ci * The chip has not been initialized since 119762306a36Sopenharmony_ci * PCI/EISA/VLB bus reset. Don't trust 119862306a36Sopenharmony_ci * "left over BIOS data". 119962306a36Sopenharmony_ci */ 120062306a36Sopenharmony_ci ahc->flags |= AHC_NO_BIOS_INIT; 120162306a36Sopenharmony_ci } 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ci /* 120462306a36Sopenharmony_ci * Next create a situation where write combining 120562306a36Sopenharmony_ci * or read prefetching could be initiated by the 120662306a36Sopenharmony_ci * CPU or host bridge. Our device does not support 120762306a36Sopenharmony_ci * either, so look for data corruption and/or flagged 120862306a36Sopenharmony_ci * PCI errors. First pause without causing another 120962306a36Sopenharmony_ci * chip reset. 121062306a36Sopenharmony_ci */ 121162306a36Sopenharmony_ci hcntrl &= ~CHIPRST; 121262306a36Sopenharmony_ci ahc_outb(ahc, HCNTRL, hcntrl|PAUSE); 121362306a36Sopenharmony_ci while (ahc_is_paused(ahc) == 0) 121462306a36Sopenharmony_ci ; 121562306a36Sopenharmony_ci 121662306a36Sopenharmony_ci /* Clear any PCI errors that occurred before our driver attached. */ 121762306a36Sopenharmony_ci status1 = ahc_pci_read_config(ahc->dev_softc, 121862306a36Sopenharmony_ci PCIR_STATUS + 1, /*bytes*/1); 121962306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 122062306a36Sopenharmony_ci status1, /*bytes*/1); 122162306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 122262306a36Sopenharmony_ci 122362306a36Sopenharmony_ci ahc_outb(ahc, SEQCTL, PERRORDIS); 122462306a36Sopenharmony_ci ahc_outb(ahc, SCBPTR, 0); 122562306a36Sopenharmony_ci ahc_outl(ahc, SCB_BASE, 0x5aa555aa); 122662306a36Sopenharmony_ci if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa) 122762306a36Sopenharmony_ci goto fail; 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_ci status1 = ahc_pci_read_config(ahc->dev_softc, 123062306a36Sopenharmony_ci PCIR_STATUS + 1, /*bytes*/1); 123162306a36Sopenharmony_ci if ((status1 & STA) != 0) 123262306a36Sopenharmony_ci goto fail; 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci error = 0; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_cifail: 123762306a36Sopenharmony_ci /* Silently clear any latched errors. */ 123862306a36Sopenharmony_ci status1 = ahc_pci_read_config(ahc->dev_softc, 123962306a36Sopenharmony_ci PCIR_STATUS + 1, /*bytes*/1); 124062306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 124162306a36Sopenharmony_ci status1, /*bytes*/1); 124262306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 124362306a36Sopenharmony_ci ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); 124462306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); 124562306a36Sopenharmony_ci return (error); 124662306a36Sopenharmony_ci} 124762306a36Sopenharmony_ci 124862306a36Sopenharmony_ci/* 124962306a36Sopenharmony_ci * Check the external port logic for a serial eeprom 125062306a36Sopenharmony_ci * and termination/cable detection contrls. 125162306a36Sopenharmony_ci */ 125262306a36Sopenharmony_cistatic void 125362306a36Sopenharmony_cicheck_extport(struct ahc_softc *ahc, u_int *sxfrctl1) 125462306a36Sopenharmony_ci{ 125562306a36Sopenharmony_ci struct seeprom_descriptor sd; 125662306a36Sopenharmony_ci struct seeprom_config *sc; 125762306a36Sopenharmony_ci int have_seeprom; 125862306a36Sopenharmony_ci int have_autoterm; 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci sd.sd_ahc = ahc; 126162306a36Sopenharmony_ci sd.sd_control_offset = SEECTL; 126262306a36Sopenharmony_ci sd.sd_status_offset = SEECTL; 126362306a36Sopenharmony_ci sd.sd_dataout_offset = SEECTL; 126462306a36Sopenharmony_ci sc = ahc->seep_config; 126562306a36Sopenharmony_ci 126662306a36Sopenharmony_ci /* 126762306a36Sopenharmony_ci * For some multi-channel devices, the c46 is simply too 126862306a36Sopenharmony_ci * small to work. For the other controller types, we can 126962306a36Sopenharmony_ci * get our information from either SEEPROM type. Set the 127062306a36Sopenharmony_ci * type to start our probe with accordingly. 127162306a36Sopenharmony_ci */ 127262306a36Sopenharmony_ci if (ahc->flags & AHC_LARGE_SEEPROM) 127362306a36Sopenharmony_ci sd.sd_chip = C56_66; 127462306a36Sopenharmony_ci else 127562306a36Sopenharmony_ci sd.sd_chip = C46; 127662306a36Sopenharmony_ci 127762306a36Sopenharmony_ci sd.sd_MS = SEEMS; 127862306a36Sopenharmony_ci sd.sd_RDY = SEERDY; 127962306a36Sopenharmony_ci sd.sd_CS = SEECS; 128062306a36Sopenharmony_ci sd.sd_CK = SEECK; 128162306a36Sopenharmony_ci sd.sd_DO = SEEDO; 128262306a36Sopenharmony_ci sd.sd_DI = SEEDI; 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci have_seeprom = ahc_acquire_seeprom(ahc, &sd); 128562306a36Sopenharmony_ci if (have_seeprom) { 128662306a36Sopenharmony_ci 128762306a36Sopenharmony_ci if (bootverbose) 128862306a36Sopenharmony_ci printk("%s: Reading SEEPROM...", ahc_name(ahc)); 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_ci for (;;) { 129162306a36Sopenharmony_ci u_int start_addr; 129262306a36Sopenharmony_ci 129362306a36Sopenharmony_ci start_addr = 32 * (ahc->channel - 'A'); 129462306a36Sopenharmony_ci 129562306a36Sopenharmony_ci have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc, 129662306a36Sopenharmony_ci start_addr, 129762306a36Sopenharmony_ci sizeof(*sc)/2); 129862306a36Sopenharmony_ci 129962306a36Sopenharmony_ci if (have_seeprom) 130062306a36Sopenharmony_ci have_seeprom = ahc_verify_cksum(sc); 130162306a36Sopenharmony_ci 130262306a36Sopenharmony_ci if (have_seeprom != 0 || sd.sd_chip == C56_66) { 130362306a36Sopenharmony_ci if (bootverbose) { 130462306a36Sopenharmony_ci if (have_seeprom == 0) 130562306a36Sopenharmony_ci printk ("checksum error\n"); 130662306a36Sopenharmony_ci else 130762306a36Sopenharmony_ci printk ("done.\n"); 130862306a36Sopenharmony_ci } 130962306a36Sopenharmony_ci break; 131062306a36Sopenharmony_ci } 131162306a36Sopenharmony_ci sd.sd_chip = C56_66; 131262306a36Sopenharmony_ci } 131362306a36Sopenharmony_ci ahc_release_seeprom(&sd); 131462306a36Sopenharmony_ci 131562306a36Sopenharmony_ci /* Remember the SEEPROM type for later */ 131662306a36Sopenharmony_ci if (sd.sd_chip == C56_66) 131762306a36Sopenharmony_ci ahc->flags |= AHC_LARGE_SEEPROM; 131862306a36Sopenharmony_ci } 131962306a36Sopenharmony_ci 132062306a36Sopenharmony_ci if (!have_seeprom) { 132162306a36Sopenharmony_ci /* 132262306a36Sopenharmony_ci * Pull scratch ram settings and treat them as 132362306a36Sopenharmony_ci * if they are the contents of an seeprom if 132462306a36Sopenharmony_ci * the 'ADPT' signature is found in SCB2. 132562306a36Sopenharmony_ci * We manually compose the data as 16bit values 132662306a36Sopenharmony_ci * to avoid endian issues. 132762306a36Sopenharmony_ci */ 132862306a36Sopenharmony_ci ahc_outb(ahc, SCBPTR, 2); 132962306a36Sopenharmony_ci if (ahc_inb(ahc, SCB_BASE) == 'A' 133062306a36Sopenharmony_ci && ahc_inb(ahc, SCB_BASE + 1) == 'D' 133162306a36Sopenharmony_ci && ahc_inb(ahc, SCB_BASE + 2) == 'P' 133262306a36Sopenharmony_ci && ahc_inb(ahc, SCB_BASE + 3) == 'T') { 133362306a36Sopenharmony_ci uint16_t *sc_data; 133462306a36Sopenharmony_ci int i; 133562306a36Sopenharmony_ci 133662306a36Sopenharmony_ci sc_data = (uint16_t *)sc; 133762306a36Sopenharmony_ci for (i = 0; i < 32; i++, sc_data++) { 133862306a36Sopenharmony_ci int j; 133962306a36Sopenharmony_ci 134062306a36Sopenharmony_ci j = i * 2; 134162306a36Sopenharmony_ci *sc_data = ahc_inb(ahc, SRAM_BASE + j) 134262306a36Sopenharmony_ci | ahc_inb(ahc, SRAM_BASE + j + 1) << 8; 134362306a36Sopenharmony_ci } 134462306a36Sopenharmony_ci have_seeprom = ahc_verify_cksum(sc); 134562306a36Sopenharmony_ci if (have_seeprom) 134662306a36Sopenharmony_ci ahc->flags |= AHC_SCB_CONFIG_USED; 134762306a36Sopenharmony_ci } 134862306a36Sopenharmony_ci /* 134962306a36Sopenharmony_ci * Clear any SCB parity errors in case this data and 135062306a36Sopenharmony_ci * its associated parity was not initialized by the BIOS 135162306a36Sopenharmony_ci */ 135262306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 135362306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRBRKADRINT); 135462306a36Sopenharmony_ci } 135562306a36Sopenharmony_ci 135662306a36Sopenharmony_ci if (!have_seeprom) { 135762306a36Sopenharmony_ci if (bootverbose) 135862306a36Sopenharmony_ci printk("%s: No SEEPROM available.\n", ahc_name(ahc)); 135962306a36Sopenharmony_ci ahc->flags |= AHC_USEDEFAULTS; 136062306a36Sopenharmony_ci kfree(ahc->seep_config); 136162306a36Sopenharmony_ci ahc->seep_config = NULL; 136262306a36Sopenharmony_ci sc = NULL; 136362306a36Sopenharmony_ci } else { 136462306a36Sopenharmony_ci ahc_parse_pci_eeprom(ahc, sc); 136562306a36Sopenharmony_ci } 136662306a36Sopenharmony_ci 136762306a36Sopenharmony_ci /* 136862306a36Sopenharmony_ci * Cards that have the external logic necessary to talk to 136962306a36Sopenharmony_ci * a SEEPROM, are almost certain to have the remaining logic 137062306a36Sopenharmony_ci * necessary for auto-termination control. This assumption 137162306a36Sopenharmony_ci * hasn't failed yet... 137262306a36Sopenharmony_ci */ 137362306a36Sopenharmony_ci have_autoterm = have_seeprom; 137462306a36Sopenharmony_ci 137562306a36Sopenharmony_ci /* 137662306a36Sopenharmony_ci * Some low-cost chips have SEEPROM and auto-term control built 137762306a36Sopenharmony_ci * in, instead of using a GAL. They can tell us directly 137862306a36Sopenharmony_ci * if the termination logic is enabled. 137962306a36Sopenharmony_ci */ 138062306a36Sopenharmony_ci if ((ahc->features & AHC_SPIOCAP) != 0) { 138162306a36Sopenharmony_ci if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0) 138262306a36Sopenharmony_ci have_autoterm = FALSE; 138362306a36Sopenharmony_ci } 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci if (have_autoterm) { 138662306a36Sopenharmony_ci ahc->flags |= AHC_HAS_TERM_LOGIC; 138762306a36Sopenharmony_ci ahc_acquire_seeprom(ahc, &sd); 138862306a36Sopenharmony_ci configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1); 138962306a36Sopenharmony_ci ahc_release_seeprom(&sd); 139062306a36Sopenharmony_ci } else if (have_seeprom) { 139162306a36Sopenharmony_ci *sxfrctl1 &= ~STPWEN; 139262306a36Sopenharmony_ci if ((sc->adapter_control & CFSTERM) != 0) 139362306a36Sopenharmony_ci *sxfrctl1 |= STPWEN; 139462306a36Sopenharmony_ci if (bootverbose) 139562306a36Sopenharmony_ci printk("%s: Low byte termination %sabled\n", 139662306a36Sopenharmony_ci ahc_name(ahc), 139762306a36Sopenharmony_ci (*sxfrctl1 & STPWEN) ? "en" : "dis"); 139862306a36Sopenharmony_ci } 139962306a36Sopenharmony_ci} 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_cistatic void 140262306a36Sopenharmony_ciahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc) 140362306a36Sopenharmony_ci{ 140462306a36Sopenharmony_ci /* 140562306a36Sopenharmony_ci * Put the data we've collected down into SRAM 140662306a36Sopenharmony_ci * where ahc_init will find it. 140762306a36Sopenharmony_ci */ 140862306a36Sopenharmony_ci int i; 140962306a36Sopenharmony_ci int max_targ = sc->max_targets & CFMAXTARG; 141062306a36Sopenharmony_ci u_int scsi_conf; 141162306a36Sopenharmony_ci uint16_t discenable; 141262306a36Sopenharmony_ci uint16_t ultraenb; 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_ci discenable = 0; 141562306a36Sopenharmony_ci ultraenb = 0; 141662306a36Sopenharmony_ci if ((sc->adapter_control & CFULTRAEN) != 0) { 141762306a36Sopenharmony_ci /* 141862306a36Sopenharmony_ci * Determine if this adapter has a "newstyle" 141962306a36Sopenharmony_ci * SEEPROM format. 142062306a36Sopenharmony_ci */ 142162306a36Sopenharmony_ci for (i = 0; i < max_targ; i++) { 142262306a36Sopenharmony_ci if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) { 142362306a36Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 142462306a36Sopenharmony_ci break; 142562306a36Sopenharmony_ci } 142662306a36Sopenharmony_ci } 142762306a36Sopenharmony_ci } 142862306a36Sopenharmony_ci 142962306a36Sopenharmony_ci for (i = 0; i < max_targ; i++) { 143062306a36Sopenharmony_ci u_int scsirate; 143162306a36Sopenharmony_ci uint16_t target_mask; 143262306a36Sopenharmony_ci 143362306a36Sopenharmony_ci target_mask = 0x01 << i; 143462306a36Sopenharmony_ci if (sc->device_flags[i] & CFDISC) 143562306a36Sopenharmony_ci discenable |= target_mask; 143662306a36Sopenharmony_ci if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) { 143762306a36Sopenharmony_ci if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) 143862306a36Sopenharmony_ci ultraenb |= target_mask; 143962306a36Sopenharmony_ci } else if ((sc->adapter_control & CFULTRAEN) != 0) { 144062306a36Sopenharmony_ci ultraenb |= target_mask; 144162306a36Sopenharmony_ci } 144262306a36Sopenharmony_ci if ((sc->device_flags[i] & CFXFER) == 0x04 144362306a36Sopenharmony_ci && (ultraenb & target_mask) != 0) { 144462306a36Sopenharmony_ci /* Treat 10MHz as a non-ultra speed */ 144562306a36Sopenharmony_ci sc->device_flags[i] &= ~CFXFER; 144662306a36Sopenharmony_ci ultraenb &= ~target_mask; 144762306a36Sopenharmony_ci } 144862306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) { 144962306a36Sopenharmony_ci u_int offset; 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_ci if (sc->device_flags[i] & CFSYNCH) 145262306a36Sopenharmony_ci offset = MAX_OFFSET_ULTRA2; 145362306a36Sopenharmony_ci else 145462306a36Sopenharmony_ci offset = 0; 145562306a36Sopenharmony_ci ahc_outb(ahc, TARG_OFFSET + i, offset); 145662306a36Sopenharmony_ci 145762306a36Sopenharmony_ci /* 145862306a36Sopenharmony_ci * The ultra enable bits contain the 145962306a36Sopenharmony_ci * high bit of the ultra2 sync rate 146062306a36Sopenharmony_ci * field. 146162306a36Sopenharmony_ci */ 146262306a36Sopenharmony_ci scsirate = (sc->device_flags[i] & CFXFER) 146362306a36Sopenharmony_ci | ((ultraenb & target_mask) ? 0x8 : 0x0); 146462306a36Sopenharmony_ci if (sc->device_flags[i] & CFWIDEB) 146562306a36Sopenharmony_ci scsirate |= WIDEXFER; 146662306a36Sopenharmony_ci } else { 146762306a36Sopenharmony_ci scsirate = (sc->device_flags[i] & CFXFER) << 4; 146862306a36Sopenharmony_ci if (sc->device_flags[i] & CFSYNCH) 146962306a36Sopenharmony_ci scsirate |= SOFS; 147062306a36Sopenharmony_ci if (sc->device_flags[i] & CFWIDEB) 147162306a36Sopenharmony_ci scsirate |= WIDEXFER; 147262306a36Sopenharmony_ci } 147362306a36Sopenharmony_ci ahc_outb(ahc, TARG_SCSIRATE + i, scsirate); 147462306a36Sopenharmony_ci } 147562306a36Sopenharmony_ci ahc->our_id = sc->brtime_id & CFSCSIID; 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_ci scsi_conf = (ahc->our_id & 0x7); 147862306a36Sopenharmony_ci if (sc->adapter_control & CFSPARITY) 147962306a36Sopenharmony_ci scsi_conf |= ENSPCHK; 148062306a36Sopenharmony_ci if (sc->adapter_control & CFRESETB) 148162306a36Sopenharmony_ci scsi_conf |= RESET_SCSI; 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT; 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci if (sc->bios_control & CFEXTEND) 148662306a36Sopenharmony_ci ahc->flags |= AHC_EXTENDED_TRANS_A; 148762306a36Sopenharmony_ci 148862306a36Sopenharmony_ci if (sc->bios_control & CFBIOSEN) 148962306a36Sopenharmony_ci ahc->flags |= AHC_BIOS_ENABLED; 149062306a36Sopenharmony_ci if (ahc->features & AHC_ULTRA 149162306a36Sopenharmony_ci && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) { 149262306a36Sopenharmony_ci /* Should we enable Ultra mode? */ 149362306a36Sopenharmony_ci if (!(sc->adapter_control & CFULTRAEN)) 149462306a36Sopenharmony_ci /* Treat us as a non-ultra card */ 149562306a36Sopenharmony_ci ultraenb = 0; 149662306a36Sopenharmony_ci } 149762306a36Sopenharmony_ci 149862306a36Sopenharmony_ci if (sc->signature == CFSIGNATURE 149962306a36Sopenharmony_ci || sc->signature == CFSIGNATURE2) { 150062306a36Sopenharmony_ci uint32_t devconfig; 150162306a36Sopenharmony_ci 150262306a36Sopenharmony_ci /* Honor the STPWLEVEL settings */ 150362306a36Sopenharmony_ci devconfig = ahc_pci_read_config(ahc->dev_softc, 150462306a36Sopenharmony_ci DEVCONFIG, /*bytes*/4); 150562306a36Sopenharmony_ci devconfig &= ~STPWLEVEL; 150662306a36Sopenharmony_ci if ((sc->bios_control & CFSTPWLEVEL) != 0) 150762306a36Sopenharmony_ci devconfig |= STPWLEVEL; 150862306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, 150962306a36Sopenharmony_ci devconfig, /*bytes*/4); 151062306a36Sopenharmony_ci } 151162306a36Sopenharmony_ci /* Set SCSICONF info */ 151262306a36Sopenharmony_ci ahc_outb(ahc, SCSICONF, scsi_conf); 151362306a36Sopenharmony_ci ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); 151462306a36Sopenharmony_ci ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); 151562306a36Sopenharmony_ci ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff); 151662306a36Sopenharmony_ci ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff); 151762306a36Sopenharmony_ci} 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_cistatic void 152062306a36Sopenharmony_ciconfigure_termination(struct ahc_softc *ahc, 152162306a36Sopenharmony_ci struct seeprom_descriptor *sd, 152262306a36Sopenharmony_ci u_int adapter_control, 152362306a36Sopenharmony_ci u_int *sxfrctl1) 152462306a36Sopenharmony_ci{ 152562306a36Sopenharmony_ci uint8_t brddat; 152662306a36Sopenharmony_ci 152762306a36Sopenharmony_ci brddat = 0; 152862306a36Sopenharmony_ci 152962306a36Sopenharmony_ci /* 153062306a36Sopenharmony_ci * Update the settings in sxfrctl1 to match the 153162306a36Sopenharmony_ci * termination settings 153262306a36Sopenharmony_ci */ 153362306a36Sopenharmony_ci *sxfrctl1 = 0; 153462306a36Sopenharmony_ci 153562306a36Sopenharmony_ci /* 153662306a36Sopenharmony_ci * SEECS must be on for the GALS to latch 153762306a36Sopenharmony_ci * the data properly. Be sure to leave MS 153862306a36Sopenharmony_ci * on or we will release the seeprom. 153962306a36Sopenharmony_ci */ 154062306a36Sopenharmony_ci SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS); 154162306a36Sopenharmony_ci if ((adapter_control & CFAUTOTERM) != 0 154262306a36Sopenharmony_ci || (ahc->features & AHC_NEW_TERMCTL) != 0) { 154362306a36Sopenharmony_ci int internal50_present; 154462306a36Sopenharmony_ci int internal68_present; 154562306a36Sopenharmony_ci int externalcable_present; 154662306a36Sopenharmony_ci int eeprom_present; 154762306a36Sopenharmony_ci int enableSEC_low; 154862306a36Sopenharmony_ci int enableSEC_high; 154962306a36Sopenharmony_ci int enablePRI_low; 155062306a36Sopenharmony_ci int enablePRI_high; 155162306a36Sopenharmony_ci int sum; 155262306a36Sopenharmony_ci 155362306a36Sopenharmony_ci enableSEC_low = 0; 155462306a36Sopenharmony_ci enableSEC_high = 0; 155562306a36Sopenharmony_ci enablePRI_low = 0; 155662306a36Sopenharmony_ci enablePRI_high = 0; 155762306a36Sopenharmony_ci if ((ahc->features & AHC_NEW_TERMCTL) != 0) { 155862306a36Sopenharmony_ci ahc_new_term_detect(ahc, &enableSEC_low, 155962306a36Sopenharmony_ci &enableSEC_high, 156062306a36Sopenharmony_ci &enablePRI_low, 156162306a36Sopenharmony_ci &enablePRI_high, 156262306a36Sopenharmony_ci &eeprom_present); 156362306a36Sopenharmony_ci if ((adapter_control & CFSEAUTOTERM) == 0) { 156462306a36Sopenharmony_ci if (bootverbose) 156562306a36Sopenharmony_ci printk("%s: Manual SE Termination\n", 156662306a36Sopenharmony_ci ahc_name(ahc)); 156762306a36Sopenharmony_ci enableSEC_low = (adapter_control & CFSELOWTERM); 156862306a36Sopenharmony_ci enableSEC_high = 156962306a36Sopenharmony_ci (adapter_control & CFSEHIGHTERM); 157062306a36Sopenharmony_ci } 157162306a36Sopenharmony_ci if ((adapter_control & CFAUTOTERM) == 0) { 157262306a36Sopenharmony_ci if (bootverbose) 157362306a36Sopenharmony_ci printk("%s: Manual LVD Termination\n", 157462306a36Sopenharmony_ci ahc_name(ahc)); 157562306a36Sopenharmony_ci enablePRI_low = (adapter_control & CFSTERM); 157662306a36Sopenharmony_ci enablePRI_high = (adapter_control & CFWSTERM); 157762306a36Sopenharmony_ci } 157862306a36Sopenharmony_ci /* Make the table calculations below happy */ 157962306a36Sopenharmony_ci internal50_present = 0; 158062306a36Sopenharmony_ci internal68_present = 1; 158162306a36Sopenharmony_ci externalcable_present = 1; 158262306a36Sopenharmony_ci } else if ((ahc->features & AHC_SPIOCAP) != 0) { 158362306a36Sopenharmony_ci aic785X_cable_detect(ahc, &internal50_present, 158462306a36Sopenharmony_ci &externalcable_present, 158562306a36Sopenharmony_ci &eeprom_present); 158662306a36Sopenharmony_ci /* Can never support a wide connector. */ 158762306a36Sopenharmony_ci internal68_present = 0; 158862306a36Sopenharmony_ci } else { 158962306a36Sopenharmony_ci aic787X_cable_detect(ahc, &internal50_present, 159062306a36Sopenharmony_ci &internal68_present, 159162306a36Sopenharmony_ci &externalcable_present, 159262306a36Sopenharmony_ci &eeprom_present); 159362306a36Sopenharmony_ci } 159462306a36Sopenharmony_ci 159562306a36Sopenharmony_ci if ((ahc->features & AHC_WIDE) == 0) 159662306a36Sopenharmony_ci internal68_present = 0; 159762306a36Sopenharmony_ci 159862306a36Sopenharmony_ci if (bootverbose 159962306a36Sopenharmony_ci && (ahc->features & AHC_ULTRA2) == 0) { 160062306a36Sopenharmony_ci printk("%s: internal 50 cable %s present", 160162306a36Sopenharmony_ci ahc_name(ahc), 160262306a36Sopenharmony_ci internal50_present ? "is":"not"); 160362306a36Sopenharmony_ci 160462306a36Sopenharmony_ci if ((ahc->features & AHC_WIDE) != 0) 160562306a36Sopenharmony_ci printk(", internal 68 cable %s present", 160662306a36Sopenharmony_ci internal68_present ? "is":"not"); 160762306a36Sopenharmony_ci printk("\n%s: external cable %s present\n", 160862306a36Sopenharmony_ci ahc_name(ahc), 160962306a36Sopenharmony_ci externalcable_present ? "is":"not"); 161062306a36Sopenharmony_ci } 161162306a36Sopenharmony_ci if (bootverbose) 161262306a36Sopenharmony_ci printk("%s: BIOS eeprom %s present\n", 161362306a36Sopenharmony_ci ahc_name(ahc), eeprom_present ? "is" : "not"); 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ci if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) { 161662306a36Sopenharmony_ci /* 161762306a36Sopenharmony_ci * The 50 pin connector is a separate bus, 161862306a36Sopenharmony_ci * so force it to always be terminated. 161962306a36Sopenharmony_ci * In the future, perform current sensing 162062306a36Sopenharmony_ci * to determine if we are in the middle of 162162306a36Sopenharmony_ci * a properly terminated bus. 162262306a36Sopenharmony_ci */ 162362306a36Sopenharmony_ci internal50_present = 0; 162462306a36Sopenharmony_ci } 162562306a36Sopenharmony_ci 162662306a36Sopenharmony_ci /* 162762306a36Sopenharmony_ci * Now set the termination based on what 162862306a36Sopenharmony_ci * we found. 162962306a36Sopenharmony_ci * Flash Enable = BRDDAT7 163062306a36Sopenharmony_ci * Secondary High Term Enable = BRDDAT6 163162306a36Sopenharmony_ci * Secondary Low Term Enable = BRDDAT5 (7890) 163262306a36Sopenharmony_ci * Primary High Term Enable = BRDDAT4 (7890) 163362306a36Sopenharmony_ci */ 163462306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) == 0 163562306a36Sopenharmony_ci && (internal50_present != 0) 163662306a36Sopenharmony_ci && (internal68_present != 0) 163762306a36Sopenharmony_ci && (externalcable_present != 0)) { 163862306a36Sopenharmony_ci printk("%s: Illegal cable configuration!!. " 163962306a36Sopenharmony_ci "Only two connectors on the " 164062306a36Sopenharmony_ci "adapter may be used at a " 164162306a36Sopenharmony_ci "time!\n", ahc_name(ahc)); 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci /* 164462306a36Sopenharmony_ci * Pretend there are no cables in the hope 164562306a36Sopenharmony_ci * that having all of the termination on 164662306a36Sopenharmony_ci * gives us a more stable bus. 164762306a36Sopenharmony_ci */ 164862306a36Sopenharmony_ci internal50_present = 0; 164962306a36Sopenharmony_ci internal68_present = 0; 165062306a36Sopenharmony_ci externalcable_present = 0; 165162306a36Sopenharmony_ci } 165262306a36Sopenharmony_ci 165362306a36Sopenharmony_ci if ((ahc->features & AHC_WIDE) != 0 165462306a36Sopenharmony_ci && ((externalcable_present == 0) 165562306a36Sopenharmony_ci || (internal68_present == 0) 165662306a36Sopenharmony_ci || (enableSEC_high != 0))) { 165762306a36Sopenharmony_ci brddat |= BRDDAT6; 165862306a36Sopenharmony_ci if (bootverbose) { 165962306a36Sopenharmony_ci if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 166062306a36Sopenharmony_ci printk("%s: 68 pin termination " 166162306a36Sopenharmony_ci "Enabled\n", ahc_name(ahc)); 166262306a36Sopenharmony_ci else 166362306a36Sopenharmony_ci printk("%s: %sHigh byte termination " 166462306a36Sopenharmony_ci "Enabled\n", ahc_name(ahc), 166562306a36Sopenharmony_ci enableSEC_high ? "Secondary " 166662306a36Sopenharmony_ci : ""); 166762306a36Sopenharmony_ci } 166862306a36Sopenharmony_ci } 166962306a36Sopenharmony_ci 167062306a36Sopenharmony_ci sum = internal50_present + internal68_present 167162306a36Sopenharmony_ci + externalcable_present; 167262306a36Sopenharmony_ci if (sum < 2 || (enableSEC_low != 0)) { 167362306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 167462306a36Sopenharmony_ci brddat |= BRDDAT5; 167562306a36Sopenharmony_ci else 167662306a36Sopenharmony_ci *sxfrctl1 |= STPWEN; 167762306a36Sopenharmony_ci if (bootverbose) { 167862306a36Sopenharmony_ci if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 167962306a36Sopenharmony_ci printk("%s: 50 pin termination " 168062306a36Sopenharmony_ci "Enabled\n", ahc_name(ahc)); 168162306a36Sopenharmony_ci else 168262306a36Sopenharmony_ci printk("%s: %sLow byte termination " 168362306a36Sopenharmony_ci "Enabled\n", ahc_name(ahc), 168462306a36Sopenharmony_ci enableSEC_low ? "Secondary " 168562306a36Sopenharmony_ci : ""); 168662306a36Sopenharmony_ci } 168762306a36Sopenharmony_ci } 168862306a36Sopenharmony_ci 168962306a36Sopenharmony_ci if (enablePRI_low != 0) { 169062306a36Sopenharmony_ci *sxfrctl1 |= STPWEN; 169162306a36Sopenharmony_ci if (bootverbose) 169262306a36Sopenharmony_ci printk("%s: Primary Low Byte termination " 169362306a36Sopenharmony_ci "Enabled\n", ahc_name(ahc)); 169462306a36Sopenharmony_ci } 169562306a36Sopenharmony_ci 169662306a36Sopenharmony_ci /* 169762306a36Sopenharmony_ci * Setup STPWEN before setting up the rest of 169862306a36Sopenharmony_ci * the termination per the tech note on the U160 cards. 169962306a36Sopenharmony_ci */ 170062306a36Sopenharmony_ci ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci if (enablePRI_high != 0) { 170362306a36Sopenharmony_ci brddat |= BRDDAT4; 170462306a36Sopenharmony_ci if (bootverbose) 170562306a36Sopenharmony_ci printk("%s: Primary High Byte " 170662306a36Sopenharmony_ci "termination Enabled\n", 170762306a36Sopenharmony_ci ahc_name(ahc)); 170862306a36Sopenharmony_ci } 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_ci write_brdctl(ahc, brddat); 171162306a36Sopenharmony_ci 171262306a36Sopenharmony_ci } else { 171362306a36Sopenharmony_ci if ((adapter_control & CFSTERM) != 0) { 171462306a36Sopenharmony_ci *sxfrctl1 |= STPWEN; 171562306a36Sopenharmony_ci 171662306a36Sopenharmony_ci if (bootverbose) 171762306a36Sopenharmony_ci printk("%s: %sLow byte termination Enabled\n", 171862306a36Sopenharmony_ci ahc_name(ahc), 171962306a36Sopenharmony_ci (ahc->features & AHC_ULTRA2) ? "Primary " 172062306a36Sopenharmony_ci : ""); 172162306a36Sopenharmony_ci } 172262306a36Sopenharmony_ci 172362306a36Sopenharmony_ci if ((adapter_control & CFWSTERM) != 0 172462306a36Sopenharmony_ci && (ahc->features & AHC_WIDE) != 0) { 172562306a36Sopenharmony_ci brddat |= BRDDAT6; 172662306a36Sopenharmony_ci if (bootverbose) 172762306a36Sopenharmony_ci printk("%s: %sHigh byte termination Enabled\n", 172862306a36Sopenharmony_ci ahc_name(ahc), 172962306a36Sopenharmony_ci (ahc->features & AHC_ULTRA2) 173062306a36Sopenharmony_ci ? "Secondary " : ""); 173162306a36Sopenharmony_ci } 173262306a36Sopenharmony_ci 173362306a36Sopenharmony_ci /* 173462306a36Sopenharmony_ci * Setup STPWEN before setting up the rest of 173562306a36Sopenharmony_ci * the termination per the tech note on the U160 cards. 173662306a36Sopenharmony_ci */ 173762306a36Sopenharmony_ci ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 173862306a36Sopenharmony_ci 173962306a36Sopenharmony_ci if ((ahc->features & AHC_WIDE) != 0) 174062306a36Sopenharmony_ci write_brdctl(ahc, brddat); 174162306a36Sopenharmony_ci } 174262306a36Sopenharmony_ci SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */ 174362306a36Sopenharmony_ci} 174462306a36Sopenharmony_ci 174562306a36Sopenharmony_cistatic void 174662306a36Sopenharmony_ciahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low, 174762306a36Sopenharmony_ci int *enableSEC_high, int *enablePRI_low, 174862306a36Sopenharmony_ci int *enablePRI_high, int *eeprom_present) 174962306a36Sopenharmony_ci{ 175062306a36Sopenharmony_ci uint8_t brdctl; 175162306a36Sopenharmony_ci 175262306a36Sopenharmony_ci /* 175362306a36Sopenharmony_ci * BRDDAT7 = Eeprom 175462306a36Sopenharmony_ci * BRDDAT6 = Enable Secondary High Byte termination 175562306a36Sopenharmony_ci * BRDDAT5 = Enable Secondary Low Byte termination 175662306a36Sopenharmony_ci * BRDDAT4 = Enable Primary high byte termination 175762306a36Sopenharmony_ci * BRDDAT3 = Enable Primary low byte termination 175862306a36Sopenharmony_ci */ 175962306a36Sopenharmony_ci brdctl = read_brdctl(ahc); 176062306a36Sopenharmony_ci *eeprom_present = brdctl & BRDDAT7; 176162306a36Sopenharmony_ci *enableSEC_high = (brdctl & BRDDAT6); 176262306a36Sopenharmony_ci *enableSEC_low = (brdctl & BRDDAT5); 176362306a36Sopenharmony_ci *enablePRI_high = (brdctl & BRDDAT4); 176462306a36Sopenharmony_ci *enablePRI_low = (brdctl & BRDDAT3); 176562306a36Sopenharmony_ci} 176662306a36Sopenharmony_ci 176762306a36Sopenharmony_cistatic void 176862306a36Sopenharmony_ciaic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 176962306a36Sopenharmony_ci int *internal68_present, int *externalcable_present, 177062306a36Sopenharmony_ci int *eeprom_present) 177162306a36Sopenharmony_ci{ 177262306a36Sopenharmony_ci uint8_t brdctl; 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci /* 177562306a36Sopenharmony_ci * First read the status of our cables. 177662306a36Sopenharmony_ci * Set the rom bank to 0 since the 177762306a36Sopenharmony_ci * bank setting serves as a multiplexor 177862306a36Sopenharmony_ci * for the cable detection logic. 177962306a36Sopenharmony_ci * BRDDAT5 controls the bank switch. 178062306a36Sopenharmony_ci */ 178162306a36Sopenharmony_ci write_brdctl(ahc, 0); 178262306a36Sopenharmony_ci 178362306a36Sopenharmony_ci /* 178462306a36Sopenharmony_ci * Now read the state of the internal 178562306a36Sopenharmony_ci * connectors. BRDDAT6 is INT50 and 178662306a36Sopenharmony_ci * BRDDAT7 is INT68. 178762306a36Sopenharmony_ci */ 178862306a36Sopenharmony_ci brdctl = read_brdctl(ahc); 178962306a36Sopenharmony_ci *internal50_present = (brdctl & BRDDAT6) ? 0 : 1; 179062306a36Sopenharmony_ci *internal68_present = (brdctl & BRDDAT7) ? 0 : 1; 179162306a36Sopenharmony_ci 179262306a36Sopenharmony_ci /* 179362306a36Sopenharmony_ci * Set the rom bank to 1 and determine 179462306a36Sopenharmony_ci * the other signals. 179562306a36Sopenharmony_ci */ 179662306a36Sopenharmony_ci write_brdctl(ahc, BRDDAT5); 179762306a36Sopenharmony_ci 179862306a36Sopenharmony_ci /* 179962306a36Sopenharmony_ci * Now read the state of the external 180062306a36Sopenharmony_ci * connectors. BRDDAT6 is EXT68 and 180162306a36Sopenharmony_ci * BRDDAT7 is EPROMPS. 180262306a36Sopenharmony_ci */ 180362306a36Sopenharmony_ci brdctl = read_brdctl(ahc); 180462306a36Sopenharmony_ci *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 180562306a36Sopenharmony_ci *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0; 180662306a36Sopenharmony_ci} 180762306a36Sopenharmony_ci 180862306a36Sopenharmony_cistatic void 180962306a36Sopenharmony_ciaic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 181062306a36Sopenharmony_ci int *externalcable_present, int *eeprom_present) 181162306a36Sopenharmony_ci{ 181262306a36Sopenharmony_ci uint8_t brdctl; 181362306a36Sopenharmony_ci uint8_t spiocap; 181462306a36Sopenharmony_ci 181562306a36Sopenharmony_ci spiocap = ahc_inb(ahc, SPIOCAP); 181662306a36Sopenharmony_ci spiocap &= ~SOFTCMDEN; 181762306a36Sopenharmony_ci spiocap |= EXT_BRDCTL; 181862306a36Sopenharmony_ci ahc_outb(ahc, SPIOCAP, spiocap); 181962306a36Sopenharmony_ci ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); 182062306a36Sopenharmony_ci ahc_flush_device_writes(ahc); 182162306a36Sopenharmony_ci ahc_delay(500); 182262306a36Sopenharmony_ci ahc_outb(ahc, BRDCTL, 0); 182362306a36Sopenharmony_ci ahc_flush_device_writes(ahc); 182462306a36Sopenharmony_ci ahc_delay(500); 182562306a36Sopenharmony_ci brdctl = ahc_inb(ahc, BRDCTL); 182662306a36Sopenharmony_ci *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; 182762306a36Sopenharmony_ci *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 182862306a36Sopenharmony_ci *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0; 182962306a36Sopenharmony_ci} 183062306a36Sopenharmony_ci 183162306a36Sopenharmony_ciint 183262306a36Sopenharmony_ciahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd) 183362306a36Sopenharmony_ci{ 183462306a36Sopenharmony_ci int wait; 183562306a36Sopenharmony_ci 183662306a36Sopenharmony_ci if ((ahc->features & AHC_SPIOCAP) != 0 183762306a36Sopenharmony_ci && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0) 183862306a36Sopenharmony_ci return (0); 183962306a36Sopenharmony_ci 184062306a36Sopenharmony_ci /* 184162306a36Sopenharmony_ci * Request access of the memory port. When access is 184262306a36Sopenharmony_ci * granted, SEERDY will go high. We use a 1 second 184362306a36Sopenharmony_ci * timeout which should be near 1 second more than 184462306a36Sopenharmony_ci * is needed. Reason: after the chip reset, there 184562306a36Sopenharmony_ci * should be no contention. 184662306a36Sopenharmony_ci */ 184762306a36Sopenharmony_ci SEEPROM_OUTB(sd, sd->sd_MS); 184862306a36Sopenharmony_ci wait = 1000; /* 1 second timeout in msec */ 184962306a36Sopenharmony_ci while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { 185062306a36Sopenharmony_ci ahc_delay(1000); /* delay 1 msec */ 185162306a36Sopenharmony_ci } 185262306a36Sopenharmony_ci if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { 185362306a36Sopenharmony_ci SEEPROM_OUTB(sd, 0); 185462306a36Sopenharmony_ci return (0); 185562306a36Sopenharmony_ci } 185662306a36Sopenharmony_ci return(1); 185762306a36Sopenharmony_ci} 185862306a36Sopenharmony_ci 185962306a36Sopenharmony_civoid 186062306a36Sopenharmony_ciahc_release_seeprom(struct seeprom_descriptor *sd) 186162306a36Sopenharmony_ci{ 186262306a36Sopenharmony_ci /* Release access to the memory port and the serial EEPROM. */ 186362306a36Sopenharmony_ci SEEPROM_OUTB(sd, 0); 186462306a36Sopenharmony_ci} 186562306a36Sopenharmony_ci 186662306a36Sopenharmony_cistatic void 186762306a36Sopenharmony_ciwrite_brdctl(struct ahc_softc *ahc, uint8_t value) 186862306a36Sopenharmony_ci{ 186962306a36Sopenharmony_ci uint8_t brdctl; 187062306a36Sopenharmony_ci 187162306a36Sopenharmony_ci if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 187262306a36Sopenharmony_ci brdctl = BRDSTB; 187362306a36Sopenharmony_ci if (ahc->channel == 'B') 187462306a36Sopenharmony_ci brdctl |= BRDCS; 187562306a36Sopenharmony_ci } else if ((ahc->features & AHC_ULTRA2) != 0) { 187662306a36Sopenharmony_ci brdctl = 0; 187762306a36Sopenharmony_ci } else { 187862306a36Sopenharmony_ci brdctl = BRDSTB|BRDCS; 187962306a36Sopenharmony_ci } 188062306a36Sopenharmony_ci ahc_outb(ahc, BRDCTL, brdctl); 188162306a36Sopenharmony_ci ahc_flush_device_writes(ahc); 188262306a36Sopenharmony_ci brdctl |= value; 188362306a36Sopenharmony_ci ahc_outb(ahc, BRDCTL, brdctl); 188462306a36Sopenharmony_ci ahc_flush_device_writes(ahc); 188562306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 188662306a36Sopenharmony_ci brdctl |= BRDSTB_ULTRA2; 188762306a36Sopenharmony_ci else 188862306a36Sopenharmony_ci brdctl &= ~BRDSTB; 188962306a36Sopenharmony_ci ahc_outb(ahc, BRDCTL, brdctl); 189062306a36Sopenharmony_ci ahc_flush_device_writes(ahc); 189162306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 189262306a36Sopenharmony_ci brdctl = 0; 189362306a36Sopenharmony_ci else 189462306a36Sopenharmony_ci brdctl &= ~BRDCS; 189562306a36Sopenharmony_ci ahc_outb(ahc, BRDCTL, brdctl); 189662306a36Sopenharmony_ci} 189762306a36Sopenharmony_ci 189862306a36Sopenharmony_cistatic uint8_t 189962306a36Sopenharmony_ciread_brdctl(struct ahc_softc *ahc) 190062306a36Sopenharmony_ci{ 190162306a36Sopenharmony_ci uint8_t brdctl; 190262306a36Sopenharmony_ci uint8_t value; 190362306a36Sopenharmony_ci 190462306a36Sopenharmony_ci if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 190562306a36Sopenharmony_ci brdctl = BRDRW; 190662306a36Sopenharmony_ci if (ahc->channel == 'B') 190762306a36Sopenharmony_ci brdctl |= BRDCS; 190862306a36Sopenharmony_ci } else if ((ahc->features & AHC_ULTRA2) != 0) { 190962306a36Sopenharmony_ci brdctl = BRDRW_ULTRA2; 191062306a36Sopenharmony_ci } else { 191162306a36Sopenharmony_ci brdctl = BRDRW|BRDCS; 191262306a36Sopenharmony_ci } 191362306a36Sopenharmony_ci ahc_outb(ahc, BRDCTL, brdctl); 191462306a36Sopenharmony_ci ahc_flush_device_writes(ahc); 191562306a36Sopenharmony_ci value = ahc_inb(ahc, BRDCTL); 191662306a36Sopenharmony_ci ahc_outb(ahc, BRDCTL, 0); 191762306a36Sopenharmony_ci return (value); 191862306a36Sopenharmony_ci} 191962306a36Sopenharmony_ci 192062306a36Sopenharmony_cistatic void 192162306a36Sopenharmony_ciahc_pci_intr(struct ahc_softc *ahc) 192262306a36Sopenharmony_ci{ 192362306a36Sopenharmony_ci u_int error; 192462306a36Sopenharmony_ci u_int status1; 192562306a36Sopenharmony_ci 192662306a36Sopenharmony_ci error = ahc_inb(ahc, ERROR); 192762306a36Sopenharmony_ci if ((error & PCIERRSTAT) == 0) 192862306a36Sopenharmony_ci return; 192962306a36Sopenharmony_ci 193062306a36Sopenharmony_ci status1 = ahc_pci_read_config(ahc->dev_softc, 193162306a36Sopenharmony_ci PCIR_STATUS + 1, /*bytes*/1); 193262306a36Sopenharmony_ci 193362306a36Sopenharmony_ci printk("%s: PCI error Interrupt at seqaddr = 0x%x\n", 193462306a36Sopenharmony_ci ahc_name(ahc), 193562306a36Sopenharmony_ci ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); 193662306a36Sopenharmony_ci 193762306a36Sopenharmony_ci if (status1 & DPE) { 193862306a36Sopenharmony_ci ahc->pci_target_perr_count++; 193962306a36Sopenharmony_ci printk("%s: Data Parity Error Detected during address " 194062306a36Sopenharmony_ci "or write data phase\n", ahc_name(ahc)); 194162306a36Sopenharmony_ci } 194262306a36Sopenharmony_ci if (status1 & SSE) { 194362306a36Sopenharmony_ci printk("%s: Signal System Error Detected\n", ahc_name(ahc)); 194462306a36Sopenharmony_ci } 194562306a36Sopenharmony_ci if (status1 & RMA) { 194662306a36Sopenharmony_ci printk("%s: Received a Master Abort\n", ahc_name(ahc)); 194762306a36Sopenharmony_ci } 194862306a36Sopenharmony_ci if (status1 & RTA) { 194962306a36Sopenharmony_ci printk("%s: Received a Target Abort\n", ahc_name(ahc)); 195062306a36Sopenharmony_ci } 195162306a36Sopenharmony_ci if (status1 & STA) { 195262306a36Sopenharmony_ci printk("%s: Signaled a Target Abort\n", ahc_name(ahc)); 195362306a36Sopenharmony_ci } 195462306a36Sopenharmony_ci if (status1 & DPR) { 195562306a36Sopenharmony_ci printk("%s: Data Parity Error has been reported via PERR#\n", 195662306a36Sopenharmony_ci ahc_name(ahc)); 195762306a36Sopenharmony_ci } 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci /* Clear latched errors. */ 196062306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 196162306a36Sopenharmony_ci status1, /*bytes*/1); 196262306a36Sopenharmony_ci 196362306a36Sopenharmony_ci if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { 196462306a36Sopenharmony_ci printk("%s: Latched PCIERR interrupt with " 196562306a36Sopenharmony_ci "no status bits set\n", ahc_name(ahc)); 196662306a36Sopenharmony_ci } else { 196762306a36Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 196862306a36Sopenharmony_ci } 196962306a36Sopenharmony_ci 197062306a36Sopenharmony_ci if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) { 197162306a36Sopenharmony_ci printk( 197262306a36Sopenharmony_ci"%s: WARNING WARNING WARNING WARNING\n" 197362306a36Sopenharmony_ci"%s: Too many PCI parity errors observed as a target.\n" 197462306a36Sopenharmony_ci"%s: Some device on this bus is generating bad parity.\n" 197562306a36Sopenharmony_ci"%s: This is an error *observed by*, not *generated by*, this controller.\n" 197662306a36Sopenharmony_ci"%s: PCI parity error checking has been disabled.\n" 197762306a36Sopenharmony_ci"%s: WARNING WARNING WARNING WARNING\n", 197862306a36Sopenharmony_ci ahc_name(ahc), ahc_name(ahc), ahc_name(ahc), 197962306a36Sopenharmony_ci ahc_name(ahc), ahc_name(ahc), ahc_name(ahc)); 198062306a36Sopenharmony_ci ahc->seqctl |= FAILDIS; 198162306a36Sopenharmony_ci ahc_outb(ahc, SEQCTL, ahc->seqctl); 198262306a36Sopenharmony_ci } 198362306a36Sopenharmony_ci ahc_unpause(ahc); 198462306a36Sopenharmony_ci} 198562306a36Sopenharmony_ci 198662306a36Sopenharmony_cistatic int 198762306a36Sopenharmony_ciahc_pci_chip_init(struct ahc_softc *ahc) 198862306a36Sopenharmony_ci{ 198962306a36Sopenharmony_ci ahc_outb(ahc, DSCOMMAND0, ahc->bus_softc.pci_softc.dscommand0); 199062306a36Sopenharmony_ci ahc_outb(ahc, DSPCISTATUS, ahc->bus_softc.pci_softc.dspcistatus); 199162306a36Sopenharmony_ci if ((ahc->features & AHC_DT) != 0) { 199262306a36Sopenharmony_ci u_int sfunct; 199362306a36Sopenharmony_ci 199462306a36Sopenharmony_ci sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 199562306a36Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 199662306a36Sopenharmony_ci ahc_outb(ahc, OPTIONMODE, ahc->bus_softc.pci_softc.optionmode); 199762306a36Sopenharmony_ci ahc_outw(ahc, TARGCRCCNT, ahc->bus_softc.pci_softc.targcrccnt); 199862306a36Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct); 199962306a36Sopenharmony_ci ahc_outb(ahc, CRCCONTROL1, 200062306a36Sopenharmony_ci ahc->bus_softc.pci_softc.crccontrol1); 200162306a36Sopenharmony_ci } 200262306a36Sopenharmony_ci if ((ahc->features & AHC_MULTI_FUNC) != 0) 200362306a36Sopenharmony_ci ahc_outb(ahc, SCBBADDR, ahc->bus_softc.pci_softc.scbbaddr); 200462306a36Sopenharmony_ci 200562306a36Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 200662306a36Sopenharmony_ci ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh); 200762306a36Sopenharmony_ci 200862306a36Sopenharmony_ci return (ahc_chip_init(ahc)); 200962306a36Sopenharmony_ci} 201062306a36Sopenharmony_ci 201162306a36Sopenharmony_civoid __maybe_unused 201262306a36Sopenharmony_ciahc_pci_resume(struct ahc_softc *ahc) 201362306a36Sopenharmony_ci{ 201462306a36Sopenharmony_ci /* 201562306a36Sopenharmony_ci * We assume that the OS has restored our register 201662306a36Sopenharmony_ci * mappings, etc. Just update the config space registers 201762306a36Sopenharmony_ci * that the OS doesn't know about and rely on our chip 201862306a36Sopenharmony_ci * reset handler to handle the rest. 201962306a36Sopenharmony_ci */ 202062306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, 202162306a36Sopenharmony_ci ahc->bus_softc.pci_softc.devconfig, /*bytes*/4); 202262306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, 202362306a36Sopenharmony_ci ahc->bus_softc.pci_softc.command, /*bytes*/1); 202462306a36Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 202562306a36Sopenharmony_ci ahc->bus_softc.pci_softc.csize_lattime, /*bytes*/1); 202662306a36Sopenharmony_ci if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) { 202762306a36Sopenharmony_ci struct seeprom_descriptor sd; 202862306a36Sopenharmony_ci u_int sxfrctl1; 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci sd.sd_ahc = ahc; 203162306a36Sopenharmony_ci sd.sd_control_offset = SEECTL; 203262306a36Sopenharmony_ci sd.sd_status_offset = SEECTL; 203362306a36Sopenharmony_ci sd.sd_dataout_offset = SEECTL; 203462306a36Sopenharmony_ci 203562306a36Sopenharmony_ci ahc_acquire_seeprom(ahc, &sd); 203662306a36Sopenharmony_ci configure_termination(ahc, &sd, 203762306a36Sopenharmony_ci ahc->seep_config->adapter_control, 203862306a36Sopenharmony_ci &sxfrctl1); 203962306a36Sopenharmony_ci ahc_release_seeprom(&sd); 204062306a36Sopenharmony_ci } 204162306a36Sopenharmony_ci} 204262306a36Sopenharmony_ci 204362306a36Sopenharmony_cistatic int 204462306a36Sopenharmony_ciahc_aic785X_setup(struct ahc_softc *ahc) 204562306a36Sopenharmony_ci{ 204662306a36Sopenharmony_ci ahc_dev_softc_t pci; 204762306a36Sopenharmony_ci uint8_t rev; 204862306a36Sopenharmony_ci 204962306a36Sopenharmony_ci pci = ahc->dev_softc; 205062306a36Sopenharmony_ci ahc->channel = 'A'; 205162306a36Sopenharmony_ci ahc->chip = AHC_AIC7850; 205262306a36Sopenharmony_ci ahc->features = AHC_AIC7850_FE; 205362306a36Sopenharmony_ci ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 205462306a36Sopenharmony_ci rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 205562306a36Sopenharmony_ci if (rev >= 1) 205662306a36Sopenharmony_ci ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 205762306a36Sopenharmony_ci ahc->instruction_ram_size = 512; 205862306a36Sopenharmony_ci return (0); 205962306a36Sopenharmony_ci} 206062306a36Sopenharmony_ci 206162306a36Sopenharmony_cistatic int 206262306a36Sopenharmony_ciahc_aic7860_setup(struct ahc_softc *ahc) 206362306a36Sopenharmony_ci{ 206462306a36Sopenharmony_ci ahc_dev_softc_t pci; 206562306a36Sopenharmony_ci uint8_t rev; 206662306a36Sopenharmony_ci 206762306a36Sopenharmony_ci pci = ahc->dev_softc; 206862306a36Sopenharmony_ci ahc->channel = 'A'; 206962306a36Sopenharmony_ci ahc->chip = AHC_AIC7860; 207062306a36Sopenharmony_ci ahc->features = AHC_AIC7860_FE; 207162306a36Sopenharmony_ci ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 207262306a36Sopenharmony_ci rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 207362306a36Sopenharmony_ci if (rev >= 1) 207462306a36Sopenharmony_ci ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 207562306a36Sopenharmony_ci ahc->instruction_ram_size = 512; 207662306a36Sopenharmony_ci return (0); 207762306a36Sopenharmony_ci} 207862306a36Sopenharmony_ci 207962306a36Sopenharmony_cistatic int 208062306a36Sopenharmony_ciahc_apa1480_setup(struct ahc_softc *ahc) 208162306a36Sopenharmony_ci{ 208262306a36Sopenharmony_ci int error; 208362306a36Sopenharmony_ci 208462306a36Sopenharmony_ci error = ahc_aic7860_setup(ahc); 208562306a36Sopenharmony_ci if (error != 0) 208662306a36Sopenharmony_ci return (error); 208762306a36Sopenharmony_ci ahc->features |= AHC_REMOVABLE; 208862306a36Sopenharmony_ci return (0); 208962306a36Sopenharmony_ci} 209062306a36Sopenharmony_ci 209162306a36Sopenharmony_cistatic int 209262306a36Sopenharmony_ciahc_aic7870_setup(struct ahc_softc *ahc) 209362306a36Sopenharmony_ci{ 209462306a36Sopenharmony_ci 209562306a36Sopenharmony_ci ahc->channel = 'A'; 209662306a36Sopenharmony_ci ahc->chip = AHC_AIC7870; 209762306a36Sopenharmony_ci ahc->features = AHC_AIC7870_FE; 209862306a36Sopenharmony_ci ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 209962306a36Sopenharmony_ci ahc->instruction_ram_size = 512; 210062306a36Sopenharmony_ci return (0); 210162306a36Sopenharmony_ci} 210262306a36Sopenharmony_ci 210362306a36Sopenharmony_cistatic int 210462306a36Sopenharmony_ciahc_aic7870h_setup(struct ahc_softc *ahc) 210562306a36Sopenharmony_ci{ 210662306a36Sopenharmony_ci int error = ahc_aic7870_setup(ahc); 210762306a36Sopenharmony_ci 210862306a36Sopenharmony_ci ahc->features |= AHC_HVD; 210962306a36Sopenharmony_ci 211062306a36Sopenharmony_ci return error; 211162306a36Sopenharmony_ci} 211262306a36Sopenharmony_ci 211362306a36Sopenharmony_cistatic int 211462306a36Sopenharmony_ciahc_aha394X_setup(struct ahc_softc *ahc) 211562306a36Sopenharmony_ci{ 211662306a36Sopenharmony_ci int error; 211762306a36Sopenharmony_ci 211862306a36Sopenharmony_ci error = ahc_aic7870_setup(ahc); 211962306a36Sopenharmony_ci if (error == 0) 212062306a36Sopenharmony_ci error = ahc_aha394XX_setup(ahc); 212162306a36Sopenharmony_ci return (error); 212262306a36Sopenharmony_ci} 212362306a36Sopenharmony_ci 212462306a36Sopenharmony_cistatic int 212562306a36Sopenharmony_ciahc_aha394Xh_setup(struct ahc_softc *ahc) 212662306a36Sopenharmony_ci{ 212762306a36Sopenharmony_ci int error = ahc_aha394X_setup(ahc); 212862306a36Sopenharmony_ci 212962306a36Sopenharmony_ci ahc->features |= AHC_HVD; 213062306a36Sopenharmony_ci 213162306a36Sopenharmony_ci return error; 213262306a36Sopenharmony_ci} 213362306a36Sopenharmony_ci 213462306a36Sopenharmony_cistatic int 213562306a36Sopenharmony_ciahc_aha398X_setup(struct ahc_softc *ahc) 213662306a36Sopenharmony_ci{ 213762306a36Sopenharmony_ci int error; 213862306a36Sopenharmony_ci 213962306a36Sopenharmony_ci error = ahc_aic7870_setup(ahc); 214062306a36Sopenharmony_ci if (error == 0) 214162306a36Sopenharmony_ci error = ahc_aha398XX_setup(ahc); 214262306a36Sopenharmony_ci return (error); 214362306a36Sopenharmony_ci} 214462306a36Sopenharmony_ci 214562306a36Sopenharmony_cistatic int 214662306a36Sopenharmony_ciahc_aha494X_setup(struct ahc_softc *ahc) 214762306a36Sopenharmony_ci{ 214862306a36Sopenharmony_ci int error; 214962306a36Sopenharmony_ci 215062306a36Sopenharmony_ci error = ahc_aic7870_setup(ahc); 215162306a36Sopenharmony_ci if (error == 0) 215262306a36Sopenharmony_ci error = ahc_aha494XX_setup(ahc); 215362306a36Sopenharmony_ci return (error); 215462306a36Sopenharmony_ci} 215562306a36Sopenharmony_ci 215662306a36Sopenharmony_cistatic int 215762306a36Sopenharmony_ciahc_aha494Xh_setup(struct ahc_softc *ahc) 215862306a36Sopenharmony_ci{ 215962306a36Sopenharmony_ci int error = ahc_aha494X_setup(ahc); 216062306a36Sopenharmony_ci 216162306a36Sopenharmony_ci ahc->features |= AHC_HVD; 216262306a36Sopenharmony_ci 216362306a36Sopenharmony_ci return error; 216462306a36Sopenharmony_ci} 216562306a36Sopenharmony_ci 216662306a36Sopenharmony_cistatic int 216762306a36Sopenharmony_ciahc_aic7880_setup(struct ahc_softc *ahc) 216862306a36Sopenharmony_ci{ 216962306a36Sopenharmony_ci ahc_dev_softc_t pci; 217062306a36Sopenharmony_ci uint8_t rev; 217162306a36Sopenharmony_ci 217262306a36Sopenharmony_ci pci = ahc->dev_softc; 217362306a36Sopenharmony_ci ahc->channel = 'A'; 217462306a36Sopenharmony_ci ahc->chip = AHC_AIC7880; 217562306a36Sopenharmony_ci ahc->features = AHC_AIC7880_FE; 217662306a36Sopenharmony_ci ahc->bugs |= AHC_TMODE_WIDEODD_BUG; 217762306a36Sopenharmony_ci rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 217862306a36Sopenharmony_ci if (rev >= 1) { 217962306a36Sopenharmony_ci ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 218062306a36Sopenharmony_ci } else { 218162306a36Sopenharmony_ci ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 218262306a36Sopenharmony_ci } 218362306a36Sopenharmony_ci ahc->instruction_ram_size = 512; 218462306a36Sopenharmony_ci return (0); 218562306a36Sopenharmony_ci} 218662306a36Sopenharmony_ci 218762306a36Sopenharmony_cistatic int 218862306a36Sopenharmony_ciahc_aic7880h_setup(struct ahc_softc *ahc) 218962306a36Sopenharmony_ci{ 219062306a36Sopenharmony_ci int error = ahc_aic7880_setup(ahc); 219162306a36Sopenharmony_ci 219262306a36Sopenharmony_ci ahc->features |= AHC_HVD; 219362306a36Sopenharmony_ci 219462306a36Sopenharmony_ci return error; 219562306a36Sopenharmony_ci} 219662306a36Sopenharmony_ci 219762306a36Sopenharmony_ci 219862306a36Sopenharmony_cistatic int 219962306a36Sopenharmony_ciahc_aha2940Pro_setup(struct ahc_softc *ahc) 220062306a36Sopenharmony_ci{ 220162306a36Sopenharmony_ci 220262306a36Sopenharmony_ci ahc->flags |= AHC_INT50_SPEEDFLEX; 220362306a36Sopenharmony_ci return (ahc_aic7880_setup(ahc)); 220462306a36Sopenharmony_ci} 220562306a36Sopenharmony_ci 220662306a36Sopenharmony_cistatic int 220762306a36Sopenharmony_ciahc_aha394XU_setup(struct ahc_softc *ahc) 220862306a36Sopenharmony_ci{ 220962306a36Sopenharmony_ci int error; 221062306a36Sopenharmony_ci 221162306a36Sopenharmony_ci error = ahc_aic7880_setup(ahc); 221262306a36Sopenharmony_ci if (error == 0) 221362306a36Sopenharmony_ci error = ahc_aha394XX_setup(ahc); 221462306a36Sopenharmony_ci return (error); 221562306a36Sopenharmony_ci} 221662306a36Sopenharmony_ci 221762306a36Sopenharmony_cistatic int 221862306a36Sopenharmony_ciahc_aha394XUh_setup(struct ahc_softc *ahc) 221962306a36Sopenharmony_ci{ 222062306a36Sopenharmony_ci int error = ahc_aha394XU_setup(ahc); 222162306a36Sopenharmony_ci 222262306a36Sopenharmony_ci ahc->features |= AHC_HVD; 222362306a36Sopenharmony_ci 222462306a36Sopenharmony_ci return error; 222562306a36Sopenharmony_ci} 222662306a36Sopenharmony_ci 222762306a36Sopenharmony_cistatic int 222862306a36Sopenharmony_ciahc_aha398XU_setup(struct ahc_softc *ahc) 222962306a36Sopenharmony_ci{ 223062306a36Sopenharmony_ci int error; 223162306a36Sopenharmony_ci 223262306a36Sopenharmony_ci error = ahc_aic7880_setup(ahc); 223362306a36Sopenharmony_ci if (error == 0) 223462306a36Sopenharmony_ci error = ahc_aha398XX_setup(ahc); 223562306a36Sopenharmony_ci return (error); 223662306a36Sopenharmony_ci} 223762306a36Sopenharmony_ci 223862306a36Sopenharmony_cistatic int 223962306a36Sopenharmony_ciahc_aic7890_setup(struct ahc_softc *ahc) 224062306a36Sopenharmony_ci{ 224162306a36Sopenharmony_ci ahc_dev_softc_t pci; 224262306a36Sopenharmony_ci uint8_t rev; 224362306a36Sopenharmony_ci 224462306a36Sopenharmony_ci pci = ahc->dev_softc; 224562306a36Sopenharmony_ci ahc->channel = 'A'; 224662306a36Sopenharmony_ci ahc->chip = AHC_AIC7890; 224762306a36Sopenharmony_ci ahc->features = AHC_AIC7890_FE; 224862306a36Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 224962306a36Sopenharmony_ci rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 225062306a36Sopenharmony_ci if (rev == 0) 225162306a36Sopenharmony_ci ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; 225262306a36Sopenharmony_ci ahc->instruction_ram_size = 768; 225362306a36Sopenharmony_ci return (0); 225462306a36Sopenharmony_ci} 225562306a36Sopenharmony_ci 225662306a36Sopenharmony_cistatic int 225762306a36Sopenharmony_ciahc_aic7892_setup(struct ahc_softc *ahc) 225862306a36Sopenharmony_ci{ 225962306a36Sopenharmony_ci 226062306a36Sopenharmony_ci ahc->channel = 'A'; 226162306a36Sopenharmony_ci ahc->chip = AHC_AIC7892; 226262306a36Sopenharmony_ci ahc->features = AHC_AIC7892_FE; 226362306a36Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 226462306a36Sopenharmony_ci ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; 226562306a36Sopenharmony_ci ahc->instruction_ram_size = 1024; 226662306a36Sopenharmony_ci return (0); 226762306a36Sopenharmony_ci} 226862306a36Sopenharmony_ci 226962306a36Sopenharmony_cistatic int 227062306a36Sopenharmony_ciahc_aic7895_setup(struct ahc_softc *ahc) 227162306a36Sopenharmony_ci{ 227262306a36Sopenharmony_ci ahc_dev_softc_t pci; 227362306a36Sopenharmony_ci uint8_t rev; 227462306a36Sopenharmony_ci 227562306a36Sopenharmony_ci pci = ahc->dev_softc; 227662306a36Sopenharmony_ci ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 227762306a36Sopenharmony_ci /* 227862306a36Sopenharmony_ci * The 'C' revision of the aic7895 has a few additional features. 227962306a36Sopenharmony_ci */ 228062306a36Sopenharmony_ci rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 228162306a36Sopenharmony_ci if (rev >= 4) { 228262306a36Sopenharmony_ci ahc->chip = AHC_AIC7895C; 228362306a36Sopenharmony_ci ahc->features = AHC_AIC7895C_FE; 228462306a36Sopenharmony_ci } else { 228562306a36Sopenharmony_ci u_int command; 228662306a36Sopenharmony_ci 228762306a36Sopenharmony_ci ahc->chip = AHC_AIC7895; 228862306a36Sopenharmony_ci ahc->features = AHC_AIC7895_FE; 228962306a36Sopenharmony_ci 229062306a36Sopenharmony_ci /* 229162306a36Sopenharmony_ci * The BIOS disables the use of MWI transactions 229262306a36Sopenharmony_ci * since it does not have the MWI bug work around 229362306a36Sopenharmony_ci * we have. Disabling MWI reduces performance, so 229462306a36Sopenharmony_ci * turn it on again. 229562306a36Sopenharmony_ci */ 229662306a36Sopenharmony_ci command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); 229762306a36Sopenharmony_ci command |= PCIM_CMD_MWRICEN; 229862306a36Sopenharmony_ci ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); 229962306a36Sopenharmony_ci ahc->bugs |= AHC_PCI_MWI_BUG; 230062306a36Sopenharmony_ci } 230162306a36Sopenharmony_ci /* 230262306a36Sopenharmony_ci * XXX Does CACHETHEN really not work??? What about PCI retry? 230362306a36Sopenharmony_ci * on C level chips. Need to test, but for now, play it safe. 230462306a36Sopenharmony_ci */ 230562306a36Sopenharmony_ci ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG 230662306a36Sopenharmony_ci | AHC_CACHETHEN_BUG; 230762306a36Sopenharmony_ci 230862306a36Sopenharmony_ci#if 0 230962306a36Sopenharmony_ci uint32_t devconfig; 231062306a36Sopenharmony_ci 231162306a36Sopenharmony_ci /* 231262306a36Sopenharmony_ci * Cachesize must also be zero due to stray DAC 231362306a36Sopenharmony_ci * problem when sitting behind some bridges. 231462306a36Sopenharmony_ci */ 231562306a36Sopenharmony_ci ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); 231662306a36Sopenharmony_ci devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1); 231762306a36Sopenharmony_ci devconfig |= MRDCEN; 231862306a36Sopenharmony_ci ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); 231962306a36Sopenharmony_ci#endif 232062306a36Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 232162306a36Sopenharmony_ci ahc->instruction_ram_size = 512; 232262306a36Sopenharmony_ci return (0); 232362306a36Sopenharmony_ci} 232462306a36Sopenharmony_ci 232562306a36Sopenharmony_cistatic int 232662306a36Sopenharmony_ciahc_aic7895h_setup(struct ahc_softc *ahc) 232762306a36Sopenharmony_ci{ 232862306a36Sopenharmony_ci int error = ahc_aic7895_setup(ahc); 232962306a36Sopenharmony_ci 233062306a36Sopenharmony_ci ahc->features |= AHC_HVD; 233162306a36Sopenharmony_ci 233262306a36Sopenharmony_ci return error; 233362306a36Sopenharmony_ci} 233462306a36Sopenharmony_ci 233562306a36Sopenharmony_cistatic int 233662306a36Sopenharmony_ciahc_aic7896_setup(struct ahc_softc *ahc) 233762306a36Sopenharmony_ci{ 233862306a36Sopenharmony_ci ahc_dev_softc_t pci; 233962306a36Sopenharmony_ci 234062306a36Sopenharmony_ci pci = ahc->dev_softc; 234162306a36Sopenharmony_ci ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 234262306a36Sopenharmony_ci ahc->chip = AHC_AIC7896; 234362306a36Sopenharmony_ci ahc->features = AHC_AIC7896_FE; 234462306a36Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 234562306a36Sopenharmony_ci ahc->bugs |= AHC_CACHETHEN_DIS_BUG; 234662306a36Sopenharmony_ci ahc->instruction_ram_size = 768; 234762306a36Sopenharmony_ci return (0); 234862306a36Sopenharmony_ci} 234962306a36Sopenharmony_ci 235062306a36Sopenharmony_cistatic int 235162306a36Sopenharmony_ciahc_aic7899_setup(struct ahc_softc *ahc) 235262306a36Sopenharmony_ci{ 235362306a36Sopenharmony_ci ahc_dev_softc_t pci; 235462306a36Sopenharmony_ci 235562306a36Sopenharmony_ci pci = ahc->dev_softc; 235662306a36Sopenharmony_ci ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 235762306a36Sopenharmony_ci ahc->chip = AHC_AIC7899; 235862306a36Sopenharmony_ci ahc->features = AHC_AIC7899_FE; 235962306a36Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 236062306a36Sopenharmony_ci ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; 236162306a36Sopenharmony_ci ahc->instruction_ram_size = 1024; 236262306a36Sopenharmony_ci return (0); 236362306a36Sopenharmony_ci} 236462306a36Sopenharmony_ci 236562306a36Sopenharmony_cistatic int 236662306a36Sopenharmony_ciahc_aha29160C_setup(struct ahc_softc *ahc) 236762306a36Sopenharmony_ci{ 236862306a36Sopenharmony_ci int error; 236962306a36Sopenharmony_ci 237062306a36Sopenharmony_ci error = ahc_aic7899_setup(ahc); 237162306a36Sopenharmony_ci if (error != 0) 237262306a36Sopenharmony_ci return (error); 237362306a36Sopenharmony_ci ahc->features |= AHC_REMOVABLE; 237462306a36Sopenharmony_ci return (0); 237562306a36Sopenharmony_ci} 237662306a36Sopenharmony_ci 237762306a36Sopenharmony_cistatic int 237862306a36Sopenharmony_ciahc_raid_setup(struct ahc_softc *ahc) 237962306a36Sopenharmony_ci{ 238062306a36Sopenharmony_ci printk("RAID functionality unsupported\n"); 238162306a36Sopenharmony_ci return (ENXIO); 238262306a36Sopenharmony_ci} 238362306a36Sopenharmony_ci 238462306a36Sopenharmony_cistatic int 238562306a36Sopenharmony_ciahc_aha394XX_setup(struct ahc_softc *ahc) 238662306a36Sopenharmony_ci{ 238762306a36Sopenharmony_ci ahc_dev_softc_t pci; 238862306a36Sopenharmony_ci 238962306a36Sopenharmony_ci pci = ahc->dev_softc; 239062306a36Sopenharmony_ci switch (ahc_get_pci_slot(pci)) { 239162306a36Sopenharmony_ci case AHC_394X_SLOT_CHANNEL_A: 239262306a36Sopenharmony_ci ahc->channel = 'A'; 239362306a36Sopenharmony_ci break; 239462306a36Sopenharmony_ci case AHC_394X_SLOT_CHANNEL_B: 239562306a36Sopenharmony_ci ahc->channel = 'B'; 239662306a36Sopenharmony_ci break; 239762306a36Sopenharmony_ci default: 239862306a36Sopenharmony_ci printk("adapter at unexpected slot %d\n" 239962306a36Sopenharmony_ci "unable to map to a channel\n", 240062306a36Sopenharmony_ci ahc_get_pci_slot(pci)); 240162306a36Sopenharmony_ci ahc->channel = 'A'; 240262306a36Sopenharmony_ci } 240362306a36Sopenharmony_ci return (0); 240462306a36Sopenharmony_ci} 240562306a36Sopenharmony_ci 240662306a36Sopenharmony_cistatic int 240762306a36Sopenharmony_ciahc_aha398XX_setup(struct ahc_softc *ahc) 240862306a36Sopenharmony_ci{ 240962306a36Sopenharmony_ci ahc_dev_softc_t pci; 241062306a36Sopenharmony_ci 241162306a36Sopenharmony_ci pci = ahc->dev_softc; 241262306a36Sopenharmony_ci switch (ahc_get_pci_slot(pci)) { 241362306a36Sopenharmony_ci case AHC_398X_SLOT_CHANNEL_A: 241462306a36Sopenharmony_ci ahc->channel = 'A'; 241562306a36Sopenharmony_ci break; 241662306a36Sopenharmony_ci case AHC_398X_SLOT_CHANNEL_B: 241762306a36Sopenharmony_ci ahc->channel = 'B'; 241862306a36Sopenharmony_ci break; 241962306a36Sopenharmony_ci case AHC_398X_SLOT_CHANNEL_C: 242062306a36Sopenharmony_ci ahc->channel = 'C'; 242162306a36Sopenharmony_ci break; 242262306a36Sopenharmony_ci default: 242362306a36Sopenharmony_ci printk("adapter at unexpected slot %d\n" 242462306a36Sopenharmony_ci "unable to map to a channel\n", 242562306a36Sopenharmony_ci ahc_get_pci_slot(pci)); 242662306a36Sopenharmony_ci ahc->channel = 'A'; 242762306a36Sopenharmony_ci break; 242862306a36Sopenharmony_ci } 242962306a36Sopenharmony_ci ahc->flags |= AHC_LARGE_SEEPROM; 243062306a36Sopenharmony_ci return (0); 243162306a36Sopenharmony_ci} 243262306a36Sopenharmony_ci 243362306a36Sopenharmony_cistatic int 243462306a36Sopenharmony_ciahc_aha494XX_setup(struct ahc_softc *ahc) 243562306a36Sopenharmony_ci{ 243662306a36Sopenharmony_ci ahc_dev_softc_t pci; 243762306a36Sopenharmony_ci 243862306a36Sopenharmony_ci pci = ahc->dev_softc; 243962306a36Sopenharmony_ci switch (ahc_get_pci_slot(pci)) { 244062306a36Sopenharmony_ci case AHC_494X_SLOT_CHANNEL_A: 244162306a36Sopenharmony_ci ahc->channel = 'A'; 244262306a36Sopenharmony_ci break; 244362306a36Sopenharmony_ci case AHC_494X_SLOT_CHANNEL_B: 244462306a36Sopenharmony_ci ahc->channel = 'B'; 244562306a36Sopenharmony_ci break; 244662306a36Sopenharmony_ci case AHC_494X_SLOT_CHANNEL_C: 244762306a36Sopenharmony_ci ahc->channel = 'C'; 244862306a36Sopenharmony_ci break; 244962306a36Sopenharmony_ci case AHC_494X_SLOT_CHANNEL_D: 245062306a36Sopenharmony_ci ahc->channel = 'D'; 245162306a36Sopenharmony_ci break; 245262306a36Sopenharmony_ci default: 245362306a36Sopenharmony_ci printk("adapter at unexpected slot %d\n" 245462306a36Sopenharmony_ci "unable to map to a channel\n", 245562306a36Sopenharmony_ci ahc_get_pci_slot(pci)); 245662306a36Sopenharmony_ci ahc->channel = 'A'; 245762306a36Sopenharmony_ci } 245862306a36Sopenharmony_ci ahc->flags |= AHC_LARGE_SEEPROM; 245962306a36Sopenharmony_ci return (0); 246062306a36Sopenharmony_ci} 2461