18c2ecf20Sopenharmony_ci/* 28c2ecf20Sopenharmony_ci * Product specific probe and attach routines for: 38c2ecf20Sopenharmony_ci * 3940, 2940, aic7895, aic7890, aic7880, 48c2ecf20Sopenharmony_ci * aic7870, aic7860 and aic7850 SCSI controllers 58c2ecf20Sopenharmony_ci * 68c2ecf20Sopenharmony_ci * Copyright (c) 1994-2001 Justin T. Gibbs. 78c2ecf20Sopenharmony_ci * Copyright (c) 2000-2001 Adaptec Inc. 88c2ecf20Sopenharmony_ci * All rights reserved. 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without 118c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions 128c2ecf20Sopenharmony_ci * are met: 138c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright 148c2ecf20Sopenharmony_ci * notice, this list of conditions, and the following disclaimer, 158c2ecf20Sopenharmony_ci * without modification. 168c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer 178c2ecf20Sopenharmony_ci * substantially similar to the "NO WARRANTY" disclaimer below 188c2ecf20Sopenharmony_ci * ("Disclaimer") and any redistribution must be conditioned upon 198c2ecf20Sopenharmony_ci * including a substantially similar Disclaimer requirement for further 208c2ecf20Sopenharmony_ci * binary redistribution. 218c2ecf20Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names 228c2ecf20Sopenharmony_ci * of any contributors may be used to endorse or promote products derived 238c2ecf20Sopenharmony_ci * from this software without specific prior written permission. 248c2ecf20Sopenharmony_ci * 258c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the 268c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free 278c2ecf20Sopenharmony_ci * Software Foundation. 288c2ecf20Sopenharmony_ci * 298c2ecf20Sopenharmony_ci * NO WARRANTY 308c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 318c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 328c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 338c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 348c2ecf20Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 358c2ecf20Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 368c2ecf20Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 378c2ecf20Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 388c2ecf20Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 398c2ecf20Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 408c2ecf20Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES. 418c2ecf20Sopenharmony_ci * 428c2ecf20Sopenharmony_ci * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $ 438c2ecf20Sopenharmony_ci */ 448c2ecf20Sopenharmony_ci 458c2ecf20Sopenharmony_ci#include "aic7xxx_osm.h" 468c2ecf20Sopenharmony_ci#include "aic7xxx_inline.h" 478c2ecf20Sopenharmony_ci#include "aic7xxx_93cx6.h" 488c2ecf20Sopenharmony_ci#include "aic7xxx_pci.h" 498c2ecf20Sopenharmony_ci 508c2ecf20Sopenharmony_cistatic inline uint64_t 518c2ecf20Sopenharmony_ciahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) 528c2ecf20Sopenharmony_ci{ 538c2ecf20Sopenharmony_ci uint64_t id; 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci id = subvendor 568c2ecf20Sopenharmony_ci | (subdevice << 16) 578c2ecf20Sopenharmony_ci | ((uint64_t)vendor << 32) 588c2ecf20Sopenharmony_ci | ((uint64_t)device << 48); 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci return (id); 618c2ecf20Sopenharmony_ci} 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */ 648c2ecf20Sopenharmony_ci#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */ 658c2ecf20Sopenharmony_ci 668c2ecf20Sopenharmony_ci#define DEVID_9005_TYPE(id) ((id) & 0xF) 678c2ecf20Sopenharmony_ci#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ 688c2ecf20Sopenharmony_ci#define DEVID_9005_TYPE_AAA 0x3 /* RAID Card */ 698c2ecf20Sopenharmony_ci#define DEVID_9005_TYPE_SISL 0x5 /* Container ROMB */ 708c2ecf20Sopenharmony_ci#define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_ci#define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4) 738c2ecf20Sopenharmony_ci#define DEVID_9005_MAXRATE_U160 0x0 748c2ecf20Sopenharmony_ci#define DEVID_9005_MAXRATE_ULTRA2 0x1 758c2ecf20Sopenharmony_ci#define DEVID_9005_MAXRATE_ULTRA 0x2 768c2ecf20Sopenharmony_ci#define DEVID_9005_MAXRATE_FAST 0x3 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci#define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6) 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8) 818c2ecf20Sopenharmony_ci#define DEVID_9005_CLASS_SPI 0x0 /* Parallel SCSI */ 828c2ecf20Sopenharmony_ci 838c2ecf20Sopenharmony_ci#define SUBID_9005_TYPE(id) ((id) & 0xF) 848c2ecf20Sopenharmony_ci#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */ 858c2ecf20Sopenharmony_ci#define SUBID_9005_TYPE_CARD 0x0 /* Standard Card */ 868c2ecf20Sopenharmony_ci#define SUBID_9005_TYPE_LCCARD 0x1 /* Low Cost Card */ 878c2ecf20Sopenharmony_ci#define SUBID_9005_TYPE_RAID 0x3 /* Combined with Raid */ 888c2ecf20Sopenharmony_ci 898c2ecf20Sopenharmony_ci#define SUBID_9005_TYPE_KNOWN(id) \ 908c2ecf20Sopenharmony_ci ((((id) & 0xF) == SUBID_9005_TYPE_MB) \ 918c2ecf20Sopenharmony_ci || (((id) & 0xF) == SUBID_9005_TYPE_CARD) \ 928c2ecf20Sopenharmony_ci || (((id) & 0xF) == SUBID_9005_TYPE_LCCARD) \ 938c2ecf20Sopenharmony_ci || (((id) & 0xF) == SUBID_9005_TYPE_RAID)) 948c2ecf20Sopenharmony_ci 958c2ecf20Sopenharmony_ci#define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4) 968c2ecf20Sopenharmony_ci#define SUBID_9005_MAXRATE_ULTRA2 0x0 978c2ecf20Sopenharmony_ci#define SUBID_9005_MAXRATE_ULTRA 0x1 988c2ecf20Sopenharmony_ci#define SUBID_9005_MAXRATE_U160 0x2 998c2ecf20Sopenharmony_ci#define SUBID_9005_MAXRATE_RESERVED 0x3 1008c2ecf20Sopenharmony_ci 1018c2ecf20Sopenharmony_ci#define SUBID_9005_SEEPTYPE(id) \ 1028c2ecf20Sopenharmony_ci ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 1038c2ecf20Sopenharmony_ci ? ((id) & 0xC0) >> 6 \ 1048c2ecf20Sopenharmony_ci : ((id) & 0x300) >> 8) 1058c2ecf20Sopenharmony_ci#define SUBID_9005_SEEPTYPE_NONE 0x0 1068c2ecf20Sopenharmony_ci#define SUBID_9005_SEEPTYPE_1K 0x1 1078c2ecf20Sopenharmony_ci#define SUBID_9005_SEEPTYPE_2K_4K 0x2 1088c2ecf20Sopenharmony_ci#define SUBID_9005_SEEPTYPE_RESERVED 0x3 1098c2ecf20Sopenharmony_ci#define SUBID_9005_AUTOTERM(id) \ 1108c2ecf20Sopenharmony_ci ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 1118c2ecf20Sopenharmony_ci ? (((id) & 0x400) >> 10) == 0 \ 1128c2ecf20Sopenharmony_ci : (((id) & 0x40) >> 6) == 0) 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci#define SUBID_9005_NUMCHAN(id) \ 1158c2ecf20Sopenharmony_ci ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 1168c2ecf20Sopenharmony_ci ? ((id) & 0x300) >> 8 \ 1178c2ecf20Sopenharmony_ci : ((id) & 0xC00) >> 10) 1188c2ecf20Sopenharmony_ci 1198c2ecf20Sopenharmony_ci#define SUBID_9005_LEGACYCONN(id) \ 1208c2ecf20Sopenharmony_ci ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 1218c2ecf20Sopenharmony_ci ? 0 \ 1228c2ecf20Sopenharmony_ci : ((id) & 0x80) >> 7) 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_ci#define SUBID_9005_MFUNCENB(id) \ 1258c2ecf20Sopenharmony_ci ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 1268c2ecf20Sopenharmony_ci ? ((id) & 0x800) >> 11 \ 1278c2ecf20Sopenharmony_ci : ((id) & 0x1000) >> 12) 1288c2ecf20Sopenharmony_ci/* 1298c2ecf20Sopenharmony_ci * Informational only. Should use chip register to be 1308c2ecf20Sopenharmony_ci * certain, but may be use in identification strings. 1318c2ecf20Sopenharmony_ci */ 1328c2ecf20Sopenharmony_ci#define SUBID_9005_CARD_SCSIWIDTH_MASK 0x2000 1338c2ecf20Sopenharmony_ci#define SUBID_9005_CARD_PCIWIDTH_MASK 0x4000 1348c2ecf20Sopenharmony_ci#define SUBID_9005_CARD_SEDIFF_MASK 0x8000 1358c2ecf20Sopenharmony_ci 1368c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic785X_setup; 1378c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7860_setup; 1388c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_apa1480_setup; 1398c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7870_setup; 1408c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7870h_setup; 1418c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha394X_setup; 1428c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha394Xh_setup; 1438c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha494X_setup; 1448c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha494Xh_setup; 1458c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha398X_setup; 1468c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7880_setup; 1478c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7880h_setup; 1488c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha2940Pro_setup; 1498c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha394XU_setup; 1508c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha394XUh_setup; 1518c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha398XU_setup; 1528c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7890_setup; 1538c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7892_setup; 1548c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7895_setup; 1558c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7895h_setup; 1568c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7896_setup; 1578c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aic7899_setup; 1588c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha29160C_setup; 1598c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_raid_setup; 1608c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha394XX_setup; 1618c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha494XX_setup; 1628c2ecf20Sopenharmony_cistatic ahc_device_setup_t ahc_aha398XX_setup; 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_cistatic const struct ahc_pci_identity ahc_pci_ident_table[] = { 1658c2ecf20Sopenharmony_ci /* aic7850 based controllers */ 1668c2ecf20Sopenharmony_ci { 1678c2ecf20Sopenharmony_ci ID_AHA_2902_04_10_15_20C_30C, 1688c2ecf20Sopenharmony_ci ID_ALL_MASK, 1698c2ecf20Sopenharmony_ci "Adaptec 2902/04/10/15/20C/30C SCSI adapter", 1708c2ecf20Sopenharmony_ci ahc_aic785X_setup 1718c2ecf20Sopenharmony_ci }, 1728c2ecf20Sopenharmony_ci /* aic7860 based controllers */ 1738c2ecf20Sopenharmony_ci { 1748c2ecf20Sopenharmony_ci ID_AHA_2930CU, 1758c2ecf20Sopenharmony_ci ID_ALL_MASK, 1768c2ecf20Sopenharmony_ci "Adaptec 2930CU SCSI adapter", 1778c2ecf20Sopenharmony_ci ahc_aic7860_setup 1788c2ecf20Sopenharmony_ci }, 1798c2ecf20Sopenharmony_ci { 1808c2ecf20Sopenharmony_ci ID_AHA_1480A & ID_DEV_VENDOR_MASK, 1818c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 1828c2ecf20Sopenharmony_ci "Adaptec 1480A Ultra SCSI adapter", 1838c2ecf20Sopenharmony_ci ahc_apa1480_setup 1848c2ecf20Sopenharmony_ci }, 1858c2ecf20Sopenharmony_ci { 1868c2ecf20Sopenharmony_ci ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK, 1878c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 1888c2ecf20Sopenharmony_ci "Adaptec 2940A Ultra SCSI adapter", 1898c2ecf20Sopenharmony_ci ahc_aic7860_setup 1908c2ecf20Sopenharmony_ci }, 1918c2ecf20Sopenharmony_ci { 1928c2ecf20Sopenharmony_ci ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK, 1938c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 1948c2ecf20Sopenharmony_ci "Adaptec 2940A/CN Ultra SCSI adapter", 1958c2ecf20Sopenharmony_ci ahc_aic7860_setup 1968c2ecf20Sopenharmony_ci }, 1978c2ecf20Sopenharmony_ci { 1988c2ecf20Sopenharmony_ci ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK, 1998c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 2008c2ecf20Sopenharmony_ci "Adaptec 2930C Ultra SCSI adapter (VAR)", 2018c2ecf20Sopenharmony_ci ahc_aic7860_setup 2028c2ecf20Sopenharmony_ci }, 2038c2ecf20Sopenharmony_ci /* aic7870 based controllers */ 2048c2ecf20Sopenharmony_ci { 2058c2ecf20Sopenharmony_ci ID_AHA_2940, 2068c2ecf20Sopenharmony_ci ID_ALL_MASK, 2078c2ecf20Sopenharmony_ci "Adaptec 2940 SCSI adapter", 2088c2ecf20Sopenharmony_ci ahc_aic7870_setup 2098c2ecf20Sopenharmony_ci }, 2108c2ecf20Sopenharmony_ci { 2118c2ecf20Sopenharmony_ci ID_AHA_3940, 2128c2ecf20Sopenharmony_ci ID_ALL_MASK, 2138c2ecf20Sopenharmony_ci "Adaptec 3940 SCSI adapter", 2148c2ecf20Sopenharmony_ci ahc_aha394X_setup 2158c2ecf20Sopenharmony_ci }, 2168c2ecf20Sopenharmony_ci { 2178c2ecf20Sopenharmony_ci ID_AHA_398X, 2188c2ecf20Sopenharmony_ci ID_ALL_MASK, 2198c2ecf20Sopenharmony_ci "Adaptec 398X SCSI RAID adapter", 2208c2ecf20Sopenharmony_ci ahc_aha398X_setup 2218c2ecf20Sopenharmony_ci }, 2228c2ecf20Sopenharmony_ci { 2238c2ecf20Sopenharmony_ci ID_AHA_2944, 2248c2ecf20Sopenharmony_ci ID_ALL_MASK, 2258c2ecf20Sopenharmony_ci "Adaptec 2944 SCSI adapter", 2268c2ecf20Sopenharmony_ci ahc_aic7870h_setup 2278c2ecf20Sopenharmony_ci }, 2288c2ecf20Sopenharmony_ci { 2298c2ecf20Sopenharmony_ci ID_AHA_3944, 2308c2ecf20Sopenharmony_ci ID_ALL_MASK, 2318c2ecf20Sopenharmony_ci "Adaptec 3944 SCSI adapter", 2328c2ecf20Sopenharmony_ci ahc_aha394Xh_setup 2338c2ecf20Sopenharmony_ci }, 2348c2ecf20Sopenharmony_ci { 2358c2ecf20Sopenharmony_ci ID_AHA_4944, 2368c2ecf20Sopenharmony_ci ID_ALL_MASK, 2378c2ecf20Sopenharmony_ci "Adaptec 4944 SCSI adapter", 2388c2ecf20Sopenharmony_ci ahc_aha494Xh_setup 2398c2ecf20Sopenharmony_ci }, 2408c2ecf20Sopenharmony_ci /* aic7880 based controllers */ 2418c2ecf20Sopenharmony_ci { 2428c2ecf20Sopenharmony_ci ID_AHA_2940U & ID_DEV_VENDOR_MASK, 2438c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 2448c2ecf20Sopenharmony_ci "Adaptec 2940 Ultra SCSI adapter", 2458c2ecf20Sopenharmony_ci ahc_aic7880_setup 2468c2ecf20Sopenharmony_ci }, 2478c2ecf20Sopenharmony_ci { 2488c2ecf20Sopenharmony_ci ID_AHA_3940U & ID_DEV_VENDOR_MASK, 2498c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 2508c2ecf20Sopenharmony_ci "Adaptec 3940 Ultra SCSI adapter", 2518c2ecf20Sopenharmony_ci ahc_aha394XU_setup 2528c2ecf20Sopenharmony_ci }, 2538c2ecf20Sopenharmony_ci { 2548c2ecf20Sopenharmony_ci ID_AHA_2944U & ID_DEV_VENDOR_MASK, 2558c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 2568c2ecf20Sopenharmony_ci "Adaptec 2944 Ultra SCSI adapter", 2578c2ecf20Sopenharmony_ci ahc_aic7880h_setup 2588c2ecf20Sopenharmony_ci }, 2598c2ecf20Sopenharmony_ci { 2608c2ecf20Sopenharmony_ci ID_AHA_3944U & ID_DEV_VENDOR_MASK, 2618c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 2628c2ecf20Sopenharmony_ci "Adaptec 3944 Ultra SCSI adapter", 2638c2ecf20Sopenharmony_ci ahc_aha394XUh_setup 2648c2ecf20Sopenharmony_ci }, 2658c2ecf20Sopenharmony_ci { 2668c2ecf20Sopenharmony_ci ID_AHA_398XU & ID_DEV_VENDOR_MASK, 2678c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 2688c2ecf20Sopenharmony_ci "Adaptec 398X Ultra SCSI RAID adapter", 2698c2ecf20Sopenharmony_ci ahc_aha398XU_setup 2708c2ecf20Sopenharmony_ci }, 2718c2ecf20Sopenharmony_ci { 2728c2ecf20Sopenharmony_ci /* 2738c2ecf20Sopenharmony_ci * XXX Don't know the slot numbers 2748c2ecf20Sopenharmony_ci * so we can't identify channels 2758c2ecf20Sopenharmony_ci */ 2768c2ecf20Sopenharmony_ci ID_AHA_4944U & ID_DEV_VENDOR_MASK, 2778c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 2788c2ecf20Sopenharmony_ci "Adaptec 4944 Ultra SCSI adapter", 2798c2ecf20Sopenharmony_ci ahc_aic7880h_setup 2808c2ecf20Sopenharmony_ci }, 2818c2ecf20Sopenharmony_ci { 2828c2ecf20Sopenharmony_ci ID_AHA_2930U & ID_DEV_VENDOR_MASK, 2838c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 2848c2ecf20Sopenharmony_ci "Adaptec 2930 Ultra SCSI adapter", 2858c2ecf20Sopenharmony_ci ahc_aic7880_setup 2868c2ecf20Sopenharmony_ci }, 2878c2ecf20Sopenharmony_ci { 2888c2ecf20Sopenharmony_ci ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK, 2898c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 2908c2ecf20Sopenharmony_ci "Adaptec 2940 Pro Ultra SCSI adapter", 2918c2ecf20Sopenharmony_ci ahc_aha2940Pro_setup 2928c2ecf20Sopenharmony_ci }, 2938c2ecf20Sopenharmony_ci { 2948c2ecf20Sopenharmony_ci ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK, 2958c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 2968c2ecf20Sopenharmony_ci "Adaptec 2940/CN Ultra SCSI adapter", 2978c2ecf20Sopenharmony_ci ahc_aic7880_setup 2988c2ecf20Sopenharmony_ci }, 2998c2ecf20Sopenharmony_ci /* Ignore all SISL (AAC on MB) based controllers. */ 3008c2ecf20Sopenharmony_ci { 3018c2ecf20Sopenharmony_ci ID_9005_SISL_ID, 3028c2ecf20Sopenharmony_ci ID_9005_SISL_MASK, 3038c2ecf20Sopenharmony_ci NULL, 3048c2ecf20Sopenharmony_ci NULL 3058c2ecf20Sopenharmony_ci }, 3068c2ecf20Sopenharmony_ci /* aic7890 based controllers */ 3078c2ecf20Sopenharmony_ci { 3088c2ecf20Sopenharmony_ci ID_AHA_2930U2, 3098c2ecf20Sopenharmony_ci ID_ALL_MASK, 3108c2ecf20Sopenharmony_ci "Adaptec 2930 Ultra2 SCSI adapter", 3118c2ecf20Sopenharmony_ci ahc_aic7890_setup 3128c2ecf20Sopenharmony_ci }, 3138c2ecf20Sopenharmony_ci { 3148c2ecf20Sopenharmony_ci ID_AHA_2940U2B, 3158c2ecf20Sopenharmony_ci ID_ALL_MASK, 3168c2ecf20Sopenharmony_ci "Adaptec 2940B Ultra2 SCSI adapter", 3178c2ecf20Sopenharmony_ci ahc_aic7890_setup 3188c2ecf20Sopenharmony_ci }, 3198c2ecf20Sopenharmony_ci { 3208c2ecf20Sopenharmony_ci ID_AHA_2940U2_OEM, 3218c2ecf20Sopenharmony_ci ID_ALL_MASK, 3228c2ecf20Sopenharmony_ci "Adaptec 2940 Ultra2 SCSI adapter (OEM)", 3238c2ecf20Sopenharmony_ci ahc_aic7890_setup 3248c2ecf20Sopenharmony_ci }, 3258c2ecf20Sopenharmony_ci { 3268c2ecf20Sopenharmony_ci ID_AHA_2940U2, 3278c2ecf20Sopenharmony_ci ID_ALL_MASK, 3288c2ecf20Sopenharmony_ci "Adaptec 2940 Ultra2 SCSI adapter", 3298c2ecf20Sopenharmony_ci ahc_aic7890_setup 3308c2ecf20Sopenharmony_ci }, 3318c2ecf20Sopenharmony_ci { 3328c2ecf20Sopenharmony_ci ID_AHA_2950U2B, 3338c2ecf20Sopenharmony_ci ID_ALL_MASK, 3348c2ecf20Sopenharmony_ci "Adaptec 2950 Ultra2 SCSI adapter", 3358c2ecf20Sopenharmony_ci ahc_aic7890_setup 3368c2ecf20Sopenharmony_ci }, 3378c2ecf20Sopenharmony_ci { 3388c2ecf20Sopenharmony_ci ID_AIC7890_ARO, 3398c2ecf20Sopenharmony_ci ID_ALL_MASK, 3408c2ecf20Sopenharmony_ci "Adaptec aic7890/91 Ultra2 SCSI adapter (ARO)", 3418c2ecf20Sopenharmony_ci ahc_aic7890_setup 3428c2ecf20Sopenharmony_ci }, 3438c2ecf20Sopenharmony_ci { 3448c2ecf20Sopenharmony_ci ID_AAA_131U2, 3458c2ecf20Sopenharmony_ci ID_ALL_MASK, 3468c2ecf20Sopenharmony_ci "Adaptec AAA-131 Ultra2 RAID adapter", 3478c2ecf20Sopenharmony_ci ahc_aic7890_setup 3488c2ecf20Sopenharmony_ci }, 3498c2ecf20Sopenharmony_ci /* aic7892 based controllers */ 3508c2ecf20Sopenharmony_ci { 3518c2ecf20Sopenharmony_ci ID_AHA_29160, 3528c2ecf20Sopenharmony_ci ID_ALL_MASK, 3538c2ecf20Sopenharmony_ci "Adaptec 29160 Ultra160 SCSI adapter", 3548c2ecf20Sopenharmony_ci ahc_aic7892_setup 3558c2ecf20Sopenharmony_ci }, 3568c2ecf20Sopenharmony_ci { 3578c2ecf20Sopenharmony_ci ID_AHA_29160_CPQ, 3588c2ecf20Sopenharmony_ci ID_ALL_MASK, 3598c2ecf20Sopenharmony_ci "Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter", 3608c2ecf20Sopenharmony_ci ahc_aic7892_setup 3618c2ecf20Sopenharmony_ci }, 3628c2ecf20Sopenharmony_ci { 3638c2ecf20Sopenharmony_ci ID_AHA_29160N, 3648c2ecf20Sopenharmony_ci ID_ALL_MASK, 3658c2ecf20Sopenharmony_ci "Adaptec 29160N Ultra160 SCSI adapter", 3668c2ecf20Sopenharmony_ci ahc_aic7892_setup 3678c2ecf20Sopenharmony_ci }, 3688c2ecf20Sopenharmony_ci { 3698c2ecf20Sopenharmony_ci ID_AHA_29160C, 3708c2ecf20Sopenharmony_ci ID_ALL_MASK, 3718c2ecf20Sopenharmony_ci "Adaptec 29160C Ultra160 SCSI adapter", 3728c2ecf20Sopenharmony_ci ahc_aha29160C_setup 3738c2ecf20Sopenharmony_ci }, 3748c2ecf20Sopenharmony_ci { 3758c2ecf20Sopenharmony_ci ID_AHA_29160B, 3768c2ecf20Sopenharmony_ci ID_ALL_MASK, 3778c2ecf20Sopenharmony_ci "Adaptec 29160B Ultra160 SCSI adapter", 3788c2ecf20Sopenharmony_ci ahc_aic7892_setup 3798c2ecf20Sopenharmony_ci }, 3808c2ecf20Sopenharmony_ci { 3818c2ecf20Sopenharmony_ci ID_AHA_19160B, 3828c2ecf20Sopenharmony_ci ID_ALL_MASK, 3838c2ecf20Sopenharmony_ci "Adaptec 19160B Ultra160 SCSI adapter", 3848c2ecf20Sopenharmony_ci ahc_aic7892_setup 3858c2ecf20Sopenharmony_ci }, 3868c2ecf20Sopenharmony_ci { 3878c2ecf20Sopenharmony_ci ID_AIC7892_ARO, 3888c2ecf20Sopenharmony_ci ID_ALL_MASK, 3898c2ecf20Sopenharmony_ci "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", 3908c2ecf20Sopenharmony_ci ahc_aic7892_setup 3918c2ecf20Sopenharmony_ci }, 3928c2ecf20Sopenharmony_ci { 3938c2ecf20Sopenharmony_ci ID_AHA_2915_30LP, 3948c2ecf20Sopenharmony_ci ID_ALL_MASK, 3958c2ecf20Sopenharmony_ci "Adaptec 2915/30LP Ultra160 SCSI adapter", 3968c2ecf20Sopenharmony_ci ahc_aic7892_setup 3978c2ecf20Sopenharmony_ci }, 3988c2ecf20Sopenharmony_ci /* aic7895 based controllers */ 3998c2ecf20Sopenharmony_ci { 4008c2ecf20Sopenharmony_ci ID_AHA_2940U_DUAL, 4018c2ecf20Sopenharmony_ci ID_ALL_MASK, 4028c2ecf20Sopenharmony_ci "Adaptec 2940/DUAL Ultra SCSI adapter", 4038c2ecf20Sopenharmony_ci ahc_aic7895_setup 4048c2ecf20Sopenharmony_ci }, 4058c2ecf20Sopenharmony_ci { 4068c2ecf20Sopenharmony_ci ID_AHA_3940AU, 4078c2ecf20Sopenharmony_ci ID_ALL_MASK, 4088c2ecf20Sopenharmony_ci "Adaptec 3940A Ultra SCSI adapter", 4098c2ecf20Sopenharmony_ci ahc_aic7895_setup 4108c2ecf20Sopenharmony_ci }, 4118c2ecf20Sopenharmony_ci { 4128c2ecf20Sopenharmony_ci ID_AHA_3944AU, 4138c2ecf20Sopenharmony_ci ID_ALL_MASK, 4148c2ecf20Sopenharmony_ci "Adaptec 3944A Ultra SCSI adapter", 4158c2ecf20Sopenharmony_ci ahc_aic7895h_setup 4168c2ecf20Sopenharmony_ci }, 4178c2ecf20Sopenharmony_ci { 4188c2ecf20Sopenharmony_ci ID_AIC7895_ARO, 4198c2ecf20Sopenharmony_ci ID_AIC7895_ARO_MASK, 4208c2ecf20Sopenharmony_ci "Adaptec aic7895 Ultra SCSI adapter (ARO)", 4218c2ecf20Sopenharmony_ci ahc_aic7895_setup 4228c2ecf20Sopenharmony_ci }, 4238c2ecf20Sopenharmony_ci /* aic7896/97 based controllers */ 4248c2ecf20Sopenharmony_ci { 4258c2ecf20Sopenharmony_ci ID_AHA_3950U2B_0, 4268c2ecf20Sopenharmony_ci ID_ALL_MASK, 4278c2ecf20Sopenharmony_ci "Adaptec 3950B Ultra2 SCSI adapter", 4288c2ecf20Sopenharmony_ci ahc_aic7896_setup 4298c2ecf20Sopenharmony_ci }, 4308c2ecf20Sopenharmony_ci { 4318c2ecf20Sopenharmony_ci ID_AHA_3950U2B_1, 4328c2ecf20Sopenharmony_ci ID_ALL_MASK, 4338c2ecf20Sopenharmony_ci "Adaptec 3950B Ultra2 SCSI adapter", 4348c2ecf20Sopenharmony_ci ahc_aic7896_setup 4358c2ecf20Sopenharmony_ci }, 4368c2ecf20Sopenharmony_ci { 4378c2ecf20Sopenharmony_ci ID_AHA_3950U2D_0, 4388c2ecf20Sopenharmony_ci ID_ALL_MASK, 4398c2ecf20Sopenharmony_ci "Adaptec 3950D Ultra2 SCSI adapter", 4408c2ecf20Sopenharmony_ci ahc_aic7896_setup 4418c2ecf20Sopenharmony_ci }, 4428c2ecf20Sopenharmony_ci { 4438c2ecf20Sopenharmony_ci ID_AHA_3950U2D_1, 4448c2ecf20Sopenharmony_ci ID_ALL_MASK, 4458c2ecf20Sopenharmony_ci "Adaptec 3950D Ultra2 SCSI adapter", 4468c2ecf20Sopenharmony_ci ahc_aic7896_setup 4478c2ecf20Sopenharmony_ci }, 4488c2ecf20Sopenharmony_ci { 4498c2ecf20Sopenharmony_ci ID_AIC7896_ARO, 4508c2ecf20Sopenharmony_ci ID_ALL_MASK, 4518c2ecf20Sopenharmony_ci "Adaptec aic7896/97 Ultra2 SCSI adapter (ARO)", 4528c2ecf20Sopenharmony_ci ahc_aic7896_setup 4538c2ecf20Sopenharmony_ci }, 4548c2ecf20Sopenharmony_ci /* aic7899 based controllers */ 4558c2ecf20Sopenharmony_ci { 4568c2ecf20Sopenharmony_ci ID_AHA_3960D, 4578c2ecf20Sopenharmony_ci ID_ALL_MASK, 4588c2ecf20Sopenharmony_ci "Adaptec 3960D Ultra160 SCSI adapter", 4598c2ecf20Sopenharmony_ci ahc_aic7899_setup 4608c2ecf20Sopenharmony_ci }, 4618c2ecf20Sopenharmony_ci { 4628c2ecf20Sopenharmony_ci ID_AHA_3960D_CPQ, 4638c2ecf20Sopenharmony_ci ID_ALL_MASK, 4648c2ecf20Sopenharmony_ci "Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter", 4658c2ecf20Sopenharmony_ci ahc_aic7899_setup 4668c2ecf20Sopenharmony_ci }, 4678c2ecf20Sopenharmony_ci { 4688c2ecf20Sopenharmony_ci ID_AIC7899_ARO, 4698c2ecf20Sopenharmony_ci ID_ALL_MASK, 4708c2ecf20Sopenharmony_ci "Adaptec aic7899 Ultra160 SCSI adapter (ARO)", 4718c2ecf20Sopenharmony_ci ahc_aic7899_setup 4728c2ecf20Sopenharmony_ci }, 4738c2ecf20Sopenharmony_ci /* Generic chip probes for devices we don't know 'exactly' */ 4748c2ecf20Sopenharmony_ci { 4758c2ecf20Sopenharmony_ci ID_AIC7850 & ID_DEV_VENDOR_MASK, 4768c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 4778c2ecf20Sopenharmony_ci "Adaptec aic7850 SCSI adapter", 4788c2ecf20Sopenharmony_ci ahc_aic785X_setup 4798c2ecf20Sopenharmony_ci }, 4808c2ecf20Sopenharmony_ci { 4818c2ecf20Sopenharmony_ci ID_AIC7855 & ID_DEV_VENDOR_MASK, 4828c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 4838c2ecf20Sopenharmony_ci "Adaptec aic7855 SCSI adapter", 4848c2ecf20Sopenharmony_ci ahc_aic785X_setup 4858c2ecf20Sopenharmony_ci }, 4868c2ecf20Sopenharmony_ci { 4878c2ecf20Sopenharmony_ci ID_AIC7859 & ID_DEV_VENDOR_MASK, 4888c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 4898c2ecf20Sopenharmony_ci "Adaptec aic7859 SCSI adapter", 4908c2ecf20Sopenharmony_ci ahc_aic7860_setup 4918c2ecf20Sopenharmony_ci }, 4928c2ecf20Sopenharmony_ci { 4938c2ecf20Sopenharmony_ci ID_AIC7860 & ID_DEV_VENDOR_MASK, 4948c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 4958c2ecf20Sopenharmony_ci "Adaptec aic7860 Ultra SCSI adapter", 4968c2ecf20Sopenharmony_ci ahc_aic7860_setup 4978c2ecf20Sopenharmony_ci }, 4988c2ecf20Sopenharmony_ci { 4998c2ecf20Sopenharmony_ci ID_AIC7870 & ID_DEV_VENDOR_MASK, 5008c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 5018c2ecf20Sopenharmony_ci "Adaptec aic7870 SCSI adapter", 5028c2ecf20Sopenharmony_ci ahc_aic7870_setup 5038c2ecf20Sopenharmony_ci }, 5048c2ecf20Sopenharmony_ci { 5058c2ecf20Sopenharmony_ci ID_AIC7880 & ID_DEV_VENDOR_MASK, 5068c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 5078c2ecf20Sopenharmony_ci "Adaptec aic7880 Ultra SCSI adapter", 5088c2ecf20Sopenharmony_ci ahc_aic7880_setup 5098c2ecf20Sopenharmony_ci }, 5108c2ecf20Sopenharmony_ci { 5118c2ecf20Sopenharmony_ci ID_AIC7890 & ID_9005_GENERIC_MASK, 5128c2ecf20Sopenharmony_ci ID_9005_GENERIC_MASK, 5138c2ecf20Sopenharmony_ci "Adaptec aic7890/91 Ultra2 SCSI adapter", 5148c2ecf20Sopenharmony_ci ahc_aic7890_setup 5158c2ecf20Sopenharmony_ci }, 5168c2ecf20Sopenharmony_ci { 5178c2ecf20Sopenharmony_ci ID_AIC7892 & ID_9005_GENERIC_MASK, 5188c2ecf20Sopenharmony_ci ID_9005_GENERIC_MASK, 5198c2ecf20Sopenharmony_ci "Adaptec aic7892 Ultra160 SCSI adapter", 5208c2ecf20Sopenharmony_ci ahc_aic7892_setup 5218c2ecf20Sopenharmony_ci }, 5228c2ecf20Sopenharmony_ci { 5238c2ecf20Sopenharmony_ci ID_AIC7895 & ID_DEV_VENDOR_MASK, 5248c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 5258c2ecf20Sopenharmony_ci "Adaptec aic7895 Ultra SCSI adapter", 5268c2ecf20Sopenharmony_ci ahc_aic7895_setup 5278c2ecf20Sopenharmony_ci }, 5288c2ecf20Sopenharmony_ci { 5298c2ecf20Sopenharmony_ci ID_AIC7896 & ID_9005_GENERIC_MASK, 5308c2ecf20Sopenharmony_ci ID_9005_GENERIC_MASK, 5318c2ecf20Sopenharmony_ci "Adaptec aic7896/97 Ultra2 SCSI adapter", 5328c2ecf20Sopenharmony_ci ahc_aic7896_setup 5338c2ecf20Sopenharmony_ci }, 5348c2ecf20Sopenharmony_ci { 5358c2ecf20Sopenharmony_ci ID_AIC7899 & ID_9005_GENERIC_MASK, 5368c2ecf20Sopenharmony_ci ID_9005_GENERIC_MASK, 5378c2ecf20Sopenharmony_ci "Adaptec aic7899 Ultra160 SCSI adapter", 5388c2ecf20Sopenharmony_ci ahc_aic7899_setup 5398c2ecf20Sopenharmony_ci }, 5408c2ecf20Sopenharmony_ci { 5418c2ecf20Sopenharmony_ci ID_AIC7810 & ID_DEV_VENDOR_MASK, 5428c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 5438c2ecf20Sopenharmony_ci "Adaptec aic7810 RAID memory controller", 5448c2ecf20Sopenharmony_ci ahc_raid_setup 5458c2ecf20Sopenharmony_ci }, 5468c2ecf20Sopenharmony_ci { 5478c2ecf20Sopenharmony_ci ID_AIC7815 & ID_DEV_VENDOR_MASK, 5488c2ecf20Sopenharmony_ci ID_DEV_VENDOR_MASK, 5498c2ecf20Sopenharmony_ci "Adaptec aic7815 RAID memory controller", 5508c2ecf20Sopenharmony_ci ahc_raid_setup 5518c2ecf20Sopenharmony_ci } 5528c2ecf20Sopenharmony_ci}; 5538c2ecf20Sopenharmony_ci 5548c2ecf20Sopenharmony_cistatic const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table); 5558c2ecf20Sopenharmony_ci 5568c2ecf20Sopenharmony_ci#define AHC_394X_SLOT_CHANNEL_A 4 5578c2ecf20Sopenharmony_ci#define AHC_394X_SLOT_CHANNEL_B 5 5588c2ecf20Sopenharmony_ci 5598c2ecf20Sopenharmony_ci#define AHC_398X_SLOT_CHANNEL_A 4 5608c2ecf20Sopenharmony_ci#define AHC_398X_SLOT_CHANNEL_B 8 5618c2ecf20Sopenharmony_ci#define AHC_398X_SLOT_CHANNEL_C 12 5628c2ecf20Sopenharmony_ci 5638c2ecf20Sopenharmony_ci#define AHC_494X_SLOT_CHANNEL_A 4 5648c2ecf20Sopenharmony_ci#define AHC_494X_SLOT_CHANNEL_B 5 5658c2ecf20Sopenharmony_ci#define AHC_494X_SLOT_CHANNEL_C 6 5668c2ecf20Sopenharmony_ci#define AHC_494X_SLOT_CHANNEL_D 7 5678c2ecf20Sopenharmony_ci 5688c2ecf20Sopenharmony_ci#define DEVCONFIG 0x40 5698c2ecf20Sopenharmony_ci#define PCIERRGENDIS 0x80000000ul 5708c2ecf20Sopenharmony_ci#define SCBSIZE32 0x00010000ul /* aic789X only */ 5718c2ecf20Sopenharmony_ci#define REXTVALID 0x00001000ul /* ultra cards only */ 5728c2ecf20Sopenharmony_ci#define MPORTMODE 0x00000400ul /* aic7870+ only */ 5738c2ecf20Sopenharmony_ci#define RAMPSM 0x00000200ul /* aic7870+ only */ 5748c2ecf20Sopenharmony_ci#define VOLSENSE 0x00000100ul 5758c2ecf20Sopenharmony_ci#define PCI64BIT 0x00000080ul /* 64Bit PCI bus (Ultra2 Only)*/ 5768c2ecf20Sopenharmony_ci#define SCBRAMSEL 0x00000080ul 5778c2ecf20Sopenharmony_ci#define MRDCEN 0x00000040ul 5788c2ecf20Sopenharmony_ci#define EXTSCBTIME 0x00000020ul /* aic7870 only */ 5798c2ecf20Sopenharmony_ci#define EXTSCBPEN 0x00000010ul /* aic7870 only */ 5808c2ecf20Sopenharmony_ci#define BERREN 0x00000008ul 5818c2ecf20Sopenharmony_ci#define DACEN 0x00000004ul 5828c2ecf20Sopenharmony_ci#define STPWLEVEL 0x00000002ul 5838c2ecf20Sopenharmony_ci#define DIFACTNEGEN 0x00000001ul /* aic7870 only */ 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci#define CSIZE_LATTIME 0x0c 5868c2ecf20Sopenharmony_ci#define CACHESIZE 0x0000003ful /* only 5 bits */ 5878c2ecf20Sopenharmony_ci#define LATTIME 0x0000ff00ul 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci/* PCI STATUS definitions */ 5908c2ecf20Sopenharmony_ci#define DPE 0x80 5918c2ecf20Sopenharmony_ci#define SSE 0x40 5928c2ecf20Sopenharmony_ci#define RMA 0x20 5938c2ecf20Sopenharmony_ci#define RTA 0x10 5948c2ecf20Sopenharmony_ci#define STA 0x08 5958c2ecf20Sopenharmony_ci#define DPR 0x01 5968c2ecf20Sopenharmony_ci 5978c2ecf20Sopenharmony_cistatic int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, 5988c2ecf20Sopenharmony_ci uint16_t subdevice, uint16_t subvendor); 5998c2ecf20Sopenharmony_cistatic int ahc_ext_scbram_present(struct ahc_softc *ahc); 6008c2ecf20Sopenharmony_cistatic void ahc_scbram_config(struct ahc_softc *ahc, int enable, 6018c2ecf20Sopenharmony_ci int pcheck, int fast, int large); 6028c2ecf20Sopenharmony_cistatic void ahc_probe_ext_scbram(struct ahc_softc *ahc); 6038c2ecf20Sopenharmony_cistatic void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1); 6048c2ecf20Sopenharmony_cistatic void ahc_parse_pci_eeprom(struct ahc_softc *ahc, 6058c2ecf20Sopenharmony_ci struct seeprom_config *sc); 6068c2ecf20Sopenharmony_cistatic void configure_termination(struct ahc_softc *ahc, 6078c2ecf20Sopenharmony_ci struct seeprom_descriptor *sd, 6088c2ecf20Sopenharmony_ci u_int adapter_control, 6098c2ecf20Sopenharmony_ci u_int *sxfrctl1); 6108c2ecf20Sopenharmony_ci 6118c2ecf20Sopenharmony_cistatic void ahc_new_term_detect(struct ahc_softc *ahc, 6128c2ecf20Sopenharmony_ci int *enableSEC_low, 6138c2ecf20Sopenharmony_ci int *enableSEC_high, 6148c2ecf20Sopenharmony_ci int *enablePRI_low, 6158c2ecf20Sopenharmony_ci int *enablePRI_high, 6168c2ecf20Sopenharmony_ci int *eeprom_present); 6178c2ecf20Sopenharmony_cistatic void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 6188c2ecf20Sopenharmony_ci int *internal68_present, 6198c2ecf20Sopenharmony_ci int *externalcable_present, 6208c2ecf20Sopenharmony_ci int *eeprom_present); 6218c2ecf20Sopenharmony_cistatic void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 6228c2ecf20Sopenharmony_ci int *externalcable_present, 6238c2ecf20Sopenharmony_ci int *eeprom_present); 6248c2ecf20Sopenharmony_cistatic void write_brdctl(struct ahc_softc *ahc, uint8_t value); 6258c2ecf20Sopenharmony_cistatic uint8_t read_brdctl(struct ahc_softc *ahc); 6268c2ecf20Sopenharmony_cistatic void ahc_pci_intr(struct ahc_softc *ahc); 6278c2ecf20Sopenharmony_cistatic int ahc_pci_chip_init(struct ahc_softc *ahc); 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_cistatic int 6308c2ecf20Sopenharmony_ciahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, 6318c2ecf20Sopenharmony_ci uint16_t subdevice, uint16_t subvendor) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci int result; 6348c2ecf20Sopenharmony_ci 6358c2ecf20Sopenharmony_ci /* Default to invalid. */ 6368c2ecf20Sopenharmony_ci result = 0; 6378c2ecf20Sopenharmony_ci if (vendor == 0x9005 6388c2ecf20Sopenharmony_ci && subvendor == 0x9005 6398c2ecf20Sopenharmony_ci && subdevice != device 6408c2ecf20Sopenharmony_ci && SUBID_9005_TYPE_KNOWN(subdevice) != 0) { 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci switch (SUBID_9005_TYPE(subdevice)) { 6438c2ecf20Sopenharmony_ci case SUBID_9005_TYPE_MB: 6448c2ecf20Sopenharmony_ci break; 6458c2ecf20Sopenharmony_ci case SUBID_9005_TYPE_CARD: 6468c2ecf20Sopenharmony_ci case SUBID_9005_TYPE_LCCARD: 6478c2ecf20Sopenharmony_ci /* 6488c2ecf20Sopenharmony_ci * Currently only trust Adaptec cards to 6498c2ecf20Sopenharmony_ci * get the sub device info correct. 6508c2ecf20Sopenharmony_ci */ 6518c2ecf20Sopenharmony_ci if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA) 6528c2ecf20Sopenharmony_ci result = 1; 6538c2ecf20Sopenharmony_ci break; 6548c2ecf20Sopenharmony_ci case SUBID_9005_TYPE_RAID: 6558c2ecf20Sopenharmony_ci break; 6568c2ecf20Sopenharmony_ci default: 6578c2ecf20Sopenharmony_ci break; 6588c2ecf20Sopenharmony_ci } 6598c2ecf20Sopenharmony_ci } 6608c2ecf20Sopenharmony_ci return (result); 6618c2ecf20Sopenharmony_ci} 6628c2ecf20Sopenharmony_ci 6638c2ecf20Sopenharmony_ciconst struct ahc_pci_identity * 6648c2ecf20Sopenharmony_ciahc_find_pci_device(ahc_dev_softc_t pci) 6658c2ecf20Sopenharmony_ci{ 6668c2ecf20Sopenharmony_ci uint64_t full_id; 6678c2ecf20Sopenharmony_ci uint16_t device; 6688c2ecf20Sopenharmony_ci uint16_t vendor; 6698c2ecf20Sopenharmony_ci uint16_t subdevice; 6708c2ecf20Sopenharmony_ci uint16_t subvendor; 6718c2ecf20Sopenharmony_ci const struct ahc_pci_identity *entry; 6728c2ecf20Sopenharmony_ci u_int i; 6738c2ecf20Sopenharmony_ci 6748c2ecf20Sopenharmony_ci vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); 6758c2ecf20Sopenharmony_ci device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); 6768c2ecf20Sopenharmony_ci subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); 6778c2ecf20Sopenharmony_ci subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); 6788c2ecf20Sopenharmony_ci full_id = ahc_compose_id(device, vendor, subdevice, subvendor); 6798c2ecf20Sopenharmony_ci 6808c2ecf20Sopenharmony_ci /* 6818c2ecf20Sopenharmony_ci * If the second function is not hooked up, ignore it. 6828c2ecf20Sopenharmony_ci * Unfortunately, not all MB vendors implement the 6838c2ecf20Sopenharmony_ci * subdevice ID as per the Adaptec spec, so do our best 6848c2ecf20Sopenharmony_ci * to sanity check it prior to accepting the subdevice 6858c2ecf20Sopenharmony_ci * ID as valid. 6868c2ecf20Sopenharmony_ci */ 6878c2ecf20Sopenharmony_ci if (ahc_get_pci_function(pci) > 0 6888c2ecf20Sopenharmony_ci && ahc_9005_subdevinfo_valid(device, vendor, subdevice, subvendor) 6898c2ecf20Sopenharmony_ci && SUBID_9005_MFUNCENB(subdevice) == 0) 6908c2ecf20Sopenharmony_ci return (NULL); 6918c2ecf20Sopenharmony_ci 6928c2ecf20Sopenharmony_ci for (i = 0; i < ahc_num_pci_devs; i++) { 6938c2ecf20Sopenharmony_ci entry = &ahc_pci_ident_table[i]; 6948c2ecf20Sopenharmony_ci if (entry->full_id == (full_id & entry->id_mask)) { 6958c2ecf20Sopenharmony_ci /* Honor exclusion entries. */ 6968c2ecf20Sopenharmony_ci if (entry->name == NULL) 6978c2ecf20Sopenharmony_ci return (NULL); 6988c2ecf20Sopenharmony_ci return (entry); 6998c2ecf20Sopenharmony_ci } 7008c2ecf20Sopenharmony_ci } 7018c2ecf20Sopenharmony_ci return (NULL); 7028c2ecf20Sopenharmony_ci} 7038c2ecf20Sopenharmony_ci 7048c2ecf20Sopenharmony_ciint 7058c2ecf20Sopenharmony_ciahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry) 7068c2ecf20Sopenharmony_ci{ 7078c2ecf20Sopenharmony_ci u_int command; 7088c2ecf20Sopenharmony_ci u_int our_id; 7098c2ecf20Sopenharmony_ci u_int sxfrctl1; 7108c2ecf20Sopenharmony_ci u_int scsiseq; 7118c2ecf20Sopenharmony_ci u_int dscommand0; 7128c2ecf20Sopenharmony_ci uint32_t devconfig; 7138c2ecf20Sopenharmony_ci int error; 7148c2ecf20Sopenharmony_ci uint8_t sblkctl; 7158c2ecf20Sopenharmony_ci 7168c2ecf20Sopenharmony_ci our_id = 0; 7178c2ecf20Sopenharmony_ci error = entry->setup(ahc); 7188c2ecf20Sopenharmony_ci if (error != 0) 7198c2ecf20Sopenharmony_ci return (error); 7208c2ecf20Sopenharmony_ci ahc->chip |= AHC_PCI; 7218c2ecf20Sopenharmony_ci ahc->description = entry->name; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0); 7248c2ecf20Sopenharmony_ci 7258c2ecf20Sopenharmony_ci error = ahc_pci_map_registers(ahc); 7268c2ecf20Sopenharmony_ci if (error != 0) 7278c2ecf20Sopenharmony_ci return (error); 7288c2ecf20Sopenharmony_ci 7298c2ecf20Sopenharmony_ci /* 7308c2ecf20Sopenharmony_ci * Before we continue probing the card, ensure that 7318c2ecf20Sopenharmony_ci * its interrupts are *disabled*. We don't want 7328c2ecf20Sopenharmony_ci * a misstep to hang the machine in an interrupt 7338c2ecf20Sopenharmony_ci * storm. 7348c2ecf20Sopenharmony_ci */ 7358c2ecf20Sopenharmony_ci ahc_intr_enable(ahc, FALSE); 7368c2ecf20Sopenharmony_ci 7378c2ecf20Sopenharmony_ci devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 7388c2ecf20Sopenharmony_ci 7398c2ecf20Sopenharmony_ci /* 7408c2ecf20Sopenharmony_ci * If we need to support high memory, enable dual 7418c2ecf20Sopenharmony_ci * address cycles. This bit must be set to enable 7428c2ecf20Sopenharmony_ci * high address bit generation even if we are on a 7438c2ecf20Sopenharmony_ci * 64bit bus (PCI64BIT set in devconfig). 7448c2ecf20Sopenharmony_ci */ 7458c2ecf20Sopenharmony_ci if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 7468c2ecf20Sopenharmony_ci 7478c2ecf20Sopenharmony_ci if (bootverbose) 7488c2ecf20Sopenharmony_ci printk("%s: Enabling 39Bit Addressing\n", 7498c2ecf20Sopenharmony_ci ahc_name(ahc)); 7508c2ecf20Sopenharmony_ci devconfig |= DACEN; 7518c2ecf20Sopenharmony_ci } 7528c2ecf20Sopenharmony_ci 7538c2ecf20Sopenharmony_ci /* Ensure that pci error generation, a test feature, is disabled. */ 7548c2ecf20Sopenharmony_ci devconfig |= PCIERRGENDIS; 7558c2ecf20Sopenharmony_ci 7568c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 7578c2ecf20Sopenharmony_ci 7588c2ecf20Sopenharmony_ci /* Ensure busmastering is enabled */ 7598c2ecf20Sopenharmony_ci command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); 7608c2ecf20Sopenharmony_ci command |= PCIM_CMD_BUSMASTEREN; 7618c2ecf20Sopenharmony_ci 7628c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci /* On all PCI adapters, we allow SCB paging */ 7658c2ecf20Sopenharmony_ci ahc->flags |= AHC_PAGESCBS; 7668c2ecf20Sopenharmony_ci 7678c2ecf20Sopenharmony_ci error = ahc_softc_init(ahc); 7688c2ecf20Sopenharmony_ci if (error != 0) 7698c2ecf20Sopenharmony_ci return (error); 7708c2ecf20Sopenharmony_ci 7718c2ecf20Sopenharmony_ci /* 7728c2ecf20Sopenharmony_ci * Disable PCI parity error checking. Users typically 7738c2ecf20Sopenharmony_ci * do this to work around broken PCI chipsets that get 7748c2ecf20Sopenharmony_ci * the parity timing wrong and thus generate lots of spurious 7758c2ecf20Sopenharmony_ci * errors. The chip only allows us to disable *all* parity 7768c2ecf20Sopenharmony_ci * error reporting when doing this, so CIO bus, scb ram, and 7778c2ecf20Sopenharmony_ci * scratch ram parity errors will be ignored too. 7788c2ecf20Sopenharmony_ci */ 7798c2ecf20Sopenharmony_ci if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0) 7808c2ecf20Sopenharmony_ci ahc->seqctl |= FAILDIS; 7818c2ecf20Sopenharmony_ci 7828c2ecf20Sopenharmony_ci ahc->bus_intr = ahc_pci_intr; 7838c2ecf20Sopenharmony_ci ahc->bus_chip_init = ahc_pci_chip_init; 7848c2ecf20Sopenharmony_ci 7858c2ecf20Sopenharmony_ci /* Remember how the card was setup in case there is no SEEPROM */ 7868c2ecf20Sopenharmony_ci if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { 7878c2ecf20Sopenharmony_ci ahc_pause(ahc); 7888c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 7898c2ecf20Sopenharmony_ci our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID; 7908c2ecf20Sopenharmony_ci else 7918c2ecf20Sopenharmony_ci our_id = ahc_inb(ahc, SCSIID) & OID; 7928c2ecf20Sopenharmony_ci sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN; 7938c2ecf20Sopenharmony_ci scsiseq = ahc_inb(ahc, SCSISEQ); 7948c2ecf20Sopenharmony_ci } else { 7958c2ecf20Sopenharmony_ci sxfrctl1 = STPWEN; 7968c2ecf20Sopenharmony_ci our_id = 7; 7978c2ecf20Sopenharmony_ci scsiseq = 0; 7988c2ecf20Sopenharmony_ci } 7998c2ecf20Sopenharmony_ci 8008c2ecf20Sopenharmony_ci error = ahc_reset(ahc, /*reinit*/FALSE); 8018c2ecf20Sopenharmony_ci if (error != 0) 8028c2ecf20Sopenharmony_ci return (ENXIO); 8038c2ecf20Sopenharmony_ci 8048c2ecf20Sopenharmony_ci if ((ahc->features & AHC_DT) != 0) { 8058c2ecf20Sopenharmony_ci u_int sfunct; 8068c2ecf20Sopenharmony_ci 8078c2ecf20Sopenharmony_ci /* Perform ALT-Mode Setup */ 8088c2ecf20Sopenharmony_ci sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 8098c2ecf20Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 8108c2ecf20Sopenharmony_ci ahc_outb(ahc, OPTIONMODE, 8118c2ecf20Sopenharmony_ci OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS); 8128c2ecf20Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct); 8138c2ecf20Sopenharmony_ci 8148c2ecf20Sopenharmony_ci /* Normal mode setup */ 8158c2ecf20Sopenharmony_ci ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN 8168c2ecf20Sopenharmony_ci |TARGCRCENDEN); 8178c2ecf20Sopenharmony_ci } 8188c2ecf20Sopenharmony_ci 8198c2ecf20Sopenharmony_ci dscommand0 = ahc_inb(ahc, DSCOMMAND0); 8208c2ecf20Sopenharmony_ci dscommand0 |= MPARCKEN|CACHETHEN; 8218c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) { 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_ci /* 8248c2ecf20Sopenharmony_ci * DPARCKEN doesn't work correctly on 8258c2ecf20Sopenharmony_ci * some MBs so don't use it. 8268c2ecf20Sopenharmony_ci */ 8278c2ecf20Sopenharmony_ci dscommand0 &= ~DPARCKEN; 8288c2ecf20Sopenharmony_ci } 8298c2ecf20Sopenharmony_ci 8308c2ecf20Sopenharmony_ci /* 8318c2ecf20Sopenharmony_ci * Handle chips that must have cache line 8328c2ecf20Sopenharmony_ci * streaming (dis/en)abled. 8338c2ecf20Sopenharmony_ci */ 8348c2ecf20Sopenharmony_ci if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0) 8358c2ecf20Sopenharmony_ci dscommand0 |= CACHETHEN; 8368c2ecf20Sopenharmony_ci 8378c2ecf20Sopenharmony_ci if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0) 8388c2ecf20Sopenharmony_ci dscommand0 &= ~CACHETHEN; 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_ci ahc_outb(ahc, DSCOMMAND0, dscommand0); 8418c2ecf20Sopenharmony_ci 8428c2ecf20Sopenharmony_ci ahc->pci_cachesize = 8438c2ecf20Sopenharmony_ci ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, 8448c2ecf20Sopenharmony_ci /*bytes*/1) & CACHESIZE; 8458c2ecf20Sopenharmony_ci ahc->pci_cachesize *= 4; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0 8488c2ecf20Sopenharmony_ci && ahc->pci_cachesize == 4) { 8498c2ecf20Sopenharmony_ci 8508c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 8518c2ecf20Sopenharmony_ci 0, /*bytes*/1); 8528c2ecf20Sopenharmony_ci ahc->pci_cachesize = 0; 8538c2ecf20Sopenharmony_ci } 8548c2ecf20Sopenharmony_ci 8558c2ecf20Sopenharmony_ci /* 8568c2ecf20Sopenharmony_ci * We cannot perform ULTRA speeds without the presence 8578c2ecf20Sopenharmony_ci * of the external precision resistor. 8588c2ecf20Sopenharmony_ci */ 8598c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA) != 0) { 8608c2ecf20Sopenharmony_ci uint32_t devconfig; 8618c2ecf20Sopenharmony_ci 8628c2ecf20Sopenharmony_ci devconfig = ahc_pci_read_config(ahc->dev_softc, 8638c2ecf20Sopenharmony_ci DEVCONFIG, /*bytes*/4); 8648c2ecf20Sopenharmony_ci if ((devconfig & REXTVALID) == 0) 8658c2ecf20Sopenharmony_ci ahc->features &= ~AHC_ULTRA; 8668c2ecf20Sopenharmony_ci } 8678c2ecf20Sopenharmony_ci 8688c2ecf20Sopenharmony_ci /* See if we have a SEEPROM and perform auto-term */ 8698c2ecf20Sopenharmony_ci check_extport(ahc, &sxfrctl1); 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ci /* 8728c2ecf20Sopenharmony_ci * Take the LED out of diagnostic mode 8738c2ecf20Sopenharmony_ci */ 8748c2ecf20Sopenharmony_ci sblkctl = ahc_inb(ahc, SBLKCTL); 8758c2ecf20Sopenharmony_ci ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON))); 8768c2ecf20Sopenharmony_ci 8778c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) { 8788c2ecf20Sopenharmony_ci ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX); 8798c2ecf20Sopenharmony_ci } else { 8808c2ecf20Sopenharmony_ci ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100); 8818c2ecf20Sopenharmony_ci } 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci if (ahc->flags & AHC_USEDEFAULTS) { 8848c2ecf20Sopenharmony_ci /* 8858c2ecf20Sopenharmony_ci * PCI Adapter default setup 8868c2ecf20Sopenharmony_ci * Should only be used if the adapter does not have 8878c2ecf20Sopenharmony_ci * a SEEPROM. 8888c2ecf20Sopenharmony_ci */ 8898c2ecf20Sopenharmony_ci /* See if someone else set us up already */ 8908c2ecf20Sopenharmony_ci if ((ahc->flags & AHC_NO_BIOS_INIT) == 0 8918c2ecf20Sopenharmony_ci && scsiseq != 0) { 8928c2ecf20Sopenharmony_ci printk("%s: Using left over BIOS settings\n", 8938c2ecf20Sopenharmony_ci ahc_name(ahc)); 8948c2ecf20Sopenharmony_ci ahc->flags &= ~AHC_USEDEFAULTS; 8958c2ecf20Sopenharmony_ci ahc->flags |= AHC_BIOS_ENABLED; 8968c2ecf20Sopenharmony_ci } else { 8978c2ecf20Sopenharmony_ci /* 8988c2ecf20Sopenharmony_ci * Assume only one connector and always turn 8998c2ecf20Sopenharmony_ci * on termination. 9008c2ecf20Sopenharmony_ci */ 9018c2ecf20Sopenharmony_ci our_id = 0x07; 9028c2ecf20Sopenharmony_ci sxfrctl1 = STPWEN; 9038c2ecf20Sopenharmony_ci } 9048c2ecf20Sopenharmony_ci ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI); 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_ci ahc->our_id = our_id; 9078c2ecf20Sopenharmony_ci } 9088c2ecf20Sopenharmony_ci 9098c2ecf20Sopenharmony_ci /* 9108c2ecf20Sopenharmony_ci * Take a look to see if we have external SRAM. 9118c2ecf20Sopenharmony_ci * We currently do not attempt to use SRAM that is 9128c2ecf20Sopenharmony_ci * shared among multiple controllers. 9138c2ecf20Sopenharmony_ci */ 9148c2ecf20Sopenharmony_ci ahc_probe_ext_scbram(ahc); 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci /* 9178c2ecf20Sopenharmony_ci * Record our termination setting for the 9188c2ecf20Sopenharmony_ci * generic initialization routine. 9198c2ecf20Sopenharmony_ci */ 9208c2ecf20Sopenharmony_ci if ((sxfrctl1 & STPWEN) != 0) 9218c2ecf20Sopenharmony_ci ahc->flags |= AHC_TERM_ENB_A; 9228c2ecf20Sopenharmony_ci 9238c2ecf20Sopenharmony_ci /* 9248c2ecf20Sopenharmony_ci * Save chip register configuration data for chip resets 9258c2ecf20Sopenharmony_ci * that occur during runtime and resume events. 9268c2ecf20Sopenharmony_ci */ 9278c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.devconfig = 9288c2ecf20Sopenharmony_ci ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 9298c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.command = 9308c2ecf20Sopenharmony_ci ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); 9318c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.csize_lattime = 9328c2ecf20Sopenharmony_ci ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1); 9338c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0); 9348c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS); 9358c2ecf20Sopenharmony_ci if ((ahc->features & AHC_DT) != 0) { 9368c2ecf20Sopenharmony_ci u_int sfunct; 9378c2ecf20Sopenharmony_ci 9388c2ecf20Sopenharmony_ci sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 9398c2ecf20Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 9408c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE); 9418c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT); 9428c2ecf20Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct); 9438c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.crccontrol1 = 9448c2ecf20Sopenharmony_ci ahc_inb(ahc, CRCCONTROL1); 9458c2ecf20Sopenharmony_ci } 9468c2ecf20Sopenharmony_ci if ((ahc->features & AHC_MULTI_FUNC) != 0) 9478c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR); 9488c2ecf20Sopenharmony_ci 9498c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 9508c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH); 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci /* Core initialization */ 9538c2ecf20Sopenharmony_ci error = ahc_init(ahc); 9548c2ecf20Sopenharmony_ci if (error != 0) 9558c2ecf20Sopenharmony_ci return (error); 9568c2ecf20Sopenharmony_ci ahc->init_level++; 9578c2ecf20Sopenharmony_ci 9588c2ecf20Sopenharmony_ci /* 9598c2ecf20Sopenharmony_ci * Allow interrupts now that we are completely setup. 9608c2ecf20Sopenharmony_ci */ 9618c2ecf20Sopenharmony_ci return ahc_pci_map_int(ahc); 9628c2ecf20Sopenharmony_ci} 9638c2ecf20Sopenharmony_ci 9648c2ecf20Sopenharmony_ci/* 9658c2ecf20Sopenharmony_ci * Test for the presence of external sram in an 9668c2ecf20Sopenharmony_ci * "unshared" configuration. 9678c2ecf20Sopenharmony_ci */ 9688c2ecf20Sopenharmony_cistatic int 9698c2ecf20Sopenharmony_ciahc_ext_scbram_present(struct ahc_softc *ahc) 9708c2ecf20Sopenharmony_ci{ 9718c2ecf20Sopenharmony_ci u_int chip; 9728c2ecf20Sopenharmony_ci int ramps; 9738c2ecf20Sopenharmony_ci int single_user; 9748c2ecf20Sopenharmony_ci uint32_t devconfig; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci chip = ahc->chip & AHC_CHIPID_MASK; 9778c2ecf20Sopenharmony_ci devconfig = ahc_pci_read_config(ahc->dev_softc, 9788c2ecf20Sopenharmony_ci DEVCONFIG, /*bytes*/4); 9798c2ecf20Sopenharmony_ci single_user = (devconfig & MPORTMODE) != 0; 9808c2ecf20Sopenharmony_ci 9818c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 9828c2ecf20Sopenharmony_ci ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0; 9838c2ecf20Sopenharmony_ci else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C) 9848c2ecf20Sopenharmony_ci /* 9858c2ecf20Sopenharmony_ci * External SCBRAM arbitration is flakey 9868c2ecf20Sopenharmony_ci * on these chips. Unfortunately this means 9878c2ecf20Sopenharmony_ci * we don't use the extra SCB ram space on the 9888c2ecf20Sopenharmony_ci * 3940AUW. 9898c2ecf20Sopenharmony_ci */ 9908c2ecf20Sopenharmony_ci ramps = 0; 9918c2ecf20Sopenharmony_ci else if (chip >= AHC_AIC7870) 9928c2ecf20Sopenharmony_ci ramps = (devconfig & RAMPSM) != 0; 9938c2ecf20Sopenharmony_ci else 9948c2ecf20Sopenharmony_ci ramps = 0; 9958c2ecf20Sopenharmony_ci 9968c2ecf20Sopenharmony_ci if (ramps && single_user) 9978c2ecf20Sopenharmony_ci return (1); 9988c2ecf20Sopenharmony_ci return (0); 9998c2ecf20Sopenharmony_ci} 10008c2ecf20Sopenharmony_ci 10018c2ecf20Sopenharmony_ci/* 10028c2ecf20Sopenharmony_ci * Enable external scbram. 10038c2ecf20Sopenharmony_ci */ 10048c2ecf20Sopenharmony_cistatic void 10058c2ecf20Sopenharmony_ciahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck, 10068c2ecf20Sopenharmony_ci int fast, int large) 10078c2ecf20Sopenharmony_ci{ 10088c2ecf20Sopenharmony_ci uint32_t devconfig; 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_ci if (ahc->features & AHC_MULTI_FUNC) { 10118c2ecf20Sopenharmony_ci /* 10128c2ecf20Sopenharmony_ci * Set the SCB Base addr (highest address bit) 10138c2ecf20Sopenharmony_ci * depending on which channel we are. 10148c2ecf20Sopenharmony_ci */ 10158c2ecf20Sopenharmony_ci ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc)); 10168c2ecf20Sopenharmony_ci } 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci ahc->flags &= ~AHC_LSCBS_ENABLED; 10198c2ecf20Sopenharmony_ci if (large) 10208c2ecf20Sopenharmony_ci ahc->flags |= AHC_LSCBS_ENABLED; 10218c2ecf20Sopenharmony_ci devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 10228c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) { 10238c2ecf20Sopenharmony_ci u_int dscommand0; 10248c2ecf20Sopenharmony_ci 10258c2ecf20Sopenharmony_ci dscommand0 = ahc_inb(ahc, DSCOMMAND0); 10268c2ecf20Sopenharmony_ci if (enable) 10278c2ecf20Sopenharmony_ci dscommand0 &= ~INTSCBRAMSEL; 10288c2ecf20Sopenharmony_ci else 10298c2ecf20Sopenharmony_ci dscommand0 |= INTSCBRAMSEL; 10308c2ecf20Sopenharmony_ci if (large) 10318c2ecf20Sopenharmony_ci dscommand0 &= ~USCBSIZE32; 10328c2ecf20Sopenharmony_ci else 10338c2ecf20Sopenharmony_ci dscommand0 |= USCBSIZE32; 10348c2ecf20Sopenharmony_ci ahc_outb(ahc, DSCOMMAND0, dscommand0); 10358c2ecf20Sopenharmony_ci } else { 10368c2ecf20Sopenharmony_ci if (fast) 10378c2ecf20Sopenharmony_ci devconfig &= ~EXTSCBTIME; 10388c2ecf20Sopenharmony_ci else 10398c2ecf20Sopenharmony_ci devconfig |= EXTSCBTIME; 10408c2ecf20Sopenharmony_ci if (enable) 10418c2ecf20Sopenharmony_ci devconfig &= ~SCBRAMSEL; 10428c2ecf20Sopenharmony_ci else 10438c2ecf20Sopenharmony_ci devconfig |= SCBRAMSEL; 10448c2ecf20Sopenharmony_ci if (large) 10458c2ecf20Sopenharmony_ci devconfig &= ~SCBSIZE32; 10468c2ecf20Sopenharmony_ci else 10478c2ecf20Sopenharmony_ci devconfig |= SCBSIZE32; 10488c2ecf20Sopenharmony_ci } 10498c2ecf20Sopenharmony_ci if (pcheck) 10508c2ecf20Sopenharmony_ci devconfig |= EXTSCBPEN; 10518c2ecf20Sopenharmony_ci else 10528c2ecf20Sopenharmony_ci devconfig &= ~EXTSCBPEN; 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 10558c2ecf20Sopenharmony_ci} 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_ci/* 10588c2ecf20Sopenharmony_ci * Take a look to see if we have external SRAM. 10598c2ecf20Sopenharmony_ci * We currently do not attempt to use SRAM that is 10608c2ecf20Sopenharmony_ci * shared among multiple controllers. 10618c2ecf20Sopenharmony_ci */ 10628c2ecf20Sopenharmony_cistatic void 10638c2ecf20Sopenharmony_ciahc_probe_ext_scbram(struct ahc_softc *ahc) 10648c2ecf20Sopenharmony_ci{ 10658c2ecf20Sopenharmony_ci int num_scbs; 10668c2ecf20Sopenharmony_ci int test_num_scbs; 10678c2ecf20Sopenharmony_ci int enable; 10688c2ecf20Sopenharmony_ci int pcheck; 10698c2ecf20Sopenharmony_ci int fast; 10708c2ecf20Sopenharmony_ci int large; 10718c2ecf20Sopenharmony_ci 10728c2ecf20Sopenharmony_ci enable = FALSE; 10738c2ecf20Sopenharmony_ci pcheck = FALSE; 10748c2ecf20Sopenharmony_ci fast = FALSE; 10758c2ecf20Sopenharmony_ci large = FALSE; 10768c2ecf20Sopenharmony_ci num_scbs = 0; 10778c2ecf20Sopenharmony_ci 10788c2ecf20Sopenharmony_ci if (ahc_ext_scbram_present(ahc) == 0) 10798c2ecf20Sopenharmony_ci goto done; 10808c2ecf20Sopenharmony_ci 10818c2ecf20Sopenharmony_ci /* 10828c2ecf20Sopenharmony_ci * Probe for the best parameters to use. 10838c2ecf20Sopenharmony_ci */ 10848c2ecf20Sopenharmony_ci ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large); 10858c2ecf20Sopenharmony_ci num_scbs = ahc_probe_scbs(ahc); 10868c2ecf20Sopenharmony_ci if (num_scbs == 0) { 10878c2ecf20Sopenharmony_ci /* The SRAM wasn't really present. */ 10888c2ecf20Sopenharmony_ci goto done; 10898c2ecf20Sopenharmony_ci } 10908c2ecf20Sopenharmony_ci enable = TRUE; 10918c2ecf20Sopenharmony_ci 10928c2ecf20Sopenharmony_ci /* 10938c2ecf20Sopenharmony_ci * Clear any outstanding parity error 10948c2ecf20Sopenharmony_ci * and ensure that parity error reporting 10958c2ecf20Sopenharmony_ci * is enabled. 10968c2ecf20Sopenharmony_ci */ 10978c2ecf20Sopenharmony_ci ahc_outb(ahc, SEQCTL, 0); 10988c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 10998c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRBRKADRINT); 11008c2ecf20Sopenharmony_ci 11018c2ecf20Sopenharmony_ci /* Now see if we can do parity */ 11028c2ecf20Sopenharmony_ci ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large); 11038c2ecf20Sopenharmony_ci num_scbs = ahc_probe_scbs(ahc); 11048c2ecf20Sopenharmony_ci if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 11058c2ecf20Sopenharmony_ci || (ahc_inb(ahc, ERROR) & MPARERR) == 0) 11068c2ecf20Sopenharmony_ci pcheck = TRUE; 11078c2ecf20Sopenharmony_ci 11088c2ecf20Sopenharmony_ci /* Clear any resulting parity error */ 11098c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 11108c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRBRKADRINT); 11118c2ecf20Sopenharmony_ci 11128c2ecf20Sopenharmony_ci /* Now see if we can do fast timing */ 11138c2ecf20Sopenharmony_ci ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large); 11148c2ecf20Sopenharmony_ci test_num_scbs = ahc_probe_scbs(ahc); 11158c2ecf20Sopenharmony_ci if (test_num_scbs == num_scbs 11168c2ecf20Sopenharmony_ci && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 11178c2ecf20Sopenharmony_ci || (ahc_inb(ahc, ERROR) & MPARERR) == 0)) 11188c2ecf20Sopenharmony_ci fast = TRUE; 11198c2ecf20Sopenharmony_ci 11208c2ecf20Sopenharmony_ci /* 11218c2ecf20Sopenharmony_ci * See if we can use large SCBs and still maintain 11228c2ecf20Sopenharmony_ci * the same overall count of SCBs. 11238c2ecf20Sopenharmony_ci */ 11248c2ecf20Sopenharmony_ci if ((ahc->features & AHC_LARGE_SCBS) != 0) { 11258c2ecf20Sopenharmony_ci ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE); 11268c2ecf20Sopenharmony_ci test_num_scbs = ahc_probe_scbs(ahc); 11278c2ecf20Sopenharmony_ci if (test_num_scbs >= num_scbs) { 11288c2ecf20Sopenharmony_ci large = TRUE; 11298c2ecf20Sopenharmony_ci num_scbs = test_num_scbs; 11308c2ecf20Sopenharmony_ci if (num_scbs >= 64) { 11318c2ecf20Sopenharmony_ci /* 11328c2ecf20Sopenharmony_ci * We have enough space to move the 11338c2ecf20Sopenharmony_ci * "busy targets table" into SCB space 11348c2ecf20Sopenharmony_ci * and make it qualify all the way to the 11358c2ecf20Sopenharmony_ci * lun level. 11368c2ecf20Sopenharmony_ci */ 11378c2ecf20Sopenharmony_ci ahc->flags |= AHC_SCB_BTT; 11388c2ecf20Sopenharmony_ci } 11398c2ecf20Sopenharmony_ci } 11408c2ecf20Sopenharmony_ci } 11418c2ecf20Sopenharmony_cidone: 11428c2ecf20Sopenharmony_ci /* 11438c2ecf20Sopenharmony_ci * Disable parity error reporting until we 11448c2ecf20Sopenharmony_ci * can load instruction ram. 11458c2ecf20Sopenharmony_ci */ 11468c2ecf20Sopenharmony_ci ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); 11478c2ecf20Sopenharmony_ci /* Clear any latched parity error */ 11488c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 11498c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRBRKADRINT); 11508c2ecf20Sopenharmony_ci if (bootverbose && enable) { 11518c2ecf20Sopenharmony_ci printk("%s: External SRAM, %s access%s, %dbytes/SCB\n", 11528c2ecf20Sopenharmony_ci ahc_name(ahc), fast ? "fast" : "slow", 11538c2ecf20Sopenharmony_ci pcheck ? ", parity checking enabled" : "", 11548c2ecf20Sopenharmony_ci large ? 64 : 32); 11558c2ecf20Sopenharmony_ci } 11568c2ecf20Sopenharmony_ci ahc_scbram_config(ahc, enable, pcheck, fast, large); 11578c2ecf20Sopenharmony_ci} 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_ci/* 11608c2ecf20Sopenharmony_ci * Perform some simple tests that should catch situations where 11618c2ecf20Sopenharmony_ci * our registers are invalidly mapped. 11628c2ecf20Sopenharmony_ci */ 11638c2ecf20Sopenharmony_ciint 11648c2ecf20Sopenharmony_ciahc_pci_test_register_access(struct ahc_softc *ahc) 11658c2ecf20Sopenharmony_ci{ 11668c2ecf20Sopenharmony_ci int error; 11678c2ecf20Sopenharmony_ci u_int status1; 11688c2ecf20Sopenharmony_ci uint32_t cmd; 11698c2ecf20Sopenharmony_ci uint8_t hcntrl; 11708c2ecf20Sopenharmony_ci 11718c2ecf20Sopenharmony_ci error = EIO; 11728c2ecf20Sopenharmony_ci 11738c2ecf20Sopenharmony_ci /* 11748c2ecf20Sopenharmony_ci * Enable PCI error interrupt status, but suppress NMIs 11758c2ecf20Sopenharmony_ci * generated by SERR raised due to target aborts. 11768c2ecf20Sopenharmony_ci */ 11778c2ecf20Sopenharmony_ci cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); 11788c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, 11798c2ecf20Sopenharmony_ci cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); 11808c2ecf20Sopenharmony_ci 11818c2ecf20Sopenharmony_ci /* 11828c2ecf20Sopenharmony_ci * First a simple test to see if any 11838c2ecf20Sopenharmony_ci * registers can be read. Reading 11848c2ecf20Sopenharmony_ci * HCNTRL has no side effects and has 11858c2ecf20Sopenharmony_ci * at least one bit that is guaranteed to 11868c2ecf20Sopenharmony_ci * be zero so it is a good register to 11878c2ecf20Sopenharmony_ci * use for this test. 11888c2ecf20Sopenharmony_ci */ 11898c2ecf20Sopenharmony_ci hcntrl = ahc_inb(ahc, HCNTRL); 11908c2ecf20Sopenharmony_ci 11918c2ecf20Sopenharmony_ci if (hcntrl == 0xFF) 11928c2ecf20Sopenharmony_ci goto fail; 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci if ((hcntrl & CHIPRST) != 0) { 11958c2ecf20Sopenharmony_ci /* 11968c2ecf20Sopenharmony_ci * The chip has not been initialized since 11978c2ecf20Sopenharmony_ci * PCI/EISA/VLB bus reset. Don't trust 11988c2ecf20Sopenharmony_ci * "left over BIOS data". 11998c2ecf20Sopenharmony_ci */ 12008c2ecf20Sopenharmony_ci ahc->flags |= AHC_NO_BIOS_INIT; 12018c2ecf20Sopenharmony_ci } 12028c2ecf20Sopenharmony_ci 12038c2ecf20Sopenharmony_ci /* 12048c2ecf20Sopenharmony_ci * Next create a situation where write combining 12058c2ecf20Sopenharmony_ci * or read prefetching could be initiated by the 12068c2ecf20Sopenharmony_ci * CPU or host bridge. Our device does not support 12078c2ecf20Sopenharmony_ci * either, so look for data corruption and/or flagged 12088c2ecf20Sopenharmony_ci * PCI errors. First pause without causing another 12098c2ecf20Sopenharmony_ci * chip reset. 12108c2ecf20Sopenharmony_ci */ 12118c2ecf20Sopenharmony_ci hcntrl &= ~CHIPRST; 12128c2ecf20Sopenharmony_ci ahc_outb(ahc, HCNTRL, hcntrl|PAUSE); 12138c2ecf20Sopenharmony_ci while (ahc_is_paused(ahc) == 0) 12148c2ecf20Sopenharmony_ci ; 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ci /* Clear any PCI errors that occurred before our driver attached. */ 12178c2ecf20Sopenharmony_ci status1 = ahc_pci_read_config(ahc->dev_softc, 12188c2ecf20Sopenharmony_ci PCIR_STATUS + 1, /*bytes*/1); 12198c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 12208c2ecf20Sopenharmony_ci status1, /*bytes*/1); 12218c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 12228c2ecf20Sopenharmony_ci 12238c2ecf20Sopenharmony_ci ahc_outb(ahc, SEQCTL, PERRORDIS); 12248c2ecf20Sopenharmony_ci ahc_outb(ahc, SCBPTR, 0); 12258c2ecf20Sopenharmony_ci ahc_outl(ahc, SCB_BASE, 0x5aa555aa); 12268c2ecf20Sopenharmony_ci if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa) 12278c2ecf20Sopenharmony_ci goto fail; 12288c2ecf20Sopenharmony_ci 12298c2ecf20Sopenharmony_ci status1 = ahc_pci_read_config(ahc->dev_softc, 12308c2ecf20Sopenharmony_ci PCIR_STATUS + 1, /*bytes*/1); 12318c2ecf20Sopenharmony_ci if ((status1 & STA) != 0) 12328c2ecf20Sopenharmony_ci goto fail; 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_ci error = 0; 12358c2ecf20Sopenharmony_ci 12368c2ecf20Sopenharmony_cifail: 12378c2ecf20Sopenharmony_ci /* Silently clear any latched errors. */ 12388c2ecf20Sopenharmony_ci status1 = ahc_pci_read_config(ahc->dev_softc, 12398c2ecf20Sopenharmony_ci PCIR_STATUS + 1, /*bytes*/1); 12408c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 12418c2ecf20Sopenharmony_ci status1, /*bytes*/1); 12428c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 12438c2ecf20Sopenharmony_ci ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); 12448c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); 12458c2ecf20Sopenharmony_ci return (error); 12468c2ecf20Sopenharmony_ci} 12478c2ecf20Sopenharmony_ci 12488c2ecf20Sopenharmony_ci/* 12498c2ecf20Sopenharmony_ci * Check the external port logic for a serial eeprom 12508c2ecf20Sopenharmony_ci * and termination/cable detection contrls. 12518c2ecf20Sopenharmony_ci */ 12528c2ecf20Sopenharmony_cistatic void 12538c2ecf20Sopenharmony_cicheck_extport(struct ahc_softc *ahc, u_int *sxfrctl1) 12548c2ecf20Sopenharmony_ci{ 12558c2ecf20Sopenharmony_ci struct seeprom_descriptor sd; 12568c2ecf20Sopenharmony_ci struct seeprom_config *sc; 12578c2ecf20Sopenharmony_ci int have_seeprom; 12588c2ecf20Sopenharmony_ci int have_autoterm; 12598c2ecf20Sopenharmony_ci 12608c2ecf20Sopenharmony_ci sd.sd_ahc = ahc; 12618c2ecf20Sopenharmony_ci sd.sd_control_offset = SEECTL; 12628c2ecf20Sopenharmony_ci sd.sd_status_offset = SEECTL; 12638c2ecf20Sopenharmony_ci sd.sd_dataout_offset = SEECTL; 12648c2ecf20Sopenharmony_ci sc = ahc->seep_config; 12658c2ecf20Sopenharmony_ci 12668c2ecf20Sopenharmony_ci /* 12678c2ecf20Sopenharmony_ci * For some multi-channel devices, the c46 is simply too 12688c2ecf20Sopenharmony_ci * small to work. For the other controller types, we can 12698c2ecf20Sopenharmony_ci * get our information from either SEEPROM type. Set the 12708c2ecf20Sopenharmony_ci * type to start our probe with accordingly. 12718c2ecf20Sopenharmony_ci */ 12728c2ecf20Sopenharmony_ci if (ahc->flags & AHC_LARGE_SEEPROM) 12738c2ecf20Sopenharmony_ci sd.sd_chip = C56_66; 12748c2ecf20Sopenharmony_ci else 12758c2ecf20Sopenharmony_ci sd.sd_chip = C46; 12768c2ecf20Sopenharmony_ci 12778c2ecf20Sopenharmony_ci sd.sd_MS = SEEMS; 12788c2ecf20Sopenharmony_ci sd.sd_RDY = SEERDY; 12798c2ecf20Sopenharmony_ci sd.sd_CS = SEECS; 12808c2ecf20Sopenharmony_ci sd.sd_CK = SEECK; 12818c2ecf20Sopenharmony_ci sd.sd_DO = SEEDO; 12828c2ecf20Sopenharmony_ci sd.sd_DI = SEEDI; 12838c2ecf20Sopenharmony_ci 12848c2ecf20Sopenharmony_ci have_seeprom = ahc_acquire_seeprom(ahc, &sd); 12858c2ecf20Sopenharmony_ci if (have_seeprom) { 12868c2ecf20Sopenharmony_ci 12878c2ecf20Sopenharmony_ci if (bootverbose) 12888c2ecf20Sopenharmony_ci printk("%s: Reading SEEPROM...", ahc_name(ahc)); 12898c2ecf20Sopenharmony_ci 12908c2ecf20Sopenharmony_ci for (;;) { 12918c2ecf20Sopenharmony_ci u_int start_addr; 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci start_addr = 32 * (ahc->channel - 'A'); 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc, 12968c2ecf20Sopenharmony_ci start_addr, 12978c2ecf20Sopenharmony_ci sizeof(*sc)/2); 12988c2ecf20Sopenharmony_ci 12998c2ecf20Sopenharmony_ci if (have_seeprom) 13008c2ecf20Sopenharmony_ci have_seeprom = ahc_verify_cksum(sc); 13018c2ecf20Sopenharmony_ci 13028c2ecf20Sopenharmony_ci if (have_seeprom != 0 || sd.sd_chip == C56_66) { 13038c2ecf20Sopenharmony_ci if (bootverbose) { 13048c2ecf20Sopenharmony_ci if (have_seeprom == 0) 13058c2ecf20Sopenharmony_ci printk ("checksum error\n"); 13068c2ecf20Sopenharmony_ci else 13078c2ecf20Sopenharmony_ci printk ("done.\n"); 13088c2ecf20Sopenharmony_ci } 13098c2ecf20Sopenharmony_ci break; 13108c2ecf20Sopenharmony_ci } 13118c2ecf20Sopenharmony_ci sd.sd_chip = C56_66; 13128c2ecf20Sopenharmony_ci } 13138c2ecf20Sopenharmony_ci ahc_release_seeprom(&sd); 13148c2ecf20Sopenharmony_ci 13158c2ecf20Sopenharmony_ci /* Remember the SEEPROM type for later */ 13168c2ecf20Sopenharmony_ci if (sd.sd_chip == C56_66) 13178c2ecf20Sopenharmony_ci ahc->flags |= AHC_LARGE_SEEPROM; 13188c2ecf20Sopenharmony_ci } 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci if (!have_seeprom) { 13218c2ecf20Sopenharmony_ci /* 13228c2ecf20Sopenharmony_ci * Pull scratch ram settings and treat them as 13238c2ecf20Sopenharmony_ci * if they are the contents of an seeprom if 13248c2ecf20Sopenharmony_ci * the 'ADPT' signature is found in SCB2. 13258c2ecf20Sopenharmony_ci * We manually compose the data as 16bit values 13268c2ecf20Sopenharmony_ci * to avoid endian issues. 13278c2ecf20Sopenharmony_ci */ 13288c2ecf20Sopenharmony_ci ahc_outb(ahc, SCBPTR, 2); 13298c2ecf20Sopenharmony_ci if (ahc_inb(ahc, SCB_BASE) == 'A' 13308c2ecf20Sopenharmony_ci && ahc_inb(ahc, SCB_BASE + 1) == 'D' 13318c2ecf20Sopenharmony_ci && ahc_inb(ahc, SCB_BASE + 2) == 'P' 13328c2ecf20Sopenharmony_ci && ahc_inb(ahc, SCB_BASE + 3) == 'T') { 13338c2ecf20Sopenharmony_ci uint16_t *sc_data; 13348c2ecf20Sopenharmony_ci int i; 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci sc_data = (uint16_t *)sc; 13378c2ecf20Sopenharmony_ci for (i = 0; i < 32; i++, sc_data++) { 13388c2ecf20Sopenharmony_ci int j; 13398c2ecf20Sopenharmony_ci 13408c2ecf20Sopenharmony_ci j = i * 2; 13418c2ecf20Sopenharmony_ci *sc_data = ahc_inb(ahc, SRAM_BASE + j) 13428c2ecf20Sopenharmony_ci | ahc_inb(ahc, SRAM_BASE + j + 1) << 8; 13438c2ecf20Sopenharmony_ci } 13448c2ecf20Sopenharmony_ci have_seeprom = ahc_verify_cksum(sc); 13458c2ecf20Sopenharmony_ci if (have_seeprom) 13468c2ecf20Sopenharmony_ci ahc->flags |= AHC_SCB_CONFIG_USED; 13478c2ecf20Sopenharmony_ci } 13488c2ecf20Sopenharmony_ci /* 13498c2ecf20Sopenharmony_ci * Clear any SCB parity errors in case this data and 13508c2ecf20Sopenharmony_ci * its associated parity was not initialized by the BIOS 13518c2ecf20Sopenharmony_ci */ 13528c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 13538c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRBRKADRINT); 13548c2ecf20Sopenharmony_ci } 13558c2ecf20Sopenharmony_ci 13568c2ecf20Sopenharmony_ci if (!have_seeprom) { 13578c2ecf20Sopenharmony_ci if (bootverbose) 13588c2ecf20Sopenharmony_ci printk("%s: No SEEPROM available.\n", ahc_name(ahc)); 13598c2ecf20Sopenharmony_ci ahc->flags |= AHC_USEDEFAULTS; 13608c2ecf20Sopenharmony_ci kfree(ahc->seep_config); 13618c2ecf20Sopenharmony_ci ahc->seep_config = NULL; 13628c2ecf20Sopenharmony_ci sc = NULL; 13638c2ecf20Sopenharmony_ci } else { 13648c2ecf20Sopenharmony_ci ahc_parse_pci_eeprom(ahc, sc); 13658c2ecf20Sopenharmony_ci } 13668c2ecf20Sopenharmony_ci 13678c2ecf20Sopenharmony_ci /* 13688c2ecf20Sopenharmony_ci * Cards that have the external logic necessary to talk to 13698c2ecf20Sopenharmony_ci * a SEEPROM, are almost certain to have the remaining logic 13708c2ecf20Sopenharmony_ci * necessary for auto-termination control. This assumption 13718c2ecf20Sopenharmony_ci * hasn't failed yet... 13728c2ecf20Sopenharmony_ci */ 13738c2ecf20Sopenharmony_ci have_autoterm = have_seeprom; 13748c2ecf20Sopenharmony_ci 13758c2ecf20Sopenharmony_ci /* 13768c2ecf20Sopenharmony_ci * Some low-cost chips have SEEPROM and auto-term control built 13778c2ecf20Sopenharmony_ci * in, instead of using a GAL. They can tell us directly 13788c2ecf20Sopenharmony_ci * if the termination logic is enabled. 13798c2ecf20Sopenharmony_ci */ 13808c2ecf20Sopenharmony_ci if ((ahc->features & AHC_SPIOCAP) != 0) { 13818c2ecf20Sopenharmony_ci if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0) 13828c2ecf20Sopenharmony_ci have_autoterm = FALSE; 13838c2ecf20Sopenharmony_ci } 13848c2ecf20Sopenharmony_ci 13858c2ecf20Sopenharmony_ci if (have_autoterm) { 13868c2ecf20Sopenharmony_ci ahc->flags |= AHC_HAS_TERM_LOGIC; 13878c2ecf20Sopenharmony_ci ahc_acquire_seeprom(ahc, &sd); 13888c2ecf20Sopenharmony_ci configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1); 13898c2ecf20Sopenharmony_ci ahc_release_seeprom(&sd); 13908c2ecf20Sopenharmony_ci } else if (have_seeprom) { 13918c2ecf20Sopenharmony_ci *sxfrctl1 &= ~STPWEN; 13928c2ecf20Sopenharmony_ci if ((sc->adapter_control & CFSTERM) != 0) 13938c2ecf20Sopenharmony_ci *sxfrctl1 |= STPWEN; 13948c2ecf20Sopenharmony_ci if (bootverbose) 13958c2ecf20Sopenharmony_ci printk("%s: Low byte termination %sabled\n", 13968c2ecf20Sopenharmony_ci ahc_name(ahc), 13978c2ecf20Sopenharmony_ci (*sxfrctl1 & STPWEN) ? "en" : "dis"); 13988c2ecf20Sopenharmony_ci } 13998c2ecf20Sopenharmony_ci} 14008c2ecf20Sopenharmony_ci 14018c2ecf20Sopenharmony_cistatic void 14028c2ecf20Sopenharmony_ciahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc) 14038c2ecf20Sopenharmony_ci{ 14048c2ecf20Sopenharmony_ci /* 14058c2ecf20Sopenharmony_ci * Put the data we've collected down into SRAM 14068c2ecf20Sopenharmony_ci * where ahc_init will find it. 14078c2ecf20Sopenharmony_ci */ 14088c2ecf20Sopenharmony_ci int i; 14098c2ecf20Sopenharmony_ci int max_targ = sc->max_targets & CFMAXTARG; 14108c2ecf20Sopenharmony_ci u_int scsi_conf; 14118c2ecf20Sopenharmony_ci uint16_t discenable; 14128c2ecf20Sopenharmony_ci uint16_t ultraenb; 14138c2ecf20Sopenharmony_ci 14148c2ecf20Sopenharmony_ci discenable = 0; 14158c2ecf20Sopenharmony_ci ultraenb = 0; 14168c2ecf20Sopenharmony_ci if ((sc->adapter_control & CFULTRAEN) != 0) { 14178c2ecf20Sopenharmony_ci /* 14188c2ecf20Sopenharmony_ci * Determine if this adapter has a "newstyle" 14198c2ecf20Sopenharmony_ci * SEEPROM format. 14208c2ecf20Sopenharmony_ci */ 14218c2ecf20Sopenharmony_ci for (i = 0; i < max_targ; i++) { 14228c2ecf20Sopenharmony_ci if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) { 14238c2ecf20Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 14248c2ecf20Sopenharmony_ci break; 14258c2ecf20Sopenharmony_ci } 14268c2ecf20Sopenharmony_ci } 14278c2ecf20Sopenharmony_ci } 14288c2ecf20Sopenharmony_ci 14298c2ecf20Sopenharmony_ci for (i = 0; i < max_targ; i++) { 14308c2ecf20Sopenharmony_ci u_int scsirate; 14318c2ecf20Sopenharmony_ci uint16_t target_mask; 14328c2ecf20Sopenharmony_ci 14338c2ecf20Sopenharmony_ci target_mask = 0x01 << i; 14348c2ecf20Sopenharmony_ci if (sc->device_flags[i] & CFDISC) 14358c2ecf20Sopenharmony_ci discenable |= target_mask; 14368c2ecf20Sopenharmony_ci if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) { 14378c2ecf20Sopenharmony_ci if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) 14388c2ecf20Sopenharmony_ci ultraenb |= target_mask; 14398c2ecf20Sopenharmony_ci } else if ((sc->adapter_control & CFULTRAEN) != 0) { 14408c2ecf20Sopenharmony_ci ultraenb |= target_mask; 14418c2ecf20Sopenharmony_ci } 14428c2ecf20Sopenharmony_ci if ((sc->device_flags[i] & CFXFER) == 0x04 14438c2ecf20Sopenharmony_ci && (ultraenb & target_mask) != 0) { 14448c2ecf20Sopenharmony_ci /* Treat 10MHz as a non-ultra speed */ 14458c2ecf20Sopenharmony_ci sc->device_flags[i] &= ~CFXFER; 14468c2ecf20Sopenharmony_ci ultraenb &= ~target_mask; 14478c2ecf20Sopenharmony_ci } 14488c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) { 14498c2ecf20Sopenharmony_ci u_int offset; 14508c2ecf20Sopenharmony_ci 14518c2ecf20Sopenharmony_ci if (sc->device_flags[i] & CFSYNCH) 14528c2ecf20Sopenharmony_ci offset = MAX_OFFSET_ULTRA2; 14538c2ecf20Sopenharmony_ci else 14548c2ecf20Sopenharmony_ci offset = 0; 14558c2ecf20Sopenharmony_ci ahc_outb(ahc, TARG_OFFSET + i, offset); 14568c2ecf20Sopenharmony_ci 14578c2ecf20Sopenharmony_ci /* 14588c2ecf20Sopenharmony_ci * The ultra enable bits contain the 14598c2ecf20Sopenharmony_ci * high bit of the ultra2 sync rate 14608c2ecf20Sopenharmony_ci * field. 14618c2ecf20Sopenharmony_ci */ 14628c2ecf20Sopenharmony_ci scsirate = (sc->device_flags[i] & CFXFER) 14638c2ecf20Sopenharmony_ci | ((ultraenb & target_mask) ? 0x8 : 0x0); 14648c2ecf20Sopenharmony_ci if (sc->device_flags[i] & CFWIDEB) 14658c2ecf20Sopenharmony_ci scsirate |= WIDEXFER; 14668c2ecf20Sopenharmony_ci } else { 14678c2ecf20Sopenharmony_ci scsirate = (sc->device_flags[i] & CFXFER) << 4; 14688c2ecf20Sopenharmony_ci if (sc->device_flags[i] & CFSYNCH) 14698c2ecf20Sopenharmony_ci scsirate |= SOFS; 14708c2ecf20Sopenharmony_ci if (sc->device_flags[i] & CFWIDEB) 14718c2ecf20Sopenharmony_ci scsirate |= WIDEXFER; 14728c2ecf20Sopenharmony_ci } 14738c2ecf20Sopenharmony_ci ahc_outb(ahc, TARG_SCSIRATE + i, scsirate); 14748c2ecf20Sopenharmony_ci } 14758c2ecf20Sopenharmony_ci ahc->our_id = sc->brtime_id & CFSCSIID; 14768c2ecf20Sopenharmony_ci 14778c2ecf20Sopenharmony_ci scsi_conf = (ahc->our_id & 0x7); 14788c2ecf20Sopenharmony_ci if (sc->adapter_control & CFSPARITY) 14798c2ecf20Sopenharmony_ci scsi_conf |= ENSPCHK; 14808c2ecf20Sopenharmony_ci if (sc->adapter_control & CFRESETB) 14818c2ecf20Sopenharmony_ci scsi_conf |= RESET_SCSI; 14828c2ecf20Sopenharmony_ci 14838c2ecf20Sopenharmony_ci ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT; 14848c2ecf20Sopenharmony_ci 14858c2ecf20Sopenharmony_ci if (sc->bios_control & CFEXTEND) 14868c2ecf20Sopenharmony_ci ahc->flags |= AHC_EXTENDED_TRANS_A; 14878c2ecf20Sopenharmony_ci 14888c2ecf20Sopenharmony_ci if (sc->bios_control & CFBIOSEN) 14898c2ecf20Sopenharmony_ci ahc->flags |= AHC_BIOS_ENABLED; 14908c2ecf20Sopenharmony_ci if (ahc->features & AHC_ULTRA 14918c2ecf20Sopenharmony_ci && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) { 14928c2ecf20Sopenharmony_ci /* Should we enable Ultra mode? */ 14938c2ecf20Sopenharmony_ci if (!(sc->adapter_control & CFULTRAEN)) 14948c2ecf20Sopenharmony_ci /* Treat us as a non-ultra card */ 14958c2ecf20Sopenharmony_ci ultraenb = 0; 14968c2ecf20Sopenharmony_ci } 14978c2ecf20Sopenharmony_ci 14988c2ecf20Sopenharmony_ci if (sc->signature == CFSIGNATURE 14998c2ecf20Sopenharmony_ci || sc->signature == CFSIGNATURE2) { 15008c2ecf20Sopenharmony_ci uint32_t devconfig; 15018c2ecf20Sopenharmony_ci 15028c2ecf20Sopenharmony_ci /* Honor the STPWLEVEL settings */ 15038c2ecf20Sopenharmony_ci devconfig = ahc_pci_read_config(ahc->dev_softc, 15048c2ecf20Sopenharmony_ci DEVCONFIG, /*bytes*/4); 15058c2ecf20Sopenharmony_ci devconfig &= ~STPWLEVEL; 15068c2ecf20Sopenharmony_ci if ((sc->bios_control & CFSTPWLEVEL) != 0) 15078c2ecf20Sopenharmony_ci devconfig |= STPWLEVEL; 15088c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, 15098c2ecf20Sopenharmony_ci devconfig, /*bytes*/4); 15108c2ecf20Sopenharmony_ci } 15118c2ecf20Sopenharmony_ci /* Set SCSICONF info */ 15128c2ecf20Sopenharmony_ci ahc_outb(ahc, SCSICONF, scsi_conf); 15138c2ecf20Sopenharmony_ci ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); 15148c2ecf20Sopenharmony_ci ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); 15158c2ecf20Sopenharmony_ci ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff); 15168c2ecf20Sopenharmony_ci ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff); 15178c2ecf20Sopenharmony_ci} 15188c2ecf20Sopenharmony_ci 15198c2ecf20Sopenharmony_cistatic void 15208c2ecf20Sopenharmony_ciconfigure_termination(struct ahc_softc *ahc, 15218c2ecf20Sopenharmony_ci struct seeprom_descriptor *sd, 15228c2ecf20Sopenharmony_ci u_int adapter_control, 15238c2ecf20Sopenharmony_ci u_int *sxfrctl1) 15248c2ecf20Sopenharmony_ci{ 15258c2ecf20Sopenharmony_ci uint8_t brddat; 15268c2ecf20Sopenharmony_ci 15278c2ecf20Sopenharmony_ci brddat = 0; 15288c2ecf20Sopenharmony_ci 15298c2ecf20Sopenharmony_ci /* 15308c2ecf20Sopenharmony_ci * Update the settings in sxfrctl1 to match the 15318c2ecf20Sopenharmony_ci * termination settings 15328c2ecf20Sopenharmony_ci */ 15338c2ecf20Sopenharmony_ci *sxfrctl1 = 0; 15348c2ecf20Sopenharmony_ci 15358c2ecf20Sopenharmony_ci /* 15368c2ecf20Sopenharmony_ci * SEECS must be on for the GALS to latch 15378c2ecf20Sopenharmony_ci * the data properly. Be sure to leave MS 15388c2ecf20Sopenharmony_ci * on or we will release the seeprom. 15398c2ecf20Sopenharmony_ci */ 15408c2ecf20Sopenharmony_ci SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS); 15418c2ecf20Sopenharmony_ci if ((adapter_control & CFAUTOTERM) != 0 15428c2ecf20Sopenharmony_ci || (ahc->features & AHC_NEW_TERMCTL) != 0) { 15438c2ecf20Sopenharmony_ci int internal50_present; 15448c2ecf20Sopenharmony_ci int internal68_present; 15458c2ecf20Sopenharmony_ci int externalcable_present; 15468c2ecf20Sopenharmony_ci int eeprom_present; 15478c2ecf20Sopenharmony_ci int enableSEC_low; 15488c2ecf20Sopenharmony_ci int enableSEC_high; 15498c2ecf20Sopenharmony_ci int enablePRI_low; 15508c2ecf20Sopenharmony_ci int enablePRI_high; 15518c2ecf20Sopenharmony_ci int sum; 15528c2ecf20Sopenharmony_ci 15538c2ecf20Sopenharmony_ci enableSEC_low = 0; 15548c2ecf20Sopenharmony_ci enableSEC_high = 0; 15558c2ecf20Sopenharmony_ci enablePRI_low = 0; 15568c2ecf20Sopenharmony_ci enablePRI_high = 0; 15578c2ecf20Sopenharmony_ci if ((ahc->features & AHC_NEW_TERMCTL) != 0) { 15588c2ecf20Sopenharmony_ci ahc_new_term_detect(ahc, &enableSEC_low, 15598c2ecf20Sopenharmony_ci &enableSEC_high, 15608c2ecf20Sopenharmony_ci &enablePRI_low, 15618c2ecf20Sopenharmony_ci &enablePRI_high, 15628c2ecf20Sopenharmony_ci &eeprom_present); 15638c2ecf20Sopenharmony_ci if ((adapter_control & CFSEAUTOTERM) == 0) { 15648c2ecf20Sopenharmony_ci if (bootverbose) 15658c2ecf20Sopenharmony_ci printk("%s: Manual SE Termination\n", 15668c2ecf20Sopenharmony_ci ahc_name(ahc)); 15678c2ecf20Sopenharmony_ci enableSEC_low = (adapter_control & CFSELOWTERM); 15688c2ecf20Sopenharmony_ci enableSEC_high = 15698c2ecf20Sopenharmony_ci (adapter_control & CFSEHIGHTERM); 15708c2ecf20Sopenharmony_ci } 15718c2ecf20Sopenharmony_ci if ((adapter_control & CFAUTOTERM) == 0) { 15728c2ecf20Sopenharmony_ci if (bootverbose) 15738c2ecf20Sopenharmony_ci printk("%s: Manual LVD Termination\n", 15748c2ecf20Sopenharmony_ci ahc_name(ahc)); 15758c2ecf20Sopenharmony_ci enablePRI_low = (adapter_control & CFSTERM); 15768c2ecf20Sopenharmony_ci enablePRI_high = (adapter_control & CFWSTERM); 15778c2ecf20Sopenharmony_ci } 15788c2ecf20Sopenharmony_ci /* Make the table calculations below happy */ 15798c2ecf20Sopenharmony_ci internal50_present = 0; 15808c2ecf20Sopenharmony_ci internal68_present = 1; 15818c2ecf20Sopenharmony_ci externalcable_present = 1; 15828c2ecf20Sopenharmony_ci } else if ((ahc->features & AHC_SPIOCAP) != 0) { 15838c2ecf20Sopenharmony_ci aic785X_cable_detect(ahc, &internal50_present, 15848c2ecf20Sopenharmony_ci &externalcable_present, 15858c2ecf20Sopenharmony_ci &eeprom_present); 15868c2ecf20Sopenharmony_ci /* Can never support a wide connector. */ 15878c2ecf20Sopenharmony_ci internal68_present = 0; 15888c2ecf20Sopenharmony_ci } else { 15898c2ecf20Sopenharmony_ci aic787X_cable_detect(ahc, &internal50_present, 15908c2ecf20Sopenharmony_ci &internal68_present, 15918c2ecf20Sopenharmony_ci &externalcable_present, 15928c2ecf20Sopenharmony_ci &eeprom_present); 15938c2ecf20Sopenharmony_ci } 15948c2ecf20Sopenharmony_ci 15958c2ecf20Sopenharmony_ci if ((ahc->features & AHC_WIDE) == 0) 15968c2ecf20Sopenharmony_ci internal68_present = 0; 15978c2ecf20Sopenharmony_ci 15988c2ecf20Sopenharmony_ci if (bootverbose 15998c2ecf20Sopenharmony_ci && (ahc->features & AHC_ULTRA2) == 0) { 16008c2ecf20Sopenharmony_ci printk("%s: internal 50 cable %s present", 16018c2ecf20Sopenharmony_ci ahc_name(ahc), 16028c2ecf20Sopenharmony_ci internal50_present ? "is":"not"); 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci if ((ahc->features & AHC_WIDE) != 0) 16058c2ecf20Sopenharmony_ci printk(", internal 68 cable %s present", 16068c2ecf20Sopenharmony_ci internal68_present ? "is":"not"); 16078c2ecf20Sopenharmony_ci printk("\n%s: external cable %s present\n", 16088c2ecf20Sopenharmony_ci ahc_name(ahc), 16098c2ecf20Sopenharmony_ci externalcable_present ? "is":"not"); 16108c2ecf20Sopenharmony_ci } 16118c2ecf20Sopenharmony_ci if (bootverbose) 16128c2ecf20Sopenharmony_ci printk("%s: BIOS eeprom %s present\n", 16138c2ecf20Sopenharmony_ci ahc_name(ahc), eeprom_present ? "is" : "not"); 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) { 16168c2ecf20Sopenharmony_ci /* 16178c2ecf20Sopenharmony_ci * The 50 pin connector is a separate bus, 16188c2ecf20Sopenharmony_ci * so force it to always be terminated. 16198c2ecf20Sopenharmony_ci * In the future, perform current sensing 16208c2ecf20Sopenharmony_ci * to determine if we are in the middle of 16218c2ecf20Sopenharmony_ci * a properly terminated bus. 16228c2ecf20Sopenharmony_ci */ 16238c2ecf20Sopenharmony_ci internal50_present = 0; 16248c2ecf20Sopenharmony_ci } 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci /* 16278c2ecf20Sopenharmony_ci * Now set the termination based on what 16288c2ecf20Sopenharmony_ci * we found. 16298c2ecf20Sopenharmony_ci * Flash Enable = BRDDAT7 16308c2ecf20Sopenharmony_ci * Secondary High Term Enable = BRDDAT6 16318c2ecf20Sopenharmony_ci * Secondary Low Term Enable = BRDDAT5 (7890) 16328c2ecf20Sopenharmony_ci * Primary High Term Enable = BRDDAT4 (7890) 16338c2ecf20Sopenharmony_ci */ 16348c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) == 0 16358c2ecf20Sopenharmony_ci && (internal50_present != 0) 16368c2ecf20Sopenharmony_ci && (internal68_present != 0) 16378c2ecf20Sopenharmony_ci && (externalcable_present != 0)) { 16388c2ecf20Sopenharmony_ci printk("%s: Illegal cable configuration!!. " 16398c2ecf20Sopenharmony_ci "Only two connectors on the " 16408c2ecf20Sopenharmony_ci "adapter may be used at a " 16418c2ecf20Sopenharmony_ci "time!\n", ahc_name(ahc)); 16428c2ecf20Sopenharmony_ci 16438c2ecf20Sopenharmony_ci /* 16448c2ecf20Sopenharmony_ci * Pretend there are no cables in the hope 16458c2ecf20Sopenharmony_ci * that having all of the termination on 16468c2ecf20Sopenharmony_ci * gives us a more stable bus. 16478c2ecf20Sopenharmony_ci */ 16488c2ecf20Sopenharmony_ci internal50_present = 0; 16498c2ecf20Sopenharmony_ci internal68_present = 0; 16508c2ecf20Sopenharmony_ci externalcable_present = 0; 16518c2ecf20Sopenharmony_ci } 16528c2ecf20Sopenharmony_ci 16538c2ecf20Sopenharmony_ci if ((ahc->features & AHC_WIDE) != 0 16548c2ecf20Sopenharmony_ci && ((externalcable_present == 0) 16558c2ecf20Sopenharmony_ci || (internal68_present == 0) 16568c2ecf20Sopenharmony_ci || (enableSEC_high != 0))) { 16578c2ecf20Sopenharmony_ci brddat |= BRDDAT6; 16588c2ecf20Sopenharmony_ci if (bootverbose) { 16598c2ecf20Sopenharmony_ci if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 16608c2ecf20Sopenharmony_ci printk("%s: 68 pin termination " 16618c2ecf20Sopenharmony_ci "Enabled\n", ahc_name(ahc)); 16628c2ecf20Sopenharmony_ci else 16638c2ecf20Sopenharmony_ci printk("%s: %sHigh byte termination " 16648c2ecf20Sopenharmony_ci "Enabled\n", ahc_name(ahc), 16658c2ecf20Sopenharmony_ci enableSEC_high ? "Secondary " 16668c2ecf20Sopenharmony_ci : ""); 16678c2ecf20Sopenharmony_ci } 16688c2ecf20Sopenharmony_ci } 16698c2ecf20Sopenharmony_ci 16708c2ecf20Sopenharmony_ci sum = internal50_present + internal68_present 16718c2ecf20Sopenharmony_ci + externalcable_present; 16728c2ecf20Sopenharmony_ci if (sum < 2 || (enableSEC_low != 0)) { 16738c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 16748c2ecf20Sopenharmony_ci brddat |= BRDDAT5; 16758c2ecf20Sopenharmony_ci else 16768c2ecf20Sopenharmony_ci *sxfrctl1 |= STPWEN; 16778c2ecf20Sopenharmony_ci if (bootverbose) { 16788c2ecf20Sopenharmony_ci if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 16798c2ecf20Sopenharmony_ci printk("%s: 50 pin termination " 16808c2ecf20Sopenharmony_ci "Enabled\n", ahc_name(ahc)); 16818c2ecf20Sopenharmony_ci else 16828c2ecf20Sopenharmony_ci printk("%s: %sLow byte termination " 16838c2ecf20Sopenharmony_ci "Enabled\n", ahc_name(ahc), 16848c2ecf20Sopenharmony_ci enableSEC_low ? "Secondary " 16858c2ecf20Sopenharmony_ci : ""); 16868c2ecf20Sopenharmony_ci } 16878c2ecf20Sopenharmony_ci } 16888c2ecf20Sopenharmony_ci 16898c2ecf20Sopenharmony_ci if (enablePRI_low != 0) { 16908c2ecf20Sopenharmony_ci *sxfrctl1 |= STPWEN; 16918c2ecf20Sopenharmony_ci if (bootverbose) 16928c2ecf20Sopenharmony_ci printk("%s: Primary Low Byte termination " 16938c2ecf20Sopenharmony_ci "Enabled\n", ahc_name(ahc)); 16948c2ecf20Sopenharmony_ci } 16958c2ecf20Sopenharmony_ci 16968c2ecf20Sopenharmony_ci /* 16978c2ecf20Sopenharmony_ci * Setup STPWEN before setting up the rest of 16988c2ecf20Sopenharmony_ci * the termination per the tech note on the U160 cards. 16998c2ecf20Sopenharmony_ci */ 17008c2ecf20Sopenharmony_ci ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 17018c2ecf20Sopenharmony_ci 17028c2ecf20Sopenharmony_ci if (enablePRI_high != 0) { 17038c2ecf20Sopenharmony_ci brddat |= BRDDAT4; 17048c2ecf20Sopenharmony_ci if (bootverbose) 17058c2ecf20Sopenharmony_ci printk("%s: Primary High Byte " 17068c2ecf20Sopenharmony_ci "termination Enabled\n", 17078c2ecf20Sopenharmony_ci ahc_name(ahc)); 17088c2ecf20Sopenharmony_ci } 17098c2ecf20Sopenharmony_ci 17108c2ecf20Sopenharmony_ci write_brdctl(ahc, brddat); 17118c2ecf20Sopenharmony_ci 17128c2ecf20Sopenharmony_ci } else { 17138c2ecf20Sopenharmony_ci if ((adapter_control & CFSTERM) != 0) { 17148c2ecf20Sopenharmony_ci *sxfrctl1 |= STPWEN; 17158c2ecf20Sopenharmony_ci 17168c2ecf20Sopenharmony_ci if (bootverbose) 17178c2ecf20Sopenharmony_ci printk("%s: %sLow byte termination Enabled\n", 17188c2ecf20Sopenharmony_ci ahc_name(ahc), 17198c2ecf20Sopenharmony_ci (ahc->features & AHC_ULTRA2) ? "Primary " 17208c2ecf20Sopenharmony_ci : ""); 17218c2ecf20Sopenharmony_ci } 17228c2ecf20Sopenharmony_ci 17238c2ecf20Sopenharmony_ci if ((adapter_control & CFWSTERM) != 0 17248c2ecf20Sopenharmony_ci && (ahc->features & AHC_WIDE) != 0) { 17258c2ecf20Sopenharmony_ci brddat |= BRDDAT6; 17268c2ecf20Sopenharmony_ci if (bootverbose) 17278c2ecf20Sopenharmony_ci printk("%s: %sHigh byte termination Enabled\n", 17288c2ecf20Sopenharmony_ci ahc_name(ahc), 17298c2ecf20Sopenharmony_ci (ahc->features & AHC_ULTRA2) 17308c2ecf20Sopenharmony_ci ? "Secondary " : ""); 17318c2ecf20Sopenharmony_ci } 17328c2ecf20Sopenharmony_ci 17338c2ecf20Sopenharmony_ci /* 17348c2ecf20Sopenharmony_ci * Setup STPWEN before setting up the rest of 17358c2ecf20Sopenharmony_ci * the termination per the tech note on the U160 cards. 17368c2ecf20Sopenharmony_ci */ 17378c2ecf20Sopenharmony_ci ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci if ((ahc->features & AHC_WIDE) != 0) 17408c2ecf20Sopenharmony_ci write_brdctl(ahc, brddat); 17418c2ecf20Sopenharmony_ci } 17428c2ecf20Sopenharmony_ci SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */ 17438c2ecf20Sopenharmony_ci} 17448c2ecf20Sopenharmony_ci 17458c2ecf20Sopenharmony_cistatic void 17468c2ecf20Sopenharmony_ciahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low, 17478c2ecf20Sopenharmony_ci int *enableSEC_high, int *enablePRI_low, 17488c2ecf20Sopenharmony_ci int *enablePRI_high, int *eeprom_present) 17498c2ecf20Sopenharmony_ci{ 17508c2ecf20Sopenharmony_ci uint8_t brdctl; 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci /* 17538c2ecf20Sopenharmony_ci * BRDDAT7 = Eeprom 17548c2ecf20Sopenharmony_ci * BRDDAT6 = Enable Secondary High Byte termination 17558c2ecf20Sopenharmony_ci * BRDDAT5 = Enable Secondary Low Byte termination 17568c2ecf20Sopenharmony_ci * BRDDAT4 = Enable Primary high byte termination 17578c2ecf20Sopenharmony_ci * BRDDAT3 = Enable Primary low byte termination 17588c2ecf20Sopenharmony_ci */ 17598c2ecf20Sopenharmony_ci brdctl = read_brdctl(ahc); 17608c2ecf20Sopenharmony_ci *eeprom_present = brdctl & BRDDAT7; 17618c2ecf20Sopenharmony_ci *enableSEC_high = (brdctl & BRDDAT6); 17628c2ecf20Sopenharmony_ci *enableSEC_low = (brdctl & BRDDAT5); 17638c2ecf20Sopenharmony_ci *enablePRI_high = (brdctl & BRDDAT4); 17648c2ecf20Sopenharmony_ci *enablePRI_low = (brdctl & BRDDAT3); 17658c2ecf20Sopenharmony_ci} 17668c2ecf20Sopenharmony_ci 17678c2ecf20Sopenharmony_cistatic void 17688c2ecf20Sopenharmony_ciaic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 17698c2ecf20Sopenharmony_ci int *internal68_present, int *externalcable_present, 17708c2ecf20Sopenharmony_ci int *eeprom_present) 17718c2ecf20Sopenharmony_ci{ 17728c2ecf20Sopenharmony_ci uint8_t brdctl; 17738c2ecf20Sopenharmony_ci 17748c2ecf20Sopenharmony_ci /* 17758c2ecf20Sopenharmony_ci * First read the status of our cables. 17768c2ecf20Sopenharmony_ci * Set the rom bank to 0 since the 17778c2ecf20Sopenharmony_ci * bank setting serves as a multiplexor 17788c2ecf20Sopenharmony_ci * for the cable detection logic. 17798c2ecf20Sopenharmony_ci * BRDDAT5 controls the bank switch. 17808c2ecf20Sopenharmony_ci */ 17818c2ecf20Sopenharmony_ci write_brdctl(ahc, 0); 17828c2ecf20Sopenharmony_ci 17838c2ecf20Sopenharmony_ci /* 17848c2ecf20Sopenharmony_ci * Now read the state of the internal 17858c2ecf20Sopenharmony_ci * connectors. BRDDAT6 is INT50 and 17868c2ecf20Sopenharmony_ci * BRDDAT7 is INT68. 17878c2ecf20Sopenharmony_ci */ 17888c2ecf20Sopenharmony_ci brdctl = read_brdctl(ahc); 17898c2ecf20Sopenharmony_ci *internal50_present = (brdctl & BRDDAT6) ? 0 : 1; 17908c2ecf20Sopenharmony_ci *internal68_present = (brdctl & BRDDAT7) ? 0 : 1; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci /* 17938c2ecf20Sopenharmony_ci * Set the rom bank to 1 and determine 17948c2ecf20Sopenharmony_ci * the other signals. 17958c2ecf20Sopenharmony_ci */ 17968c2ecf20Sopenharmony_ci write_brdctl(ahc, BRDDAT5); 17978c2ecf20Sopenharmony_ci 17988c2ecf20Sopenharmony_ci /* 17998c2ecf20Sopenharmony_ci * Now read the state of the external 18008c2ecf20Sopenharmony_ci * connectors. BRDDAT6 is EXT68 and 18018c2ecf20Sopenharmony_ci * BRDDAT7 is EPROMPS. 18028c2ecf20Sopenharmony_ci */ 18038c2ecf20Sopenharmony_ci brdctl = read_brdctl(ahc); 18048c2ecf20Sopenharmony_ci *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 18058c2ecf20Sopenharmony_ci *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0; 18068c2ecf20Sopenharmony_ci} 18078c2ecf20Sopenharmony_ci 18088c2ecf20Sopenharmony_cistatic void 18098c2ecf20Sopenharmony_ciaic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 18108c2ecf20Sopenharmony_ci int *externalcable_present, int *eeprom_present) 18118c2ecf20Sopenharmony_ci{ 18128c2ecf20Sopenharmony_ci uint8_t brdctl; 18138c2ecf20Sopenharmony_ci uint8_t spiocap; 18148c2ecf20Sopenharmony_ci 18158c2ecf20Sopenharmony_ci spiocap = ahc_inb(ahc, SPIOCAP); 18168c2ecf20Sopenharmony_ci spiocap &= ~SOFTCMDEN; 18178c2ecf20Sopenharmony_ci spiocap |= EXT_BRDCTL; 18188c2ecf20Sopenharmony_ci ahc_outb(ahc, SPIOCAP, spiocap); 18198c2ecf20Sopenharmony_ci ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); 18208c2ecf20Sopenharmony_ci ahc_flush_device_writes(ahc); 18218c2ecf20Sopenharmony_ci ahc_delay(500); 18228c2ecf20Sopenharmony_ci ahc_outb(ahc, BRDCTL, 0); 18238c2ecf20Sopenharmony_ci ahc_flush_device_writes(ahc); 18248c2ecf20Sopenharmony_ci ahc_delay(500); 18258c2ecf20Sopenharmony_ci brdctl = ahc_inb(ahc, BRDCTL); 18268c2ecf20Sopenharmony_ci *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; 18278c2ecf20Sopenharmony_ci *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 18288c2ecf20Sopenharmony_ci *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0; 18298c2ecf20Sopenharmony_ci} 18308c2ecf20Sopenharmony_ci 18318c2ecf20Sopenharmony_ciint 18328c2ecf20Sopenharmony_ciahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd) 18338c2ecf20Sopenharmony_ci{ 18348c2ecf20Sopenharmony_ci int wait; 18358c2ecf20Sopenharmony_ci 18368c2ecf20Sopenharmony_ci if ((ahc->features & AHC_SPIOCAP) != 0 18378c2ecf20Sopenharmony_ci && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0) 18388c2ecf20Sopenharmony_ci return (0); 18398c2ecf20Sopenharmony_ci 18408c2ecf20Sopenharmony_ci /* 18418c2ecf20Sopenharmony_ci * Request access of the memory port. When access is 18428c2ecf20Sopenharmony_ci * granted, SEERDY will go high. We use a 1 second 18438c2ecf20Sopenharmony_ci * timeout which should be near 1 second more than 18448c2ecf20Sopenharmony_ci * is needed. Reason: after the chip reset, there 18458c2ecf20Sopenharmony_ci * should be no contention. 18468c2ecf20Sopenharmony_ci */ 18478c2ecf20Sopenharmony_ci SEEPROM_OUTB(sd, sd->sd_MS); 18488c2ecf20Sopenharmony_ci wait = 1000; /* 1 second timeout in msec */ 18498c2ecf20Sopenharmony_ci while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { 18508c2ecf20Sopenharmony_ci ahc_delay(1000); /* delay 1 msec */ 18518c2ecf20Sopenharmony_ci } 18528c2ecf20Sopenharmony_ci if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { 18538c2ecf20Sopenharmony_ci SEEPROM_OUTB(sd, 0); 18548c2ecf20Sopenharmony_ci return (0); 18558c2ecf20Sopenharmony_ci } 18568c2ecf20Sopenharmony_ci return(1); 18578c2ecf20Sopenharmony_ci} 18588c2ecf20Sopenharmony_ci 18598c2ecf20Sopenharmony_civoid 18608c2ecf20Sopenharmony_ciahc_release_seeprom(struct seeprom_descriptor *sd) 18618c2ecf20Sopenharmony_ci{ 18628c2ecf20Sopenharmony_ci /* Release access to the memory port and the serial EEPROM. */ 18638c2ecf20Sopenharmony_ci SEEPROM_OUTB(sd, 0); 18648c2ecf20Sopenharmony_ci} 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_cistatic void 18678c2ecf20Sopenharmony_ciwrite_brdctl(struct ahc_softc *ahc, uint8_t value) 18688c2ecf20Sopenharmony_ci{ 18698c2ecf20Sopenharmony_ci uint8_t brdctl; 18708c2ecf20Sopenharmony_ci 18718c2ecf20Sopenharmony_ci if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 18728c2ecf20Sopenharmony_ci brdctl = BRDSTB; 18738c2ecf20Sopenharmony_ci if (ahc->channel == 'B') 18748c2ecf20Sopenharmony_ci brdctl |= BRDCS; 18758c2ecf20Sopenharmony_ci } else if ((ahc->features & AHC_ULTRA2) != 0) { 18768c2ecf20Sopenharmony_ci brdctl = 0; 18778c2ecf20Sopenharmony_ci } else { 18788c2ecf20Sopenharmony_ci brdctl = BRDSTB|BRDCS; 18798c2ecf20Sopenharmony_ci } 18808c2ecf20Sopenharmony_ci ahc_outb(ahc, BRDCTL, brdctl); 18818c2ecf20Sopenharmony_ci ahc_flush_device_writes(ahc); 18828c2ecf20Sopenharmony_ci brdctl |= value; 18838c2ecf20Sopenharmony_ci ahc_outb(ahc, BRDCTL, brdctl); 18848c2ecf20Sopenharmony_ci ahc_flush_device_writes(ahc); 18858c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 18868c2ecf20Sopenharmony_ci brdctl |= BRDSTB_ULTRA2; 18878c2ecf20Sopenharmony_ci else 18888c2ecf20Sopenharmony_ci brdctl &= ~BRDSTB; 18898c2ecf20Sopenharmony_ci ahc_outb(ahc, BRDCTL, brdctl); 18908c2ecf20Sopenharmony_ci ahc_flush_device_writes(ahc); 18918c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 18928c2ecf20Sopenharmony_ci brdctl = 0; 18938c2ecf20Sopenharmony_ci else 18948c2ecf20Sopenharmony_ci brdctl &= ~BRDCS; 18958c2ecf20Sopenharmony_ci ahc_outb(ahc, BRDCTL, brdctl); 18968c2ecf20Sopenharmony_ci} 18978c2ecf20Sopenharmony_ci 18988c2ecf20Sopenharmony_cistatic uint8_t 18998c2ecf20Sopenharmony_ciread_brdctl(struct ahc_softc *ahc) 19008c2ecf20Sopenharmony_ci{ 19018c2ecf20Sopenharmony_ci uint8_t brdctl; 19028c2ecf20Sopenharmony_ci uint8_t value; 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 19058c2ecf20Sopenharmony_ci brdctl = BRDRW; 19068c2ecf20Sopenharmony_ci if (ahc->channel == 'B') 19078c2ecf20Sopenharmony_ci brdctl |= BRDCS; 19088c2ecf20Sopenharmony_ci } else if ((ahc->features & AHC_ULTRA2) != 0) { 19098c2ecf20Sopenharmony_ci brdctl = BRDRW_ULTRA2; 19108c2ecf20Sopenharmony_ci } else { 19118c2ecf20Sopenharmony_ci brdctl = BRDRW|BRDCS; 19128c2ecf20Sopenharmony_ci } 19138c2ecf20Sopenharmony_ci ahc_outb(ahc, BRDCTL, brdctl); 19148c2ecf20Sopenharmony_ci ahc_flush_device_writes(ahc); 19158c2ecf20Sopenharmony_ci value = ahc_inb(ahc, BRDCTL); 19168c2ecf20Sopenharmony_ci ahc_outb(ahc, BRDCTL, 0); 19178c2ecf20Sopenharmony_ci return (value); 19188c2ecf20Sopenharmony_ci} 19198c2ecf20Sopenharmony_ci 19208c2ecf20Sopenharmony_cistatic void 19218c2ecf20Sopenharmony_ciahc_pci_intr(struct ahc_softc *ahc) 19228c2ecf20Sopenharmony_ci{ 19238c2ecf20Sopenharmony_ci u_int error; 19248c2ecf20Sopenharmony_ci u_int status1; 19258c2ecf20Sopenharmony_ci 19268c2ecf20Sopenharmony_ci error = ahc_inb(ahc, ERROR); 19278c2ecf20Sopenharmony_ci if ((error & PCIERRSTAT) == 0) 19288c2ecf20Sopenharmony_ci return; 19298c2ecf20Sopenharmony_ci 19308c2ecf20Sopenharmony_ci status1 = ahc_pci_read_config(ahc->dev_softc, 19318c2ecf20Sopenharmony_ci PCIR_STATUS + 1, /*bytes*/1); 19328c2ecf20Sopenharmony_ci 19338c2ecf20Sopenharmony_ci printk("%s: PCI error Interrupt at seqaddr = 0x%x\n", 19348c2ecf20Sopenharmony_ci ahc_name(ahc), 19358c2ecf20Sopenharmony_ci ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); 19368c2ecf20Sopenharmony_ci 19378c2ecf20Sopenharmony_ci if (status1 & DPE) { 19388c2ecf20Sopenharmony_ci ahc->pci_target_perr_count++; 19398c2ecf20Sopenharmony_ci printk("%s: Data Parity Error Detected during address " 19408c2ecf20Sopenharmony_ci "or write data phase\n", ahc_name(ahc)); 19418c2ecf20Sopenharmony_ci } 19428c2ecf20Sopenharmony_ci if (status1 & SSE) { 19438c2ecf20Sopenharmony_ci printk("%s: Signal System Error Detected\n", ahc_name(ahc)); 19448c2ecf20Sopenharmony_ci } 19458c2ecf20Sopenharmony_ci if (status1 & RMA) { 19468c2ecf20Sopenharmony_ci printk("%s: Received a Master Abort\n", ahc_name(ahc)); 19478c2ecf20Sopenharmony_ci } 19488c2ecf20Sopenharmony_ci if (status1 & RTA) { 19498c2ecf20Sopenharmony_ci printk("%s: Received a Target Abort\n", ahc_name(ahc)); 19508c2ecf20Sopenharmony_ci } 19518c2ecf20Sopenharmony_ci if (status1 & STA) { 19528c2ecf20Sopenharmony_ci printk("%s: Signaled a Target Abort\n", ahc_name(ahc)); 19538c2ecf20Sopenharmony_ci } 19548c2ecf20Sopenharmony_ci if (status1 & DPR) { 19558c2ecf20Sopenharmony_ci printk("%s: Data Parity Error has been reported via PERR#\n", 19568c2ecf20Sopenharmony_ci ahc_name(ahc)); 19578c2ecf20Sopenharmony_ci } 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci /* Clear latched errors. */ 19608c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 19618c2ecf20Sopenharmony_ci status1, /*bytes*/1); 19628c2ecf20Sopenharmony_ci 19638c2ecf20Sopenharmony_ci if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { 19648c2ecf20Sopenharmony_ci printk("%s: Latched PCIERR interrupt with " 19658c2ecf20Sopenharmony_ci "no status bits set\n", ahc_name(ahc)); 19668c2ecf20Sopenharmony_ci } else { 19678c2ecf20Sopenharmony_ci ahc_outb(ahc, CLRINT, CLRPARERR); 19688c2ecf20Sopenharmony_ci } 19698c2ecf20Sopenharmony_ci 19708c2ecf20Sopenharmony_ci if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) { 19718c2ecf20Sopenharmony_ci printk( 19728c2ecf20Sopenharmony_ci"%s: WARNING WARNING WARNING WARNING\n" 19738c2ecf20Sopenharmony_ci"%s: Too many PCI parity errors observed as a target.\n" 19748c2ecf20Sopenharmony_ci"%s: Some device on this bus is generating bad parity.\n" 19758c2ecf20Sopenharmony_ci"%s: This is an error *observed by*, not *generated by*, this controller.\n" 19768c2ecf20Sopenharmony_ci"%s: PCI parity error checking has been disabled.\n" 19778c2ecf20Sopenharmony_ci"%s: WARNING WARNING WARNING WARNING\n", 19788c2ecf20Sopenharmony_ci ahc_name(ahc), ahc_name(ahc), ahc_name(ahc), 19798c2ecf20Sopenharmony_ci ahc_name(ahc), ahc_name(ahc), ahc_name(ahc)); 19808c2ecf20Sopenharmony_ci ahc->seqctl |= FAILDIS; 19818c2ecf20Sopenharmony_ci ahc_outb(ahc, SEQCTL, ahc->seqctl); 19828c2ecf20Sopenharmony_ci } 19838c2ecf20Sopenharmony_ci ahc_unpause(ahc); 19848c2ecf20Sopenharmony_ci} 19858c2ecf20Sopenharmony_ci 19868c2ecf20Sopenharmony_cistatic int 19878c2ecf20Sopenharmony_ciahc_pci_chip_init(struct ahc_softc *ahc) 19888c2ecf20Sopenharmony_ci{ 19898c2ecf20Sopenharmony_ci ahc_outb(ahc, DSCOMMAND0, ahc->bus_softc.pci_softc.dscommand0); 19908c2ecf20Sopenharmony_ci ahc_outb(ahc, DSPCISTATUS, ahc->bus_softc.pci_softc.dspcistatus); 19918c2ecf20Sopenharmony_ci if ((ahc->features & AHC_DT) != 0) { 19928c2ecf20Sopenharmony_ci u_int sfunct; 19938c2ecf20Sopenharmony_ci 19948c2ecf20Sopenharmony_ci sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 19958c2ecf20Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 19968c2ecf20Sopenharmony_ci ahc_outb(ahc, OPTIONMODE, ahc->bus_softc.pci_softc.optionmode); 19978c2ecf20Sopenharmony_ci ahc_outw(ahc, TARGCRCCNT, ahc->bus_softc.pci_softc.targcrccnt); 19988c2ecf20Sopenharmony_ci ahc_outb(ahc, SFUNCT, sfunct); 19998c2ecf20Sopenharmony_ci ahc_outb(ahc, CRCCONTROL1, 20008c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.crccontrol1); 20018c2ecf20Sopenharmony_ci } 20028c2ecf20Sopenharmony_ci if ((ahc->features & AHC_MULTI_FUNC) != 0) 20038c2ecf20Sopenharmony_ci ahc_outb(ahc, SCBBADDR, ahc->bus_softc.pci_softc.scbbaddr); 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_ci if ((ahc->features & AHC_ULTRA2) != 0) 20068c2ecf20Sopenharmony_ci ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh); 20078c2ecf20Sopenharmony_ci 20088c2ecf20Sopenharmony_ci return (ahc_chip_init(ahc)); 20098c2ecf20Sopenharmony_ci} 20108c2ecf20Sopenharmony_ci 20118c2ecf20Sopenharmony_ci#ifdef CONFIG_PM 20128c2ecf20Sopenharmony_civoid 20138c2ecf20Sopenharmony_ciahc_pci_resume(struct ahc_softc *ahc) 20148c2ecf20Sopenharmony_ci{ 20158c2ecf20Sopenharmony_ci /* 20168c2ecf20Sopenharmony_ci * We assume that the OS has restored our register 20178c2ecf20Sopenharmony_ci * mappings, etc. Just update the config space registers 20188c2ecf20Sopenharmony_ci * that the OS doesn't know about and rely on our chip 20198c2ecf20Sopenharmony_ci * reset handler to handle the rest. 20208c2ecf20Sopenharmony_ci */ 20218c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, 20228c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.devconfig, /*bytes*/4); 20238c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, 20248c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.command, /*bytes*/1); 20258c2ecf20Sopenharmony_ci ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 20268c2ecf20Sopenharmony_ci ahc->bus_softc.pci_softc.csize_lattime, /*bytes*/1); 20278c2ecf20Sopenharmony_ci if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) { 20288c2ecf20Sopenharmony_ci struct seeprom_descriptor sd; 20298c2ecf20Sopenharmony_ci u_int sxfrctl1; 20308c2ecf20Sopenharmony_ci 20318c2ecf20Sopenharmony_ci sd.sd_ahc = ahc; 20328c2ecf20Sopenharmony_ci sd.sd_control_offset = SEECTL; 20338c2ecf20Sopenharmony_ci sd.sd_status_offset = SEECTL; 20348c2ecf20Sopenharmony_ci sd.sd_dataout_offset = SEECTL; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci ahc_acquire_seeprom(ahc, &sd); 20378c2ecf20Sopenharmony_ci configure_termination(ahc, &sd, 20388c2ecf20Sopenharmony_ci ahc->seep_config->adapter_control, 20398c2ecf20Sopenharmony_ci &sxfrctl1); 20408c2ecf20Sopenharmony_ci ahc_release_seeprom(&sd); 20418c2ecf20Sopenharmony_ci } 20428c2ecf20Sopenharmony_ci} 20438c2ecf20Sopenharmony_ci#endif 20448c2ecf20Sopenharmony_ci 20458c2ecf20Sopenharmony_cistatic int 20468c2ecf20Sopenharmony_ciahc_aic785X_setup(struct ahc_softc *ahc) 20478c2ecf20Sopenharmony_ci{ 20488c2ecf20Sopenharmony_ci ahc_dev_softc_t pci; 20498c2ecf20Sopenharmony_ci uint8_t rev; 20508c2ecf20Sopenharmony_ci 20518c2ecf20Sopenharmony_ci pci = ahc->dev_softc; 20528c2ecf20Sopenharmony_ci ahc->channel = 'A'; 20538c2ecf20Sopenharmony_ci ahc->chip = AHC_AIC7850; 20548c2ecf20Sopenharmony_ci ahc->features = AHC_AIC7850_FE; 20558c2ecf20Sopenharmony_ci ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 20568c2ecf20Sopenharmony_ci rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 20578c2ecf20Sopenharmony_ci if (rev >= 1) 20588c2ecf20Sopenharmony_ci ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 20598c2ecf20Sopenharmony_ci ahc->instruction_ram_size = 512; 20608c2ecf20Sopenharmony_ci return (0); 20618c2ecf20Sopenharmony_ci} 20628c2ecf20Sopenharmony_ci 20638c2ecf20Sopenharmony_cistatic int 20648c2ecf20Sopenharmony_ciahc_aic7860_setup(struct ahc_softc *ahc) 20658c2ecf20Sopenharmony_ci{ 20668c2ecf20Sopenharmony_ci ahc_dev_softc_t pci; 20678c2ecf20Sopenharmony_ci uint8_t rev; 20688c2ecf20Sopenharmony_ci 20698c2ecf20Sopenharmony_ci pci = ahc->dev_softc; 20708c2ecf20Sopenharmony_ci ahc->channel = 'A'; 20718c2ecf20Sopenharmony_ci ahc->chip = AHC_AIC7860; 20728c2ecf20Sopenharmony_ci ahc->features = AHC_AIC7860_FE; 20738c2ecf20Sopenharmony_ci ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 20748c2ecf20Sopenharmony_ci rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 20758c2ecf20Sopenharmony_ci if (rev >= 1) 20768c2ecf20Sopenharmony_ci ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 20778c2ecf20Sopenharmony_ci ahc->instruction_ram_size = 512; 20788c2ecf20Sopenharmony_ci return (0); 20798c2ecf20Sopenharmony_ci} 20808c2ecf20Sopenharmony_ci 20818c2ecf20Sopenharmony_cistatic int 20828c2ecf20Sopenharmony_ciahc_apa1480_setup(struct ahc_softc *ahc) 20838c2ecf20Sopenharmony_ci{ 20848c2ecf20Sopenharmony_ci int error; 20858c2ecf20Sopenharmony_ci 20868c2ecf20Sopenharmony_ci error = ahc_aic7860_setup(ahc); 20878c2ecf20Sopenharmony_ci if (error != 0) 20888c2ecf20Sopenharmony_ci return (error); 20898c2ecf20Sopenharmony_ci ahc->features |= AHC_REMOVABLE; 20908c2ecf20Sopenharmony_ci return (0); 20918c2ecf20Sopenharmony_ci} 20928c2ecf20Sopenharmony_ci 20938c2ecf20Sopenharmony_cistatic int 20948c2ecf20Sopenharmony_ciahc_aic7870_setup(struct ahc_softc *ahc) 20958c2ecf20Sopenharmony_ci{ 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci ahc->channel = 'A'; 20988c2ecf20Sopenharmony_ci ahc->chip = AHC_AIC7870; 20998c2ecf20Sopenharmony_ci ahc->features = AHC_AIC7870_FE; 21008c2ecf20Sopenharmony_ci ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 21018c2ecf20Sopenharmony_ci ahc->instruction_ram_size = 512; 21028c2ecf20Sopenharmony_ci return (0); 21038c2ecf20Sopenharmony_ci} 21048c2ecf20Sopenharmony_ci 21058c2ecf20Sopenharmony_cistatic int 21068c2ecf20Sopenharmony_ciahc_aic7870h_setup(struct ahc_softc *ahc) 21078c2ecf20Sopenharmony_ci{ 21088c2ecf20Sopenharmony_ci int error = ahc_aic7870_setup(ahc); 21098c2ecf20Sopenharmony_ci 21108c2ecf20Sopenharmony_ci ahc->features |= AHC_HVD; 21118c2ecf20Sopenharmony_ci 21128c2ecf20Sopenharmony_ci return error; 21138c2ecf20Sopenharmony_ci} 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_cistatic int 21168c2ecf20Sopenharmony_ciahc_aha394X_setup(struct ahc_softc *ahc) 21178c2ecf20Sopenharmony_ci{ 21188c2ecf20Sopenharmony_ci int error; 21198c2ecf20Sopenharmony_ci 21208c2ecf20Sopenharmony_ci error = ahc_aic7870_setup(ahc); 21218c2ecf20Sopenharmony_ci if (error == 0) 21228c2ecf20Sopenharmony_ci error = ahc_aha394XX_setup(ahc); 21238c2ecf20Sopenharmony_ci return (error); 21248c2ecf20Sopenharmony_ci} 21258c2ecf20Sopenharmony_ci 21268c2ecf20Sopenharmony_cistatic int 21278c2ecf20Sopenharmony_ciahc_aha394Xh_setup(struct ahc_softc *ahc) 21288c2ecf20Sopenharmony_ci{ 21298c2ecf20Sopenharmony_ci int error = ahc_aha394X_setup(ahc); 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_ci ahc->features |= AHC_HVD; 21328c2ecf20Sopenharmony_ci 21338c2ecf20Sopenharmony_ci return error; 21348c2ecf20Sopenharmony_ci} 21358c2ecf20Sopenharmony_ci 21368c2ecf20Sopenharmony_cistatic int 21378c2ecf20Sopenharmony_ciahc_aha398X_setup(struct ahc_softc *ahc) 21388c2ecf20Sopenharmony_ci{ 21398c2ecf20Sopenharmony_ci int error; 21408c2ecf20Sopenharmony_ci 21418c2ecf20Sopenharmony_ci error = ahc_aic7870_setup(ahc); 21428c2ecf20Sopenharmony_ci if (error == 0) 21438c2ecf20Sopenharmony_ci error = ahc_aha398XX_setup(ahc); 21448c2ecf20Sopenharmony_ci return (error); 21458c2ecf20Sopenharmony_ci} 21468c2ecf20Sopenharmony_ci 21478c2ecf20Sopenharmony_cistatic int 21488c2ecf20Sopenharmony_ciahc_aha494X_setup(struct ahc_softc *ahc) 21498c2ecf20Sopenharmony_ci{ 21508c2ecf20Sopenharmony_ci int error; 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_ci error = ahc_aic7870_setup(ahc); 21538c2ecf20Sopenharmony_ci if (error == 0) 21548c2ecf20Sopenharmony_ci error = ahc_aha494XX_setup(ahc); 21558c2ecf20Sopenharmony_ci return (error); 21568c2ecf20Sopenharmony_ci} 21578c2ecf20Sopenharmony_ci 21588c2ecf20Sopenharmony_cistatic int 21598c2ecf20Sopenharmony_ciahc_aha494Xh_setup(struct ahc_softc *ahc) 21608c2ecf20Sopenharmony_ci{ 21618c2ecf20Sopenharmony_ci int error = ahc_aha494X_setup(ahc); 21628c2ecf20Sopenharmony_ci 21638c2ecf20Sopenharmony_ci ahc->features |= AHC_HVD; 21648c2ecf20Sopenharmony_ci 21658c2ecf20Sopenharmony_ci return error; 21668c2ecf20Sopenharmony_ci} 21678c2ecf20Sopenharmony_ci 21688c2ecf20Sopenharmony_cistatic int 21698c2ecf20Sopenharmony_ciahc_aic7880_setup(struct ahc_softc *ahc) 21708c2ecf20Sopenharmony_ci{ 21718c2ecf20Sopenharmony_ci ahc_dev_softc_t pci; 21728c2ecf20Sopenharmony_ci uint8_t rev; 21738c2ecf20Sopenharmony_ci 21748c2ecf20Sopenharmony_ci pci = ahc->dev_softc; 21758c2ecf20Sopenharmony_ci ahc->channel = 'A'; 21768c2ecf20Sopenharmony_ci ahc->chip = AHC_AIC7880; 21778c2ecf20Sopenharmony_ci ahc->features = AHC_AIC7880_FE; 21788c2ecf20Sopenharmony_ci ahc->bugs |= AHC_TMODE_WIDEODD_BUG; 21798c2ecf20Sopenharmony_ci rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 21808c2ecf20Sopenharmony_ci if (rev >= 1) { 21818c2ecf20Sopenharmony_ci ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 21828c2ecf20Sopenharmony_ci } else { 21838c2ecf20Sopenharmony_ci ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 21848c2ecf20Sopenharmony_ci } 21858c2ecf20Sopenharmony_ci ahc->instruction_ram_size = 512; 21868c2ecf20Sopenharmony_ci return (0); 21878c2ecf20Sopenharmony_ci} 21888c2ecf20Sopenharmony_ci 21898c2ecf20Sopenharmony_cistatic int 21908c2ecf20Sopenharmony_ciahc_aic7880h_setup(struct ahc_softc *ahc) 21918c2ecf20Sopenharmony_ci{ 21928c2ecf20Sopenharmony_ci int error = ahc_aic7880_setup(ahc); 21938c2ecf20Sopenharmony_ci 21948c2ecf20Sopenharmony_ci ahc->features |= AHC_HVD; 21958c2ecf20Sopenharmony_ci 21968c2ecf20Sopenharmony_ci return error; 21978c2ecf20Sopenharmony_ci} 21988c2ecf20Sopenharmony_ci 21998c2ecf20Sopenharmony_ci 22008c2ecf20Sopenharmony_cistatic int 22018c2ecf20Sopenharmony_ciahc_aha2940Pro_setup(struct ahc_softc *ahc) 22028c2ecf20Sopenharmony_ci{ 22038c2ecf20Sopenharmony_ci 22048c2ecf20Sopenharmony_ci ahc->flags |= AHC_INT50_SPEEDFLEX; 22058c2ecf20Sopenharmony_ci return (ahc_aic7880_setup(ahc)); 22068c2ecf20Sopenharmony_ci} 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_cistatic int 22098c2ecf20Sopenharmony_ciahc_aha394XU_setup(struct ahc_softc *ahc) 22108c2ecf20Sopenharmony_ci{ 22118c2ecf20Sopenharmony_ci int error; 22128c2ecf20Sopenharmony_ci 22138c2ecf20Sopenharmony_ci error = ahc_aic7880_setup(ahc); 22148c2ecf20Sopenharmony_ci if (error == 0) 22158c2ecf20Sopenharmony_ci error = ahc_aha394XX_setup(ahc); 22168c2ecf20Sopenharmony_ci return (error); 22178c2ecf20Sopenharmony_ci} 22188c2ecf20Sopenharmony_ci 22198c2ecf20Sopenharmony_cistatic int 22208c2ecf20Sopenharmony_ciahc_aha394XUh_setup(struct ahc_softc *ahc) 22218c2ecf20Sopenharmony_ci{ 22228c2ecf20Sopenharmony_ci int error = ahc_aha394XU_setup(ahc); 22238c2ecf20Sopenharmony_ci 22248c2ecf20Sopenharmony_ci ahc->features |= AHC_HVD; 22258c2ecf20Sopenharmony_ci 22268c2ecf20Sopenharmony_ci return error; 22278c2ecf20Sopenharmony_ci} 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_cistatic int 22308c2ecf20Sopenharmony_ciahc_aha398XU_setup(struct ahc_softc *ahc) 22318c2ecf20Sopenharmony_ci{ 22328c2ecf20Sopenharmony_ci int error; 22338c2ecf20Sopenharmony_ci 22348c2ecf20Sopenharmony_ci error = ahc_aic7880_setup(ahc); 22358c2ecf20Sopenharmony_ci if (error == 0) 22368c2ecf20Sopenharmony_ci error = ahc_aha398XX_setup(ahc); 22378c2ecf20Sopenharmony_ci return (error); 22388c2ecf20Sopenharmony_ci} 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_cistatic int 22418c2ecf20Sopenharmony_ciahc_aic7890_setup(struct ahc_softc *ahc) 22428c2ecf20Sopenharmony_ci{ 22438c2ecf20Sopenharmony_ci ahc_dev_softc_t pci; 22448c2ecf20Sopenharmony_ci uint8_t rev; 22458c2ecf20Sopenharmony_ci 22468c2ecf20Sopenharmony_ci pci = ahc->dev_softc; 22478c2ecf20Sopenharmony_ci ahc->channel = 'A'; 22488c2ecf20Sopenharmony_ci ahc->chip = AHC_AIC7890; 22498c2ecf20Sopenharmony_ci ahc->features = AHC_AIC7890_FE; 22508c2ecf20Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 22518c2ecf20Sopenharmony_ci rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 22528c2ecf20Sopenharmony_ci if (rev == 0) 22538c2ecf20Sopenharmony_ci ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; 22548c2ecf20Sopenharmony_ci ahc->instruction_ram_size = 768; 22558c2ecf20Sopenharmony_ci return (0); 22568c2ecf20Sopenharmony_ci} 22578c2ecf20Sopenharmony_ci 22588c2ecf20Sopenharmony_cistatic int 22598c2ecf20Sopenharmony_ciahc_aic7892_setup(struct ahc_softc *ahc) 22608c2ecf20Sopenharmony_ci{ 22618c2ecf20Sopenharmony_ci 22628c2ecf20Sopenharmony_ci ahc->channel = 'A'; 22638c2ecf20Sopenharmony_ci ahc->chip = AHC_AIC7892; 22648c2ecf20Sopenharmony_ci ahc->features = AHC_AIC7892_FE; 22658c2ecf20Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 22668c2ecf20Sopenharmony_ci ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; 22678c2ecf20Sopenharmony_ci ahc->instruction_ram_size = 1024; 22688c2ecf20Sopenharmony_ci return (0); 22698c2ecf20Sopenharmony_ci} 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_cistatic int 22728c2ecf20Sopenharmony_ciahc_aic7895_setup(struct ahc_softc *ahc) 22738c2ecf20Sopenharmony_ci{ 22748c2ecf20Sopenharmony_ci ahc_dev_softc_t pci; 22758c2ecf20Sopenharmony_ci uint8_t rev; 22768c2ecf20Sopenharmony_ci 22778c2ecf20Sopenharmony_ci pci = ahc->dev_softc; 22788c2ecf20Sopenharmony_ci ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 22798c2ecf20Sopenharmony_ci /* 22808c2ecf20Sopenharmony_ci * The 'C' revision of the aic7895 has a few additional features. 22818c2ecf20Sopenharmony_ci */ 22828c2ecf20Sopenharmony_ci rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 22838c2ecf20Sopenharmony_ci if (rev >= 4) { 22848c2ecf20Sopenharmony_ci ahc->chip = AHC_AIC7895C; 22858c2ecf20Sopenharmony_ci ahc->features = AHC_AIC7895C_FE; 22868c2ecf20Sopenharmony_ci } else { 22878c2ecf20Sopenharmony_ci u_int command; 22888c2ecf20Sopenharmony_ci 22898c2ecf20Sopenharmony_ci ahc->chip = AHC_AIC7895; 22908c2ecf20Sopenharmony_ci ahc->features = AHC_AIC7895_FE; 22918c2ecf20Sopenharmony_ci 22928c2ecf20Sopenharmony_ci /* 22938c2ecf20Sopenharmony_ci * The BIOS disables the use of MWI transactions 22948c2ecf20Sopenharmony_ci * since it does not have the MWI bug work around 22958c2ecf20Sopenharmony_ci * we have. Disabling MWI reduces performance, so 22968c2ecf20Sopenharmony_ci * turn it on again. 22978c2ecf20Sopenharmony_ci */ 22988c2ecf20Sopenharmony_ci command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); 22998c2ecf20Sopenharmony_ci command |= PCIM_CMD_MWRICEN; 23008c2ecf20Sopenharmony_ci ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); 23018c2ecf20Sopenharmony_ci ahc->bugs |= AHC_PCI_MWI_BUG; 23028c2ecf20Sopenharmony_ci } 23038c2ecf20Sopenharmony_ci /* 23048c2ecf20Sopenharmony_ci * XXX Does CACHETHEN really not work??? What about PCI retry? 23058c2ecf20Sopenharmony_ci * on C level chips. Need to test, but for now, play it safe. 23068c2ecf20Sopenharmony_ci */ 23078c2ecf20Sopenharmony_ci ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG 23088c2ecf20Sopenharmony_ci | AHC_CACHETHEN_BUG; 23098c2ecf20Sopenharmony_ci 23108c2ecf20Sopenharmony_ci#if 0 23118c2ecf20Sopenharmony_ci uint32_t devconfig; 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_ci /* 23148c2ecf20Sopenharmony_ci * Cachesize must also be zero due to stray DAC 23158c2ecf20Sopenharmony_ci * problem when sitting behind some bridges. 23168c2ecf20Sopenharmony_ci */ 23178c2ecf20Sopenharmony_ci ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); 23188c2ecf20Sopenharmony_ci devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1); 23198c2ecf20Sopenharmony_ci devconfig |= MRDCEN; 23208c2ecf20Sopenharmony_ci ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); 23218c2ecf20Sopenharmony_ci#endif 23228c2ecf20Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 23238c2ecf20Sopenharmony_ci ahc->instruction_ram_size = 512; 23248c2ecf20Sopenharmony_ci return (0); 23258c2ecf20Sopenharmony_ci} 23268c2ecf20Sopenharmony_ci 23278c2ecf20Sopenharmony_cistatic int 23288c2ecf20Sopenharmony_ciahc_aic7895h_setup(struct ahc_softc *ahc) 23298c2ecf20Sopenharmony_ci{ 23308c2ecf20Sopenharmony_ci int error = ahc_aic7895_setup(ahc); 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci ahc->features |= AHC_HVD; 23338c2ecf20Sopenharmony_ci 23348c2ecf20Sopenharmony_ci return error; 23358c2ecf20Sopenharmony_ci} 23368c2ecf20Sopenharmony_ci 23378c2ecf20Sopenharmony_cistatic int 23388c2ecf20Sopenharmony_ciahc_aic7896_setup(struct ahc_softc *ahc) 23398c2ecf20Sopenharmony_ci{ 23408c2ecf20Sopenharmony_ci ahc_dev_softc_t pci; 23418c2ecf20Sopenharmony_ci 23428c2ecf20Sopenharmony_ci pci = ahc->dev_softc; 23438c2ecf20Sopenharmony_ci ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 23448c2ecf20Sopenharmony_ci ahc->chip = AHC_AIC7896; 23458c2ecf20Sopenharmony_ci ahc->features = AHC_AIC7896_FE; 23468c2ecf20Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 23478c2ecf20Sopenharmony_ci ahc->bugs |= AHC_CACHETHEN_DIS_BUG; 23488c2ecf20Sopenharmony_ci ahc->instruction_ram_size = 768; 23498c2ecf20Sopenharmony_ci return (0); 23508c2ecf20Sopenharmony_ci} 23518c2ecf20Sopenharmony_ci 23528c2ecf20Sopenharmony_cistatic int 23538c2ecf20Sopenharmony_ciahc_aic7899_setup(struct ahc_softc *ahc) 23548c2ecf20Sopenharmony_ci{ 23558c2ecf20Sopenharmony_ci ahc_dev_softc_t pci; 23568c2ecf20Sopenharmony_ci 23578c2ecf20Sopenharmony_ci pci = ahc->dev_softc; 23588c2ecf20Sopenharmony_ci ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 23598c2ecf20Sopenharmony_ci ahc->chip = AHC_AIC7899; 23608c2ecf20Sopenharmony_ci ahc->features = AHC_AIC7899_FE; 23618c2ecf20Sopenharmony_ci ahc->flags |= AHC_NEWEEPROM_FMT; 23628c2ecf20Sopenharmony_ci ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; 23638c2ecf20Sopenharmony_ci ahc->instruction_ram_size = 1024; 23648c2ecf20Sopenharmony_ci return (0); 23658c2ecf20Sopenharmony_ci} 23668c2ecf20Sopenharmony_ci 23678c2ecf20Sopenharmony_cistatic int 23688c2ecf20Sopenharmony_ciahc_aha29160C_setup(struct ahc_softc *ahc) 23698c2ecf20Sopenharmony_ci{ 23708c2ecf20Sopenharmony_ci int error; 23718c2ecf20Sopenharmony_ci 23728c2ecf20Sopenharmony_ci error = ahc_aic7899_setup(ahc); 23738c2ecf20Sopenharmony_ci if (error != 0) 23748c2ecf20Sopenharmony_ci return (error); 23758c2ecf20Sopenharmony_ci ahc->features |= AHC_REMOVABLE; 23768c2ecf20Sopenharmony_ci return (0); 23778c2ecf20Sopenharmony_ci} 23788c2ecf20Sopenharmony_ci 23798c2ecf20Sopenharmony_cistatic int 23808c2ecf20Sopenharmony_ciahc_raid_setup(struct ahc_softc *ahc) 23818c2ecf20Sopenharmony_ci{ 23828c2ecf20Sopenharmony_ci printk("RAID functionality unsupported\n"); 23838c2ecf20Sopenharmony_ci return (ENXIO); 23848c2ecf20Sopenharmony_ci} 23858c2ecf20Sopenharmony_ci 23868c2ecf20Sopenharmony_cistatic int 23878c2ecf20Sopenharmony_ciahc_aha394XX_setup(struct ahc_softc *ahc) 23888c2ecf20Sopenharmony_ci{ 23898c2ecf20Sopenharmony_ci ahc_dev_softc_t pci; 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_ci pci = ahc->dev_softc; 23928c2ecf20Sopenharmony_ci switch (ahc_get_pci_slot(pci)) { 23938c2ecf20Sopenharmony_ci case AHC_394X_SLOT_CHANNEL_A: 23948c2ecf20Sopenharmony_ci ahc->channel = 'A'; 23958c2ecf20Sopenharmony_ci break; 23968c2ecf20Sopenharmony_ci case AHC_394X_SLOT_CHANNEL_B: 23978c2ecf20Sopenharmony_ci ahc->channel = 'B'; 23988c2ecf20Sopenharmony_ci break; 23998c2ecf20Sopenharmony_ci default: 24008c2ecf20Sopenharmony_ci printk("adapter at unexpected slot %d\n" 24018c2ecf20Sopenharmony_ci "unable to map to a channel\n", 24028c2ecf20Sopenharmony_ci ahc_get_pci_slot(pci)); 24038c2ecf20Sopenharmony_ci ahc->channel = 'A'; 24048c2ecf20Sopenharmony_ci } 24058c2ecf20Sopenharmony_ci return (0); 24068c2ecf20Sopenharmony_ci} 24078c2ecf20Sopenharmony_ci 24088c2ecf20Sopenharmony_cistatic int 24098c2ecf20Sopenharmony_ciahc_aha398XX_setup(struct ahc_softc *ahc) 24108c2ecf20Sopenharmony_ci{ 24118c2ecf20Sopenharmony_ci ahc_dev_softc_t pci; 24128c2ecf20Sopenharmony_ci 24138c2ecf20Sopenharmony_ci pci = ahc->dev_softc; 24148c2ecf20Sopenharmony_ci switch (ahc_get_pci_slot(pci)) { 24158c2ecf20Sopenharmony_ci case AHC_398X_SLOT_CHANNEL_A: 24168c2ecf20Sopenharmony_ci ahc->channel = 'A'; 24178c2ecf20Sopenharmony_ci break; 24188c2ecf20Sopenharmony_ci case AHC_398X_SLOT_CHANNEL_B: 24198c2ecf20Sopenharmony_ci ahc->channel = 'B'; 24208c2ecf20Sopenharmony_ci break; 24218c2ecf20Sopenharmony_ci case AHC_398X_SLOT_CHANNEL_C: 24228c2ecf20Sopenharmony_ci ahc->channel = 'C'; 24238c2ecf20Sopenharmony_ci break; 24248c2ecf20Sopenharmony_ci default: 24258c2ecf20Sopenharmony_ci printk("adapter at unexpected slot %d\n" 24268c2ecf20Sopenharmony_ci "unable to map to a channel\n", 24278c2ecf20Sopenharmony_ci ahc_get_pci_slot(pci)); 24288c2ecf20Sopenharmony_ci ahc->channel = 'A'; 24298c2ecf20Sopenharmony_ci break; 24308c2ecf20Sopenharmony_ci } 24318c2ecf20Sopenharmony_ci ahc->flags |= AHC_LARGE_SEEPROM; 24328c2ecf20Sopenharmony_ci return (0); 24338c2ecf20Sopenharmony_ci} 24348c2ecf20Sopenharmony_ci 24358c2ecf20Sopenharmony_cistatic int 24368c2ecf20Sopenharmony_ciahc_aha494XX_setup(struct ahc_softc *ahc) 24378c2ecf20Sopenharmony_ci{ 24388c2ecf20Sopenharmony_ci ahc_dev_softc_t pci; 24398c2ecf20Sopenharmony_ci 24408c2ecf20Sopenharmony_ci pci = ahc->dev_softc; 24418c2ecf20Sopenharmony_ci switch (ahc_get_pci_slot(pci)) { 24428c2ecf20Sopenharmony_ci case AHC_494X_SLOT_CHANNEL_A: 24438c2ecf20Sopenharmony_ci ahc->channel = 'A'; 24448c2ecf20Sopenharmony_ci break; 24458c2ecf20Sopenharmony_ci case AHC_494X_SLOT_CHANNEL_B: 24468c2ecf20Sopenharmony_ci ahc->channel = 'B'; 24478c2ecf20Sopenharmony_ci break; 24488c2ecf20Sopenharmony_ci case AHC_494X_SLOT_CHANNEL_C: 24498c2ecf20Sopenharmony_ci ahc->channel = 'C'; 24508c2ecf20Sopenharmony_ci break; 24518c2ecf20Sopenharmony_ci case AHC_494X_SLOT_CHANNEL_D: 24528c2ecf20Sopenharmony_ci ahc->channel = 'D'; 24538c2ecf20Sopenharmony_ci break; 24548c2ecf20Sopenharmony_ci default: 24558c2ecf20Sopenharmony_ci printk("adapter at unexpected slot %d\n" 24568c2ecf20Sopenharmony_ci "unable to map to a channel\n", 24578c2ecf20Sopenharmony_ci ahc_get_pci_slot(pci)); 24588c2ecf20Sopenharmony_ci ahc->channel = 'A'; 24598c2ecf20Sopenharmony_ci } 24608c2ecf20Sopenharmony_ci ahc->flags |= AHC_LARGE_SEEPROM; 24618c2ecf20Sopenharmony_ci return (0); 24628c2ecf20Sopenharmony_ci} 2463