aic7xxx_pci.c revision 120445
165942Sgibbs/* 265942Sgibbs * Product specific probe and attach routines for: 365942Sgibbs * 3940, 2940, aic7895, aic7890, aic7880, 465942Sgibbs * aic7870, aic7860 and aic7850 SCSI controllers 565942Sgibbs * 695378Sgibbs * Copyright (c) 1994-2001 Justin T. Gibbs. 795378Sgibbs * Copyright (c) 2000-2001 Adaptec Inc. 865942Sgibbs * All rights reserved. 965942Sgibbs * 1065942Sgibbs * Redistribution and use in source and binary forms, with or without 1165942Sgibbs * modification, are permitted provided that the following conditions 1265942Sgibbs * are met: 1365942Sgibbs * 1. Redistributions of source code must retain the above copyright 1465942Sgibbs * notice, this list of conditions, and the following disclaimer, 1595378Sgibbs * without modification. 1695378Sgibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1795378Sgibbs * substantially similar to the "NO WARRANTY" disclaimer below 1895378Sgibbs * ("Disclaimer") and any redistribution must be conditioned upon 1995378Sgibbs * including a substantially similar Disclaimer requirement for further 2095378Sgibbs * binary redistribution. 2195378Sgibbs * 3. Neither the names of the above-listed copyright holders nor the names 2295378Sgibbs * of any contributors may be used to endorse or promote products derived 2395378Sgibbs * from this software without specific prior written permission. 2465942Sgibbs * 2565942Sgibbs * Alternatively, this software may be distributed under the terms of the 2695378Sgibbs * GNU General Public License ("GPL") version 2 as published by the Free 2795378Sgibbs * Software Foundation. 2865942Sgibbs * 2995378Sgibbs * NO WARRANTY 3095378Sgibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3195378Sgibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3295378Sgibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3395378Sgibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3495378Sgibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3565942Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3665942Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3795378Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3895378Sgibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 3995378Sgibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4095378Sgibbs * POSSIBILITY OF SUCH DAMAGES. 4165942Sgibbs * 42120445Sscottl * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#72 $ 4365942Sgibbs */ 4465942Sgibbs 45119418Sobrien#include <sys/cdefs.h> 46119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/aic7xxx/aic7xxx_pci.c 120445 2003-09-25 23:36:41Z scottl $"); 47119418Sobrien 4895378Sgibbs#ifdef __linux__ 4995378Sgibbs#include "aic7xxx_osm.h" 5095378Sgibbs#include "aic7xxx_inline.h" 5195378Sgibbs#include "aic7xxx_93cx6.h" 5295378Sgibbs#else 5395378Sgibbs#include <dev/aic7xxx/aic7xxx_osm.h> 5465942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h> 5565942Sgibbs#include <dev/aic7xxx/aic7xxx_93cx6.h> 5695378Sgibbs#endif 5765942Sgibbs 58119690Sjhb#define AHC_PCI_IOADDR PCIR_BAR(0) /* I/O Address */ 59119690Sjhb#define AHC_PCI_MEMADDR PCIR_BAR(1) /* Mem I/O Address */ 6065942Sgibbs 6165942Sgibbsstatic __inline uint64_t 6265942Sgibbsahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) 6365942Sgibbs{ 6465942Sgibbs uint64_t id; 6565942Sgibbs 6665942Sgibbs id = subvendor 6765942Sgibbs | (subdevice << 16) 6865942Sgibbs | ((uint64_t)vendor << 32) 6965942Sgibbs | ((uint64_t)device << 48); 7065942Sgibbs 7165942Sgibbs return (id); 7265942Sgibbs} 7365942Sgibbs 7474094Sgibbs#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull 7574094Sgibbs#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull 7674094Sgibbs#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull 7774094Sgibbs#define ID_9005_SISL_MASK 0x000FFFFF00000000ull 7874094Sgibbs#define ID_9005_SISL_ID 0x0005900500000000ull 7974094Sgibbs#define ID_AIC7850 0x5078900400000000ull 80115338Sgibbs#define ID_AHA_2902_04_10_15_20C_30C 0x5078900478509004ull 8174094Sgibbs#define ID_AIC7855 0x5578900400000000ull 8274094Sgibbs#define ID_AIC7859 0x3860900400000000ull 8374094Sgibbs#define ID_AHA_2930CU 0x3860900438699004ull 8474094Sgibbs#define ID_AIC7860 0x6078900400000000ull 8574094Sgibbs#define ID_AIC7860C 0x6078900478609004ull 8674094Sgibbs#define ID_AHA_1480A 0x6075900400000000ull 8774094Sgibbs#define ID_AHA_2940AU_0 0x6178900400000000ull 8874094Sgibbs#define ID_AHA_2940AU_1 0x6178900478619004ull 8974094Sgibbs#define ID_AHA_2940AU_CN 0x2178900478219004ull 9074094Sgibbs#define ID_AHA_2930C_VAR 0x6038900438689004ull 9165942Sgibbs 9274094Sgibbs#define ID_AIC7870 0x7078900400000000ull 9374094Sgibbs#define ID_AHA_2940 0x7178900400000000ull 9474094Sgibbs#define ID_AHA_3940 0x7278900400000000ull 9574094Sgibbs#define ID_AHA_398X 0x7378900400000000ull 9674094Sgibbs#define ID_AHA_2944 0x7478900400000000ull 9774094Sgibbs#define ID_AHA_3944 0x7578900400000000ull 9874094Sgibbs#define ID_AHA_4944 0x7678900400000000ull 9965942Sgibbs 10074094Sgibbs#define ID_AIC7880 0x8078900400000000ull 10174094Sgibbs#define ID_AIC7880_B 0x8078900478809004ull 10274094Sgibbs#define ID_AHA_2940U 0x8178900400000000ull 10374094Sgibbs#define ID_AHA_3940U 0x8278900400000000ull 10474094Sgibbs#define ID_AHA_2944U 0x8478900400000000ull 10574094Sgibbs#define ID_AHA_3944U 0x8578900400000000ull 10674094Sgibbs#define ID_AHA_398XU 0x8378900400000000ull 10774094Sgibbs#define ID_AHA_4944U 0x8678900400000000ull 10874094Sgibbs#define ID_AHA_2940UB 0x8178900478819004ull 10974094Sgibbs#define ID_AHA_2930U 0x8878900478889004ull 11074094Sgibbs#define ID_AHA_2940U_PRO 0x8778900478879004ull 11174094Sgibbs#define ID_AHA_2940U_CN 0x0078900478009004ull 11265942Sgibbs 11374094Sgibbs#define ID_AIC7895 0x7895900478959004ull 11474094Sgibbs#define ID_AIC7895_ARO 0x7890900478939004ull 11574094Sgibbs#define ID_AIC7895_ARO_MASK 0xFFF0FFFFFFFFFFFFull 11674094Sgibbs#define ID_AHA_2940U_DUAL 0x7895900478919004ull 11774094Sgibbs#define ID_AHA_3940AU 0x7895900478929004ull 11874094Sgibbs#define ID_AHA_3944AU 0x7895900478949004ull 11965942Sgibbs 12074094Sgibbs#define ID_AIC7890 0x001F9005000F9005ull 12174094Sgibbs#define ID_AIC7890_ARO 0x00139005000F9005ull 12274094Sgibbs#define ID_AAA_131U2 0x0013900500039005ull 12374094Sgibbs#define ID_AHA_2930U2 0x0011900501819005ull 12474094Sgibbs#define ID_AHA_2940U2B 0x00109005A1009005ull 12574094Sgibbs#define ID_AHA_2940U2_OEM 0x0010900521809005ull 12674094Sgibbs#define ID_AHA_2940U2 0x00109005A1809005ull 12774094Sgibbs#define ID_AHA_2950U2B 0x00109005E1009005ull 12865942Sgibbs 12974094Sgibbs#define ID_AIC7892 0x008F9005FFFF9005ull 13074094Sgibbs#define ID_AIC7892_ARO 0x00839005FFFF9005ull 13174094Sgibbs#define ID_AHA_29160 0x00809005E2A09005ull 13274094Sgibbs#define ID_AHA_29160_CPQ 0x00809005E2A00E11ull 13374094Sgibbs#define ID_AHA_29160N 0x0080900562A09005ull 13474094Sgibbs#define ID_AHA_29160C 0x0080900562209005ull 13574094Sgibbs#define ID_AHA_29160B 0x00809005E2209005ull 13674094Sgibbs#define ID_AHA_19160B 0x0081900562A19005ull 13765942Sgibbs 13874094Sgibbs#define ID_AIC7896 0x005F9005FFFF9005ull 13974094Sgibbs#define ID_AIC7896_ARO 0x00539005FFFF9005ull 14074094Sgibbs#define ID_AHA_3950U2B_0 0x00509005FFFF9005ull 14174094Sgibbs#define ID_AHA_3950U2B_1 0x00509005F5009005ull 14274094Sgibbs#define ID_AHA_3950U2D_0 0x00519005FFFF9005ull 14374094Sgibbs#define ID_AHA_3950U2D_1 0x00519005B5009005ull 14465942Sgibbs 14574094Sgibbs#define ID_AIC7899 0x00CF9005FFFF9005ull 14674094Sgibbs#define ID_AIC7899_ARO 0x00C39005FFFF9005ull 14774094Sgibbs#define ID_AHA_3960D 0x00C09005F6209005ull 14874094Sgibbs#define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull 14965942Sgibbs 15074094Sgibbs#define ID_AIC7810 0x1078900400000000ull 15174094Sgibbs#define ID_AIC7815 0x7815900400000000ull 15265942Sgibbs 15372325Sgibbs#define DEVID_9005_TYPE(id) ((id) & 0xF) 15472325Sgibbs#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ 15572325Sgibbs#define DEVID_9005_TYPE_AAA 0x3 /* RAID Card */ 15695378Sgibbs#define DEVID_9005_TYPE_SISL 0x5 /* Container ROMB */ 15772325Sgibbs#define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ 15872325Sgibbs 15972325Sgibbs#define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4) 16072325Sgibbs#define DEVID_9005_MAXRATE_U160 0x0 16172325Sgibbs#define DEVID_9005_MAXRATE_ULTRA2 0x1 16272325Sgibbs#define DEVID_9005_MAXRATE_ULTRA 0x2 16372325Sgibbs#define DEVID_9005_MAXRATE_FAST 0x3 16472325Sgibbs 16572325Sgibbs#define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6) 16672325Sgibbs 16772325Sgibbs#define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8) 16872325Sgibbs#define DEVID_9005_CLASS_SPI 0x0 /* Parallel SCSI */ 16972325Sgibbs 17070693Sgibbs#define SUBID_9005_TYPE(id) ((id) & 0xF) 17170693Sgibbs#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */ 17270693Sgibbs#define SUBID_9005_TYPE_CARD 0x0 /* Standard Card */ 17370693Sgibbs#define SUBID_9005_TYPE_LCCARD 0x1 /* Low Cost Card */ 17470693Sgibbs#define SUBID_9005_TYPE_RAID 0x3 /* Combined with Raid */ 17570204Sgibbs 17672811Sgibbs#define SUBID_9005_TYPE_KNOWN(id) \ 17772811Sgibbs ((((id) & 0xF) == SUBID_9005_TYPE_MB) \ 17872811Sgibbs || (((id) & 0xF) == SUBID_9005_TYPE_CARD) \ 17972811Sgibbs || (((id) & 0xF) == SUBID_9005_TYPE_LCCARD) \ 18072811Sgibbs || (((id) & 0xF) == SUBID_9005_TYPE_RAID)) 18172811Sgibbs 18270693Sgibbs#define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4) 18370693Sgibbs#define SUBID_9005_MAXRATE_ULTRA2 0x0 18470693Sgibbs#define SUBID_9005_MAXRATE_ULTRA 0x1 18570693Sgibbs#define SUBID_9005_MAXRATE_U160 0x2 18670693Sgibbs#define SUBID_9005_MAXRATE_RESERVED 0x3 18770693Sgibbs 18870693Sgibbs#define SUBID_9005_SEEPTYPE(id) \ 18970693Sgibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 19070693Sgibbs ? ((id) & 0xC0) >> 6 \ 19170693Sgibbs : ((id) & 0x300) >> 8) 19270693Sgibbs#define SUBID_9005_SEEPTYPE_NONE 0x0 19370693Sgibbs#define SUBID_9005_SEEPTYPE_1K 0x1 19470693Sgibbs#define SUBID_9005_SEEPTYPE_2K_4K 0x2 19570693Sgibbs#define SUBID_9005_SEEPTYPE_RESERVED 0x3 19670693Sgibbs#define SUBID_9005_AUTOTERM(id) \ 19770693Sgibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 19870693Sgibbs ? (((id) & 0x400) >> 10) == 0 \ 19970693Sgibbs : (((id) & 0x40) >> 6) == 0) 20070693Sgibbs 20170693Sgibbs#define SUBID_9005_NUMCHAN(id) \ 20270693Sgibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 20370693Sgibbs ? ((id) & 0x300) >> 8 \ 20470693Sgibbs : ((id) & 0xC00) >> 10) 20570693Sgibbs 20670693Sgibbs#define SUBID_9005_LEGACYCONN(id) \ 20770693Sgibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 20870693Sgibbs ? 0 \ 20970693Sgibbs : ((id) & 0x80) >> 7) 21070693Sgibbs 21170693Sgibbs#define SUBID_9005_MFUNCENB(id) \ 21270693Sgibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 21370693Sgibbs ? ((id) & 0x800) >> 11 \ 21470693Sgibbs : ((id) & 0x1000) >> 12) 21570693Sgibbs/* 21670693Sgibbs * Informational only. Should use chip register to be 21795378Sgibbs * certain, but may be use in identification strings. 21870693Sgibbs */ 21970693Sgibbs#define SUBID_9005_CARD_SCSIWIDTH_MASK 0x2000 22070693Sgibbs#define SUBID_9005_CARD_PCIWIDTH_MASK 0x4000 22170693Sgibbs#define SUBID_9005_CARD_SEDIFF_MASK 0x8000 22270693Sgibbs 22374094Sgibbsstatic ahc_device_setup_t ahc_aic785X_setup; 22465942Sgibbsstatic ahc_device_setup_t ahc_aic7860_setup; 22571390Sgibbsstatic ahc_device_setup_t ahc_apa1480_setup; 22665942Sgibbsstatic ahc_device_setup_t ahc_aic7870_setup; 22765942Sgibbsstatic ahc_device_setup_t ahc_aha394X_setup; 22865942Sgibbsstatic ahc_device_setup_t ahc_aha494X_setup; 22965942Sgibbsstatic ahc_device_setup_t ahc_aha398X_setup; 23065942Sgibbsstatic ahc_device_setup_t ahc_aic7880_setup; 23171390Sgibbsstatic ahc_device_setup_t ahc_aha2940Pro_setup; 23265942Sgibbsstatic ahc_device_setup_t ahc_aha394XU_setup; 23365942Sgibbsstatic ahc_device_setup_t ahc_aha398XU_setup; 23465942Sgibbsstatic ahc_device_setup_t ahc_aic7890_setup; 23565942Sgibbsstatic ahc_device_setup_t ahc_aic7892_setup; 23665942Sgibbsstatic ahc_device_setup_t ahc_aic7895_setup; 23765942Sgibbsstatic ahc_device_setup_t ahc_aic7896_setup; 23865942Sgibbsstatic ahc_device_setup_t ahc_aic7899_setup; 23971390Sgibbsstatic ahc_device_setup_t ahc_aha29160C_setup; 24065942Sgibbsstatic ahc_device_setup_t ahc_raid_setup; 24165942Sgibbsstatic ahc_device_setup_t ahc_aha394XX_setup; 24265942Sgibbsstatic ahc_device_setup_t ahc_aha494XX_setup; 24365942Sgibbsstatic ahc_device_setup_t ahc_aha398XX_setup; 24465942Sgibbs 24565942Sgibbsstruct ahc_pci_identity ahc_pci_ident_table [] = 24665942Sgibbs{ 24765942Sgibbs /* aic7850 based controllers */ 24865942Sgibbs { 249115338Sgibbs ID_AHA_2902_04_10_15_20C_30C, 25065942Sgibbs ID_ALL_MASK, 251115338Sgibbs "Adaptec 2902/04/10/15/20C/30C SCSI adapter", 25274094Sgibbs ahc_aic785X_setup 25365942Sgibbs }, 25465942Sgibbs /* aic7860 based controllers */ 25565942Sgibbs { 25665942Sgibbs ID_AHA_2930CU, 25765942Sgibbs ID_ALL_MASK, 25865942Sgibbs "Adaptec 2930CU SCSI adapter", 25965942Sgibbs ahc_aic7860_setup 26065942Sgibbs }, 26165942Sgibbs { 26265942Sgibbs ID_AHA_1480A & ID_DEV_VENDOR_MASK, 26365942Sgibbs ID_DEV_VENDOR_MASK, 26465942Sgibbs "Adaptec 1480A Ultra SCSI adapter", 26571390Sgibbs ahc_apa1480_setup 26665942Sgibbs }, 26765942Sgibbs { 26865942Sgibbs ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK, 26965942Sgibbs ID_DEV_VENDOR_MASK, 27065942Sgibbs "Adaptec 2940A Ultra SCSI adapter", 27165942Sgibbs ahc_aic7860_setup 27265942Sgibbs }, 27365942Sgibbs { 27465942Sgibbs ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK, 27565942Sgibbs ID_DEV_VENDOR_MASK, 27665942Sgibbs "Adaptec 2940A/CN Ultra SCSI adapter", 27765942Sgibbs ahc_aic7860_setup 27865942Sgibbs }, 27965942Sgibbs { 28065942Sgibbs ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK, 28165942Sgibbs ID_DEV_VENDOR_MASK, 28276634Sgibbs "Adaptec 2930C Ultra SCSI adapter (VAR)", 28365942Sgibbs ahc_aic7860_setup 28465942Sgibbs }, 28565942Sgibbs /* aic7870 based controllers */ 28665942Sgibbs { 28765942Sgibbs ID_AHA_2940, 28865942Sgibbs ID_ALL_MASK, 28965942Sgibbs "Adaptec 2940 SCSI adapter", 29065942Sgibbs ahc_aic7870_setup 29165942Sgibbs }, 29265942Sgibbs { 29365942Sgibbs ID_AHA_3940, 29465942Sgibbs ID_ALL_MASK, 29565942Sgibbs "Adaptec 3940 SCSI adapter", 29665942Sgibbs ahc_aha394X_setup 29765942Sgibbs }, 29865942Sgibbs { 29965942Sgibbs ID_AHA_398X, 30065942Sgibbs ID_ALL_MASK, 30165942Sgibbs "Adaptec 398X SCSI RAID adapter", 30265942Sgibbs ahc_aha398X_setup 30365942Sgibbs }, 30465942Sgibbs { 30565942Sgibbs ID_AHA_2944, 30665942Sgibbs ID_ALL_MASK, 30765942Sgibbs "Adaptec 2944 SCSI adapter", 30865942Sgibbs ahc_aic7870_setup 30965942Sgibbs }, 31065942Sgibbs { 31165942Sgibbs ID_AHA_3944, 31265942Sgibbs ID_ALL_MASK, 31365942Sgibbs "Adaptec 3944 SCSI adapter", 31465942Sgibbs ahc_aha394X_setup 31565942Sgibbs }, 31665942Sgibbs { 31765942Sgibbs ID_AHA_4944, 31865942Sgibbs ID_ALL_MASK, 31965942Sgibbs "Adaptec 4944 SCSI adapter", 32065942Sgibbs ahc_aha494X_setup 32165942Sgibbs }, 32265942Sgibbs /* aic7880 based controllers */ 32365942Sgibbs { 32465942Sgibbs ID_AHA_2940U & ID_DEV_VENDOR_MASK, 32565942Sgibbs ID_DEV_VENDOR_MASK, 32665942Sgibbs "Adaptec 2940 Ultra SCSI adapter", 32765942Sgibbs ahc_aic7880_setup 32865942Sgibbs }, 32965942Sgibbs { 33065942Sgibbs ID_AHA_3940U & ID_DEV_VENDOR_MASK, 33165942Sgibbs ID_DEV_VENDOR_MASK, 33265942Sgibbs "Adaptec 3940 Ultra SCSI adapter", 33365942Sgibbs ahc_aha394XU_setup 33465942Sgibbs }, 33565942Sgibbs { 33665942Sgibbs ID_AHA_2944U & ID_DEV_VENDOR_MASK, 33765942Sgibbs ID_DEV_VENDOR_MASK, 33865942Sgibbs "Adaptec 2944 Ultra SCSI adapter", 33965942Sgibbs ahc_aic7880_setup 34065942Sgibbs }, 34165942Sgibbs { 34265942Sgibbs ID_AHA_3944U & ID_DEV_VENDOR_MASK, 34365942Sgibbs ID_DEV_VENDOR_MASK, 34465942Sgibbs "Adaptec 3944 Ultra SCSI adapter", 34565942Sgibbs ahc_aha394XU_setup 34665942Sgibbs }, 34765942Sgibbs { 34865942Sgibbs ID_AHA_398XU & ID_DEV_VENDOR_MASK, 34965942Sgibbs ID_DEV_VENDOR_MASK, 35065942Sgibbs "Adaptec 398X Ultra SCSI RAID adapter", 35165942Sgibbs ahc_aha398XU_setup 35265942Sgibbs }, 35365942Sgibbs { 35465942Sgibbs /* 35565942Sgibbs * XXX Don't know the slot numbers 35665942Sgibbs * so we can't identify channels 35765942Sgibbs */ 35865942Sgibbs ID_AHA_4944U & ID_DEV_VENDOR_MASK, 35965942Sgibbs ID_DEV_VENDOR_MASK, 36065942Sgibbs "Adaptec 4944 Ultra SCSI adapter", 36165942Sgibbs ahc_aic7880_setup 36265942Sgibbs }, 36365942Sgibbs { 36465942Sgibbs ID_AHA_2930U & ID_DEV_VENDOR_MASK, 36565942Sgibbs ID_DEV_VENDOR_MASK, 36665942Sgibbs "Adaptec 2930 Ultra SCSI adapter", 36765942Sgibbs ahc_aic7880_setup 36865942Sgibbs }, 36965942Sgibbs { 37065942Sgibbs ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK, 37165942Sgibbs ID_DEV_VENDOR_MASK, 37265942Sgibbs "Adaptec 2940 Pro Ultra SCSI adapter", 37371390Sgibbs ahc_aha2940Pro_setup 37465942Sgibbs }, 37565942Sgibbs { 37665942Sgibbs ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK, 37765942Sgibbs ID_DEV_VENDOR_MASK, 37865942Sgibbs "Adaptec 2940/CN Ultra SCSI adapter", 37965942Sgibbs ahc_aic7880_setup 38065942Sgibbs }, 38172811Sgibbs /* Ignore all SISL (AAC on MB) based controllers. */ 38272811Sgibbs { 38372811Sgibbs ID_9005_SISL_ID, 38472811Sgibbs ID_9005_SISL_MASK, 38572811Sgibbs NULL, 38672811Sgibbs NULL 38772811Sgibbs }, 38865942Sgibbs /* aic7890 based controllers */ 38965942Sgibbs { 39065942Sgibbs ID_AHA_2930U2, 39165942Sgibbs ID_ALL_MASK, 39265942Sgibbs "Adaptec 2930 Ultra2 SCSI adapter", 39365942Sgibbs ahc_aic7890_setup 39465942Sgibbs }, 39565942Sgibbs { 39665942Sgibbs ID_AHA_2940U2B, 39765942Sgibbs ID_ALL_MASK, 39865942Sgibbs "Adaptec 2940B Ultra2 SCSI adapter", 39965942Sgibbs ahc_aic7890_setup 40065942Sgibbs }, 40165942Sgibbs { 40265942Sgibbs ID_AHA_2940U2_OEM, 40365942Sgibbs ID_ALL_MASK, 40465942Sgibbs "Adaptec 2940 Ultra2 SCSI adapter (OEM)", 40565942Sgibbs ahc_aic7890_setup 40665942Sgibbs }, 40765942Sgibbs { 40865942Sgibbs ID_AHA_2940U2, 40965942Sgibbs ID_ALL_MASK, 41065942Sgibbs "Adaptec 2940 Ultra2 SCSI adapter", 41165942Sgibbs ahc_aic7890_setup 41265942Sgibbs }, 41365942Sgibbs { 41465942Sgibbs ID_AHA_2950U2B, 41565942Sgibbs ID_ALL_MASK, 41665942Sgibbs "Adaptec 2950 Ultra2 SCSI adapter", 41765942Sgibbs ahc_aic7890_setup 41865942Sgibbs }, 41965942Sgibbs { 42072811Sgibbs ID_AIC7890_ARO, 42172811Sgibbs ID_ALL_MASK, 42272811Sgibbs "Adaptec aic7890/91 Ultra2 SCSI adapter (ARO)", 42372811Sgibbs ahc_aic7890_setup 42472811Sgibbs }, 42572811Sgibbs { 42665942Sgibbs ID_AAA_131U2, 42765942Sgibbs ID_ALL_MASK, 42865942Sgibbs "Adaptec AAA-131 Ultra2 RAID adapter", 42965942Sgibbs ahc_aic7890_setup 43065942Sgibbs }, 43165942Sgibbs /* aic7892 based controllers */ 43265942Sgibbs { 43365942Sgibbs ID_AHA_29160, 43465942Sgibbs ID_ALL_MASK, 43565942Sgibbs "Adaptec 29160 Ultra160 SCSI adapter", 43665942Sgibbs ahc_aic7892_setup 43765942Sgibbs }, 43865942Sgibbs { 43965942Sgibbs ID_AHA_29160_CPQ, 44065942Sgibbs ID_ALL_MASK, 44165942Sgibbs "Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter", 44265942Sgibbs ahc_aic7892_setup 44365942Sgibbs }, 44465942Sgibbs { 44565942Sgibbs ID_AHA_29160N, 44665942Sgibbs ID_ALL_MASK, 44765942Sgibbs "Adaptec 29160N Ultra160 SCSI adapter", 44865942Sgibbs ahc_aic7892_setup 44965942Sgibbs }, 45065942Sgibbs { 45170204Sgibbs ID_AHA_29160C, 45270204Sgibbs ID_ALL_MASK, 45370204Sgibbs "Adaptec 29160C Ultra160 SCSI adapter", 45471390Sgibbs ahc_aha29160C_setup 45570204Sgibbs }, 45670204Sgibbs { 45765942Sgibbs ID_AHA_29160B, 45865942Sgibbs ID_ALL_MASK, 45965942Sgibbs "Adaptec 29160B Ultra160 SCSI adapter", 46065942Sgibbs ahc_aic7892_setup 46165942Sgibbs }, 46265942Sgibbs { 46365942Sgibbs ID_AHA_19160B, 46465942Sgibbs ID_ALL_MASK, 46565942Sgibbs "Adaptec 19160B Ultra160 SCSI adapter", 46665942Sgibbs ahc_aic7892_setup 46765942Sgibbs }, 46872811Sgibbs { 46972811Sgibbs ID_AIC7892_ARO, 47072811Sgibbs ID_ALL_MASK, 47176634Sgibbs "Adaptec aic7892 Ultra160 SCSI adapter (ARO)", 47272811Sgibbs ahc_aic7892_setup 47372811Sgibbs }, 47465942Sgibbs /* aic7895 based controllers */ 47565942Sgibbs { 47665942Sgibbs ID_AHA_2940U_DUAL, 47765942Sgibbs ID_ALL_MASK, 47865942Sgibbs "Adaptec 2940/DUAL Ultra SCSI adapter", 47965942Sgibbs ahc_aic7895_setup 48065942Sgibbs }, 48165942Sgibbs { 48265942Sgibbs ID_AHA_3940AU, 48365942Sgibbs ID_ALL_MASK, 48465942Sgibbs "Adaptec 3940A Ultra SCSI adapter", 48565942Sgibbs ahc_aic7895_setup 48665942Sgibbs }, 48765942Sgibbs { 48865942Sgibbs ID_AHA_3944AU, 48965942Sgibbs ID_ALL_MASK, 49065942Sgibbs "Adaptec 3944A Ultra SCSI adapter", 49165942Sgibbs ahc_aic7895_setup 49265942Sgibbs }, 49372811Sgibbs { 49472811Sgibbs ID_AIC7895_ARO, 49572811Sgibbs ID_AIC7895_ARO_MASK, 49672811Sgibbs "Adaptec aic7895 Ultra SCSI adapter (ARO)", 49772811Sgibbs ahc_aic7895_setup 49872811Sgibbs }, 49965942Sgibbs /* aic7896/97 based controllers */ 50065942Sgibbs { 50165942Sgibbs ID_AHA_3950U2B_0, 50265942Sgibbs ID_ALL_MASK, 50365942Sgibbs "Adaptec 3950B Ultra2 SCSI adapter", 50465942Sgibbs ahc_aic7896_setup 50565942Sgibbs }, 50665942Sgibbs { 50765942Sgibbs ID_AHA_3950U2B_1, 50865942Sgibbs ID_ALL_MASK, 50965942Sgibbs "Adaptec 3950B Ultra2 SCSI adapter", 51065942Sgibbs ahc_aic7896_setup 51165942Sgibbs }, 51265942Sgibbs { 51365942Sgibbs ID_AHA_3950U2D_0, 51465942Sgibbs ID_ALL_MASK, 51565942Sgibbs "Adaptec 3950D Ultra2 SCSI adapter", 51665942Sgibbs ahc_aic7896_setup 51765942Sgibbs }, 51865942Sgibbs { 51965942Sgibbs ID_AHA_3950U2D_1, 52065942Sgibbs ID_ALL_MASK, 52165942Sgibbs "Adaptec 3950D Ultra2 SCSI adapter", 52265942Sgibbs ahc_aic7896_setup 52365942Sgibbs }, 52472811Sgibbs { 52572811Sgibbs ID_AIC7896_ARO, 52672811Sgibbs ID_ALL_MASK, 52772811Sgibbs "Adaptec aic7896/97 Ultra2 SCSI adapter (ARO)", 52872811Sgibbs ahc_aic7896_setup 52972811Sgibbs }, 53065942Sgibbs /* aic7899 based controllers */ 53165942Sgibbs { 53265942Sgibbs ID_AHA_3960D, 53365942Sgibbs ID_ALL_MASK, 53465942Sgibbs "Adaptec 3960D Ultra160 SCSI adapter", 53565942Sgibbs ahc_aic7899_setup 53665942Sgibbs }, 53765942Sgibbs { 53865942Sgibbs ID_AHA_3960D_CPQ, 53965942Sgibbs ID_ALL_MASK, 54065942Sgibbs "Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter", 54165942Sgibbs ahc_aic7899_setup 54265942Sgibbs }, 54372811Sgibbs { 54472811Sgibbs ID_AIC7899_ARO, 54572811Sgibbs ID_ALL_MASK, 54672811Sgibbs "Adaptec aic7899 Ultra160 SCSI adapter (ARO)", 54772811Sgibbs ahc_aic7899_setup 54872811Sgibbs }, 54965942Sgibbs /* Generic chip probes for devices we don't know 'exactly' */ 55065942Sgibbs { 55165942Sgibbs ID_AIC7850 & ID_DEV_VENDOR_MASK, 55265942Sgibbs ID_DEV_VENDOR_MASK, 55365942Sgibbs "Adaptec aic7850 SCSI adapter", 55474094Sgibbs ahc_aic785X_setup 55565942Sgibbs }, 55665942Sgibbs { 55765942Sgibbs ID_AIC7855 & ID_DEV_VENDOR_MASK, 55865942Sgibbs ID_DEV_VENDOR_MASK, 55965942Sgibbs "Adaptec aic7855 SCSI adapter", 56074094Sgibbs ahc_aic785X_setup 56165942Sgibbs }, 56265942Sgibbs { 56365942Sgibbs ID_AIC7859 & ID_DEV_VENDOR_MASK, 56465942Sgibbs ID_DEV_VENDOR_MASK, 56576634Sgibbs "Adaptec aic7859 SCSI adapter", 56665942Sgibbs ahc_aic7860_setup 56765942Sgibbs }, 56865942Sgibbs { 56965942Sgibbs ID_AIC7860 & ID_DEV_VENDOR_MASK, 57065942Sgibbs ID_DEV_VENDOR_MASK, 57176634Sgibbs "Adaptec aic7860 Ultra SCSI adapter", 57265942Sgibbs ahc_aic7860_setup 57365942Sgibbs }, 57465942Sgibbs { 57565942Sgibbs ID_AIC7870 & ID_DEV_VENDOR_MASK, 57665942Sgibbs ID_DEV_VENDOR_MASK, 57765942Sgibbs "Adaptec aic7870 SCSI adapter", 57865942Sgibbs ahc_aic7870_setup 57965942Sgibbs }, 58065942Sgibbs { 58165942Sgibbs ID_AIC7880 & ID_DEV_VENDOR_MASK, 58265942Sgibbs ID_DEV_VENDOR_MASK, 58365942Sgibbs "Adaptec aic7880 Ultra SCSI adapter", 58465942Sgibbs ahc_aic7880_setup 58565942Sgibbs }, 58665942Sgibbs { 58772325Sgibbs ID_AIC7890 & ID_9005_GENERIC_MASK, 58872325Sgibbs ID_9005_GENERIC_MASK, 58965942Sgibbs "Adaptec aic7890/91 Ultra2 SCSI adapter", 59065942Sgibbs ahc_aic7890_setup 59165942Sgibbs }, 59265942Sgibbs { 59372325Sgibbs ID_AIC7892 & ID_9005_GENERIC_MASK, 59472325Sgibbs ID_9005_GENERIC_MASK, 59565942Sgibbs "Adaptec aic7892 Ultra160 SCSI adapter", 59665942Sgibbs ahc_aic7892_setup 59765942Sgibbs }, 59865942Sgibbs { 59965942Sgibbs ID_AIC7895 & ID_DEV_VENDOR_MASK, 60065942Sgibbs ID_DEV_VENDOR_MASK, 60165942Sgibbs "Adaptec aic7895 Ultra SCSI adapter", 60265942Sgibbs ahc_aic7895_setup 60365942Sgibbs }, 60465942Sgibbs { 60572325Sgibbs ID_AIC7896 & ID_9005_GENERIC_MASK, 60672325Sgibbs ID_9005_GENERIC_MASK, 60765942Sgibbs "Adaptec aic7896/97 Ultra2 SCSI adapter", 60865942Sgibbs ahc_aic7896_setup 60965942Sgibbs }, 61065942Sgibbs { 61172325Sgibbs ID_AIC7899 & ID_9005_GENERIC_MASK, 61272325Sgibbs ID_9005_GENERIC_MASK, 61365942Sgibbs "Adaptec aic7899 Ultra160 SCSI adapter", 61465942Sgibbs ahc_aic7899_setup 61565942Sgibbs }, 61665942Sgibbs { 61765942Sgibbs ID_AIC7810 & ID_DEV_VENDOR_MASK, 61865942Sgibbs ID_DEV_VENDOR_MASK, 61965942Sgibbs "Adaptec aic7810 RAID memory controller", 62065942Sgibbs ahc_raid_setup 62165942Sgibbs }, 62265942Sgibbs { 62365942Sgibbs ID_AIC7815 & ID_DEV_VENDOR_MASK, 62465942Sgibbs ID_DEV_VENDOR_MASK, 62565942Sgibbs "Adaptec aic7815 RAID memory controller", 62665942Sgibbs ahc_raid_setup 62765942Sgibbs } 62865942Sgibbs}; 62965942Sgibbs 63070204Sgibbsconst u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table); 63165942Sgibbs 63265942Sgibbs#define AHC_394X_SLOT_CHANNEL_A 4 63365942Sgibbs#define AHC_394X_SLOT_CHANNEL_B 5 63465942Sgibbs 63565942Sgibbs#define AHC_398X_SLOT_CHANNEL_A 4 63665942Sgibbs#define AHC_398X_SLOT_CHANNEL_B 8 63765942Sgibbs#define AHC_398X_SLOT_CHANNEL_C 12 63865942Sgibbs 63965942Sgibbs#define AHC_494X_SLOT_CHANNEL_A 4 64065942Sgibbs#define AHC_494X_SLOT_CHANNEL_B 5 64165942Sgibbs#define AHC_494X_SLOT_CHANNEL_C 6 64265942Sgibbs#define AHC_494X_SLOT_CHANNEL_D 7 64365942Sgibbs 64465942Sgibbs#define DEVCONFIG 0x40 645109590Sgibbs#define PCIERRGENDIS 0x80000000ul 64665942Sgibbs#define SCBSIZE32 0x00010000ul /* aic789X only */ 64774094Sgibbs#define REXTVALID 0x00001000ul /* ultra cards only */ 64879874Sgibbs#define MPORTMODE 0x00000400ul /* aic7870+ only */ 64979874Sgibbs#define RAMPSM 0x00000200ul /* aic7870+ only */ 65065942Sgibbs#define VOLSENSE 0x00000100ul 65179874Sgibbs#define PCI64BIT 0x00000080ul /* 64Bit PCI bus (Ultra2 Only)*/ 65265942Sgibbs#define SCBRAMSEL 0x00000080ul 65365942Sgibbs#define MRDCEN 0x00000040ul 65465942Sgibbs#define EXTSCBTIME 0x00000020ul /* aic7870 only */ 65565942Sgibbs#define EXTSCBPEN 0x00000010ul /* aic7870 only */ 65665942Sgibbs#define BERREN 0x00000008ul 65765942Sgibbs#define DACEN 0x00000004ul 65865942Sgibbs#define STPWLEVEL 0x00000002ul 65965942Sgibbs#define DIFACTNEGEN 0x00000001ul /* aic7870 only */ 66065942Sgibbs 66165942Sgibbs#define CSIZE_LATTIME 0x0c 66265942Sgibbs#define CACHESIZE 0x0000003ful /* only 5 bits */ 66365942Sgibbs#define LATTIME 0x0000ff00ul 66465942Sgibbs 665107419Sscottl/* PCI STATUS definitions */ 666107419Sscottl#define DPE 0x80 667107419Sscottl#define SSE 0x40 668107419Sscottl#define RMA 0x20 669107419Sscottl#define RTA 0x10 670107419Sscottl#define STA 0x08 671107419Sscottl#define DPR 0x01 672107419Sscottl 67395378Sgibbsstatic int ahc_9005_subdevinfo_valid(uint16_t vendor, uint16_t device, 67495378Sgibbs uint16_t subvendor, uint16_t subdevice); 67565942Sgibbsstatic int ahc_ext_scbram_present(struct ahc_softc *ahc); 67665942Sgibbsstatic void ahc_scbram_config(struct ahc_softc *ahc, int enable, 67765942Sgibbs int pcheck, int fast, int large); 67865942Sgibbsstatic void ahc_probe_ext_scbram(struct ahc_softc *ahc); 67965942Sgibbsstatic void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1); 680102676Sgibbsstatic void ahc_parse_pci_eeprom(struct ahc_softc *ahc, 681102676Sgibbs struct seeprom_config *sc); 68265942Sgibbsstatic void configure_termination(struct ahc_softc *ahc, 68365942Sgibbs struct seeprom_descriptor *sd, 68465942Sgibbs u_int adapter_control, 68565942Sgibbs u_int *sxfrctl1); 68665942Sgibbs 68765942Sgibbsstatic void ahc_new_term_detect(struct ahc_softc *ahc, 68865942Sgibbs int *enableSEC_low, 68965942Sgibbs int *enableSEC_high, 69065942Sgibbs int *enablePRI_low, 69165942Sgibbs int *enablePRI_high, 69265942Sgibbs int *eeprom_present); 69365942Sgibbsstatic void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 69465942Sgibbs int *internal68_present, 69565942Sgibbs int *externalcable_present, 69665942Sgibbs int *eeprom_present); 69765942Sgibbsstatic void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 69865942Sgibbs int *externalcable_present, 69965942Sgibbs int *eeprom_present); 700114621Sgibbsstatic void write_brdctl(struct ahc_softc *ahc, uint8_t value); 70165942Sgibbsstatic uint8_t read_brdctl(struct ahc_softc *ahc); 702114621Sgibbsstatic void ahc_pci_intr(struct ahc_softc *ahc); 703114621Sgibbsstatic int ahc_pci_chip_init(struct ahc_softc *ahc); 704114621Sgibbsstatic int ahc_pci_suspend(struct ahc_softc *ahc); 705114621Sgibbsstatic int ahc_pci_resume(struct ahc_softc *ahc); 70665942Sgibbs 70795378Sgibbsstatic int 70895378Sgibbsahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor, 70995378Sgibbs uint16_t subdevice, uint16_t subvendor) 71095378Sgibbs{ 71195378Sgibbs int result; 71295378Sgibbs 71395378Sgibbs /* Default to invalid. */ 71495378Sgibbs result = 0; 71595378Sgibbs if (vendor == 0x9005 71695378Sgibbs && subvendor == 0x9005 71795378Sgibbs && subdevice != device 71895378Sgibbs && SUBID_9005_TYPE_KNOWN(subdevice) != 0) { 71995378Sgibbs 72095378Sgibbs switch (SUBID_9005_TYPE(subdevice)) { 72195378Sgibbs case SUBID_9005_TYPE_MB: 72295378Sgibbs break; 72395378Sgibbs case SUBID_9005_TYPE_CARD: 72495378Sgibbs case SUBID_9005_TYPE_LCCARD: 72595378Sgibbs /* 72695378Sgibbs * Currently only trust Adaptec cards to 72795378Sgibbs * get the sub device info correct. 72895378Sgibbs */ 72995378Sgibbs if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA) 73095378Sgibbs result = 1; 73195378Sgibbs break; 73295378Sgibbs case SUBID_9005_TYPE_RAID: 73395378Sgibbs break; 73495378Sgibbs default: 73595378Sgibbs break; 73695378Sgibbs } 73795378Sgibbs } 73895378Sgibbs return (result); 73995378Sgibbs} 74095378Sgibbs 74165942Sgibbsstruct ahc_pci_identity * 74265942Sgibbsahc_find_pci_device(ahc_dev_softc_t pci) 74365942Sgibbs{ 74465942Sgibbs uint64_t full_id; 74565942Sgibbs uint16_t device; 74665942Sgibbs uint16_t vendor; 74765942Sgibbs uint16_t subdevice; 74865942Sgibbs uint16_t subvendor; 74965942Sgibbs struct ahc_pci_identity *entry; 75065942Sgibbs u_int i; 75165942Sgibbs 75265942Sgibbs vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); 75365942Sgibbs device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); 75465942Sgibbs subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); 75565942Sgibbs subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); 756114621Sgibbs full_id = ahc_compose_id(device, vendor, subdevice, subvendor); 75765942Sgibbs 75879874Sgibbs /* 75979874Sgibbs * If the second function is not hooked up, ignore it. 76079874Sgibbs * Unfortunately, not all MB vendors implement the 76179874Sgibbs * subdevice ID as per the Adaptec spec, so do our best 76279874Sgibbs * to sanity check it prior to accepting the subdevice 76379874Sgibbs * ID as valid. 76479874Sgibbs */ 76570204Sgibbs if (ahc_get_pci_function(pci) > 0 76695378Sgibbs && ahc_9005_subdevinfo_valid(vendor, device, subvendor, subdevice) 76770693Sgibbs && SUBID_9005_MFUNCENB(subdevice) == 0) 76870204Sgibbs return (NULL); 76970204Sgibbs 77065942Sgibbs for (i = 0; i < ahc_num_pci_devs; i++) { 77165942Sgibbs entry = &ahc_pci_ident_table[i]; 77272811Sgibbs if (entry->full_id == (full_id & entry->id_mask)) { 77372811Sgibbs /* Honor exclusion entries. */ 77472811Sgibbs if (entry->name == NULL) 77572811Sgibbs return (NULL); 77665942Sgibbs return (entry); 77772811Sgibbs } 77865942Sgibbs } 77965942Sgibbs return (NULL); 78065942Sgibbs} 78165942Sgibbs 78265942Sgibbsint 78365942Sgibbsahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) 78465942Sgibbs{ 785102676Sgibbs u_long l; 786102676Sgibbs u_int command; 787102676Sgibbs u_int our_id; 788102676Sgibbs u_int sxfrctl1; 789102676Sgibbs u_int scsiseq; 790102676Sgibbs u_int dscommand0; 791109590Sgibbs uint32_t devconfig; 792102676Sgibbs int error; 793102676Sgibbs uint8_t sblkctl; 79465942Sgibbs 795102676Sgibbs our_id = 0; 79679874Sgibbs error = entry->setup(ahc); 79765942Sgibbs if (error != 0) 79865942Sgibbs return (error); 79979874Sgibbs ahc->chip |= AHC_PCI; 80079874Sgibbs ahc->description = entry->name; 80165942Sgibbs 80295378Sgibbs ahc_power_state_change(ahc, AHC_POWER_STATE_D0); 80395378Sgibbs 80465942Sgibbs error = ahc_pci_map_registers(ahc); 80565942Sgibbs if (error != 0) 80665942Sgibbs return (error); 80765942Sgibbs 80895378Sgibbs /* 80995378Sgibbs * Before we continue probing the card, ensure that 81095378Sgibbs * its interrupts are *disabled*. We don't want 81195378Sgibbs * a misstep to hang the machine in an interrupt 81295378Sgibbs * storm. 81395378Sgibbs */ 81495378Sgibbs ahc_intr_enable(ahc, FALSE); 81570204Sgibbs 816109590Sgibbs devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 817109590Sgibbs 81879874Sgibbs /* 81979874Sgibbs * If we need to support high memory, enable dual 82079874Sgibbs * address cycles. This bit must be set to enable 82179874Sgibbs * high address bit generation even if we are on a 82279874Sgibbs * 64bit bus (PCI64BIT set in devconfig). 82379874Sgibbs */ 82479874Sgibbs if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) { 82579874Sgibbs 82679874Sgibbs if (bootverbose) 82779874Sgibbs printf("%s: Enabling 39Bit Addressing\n", 82879874Sgibbs ahc_name(ahc)); 82979874Sgibbs devconfig |= DACEN; 83079874Sgibbs } 83179874Sgibbs 832109590Sgibbs /* Ensure that pci error generation, a test feature, is disabled. */ 833109590Sgibbs devconfig |= PCIERRGENDIS; 834109590Sgibbs 835109590Sgibbs ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 836109590Sgibbs 83765942Sgibbs /* Ensure busmastering is enabled */ 838114621Sgibbs command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); 83965942Sgibbs command |= PCIM_CMD_BUSMASTEREN; 840109590Sgibbs 841114621Sgibbs ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2); 84265942Sgibbs 84365942Sgibbs /* On all PCI adapters, we allow SCB paging */ 84479874Sgibbs ahc->flags |= AHC_PAGESCBS; 84565942Sgibbs 84679874Sgibbs error = ahc_softc_init(ahc); 84765942Sgibbs if (error != 0) 84865942Sgibbs return (error); 84965942Sgibbs 850114621Sgibbs /* 851114621Sgibbs * Disable PCI parity error checking. Users typically 852114621Sgibbs * do this to work around broken PCI chipsets that get 853114621Sgibbs * the parity timing wrong and thus generate lots of spurious 854114621Sgibbs * errors. The chip only allows us to disable *all* parity 855114621Sgibbs * error reporting when doing this, so CIO bus, scb ram, and 856114621Sgibbs * scratch ram parity errors will be ignored too. 857114621Sgibbs */ 858115332Sgibbs if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0) 859115332Sgibbs ahc->seqctl |= FAILDIS; 860114621Sgibbs 86174972Sgibbs ahc->bus_intr = ahc_pci_intr; 862114621Sgibbs ahc->bus_chip_init = ahc_pci_chip_init; 863114621Sgibbs ahc->bus_suspend = ahc_pci_suspend; 864114621Sgibbs ahc->bus_resume = ahc_pci_resume; 86574972Sgibbs 86665942Sgibbs /* Remeber how the card was setup in case there is no SEEPROM */ 86770204Sgibbs if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { 86874094Sgibbs ahc_pause(ahc); 86970204Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 87070204Sgibbs our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID; 87170204Sgibbs else 87270204Sgibbs our_id = ahc_inb(ahc, SCSIID) & OID; 87370204Sgibbs sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN; 87470204Sgibbs scsiseq = ahc_inb(ahc, SCSISEQ); 87570204Sgibbs } else { 87670204Sgibbs sxfrctl1 = STPWEN; 87770204Sgibbs our_id = 7; 87870204Sgibbs scsiseq = 0; 87970204Sgibbs } 88065942Sgibbs 881115917Sgibbs error = ahc_reset(ahc, /*reinit*/FALSE); 88265942Sgibbs if (error != 0) 88365942Sgibbs return (ENXIO); 88465942Sgibbs 88565942Sgibbs if ((ahc->features & AHC_DT) != 0) { 88665942Sgibbs u_int sfunct; 88765942Sgibbs 88865942Sgibbs /* Perform ALT-Mode Setup */ 88965942Sgibbs sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 89065942Sgibbs ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 89176634Sgibbs ahc_outb(ahc, OPTIONMODE, 89276634Sgibbs OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS); 89365942Sgibbs ahc_outb(ahc, SFUNCT, sfunct); 89465942Sgibbs 89565942Sgibbs /* Normal mode setup */ 89665942Sgibbs ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN 89770204Sgibbs |TARGCRCENDEN); 89865942Sgibbs } 89965942Sgibbs 90065942Sgibbs dscommand0 = ahc_inb(ahc, DSCOMMAND0); 90166647Sgibbs dscommand0 |= MPARCKEN|CACHETHEN; 90265942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 90365942Sgibbs 90465942Sgibbs /* 90565942Sgibbs * DPARCKEN doesn't work correctly on 90665942Sgibbs * some MBs so don't use it. 90765942Sgibbs */ 90865942Sgibbs dscommand0 &= ~DPARCKEN; 90965942Sgibbs } 91065942Sgibbs 91165942Sgibbs /* 91265942Sgibbs * Handle chips that must have cache line 91365942Sgibbs * streaming (dis/en)abled. 91465942Sgibbs */ 91565942Sgibbs if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0) 91665942Sgibbs dscommand0 |= CACHETHEN; 91765942Sgibbs 91865942Sgibbs if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0) 91965942Sgibbs dscommand0 &= ~CACHETHEN; 92065942Sgibbs 92165942Sgibbs ahc_outb(ahc, DSCOMMAND0, dscommand0); 92265942Sgibbs 92365942Sgibbs ahc->pci_cachesize = 92465942Sgibbs ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, 92565942Sgibbs /*bytes*/1) & CACHESIZE; 92665942Sgibbs ahc->pci_cachesize *= 4; 92765942Sgibbs 92881170Sgibbs if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0 92981170Sgibbs && ahc->pci_cachesize == 4) { 93081170Sgibbs 93181170Sgibbs ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, 93281170Sgibbs 0, /*bytes*/1); 93381170Sgibbs ahc->pci_cachesize = 0; 93481170Sgibbs } 93581170Sgibbs 93676634Sgibbs /* 93776634Sgibbs * We cannot perform ULTRA speeds without the presense 93876634Sgibbs * of the external precision resistor. 93976634Sgibbs */ 94076634Sgibbs if ((ahc->features & AHC_ULTRA) != 0) { 94176634Sgibbs uint32_t devconfig; 94276634Sgibbs 94376634Sgibbs devconfig = ahc_pci_read_config(ahc->dev_softc, 94476634Sgibbs DEVCONFIG, /*bytes*/4); 94576634Sgibbs if ((devconfig & REXTVALID) == 0) 94676634Sgibbs ahc->features &= ~AHC_ULTRA; 94776634Sgibbs } 94876634Sgibbs 94965942Sgibbs /* See if we have a SEEPROM and perform auto-term */ 95065942Sgibbs check_extport(ahc, &sxfrctl1); 95165942Sgibbs 95265942Sgibbs /* 95365942Sgibbs * Take the LED out of diagnostic mode 95465942Sgibbs */ 95565942Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL); 95665942Sgibbs ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON))); 95765942Sgibbs 95865942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 95968087Sgibbs ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX); 96065942Sgibbs } else { 96165942Sgibbs ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100); 96265942Sgibbs } 96365942Sgibbs 96465942Sgibbs if (ahc->flags & AHC_USEDEFAULTS) { 96565942Sgibbs /* 96665942Sgibbs * PCI Adapter default setup 96765942Sgibbs * Should only be used if the adapter does not have 96865942Sgibbs * a SEEPROM. 96965942Sgibbs */ 97065942Sgibbs /* See if someone else set us up already */ 971109590Sgibbs if ((ahc->flags & AHC_NO_BIOS_INIT) == 0 972109590Sgibbs && scsiseq != 0) { 97365942Sgibbs printf("%s: Using left over BIOS settings\n", 97465942Sgibbs ahc_name(ahc)); 97565942Sgibbs ahc->flags &= ~AHC_USEDEFAULTS; 97672325Sgibbs ahc->flags |= AHC_BIOS_ENABLED; 97765942Sgibbs } else { 97865942Sgibbs /* 97965942Sgibbs * Assume only one connector and always turn 98065942Sgibbs * on termination. 98165942Sgibbs */ 98265942Sgibbs our_id = 0x07; 98365942Sgibbs sxfrctl1 = STPWEN; 98465942Sgibbs } 98565942Sgibbs ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI); 98665942Sgibbs 98765942Sgibbs ahc->our_id = our_id; 98865942Sgibbs } 98965942Sgibbs 99065942Sgibbs /* 99165942Sgibbs * Take a look to see if we have external SRAM. 99265942Sgibbs * We currently do not attempt to use SRAM that is 99365942Sgibbs * shared among multiple controllers. 99465942Sgibbs */ 99565942Sgibbs ahc_probe_ext_scbram(ahc); 99665942Sgibbs 99765942Sgibbs /* 99865942Sgibbs * Record our termination setting for the 99965942Sgibbs * generic initialization routine. 100065942Sgibbs */ 100165942Sgibbs if ((sxfrctl1 & STPWEN) != 0) 100265942Sgibbs ahc->flags |= AHC_TERM_ENB_A; 100365942Sgibbs 1004114621Sgibbs /* 1005114621Sgibbs * Save chip register configuration data for chip resets 1006114621Sgibbs * that occur during runtime and resume events. 1007114621Sgibbs */ 1008114621Sgibbs ahc->bus_softc.pci_softc.devconfig = 1009114621Sgibbs ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 1010114621Sgibbs ahc->bus_softc.pci_softc.command = 1011114621Sgibbs ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); 1012114621Sgibbs ahc->bus_softc.pci_softc.csize_lattime = 1013114621Sgibbs ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1); 1014114621Sgibbs ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0); 1015114621Sgibbs ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS); 1016114621Sgibbs if ((ahc->features & AHC_DT) != 0) { 1017114621Sgibbs u_int sfunct; 1018114621Sgibbs 1019114621Sgibbs sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 1020114621Sgibbs ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 1021114621Sgibbs ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE); 1022114621Sgibbs ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT); 1023114621Sgibbs ahc_outb(ahc, SFUNCT, sfunct); 1024114621Sgibbs ahc->bus_softc.pci_softc.crccontrol1 = 1025114621Sgibbs ahc_inb(ahc, CRCCONTROL1); 1026114621Sgibbs } 1027114621Sgibbs if ((ahc->features & AHC_MULTI_FUNC) != 0) 1028114621Sgibbs ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR); 1029114621Sgibbs 1030114621Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 1031114621Sgibbs ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH); 1032114621Sgibbs 103365942Sgibbs /* Core initialization */ 103465942Sgibbs error = ahc_init(ahc); 103565942Sgibbs if (error != 0) 103665942Sgibbs return (error); 103765942Sgibbs 103865942Sgibbs /* 103974972Sgibbs * Allow interrupts now that we are completely setup. 104074972Sgibbs */ 104176634Sgibbs error = ahc_pci_map_int(ahc); 104276634Sgibbs if (error != 0) 104376634Sgibbs return (error); 104476634Sgibbs 1045102676Sgibbs ahc_list_lock(&l); 1046102676Sgibbs /* 1047102676Sgibbs * Link this softc in with all other ahc instances. 1048102676Sgibbs */ 1049102676Sgibbs ahc_softc_insert(ahc); 1050102676Sgibbs ahc_list_unlock(&l); 105165942Sgibbs return (0); 105265942Sgibbs} 105365942Sgibbs 105465942Sgibbs/* 105565942Sgibbs * Test for the presense of external sram in an 105665942Sgibbs * "unshared" configuration. 105765942Sgibbs */ 105865942Sgibbsstatic int 105965942Sgibbsahc_ext_scbram_present(struct ahc_softc *ahc) 106065942Sgibbs{ 106168087Sgibbs u_int chip; 106265942Sgibbs int ramps; 106365942Sgibbs int single_user; 106465942Sgibbs uint32_t devconfig; 106565942Sgibbs 106668087Sgibbs chip = ahc->chip & AHC_CHIPID_MASK; 106765942Sgibbs devconfig = ahc_pci_read_config(ahc->dev_softc, 106865942Sgibbs DEVCONFIG, /*bytes*/4); 106965942Sgibbs single_user = (devconfig & MPORTMODE) != 0; 107065942Sgibbs 107165942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 107265942Sgibbs ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0; 107395378Sgibbs else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C) 107495378Sgibbs /* 107595378Sgibbs * External SCBRAM arbitration is flakey 107695378Sgibbs * on these chips. Unfortunately this means 107795378Sgibbs * we don't use the extra SCB ram space on the 107895378Sgibbs * 3940AUW. 107995378Sgibbs */ 108095378Sgibbs ramps = 0; 108168087Sgibbs else if (chip >= AHC_AIC7870) 108265942Sgibbs ramps = (devconfig & RAMPSM) != 0; 108365942Sgibbs else 108465942Sgibbs ramps = 0; 108565942Sgibbs 108665942Sgibbs if (ramps && single_user) 108765942Sgibbs return (1); 108865942Sgibbs return (0); 108965942Sgibbs} 109065942Sgibbs 109165942Sgibbs/* 109265942Sgibbs * Enable external scbram. 109365942Sgibbs */ 109465942Sgibbsstatic void 109565942Sgibbsahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck, 109665942Sgibbs int fast, int large) 109765942Sgibbs{ 109865942Sgibbs uint32_t devconfig; 109965942Sgibbs 110065942Sgibbs if (ahc->features & AHC_MULTI_FUNC) { 110165942Sgibbs /* 110265942Sgibbs * Set the SCB Base addr (highest address bit) 110365942Sgibbs * depending on which channel we are. 110465942Sgibbs */ 110565942Sgibbs ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc)); 110665942Sgibbs } 110765942Sgibbs 1108102676Sgibbs ahc->flags &= ~AHC_LSCBS_ENABLED; 1109102676Sgibbs if (large) 1110102676Sgibbs ahc->flags |= AHC_LSCBS_ENABLED; 111165942Sgibbs devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 111265942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 111365942Sgibbs u_int dscommand0; 111465942Sgibbs 111565942Sgibbs dscommand0 = ahc_inb(ahc, DSCOMMAND0); 111665942Sgibbs if (enable) 111765942Sgibbs dscommand0 &= ~INTSCBRAMSEL; 111865942Sgibbs else 111965942Sgibbs dscommand0 |= INTSCBRAMSEL; 112065942Sgibbs if (large) 112165942Sgibbs dscommand0 &= ~USCBSIZE32; 112265942Sgibbs else 112365942Sgibbs dscommand0 |= USCBSIZE32; 112465942Sgibbs ahc_outb(ahc, DSCOMMAND0, dscommand0); 112565942Sgibbs } else { 112665942Sgibbs if (fast) 112765942Sgibbs devconfig &= ~EXTSCBTIME; 112865942Sgibbs else 112965942Sgibbs devconfig |= EXTSCBTIME; 113065942Sgibbs if (enable) 113165942Sgibbs devconfig &= ~SCBRAMSEL; 113265942Sgibbs else 113365942Sgibbs devconfig |= SCBRAMSEL; 113465942Sgibbs if (large) 113565942Sgibbs devconfig &= ~SCBSIZE32; 113665942Sgibbs else 113765942Sgibbs devconfig |= SCBSIZE32; 113865942Sgibbs } 113965942Sgibbs if (pcheck) 114065942Sgibbs devconfig |= EXTSCBPEN; 114165942Sgibbs else 114265942Sgibbs devconfig &= ~EXTSCBPEN; 114365942Sgibbs 114465942Sgibbs ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 114565942Sgibbs} 114665942Sgibbs 114765942Sgibbs/* 114865942Sgibbs * Take a look to see if we have external SRAM. 114965942Sgibbs * We currently do not attempt to use SRAM that is 115065942Sgibbs * shared among multiple controllers. 115165942Sgibbs */ 115265942Sgibbsstatic void 115365942Sgibbsahc_probe_ext_scbram(struct ahc_softc *ahc) 115465942Sgibbs{ 115565942Sgibbs int num_scbs; 115665942Sgibbs int test_num_scbs; 115765942Sgibbs int enable; 115865942Sgibbs int pcheck; 115965942Sgibbs int fast; 116065942Sgibbs int large; 116165942Sgibbs 116265942Sgibbs enable = FALSE; 116365942Sgibbs pcheck = FALSE; 116465942Sgibbs fast = FALSE; 116565942Sgibbs large = FALSE; 116665942Sgibbs num_scbs = 0; 116765942Sgibbs 116865942Sgibbs if (ahc_ext_scbram_present(ahc) == 0) 116965942Sgibbs goto done; 117065942Sgibbs 117165942Sgibbs /* 117265942Sgibbs * Probe for the best parameters to use. 117365942Sgibbs */ 117465942Sgibbs ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large); 117565942Sgibbs num_scbs = ahc_probe_scbs(ahc); 117665942Sgibbs if (num_scbs == 0) { 117765942Sgibbs /* The SRAM wasn't really present. */ 117865942Sgibbs goto done; 117965942Sgibbs } 118065942Sgibbs enable = TRUE; 118165942Sgibbs 118265942Sgibbs /* 118365942Sgibbs * Clear any outstanding parity error 118465942Sgibbs * and ensure that parity error reporting 118565942Sgibbs * is enabled. 118665942Sgibbs */ 118765942Sgibbs ahc_outb(ahc, SEQCTL, 0); 118865942Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 118965942Sgibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 119065942Sgibbs 119165942Sgibbs /* Now see if we can do parity */ 119265942Sgibbs ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large); 119365942Sgibbs num_scbs = ahc_probe_scbs(ahc); 119465942Sgibbs if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 119565942Sgibbs || (ahc_inb(ahc, ERROR) & MPARERR) == 0) 119665942Sgibbs pcheck = TRUE; 119765942Sgibbs 119865942Sgibbs /* Clear any resulting parity error */ 119965942Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 120065942Sgibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 120165942Sgibbs 120265942Sgibbs /* Now see if we can do fast timing */ 120365942Sgibbs ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large); 120465942Sgibbs test_num_scbs = ahc_probe_scbs(ahc); 120565942Sgibbs if (test_num_scbs == num_scbs 120665942Sgibbs && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 120765942Sgibbs || (ahc_inb(ahc, ERROR) & MPARERR) == 0)) 120865942Sgibbs fast = TRUE; 120965942Sgibbs 121065942Sgibbs /* 121165942Sgibbs * See if we can use large SCBs and still maintain 121265942Sgibbs * the same overall count of SCBs. 121365942Sgibbs */ 121465942Sgibbs if ((ahc->features & AHC_LARGE_SCBS) != 0) { 121565942Sgibbs ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE); 121665942Sgibbs test_num_scbs = ahc_probe_scbs(ahc); 121765942Sgibbs if (test_num_scbs >= num_scbs) { 121865942Sgibbs large = TRUE; 121965942Sgibbs num_scbs = test_num_scbs; 122065942Sgibbs if (num_scbs >= 64) { 122165942Sgibbs /* 122265942Sgibbs * We have enough space to move the 122365942Sgibbs * "busy targets table" into SCB space 122465942Sgibbs * and make it qualify all the way to the 122565942Sgibbs * lun level. 122665942Sgibbs */ 122765942Sgibbs ahc->flags |= AHC_SCB_BTT; 122865942Sgibbs } 122965942Sgibbs } 123065942Sgibbs } 123165942Sgibbsdone: 123265942Sgibbs /* 123365942Sgibbs * Disable parity error reporting until we 123465942Sgibbs * can load instruction ram. 123565942Sgibbs */ 123665942Sgibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); 123765942Sgibbs /* Clear any latched parity error */ 123865942Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 123965942Sgibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 124065942Sgibbs if (bootverbose && enable) { 124165942Sgibbs printf("%s: External SRAM, %s access%s, %dbytes/SCB\n", 124265942Sgibbs ahc_name(ahc), fast ? "fast" : "slow", 124365942Sgibbs pcheck ? ", parity checking enabled" : "", 124465942Sgibbs large ? 64 : 32); 124565942Sgibbs } 124665942Sgibbs ahc_scbram_config(ahc, enable, pcheck, fast, large); 124765942Sgibbs} 124865942Sgibbs 124965942Sgibbs/* 1250107419Sscottl * Perform some simple tests that should catch situations where 1251107419Sscottl * our registers are invalidly mapped. 1252107419Sscottl */ 1253107419Sscottlint 1254107419Sscottlahc_pci_test_register_access(struct ahc_softc *ahc) 1255107419Sscottl{ 1256109590Sgibbs int error; 1257109590Sgibbs u_int status1; 1258109590Sgibbs uint32_t cmd; 1259109590Sgibbs uint8_t hcntrl; 1260107419Sscottl 1261107623Sscottl error = EIO; 1262107623Sscottl 1263109590Sgibbs /* 1264109590Sgibbs * Enable PCI error interrupt status, but suppress NMIs 1265109590Sgibbs * generated by SERR raised due to target aborts. 1266109590Sgibbs */ 1267109590Sgibbs cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2); 1268109590Sgibbs ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, 1269109590Sgibbs cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); 1270107623Sscottl 1271107419Sscottl /* 1272107419Sscottl * First a simple test to see if any 1273107419Sscottl * registers can be read. Reading 1274107419Sscottl * HCNTRL has no side effects and has 1275107419Sscottl * at least one bit that is guaranteed to 1276107419Sscottl * be zero so it is a good register to 1277107419Sscottl * use for this test. 1278107419Sscottl */ 1279109590Sgibbs hcntrl = ahc_inb(ahc, HCNTRL); 1280109590Sgibbs if (hcntrl == 0xFF) 1281107623Sscottl goto fail; 1282107419Sscottl 1283107419Sscottl /* 1284107419Sscottl * Next create a situation where write combining 1285107419Sscottl * or read prefetching could be initiated by the 1286107419Sscottl * CPU or host bridge. Our device does not support 1287107419Sscottl * either, so look for data corruption and/or flagged 1288120445Sscottl * PCI errors. First pause without causing another 1289120445Sscottl * chip reset. 1290107419Sscottl */ 1291120445Sscottl hcntrl &= ~CHIPRST; 1292109590Sgibbs ahc_outb(ahc, HCNTRL, hcntrl|PAUSE); 1293109590Sgibbs while (ahc_is_paused(ahc) == 0) 1294109590Sgibbs ; 1295115919Sgibbs 1296115919Sgibbs /* Clear any PCI errors that occurred before our driver attached. */ 1297115919Sgibbs status1 = ahc_pci_read_config(ahc->dev_softc, 1298115919Sgibbs PCIR_STATUS + 1, /*bytes*/1); 1299115919Sgibbs ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 1300115919Sgibbs status1, /*bytes*/1); 1301115919Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 1302115919Sgibbs 1303109590Sgibbs ahc_outb(ahc, SEQCTL, PERRORDIS); 1304109590Sgibbs ahc_outb(ahc, SCBPTR, 0); 1305109590Sgibbs ahc_outl(ahc, SCB_BASE, 0x5aa555aa); 1306109590Sgibbs if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa) 1307107623Sscottl goto fail; 1308107419Sscottl 1309107419Sscottl status1 = ahc_pci_read_config(ahc->dev_softc, 1310107419Sscottl PCIR_STATUS + 1, /*bytes*/1); 1311107623Sscottl if ((status1 & STA) != 0) 1312107623Sscottl goto fail; 1313107419Sscottl 1314107623Sscottl error = 0; 1315107419Sscottl 1316107623Sscottlfail: 1317107623Sscottl /* Silently clear any latched errors. */ 1318107623Sscottl status1 = ahc_pci_read_config(ahc->dev_softc, 1319107623Sscottl PCIR_STATUS + 1, /*bytes*/1); 1320107623Sscottl ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 1321107623Sscottl status1, /*bytes*/1); 1322107623Sscottl ahc_outb(ahc, CLRINT, CLRPARERR); 1323109590Sgibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); 1324109590Sgibbs ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); 1325107623Sscottl return (error); 1326107419Sscottl} 1327107419Sscottl 1328107419Sscottl/* 132965942Sgibbs * Check the external port logic for a serial eeprom 133065942Sgibbs * and termination/cable detection contrls. 133165942Sgibbs */ 133265942Sgibbsstatic void 133365942Sgibbscheck_extport(struct ahc_softc *ahc, u_int *sxfrctl1) 133465942Sgibbs{ 133565942Sgibbs struct seeprom_descriptor sd; 1336102676Sgibbs struct seeprom_config *sc; 133765942Sgibbs int have_seeprom; 133865942Sgibbs int have_autoterm; 133965942Sgibbs 134065942Sgibbs sd.sd_ahc = ahc; 134165942Sgibbs sd.sd_control_offset = SEECTL; 134265942Sgibbs sd.sd_status_offset = SEECTL; 134365942Sgibbs sd.sd_dataout_offset = SEECTL; 1344102676Sgibbs sc = ahc->seep_config; 134565942Sgibbs 134665942Sgibbs /* 134765942Sgibbs * For some multi-channel devices, the c46 is simply too 134865942Sgibbs * small to work. For the other controller types, we can 134965942Sgibbs * get our information from either SEEPROM type. Set the 135065942Sgibbs * type to start our probe with accordingly. 135165942Sgibbs */ 135265942Sgibbs if (ahc->flags & AHC_LARGE_SEEPROM) 135365942Sgibbs sd.sd_chip = C56_66; 135465942Sgibbs else 135565942Sgibbs sd.sd_chip = C46; 135665942Sgibbs 135765942Sgibbs sd.sd_MS = SEEMS; 135865942Sgibbs sd.sd_RDY = SEERDY; 135965942Sgibbs sd.sd_CS = SEECS; 136065942Sgibbs sd.sd_CK = SEECK; 136165942Sgibbs sd.sd_DO = SEEDO; 136265942Sgibbs sd.sd_DI = SEEDI; 136365942Sgibbs 136495378Sgibbs have_seeprom = ahc_acquire_seeprom(ahc, &sd); 136565942Sgibbs if (have_seeprom) { 136665942Sgibbs 136765942Sgibbs if (bootverbose) 136865942Sgibbs printf("%s: Reading SEEPROM...", ahc_name(ahc)); 136965942Sgibbs 137065942Sgibbs for (;;) { 137165942Sgibbs u_int start_addr; 137265942Sgibbs 137365942Sgibbs start_addr = 32 * (ahc->channel - 'A'); 137465942Sgibbs 1375102676Sgibbs have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc, 137695378Sgibbs start_addr, 1377102676Sgibbs sizeof(*sc)/2); 137865942Sgibbs 137965942Sgibbs if (have_seeprom) 1380102676Sgibbs have_seeprom = ahc_verify_cksum(sc); 138165942Sgibbs 138265942Sgibbs if (have_seeprom != 0 || sd.sd_chip == C56_66) { 138365942Sgibbs if (bootverbose) { 138465942Sgibbs if (have_seeprom == 0) 138565942Sgibbs printf ("checksum error\n"); 138665942Sgibbs else 138765942Sgibbs printf ("done.\n"); 138865942Sgibbs } 138965942Sgibbs break; 139065942Sgibbs } 139165942Sgibbs sd.sd_chip = C56_66; 139265942Sgibbs } 139395378Sgibbs ahc_release_seeprom(&sd); 139465942Sgibbs } 139565942Sgibbs 139665942Sgibbs if (!have_seeprom) { 139765942Sgibbs /* 139865942Sgibbs * Pull scratch ram settings and treat them as 139965942Sgibbs * if they are the contents of an seeprom if 140065942Sgibbs * the 'ADPT' signature is found in SCB2. 140174094Sgibbs * We manually compose the data as 16bit values 140274094Sgibbs * to avoid endian issues. 140365942Sgibbs */ 140465942Sgibbs ahc_outb(ahc, SCBPTR, 2); 140565942Sgibbs if (ahc_inb(ahc, SCB_BASE) == 'A' 140665942Sgibbs && ahc_inb(ahc, SCB_BASE + 1) == 'D' 140765942Sgibbs && ahc_inb(ahc, SCB_BASE + 2) == 'P' 140865942Sgibbs && ahc_inb(ahc, SCB_BASE + 3) == 'T') { 140974094Sgibbs uint16_t *sc_data; 141065942Sgibbs int i; 141165942Sgibbs 1412102676Sgibbs sc_data = (uint16_t *)sc; 1413102676Sgibbs for (i = 0; i < 32; i++, sc_data++) { 1414102676Sgibbs int j; 141574094Sgibbs 141674094Sgibbs j = i * 2; 1417102676Sgibbs *sc_data = ahc_inb(ahc, SRAM_BASE + j) 1418102676Sgibbs | ahc_inb(ahc, SRAM_BASE + j + 1) << 8; 141974094Sgibbs } 1420102676Sgibbs have_seeprom = ahc_verify_cksum(sc); 1421102676Sgibbs if (have_seeprom) 1422102676Sgibbs ahc->flags |= AHC_SCB_CONFIG_USED; 142365942Sgibbs } 142495378Sgibbs /* 142595378Sgibbs * Clear any SCB parity errors in case this data and 142695378Sgibbs * its associated parity was not initialized by the BIOS 142795378Sgibbs */ 142895378Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 142995378Sgibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 143065942Sgibbs } 143165942Sgibbs 143265942Sgibbs if (!have_seeprom) { 143365942Sgibbs if (bootverbose) 143465942Sgibbs printf("%s: No SEEPROM available.\n", ahc_name(ahc)); 143565942Sgibbs ahc->flags |= AHC_USEDEFAULTS; 1436102676Sgibbs free(ahc->seep_config, M_DEVBUF); 1437102676Sgibbs ahc->seep_config = NULL; 1438102676Sgibbs sc = NULL; 143965942Sgibbs } else { 1440102676Sgibbs ahc_parse_pci_eeprom(ahc, sc); 144165942Sgibbs } 144265942Sgibbs 144365942Sgibbs /* 144465942Sgibbs * Cards that have the external logic necessary to talk to 144565942Sgibbs * a SEEPROM, are almost certain to have the remaining logic 144665942Sgibbs * necessary for auto-termination control. This assumption 144765942Sgibbs * hasn't failed yet... 144865942Sgibbs */ 144965942Sgibbs have_autoterm = have_seeprom; 145065942Sgibbs 145165942Sgibbs /* 145265942Sgibbs * Some low-cost chips have SEEPROM and auto-term control built 145365942Sgibbs * in, instead of using a GAL. They can tell us directly 145465942Sgibbs * if the termination logic is enabled. 145565942Sgibbs */ 145665942Sgibbs if ((ahc->features & AHC_SPIOCAP) != 0) { 1457102676Sgibbs if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0) 145865942Sgibbs have_autoterm = FALSE; 145965942Sgibbs } 146065942Sgibbs 146174094Sgibbs if (have_autoterm) { 1462114621Sgibbs ahc->flags |= AHC_HAS_TERM_LOGIC; 146395378Sgibbs ahc_acquire_seeprom(ahc, &sd); 1464102676Sgibbs configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1); 146595378Sgibbs ahc_release_seeprom(&sd); 1466102676Sgibbs } else if (have_seeprom) { 1467102676Sgibbs *sxfrctl1 &= ~STPWEN; 1468102676Sgibbs if ((sc->adapter_control & CFSTERM) != 0) 1469102676Sgibbs *sxfrctl1 |= STPWEN; 1470102676Sgibbs if (bootverbose) 1471102676Sgibbs printf("%s: Low byte termination %sabled\n", 1472102676Sgibbs ahc_name(ahc), 1473102676Sgibbs (*sxfrctl1 & STPWEN) ? "en" : "dis"); 147474094Sgibbs } 147565942Sgibbs} 147665942Sgibbs 147765942Sgibbsstatic void 1478102676Sgibbsahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc) 1479102676Sgibbs{ 1480102676Sgibbs /* 1481102676Sgibbs * Put the data we've collected down into SRAM 1482102676Sgibbs * where ahc_init will find it. 1483102676Sgibbs */ 1484102676Sgibbs int i; 1485102676Sgibbs int max_targ = sc->max_targets & CFMAXTARG; 1486102676Sgibbs u_int scsi_conf; 1487102676Sgibbs uint16_t discenable; 1488102676Sgibbs uint16_t ultraenb; 1489102676Sgibbs 1490102676Sgibbs discenable = 0; 1491102676Sgibbs ultraenb = 0; 1492102676Sgibbs if ((sc->adapter_control & CFULTRAEN) != 0) { 1493102676Sgibbs /* 1494102676Sgibbs * Determine if this adapter has a "newstyle" 1495102676Sgibbs * SEEPROM format. 1496102676Sgibbs */ 1497102676Sgibbs for (i = 0; i < max_targ; i++) { 1498102676Sgibbs if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) { 1499102676Sgibbs ahc->flags |= AHC_NEWEEPROM_FMT; 1500102676Sgibbs break; 1501102676Sgibbs } 1502102676Sgibbs } 1503102676Sgibbs } 1504102676Sgibbs 1505102676Sgibbs for (i = 0; i < max_targ; i++) { 1506102676Sgibbs u_int scsirate; 1507102676Sgibbs uint16_t target_mask; 1508102676Sgibbs 1509102676Sgibbs target_mask = 0x01 << i; 1510102676Sgibbs if (sc->device_flags[i] & CFDISC) 1511102676Sgibbs discenable |= target_mask; 1512102676Sgibbs if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) { 1513102676Sgibbs if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) 1514102676Sgibbs ultraenb |= target_mask; 1515102676Sgibbs } else if ((sc->adapter_control & CFULTRAEN) != 0) { 1516102676Sgibbs ultraenb |= target_mask; 1517102676Sgibbs } 1518102676Sgibbs if ((sc->device_flags[i] & CFXFER) == 0x04 1519102676Sgibbs && (ultraenb & target_mask) != 0) { 1520102676Sgibbs /* Treat 10MHz as a non-ultra speed */ 1521102676Sgibbs sc->device_flags[i] &= ~CFXFER; 1522102676Sgibbs ultraenb &= ~target_mask; 1523102676Sgibbs } 1524102676Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 1525102676Sgibbs u_int offset; 1526102676Sgibbs 1527102676Sgibbs if (sc->device_flags[i] & CFSYNCH) 1528102676Sgibbs offset = MAX_OFFSET_ULTRA2; 1529102676Sgibbs else 1530102676Sgibbs offset = 0; 1531102676Sgibbs ahc_outb(ahc, TARG_OFFSET + i, offset); 1532102676Sgibbs 1533102676Sgibbs /* 1534102676Sgibbs * The ultra enable bits contain the 1535102676Sgibbs * high bit of the ultra2 sync rate 1536102676Sgibbs * field. 1537102676Sgibbs */ 1538102676Sgibbs scsirate = (sc->device_flags[i] & CFXFER) 1539102676Sgibbs | ((ultraenb & target_mask) ? 0x8 : 0x0); 1540102676Sgibbs if (sc->device_flags[i] & CFWIDEB) 1541102676Sgibbs scsirate |= WIDEXFER; 1542102676Sgibbs } else { 1543102676Sgibbs scsirate = (sc->device_flags[i] & CFXFER) << 4; 1544102676Sgibbs if (sc->device_flags[i] & CFSYNCH) 1545102676Sgibbs scsirate |= SOFS; 1546102676Sgibbs if (sc->device_flags[i] & CFWIDEB) 1547102676Sgibbs scsirate |= WIDEXFER; 1548102676Sgibbs } 1549102676Sgibbs ahc_outb(ahc, TARG_SCSIRATE + i, scsirate); 1550102676Sgibbs } 1551102676Sgibbs ahc->our_id = sc->brtime_id & CFSCSIID; 1552102676Sgibbs 1553102676Sgibbs scsi_conf = (ahc->our_id & 0x7); 1554102676Sgibbs if (sc->adapter_control & CFSPARITY) 1555102676Sgibbs scsi_conf |= ENSPCHK; 1556102676Sgibbs if (sc->adapter_control & CFRESETB) 1557102676Sgibbs scsi_conf |= RESET_SCSI; 1558102676Sgibbs 1559102676Sgibbs ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT; 1560102676Sgibbs 1561102676Sgibbs if (sc->bios_control & CFEXTEND) 1562102676Sgibbs ahc->flags |= AHC_EXTENDED_TRANS_A; 1563102676Sgibbs 1564102676Sgibbs if (sc->bios_control & CFBIOSEN) 1565102676Sgibbs ahc->flags |= AHC_BIOS_ENABLED; 1566102676Sgibbs if (ahc->features & AHC_ULTRA 1567102676Sgibbs && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) { 1568102676Sgibbs /* Should we enable Ultra mode? */ 1569102676Sgibbs if (!(sc->adapter_control & CFULTRAEN)) 1570102676Sgibbs /* Treat us as a non-ultra card */ 1571102676Sgibbs ultraenb = 0; 1572102676Sgibbs } 1573102676Sgibbs 1574102676Sgibbs if (sc->signature == CFSIGNATURE 1575102676Sgibbs || sc->signature == CFSIGNATURE2) { 1576102676Sgibbs uint32_t devconfig; 1577102676Sgibbs 1578102676Sgibbs /* Honor the STPWLEVEL settings */ 1579102676Sgibbs devconfig = ahc_pci_read_config(ahc->dev_softc, 1580102676Sgibbs DEVCONFIG, /*bytes*/4); 1581102676Sgibbs devconfig &= ~STPWLEVEL; 1582102676Sgibbs if ((sc->bios_control & CFSTPWLEVEL) != 0) 1583102676Sgibbs devconfig |= STPWLEVEL; 1584102676Sgibbs ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, 1585102676Sgibbs devconfig, /*bytes*/4); 1586102676Sgibbs } 1587102676Sgibbs /* Set SCSICONF info */ 1588102676Sgibbs ahc_outb(ahc, SCSICONF, scsi_conf); 1589102676Sgibbs ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); 1590102676Sgibbs ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); 1591102676Sgibbs ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff); 1592102676Sgibbs ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff); 1593102676Sgibbs} 1594102676Sgibbs 1595102676Sgibbsstatic void 159665942Sgibbsconfigure_termination(struct ahc_softc *ahc, 159765942Sgibbs struct seeprom_descriptor *sd, 159865942Sgibbs u_int adapter_control, 159965942Sgibbs u_int *sxfrctl1) 160065942Sgibbs{ 160165942Sgibbs uint8_t brddat; 160265942Sgibbs 160365942Sgibbs brddat = 0; 160465942Sgibbs 160565942Sgibbs /* 160665942Sgibbs * Update the settings in sxfrctl1 to match the 160765942Sgibbs * termination settings 160865942Sgibbs */ 160965942Sgibbs *sxfrctl1 = 0; 161065942Sgibbs 161165942Sgibbs /* 161265942Sgibbs * SEECS must be on for the GALS to latch 161365942Sgibbs * the data properly. Be sure to leave MS 161465942Sgibbs * on or we will release the seeprom. 161565942Sgibbs */ 161665942Sgibbs SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS); 161765942Sgibbs if ((adapter_control & CFAUTOTERM) != 0 161865942Sgibbs || (ahc->features & AHC_NEW_TERMCTL) != 0) { 161965942Sgibbs int internal50_present; 162065942Sgibbs int internal68_present; 162165942Sgibbs int externalcable_present; 162265942Sgibbs int eeprom_present; 162365942Sgibbs int enableSEC_low; 162465942Sgibbs int enableSEC_high; 162565942Sgibbs int enablePRI_low; 162665942Sgibbs int enablePRI_high; 162771390Sgibbs int sum; 162865942Sgibbs 162965942Sgibbs enableSEC_low = 0; 163065942Sgibbs enableSEC_high = 0; 163165942Sgibbs enablePRI_low = 0; 163265942Sgibbs enablePRI_high = 0; 163365942Sgibbs if ((ahc->features & AHC_NEW_TERMCTL) != 0) { 163465942Sgibbs ahc_new_term_detect(ahc, &enableSEC_low, 1635102676Sgibbs &enableSEC_high, 1636102676Sgibbs &enablePRI_low, 1637102676Sgibbs &enablePRI_high, 1638102676Sgibbs &eeprom_present); 163965942Sgibbs if ((adapter_control & CFSEAUTOTERM) == 0) { 164065942Sgibbs if (bootverbose) 164165942Sgibbs printf("%s: Manual SE Termination\n", 164265942Sgibbs ahc_name(ahc)); 164365942Sgibbs enableSEC_low = (adapter_control & CFSELOWTERM); 164465942Sgibbs enableSEC_high = 164565942Sgibbs (adapter_control & CFSEHIGHTERM); 164665942Sgibbs } 164765942Sgibbs if ((adapter_control & CFAUTOTERM) == 0) { 164865942Sgibbs if (bootverbose) 164965942Sgibbs printf("%s: Manual LVD Termination\n", 165065942Sgibbs ahc_name(ahc)); 165165942Sgibbs enablePRI_low = (adapter_control & CFSTERM); 165265942Sgibbs enablePRI_high = (adapter_control & CFWSTERM); 165365942Sgibbs } 165465942Sgibbs /* Make the table calculations below happy */ 165565942Sgibbs internal50_present = 0; 165665942Sgibbs internal68_present = 1; 165765942Sgibbs externalcable_present = 1; 165865942Sgibbs } else if ((ahc->features & AHC_SPIOCAP) != 0) { 165965942Sgibbs aic785X_cable_detect(ahc, &internal50_present, 166065942Sgibbs &externalcable_present, 166165942Sgibbs &eeprom_present); 1662102676Sgibbs /* Can never support a wide connector. */ 1663102676Sgibbs internal68_present = 0; 166465942Sgibbs } else { 166565942Sgibbs aic787X_cable_detect(ahc, &internal50_present, 166665942Sgibbs &internal68_present, 166765942Sgibbs &externalcable_present, 166865942Sgibbs &eeprom_present); 166965942Sgibbs } 167065942Sgibbs 167165942Sgibbs if ((ahc->features & AHC_WIDE) == 0) 167265942Sgibbs internal68_present = 0; 167365942Sgibbs 167471390Sgibbs if (bootverbose 167571390Sgibbs && (ahc->features & AHC_ULTRA2) == 0) { 167671390Sgibbs printf("%s: internal 50 cable %s present", 167771390Sgibbs ahc_name(ahc), 167871390Sgibbs internal50_present ? "is":"not"); 167971390Sgibbs 168071390Sgibbs if ((ahc->features & AHC_WIDE) != 0) 168171390Sgibbs printf(", internal 68 cable %s present", 168265942Sgibbs internal68_present ? "is":"not"); 168371390Sgibbs printf("\n%s: external cable %s present\n", 168471390Sgibbs ahc_name(ahc), 168571390Sgibbs externalcable_present ? "is":"not"); 168671390Sgibbs } 168771390Sgibbs if (bootverbose) 168865942Sgibbs printf("%s: BIOS eeprom %s present\n", 168965942Sgibbs ahc_name(ahc), eeprom_present ? "is" : "not"); 169065942Sgibbs 169165942Sgibbs if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) { 169265942Sgibbs /* 169365942Sgibbs * The 50 pin connector is a separate bus, 169465942Sgibbs * so force it to always be terminated. 169565942Sgibbs * In the future, perform current sensing 169665942Sgibbs * to determine if we are in the middle of 169765942Sgibbs * a properly terminated bus. 169865942Sgibbs */ 169965942Sgibbs internal50_present = 0; 170065942Sgibbs } 170165942Sgibbs 170265942Sgibbs /* 170365942Sgibbs * Now set the termination based on what 170465942Sgibbs * we found. 170565942Sgibbs * Flash Enable = BRDDAT7 170665942Sgibbs * Secondary High Term Enable = BRDDAT6 170765942Sgibbs * Secondary Low Term Enable = BRDDAT5 (7890) 170865942Sgibbs * Primary High Term Enable = BRDDAT4 (7890) 170965942Sgibbs */ 171065942Sgibbs if ((ahc->features & AHC_ULTRA2) == 0 171171390Sgibbs && (internal50_present != 0) 171271390Sgibbs && (internal68_present != 0) 171371390Sgibbs && (externalcable_present != 0)) { 171465942Sgibbs printf("%s: Illegal cable configuration!!. " 171565942Sgibbs "Only two connectors on the " 171665942Sgibbs "adapter may be used at a " 171765942Sgibbs "time!\n", ahc_name(ahc)); 171895378Sgibbs 171995378Sgibbs /* 172095378Sgibbs * Pretend there are no cables in the hope 172195378Sgibbs * that having all of the termination on 172295378Sgibbs * gives us a more stable bus. 172395378Sgibbs */ 172495378Sgibbs internal50_present = 0; 172595378Sgibbs internal68_present = 0; 172695378Sgibbs externalcable_present = 0; 172765942Sgibbs } 172865942Sgibbs 172965942Sgibbs if ((ahc->features & AHC_WIDE) != 0 173065942Sgibbs && ((externalcable_present == 0) 173165942Sgibbs || (internal68_present == 0) 173265942Sgibbs || (enableSEC_high != 0))) { 173365942Sgibbs brddat |= BRDDAT6; 173465942Sgibbs if (bootverbose) { 173565942Sgibbs if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 173665942Sgibbs printf("%s: 68 pin termination " 173765942Sgibbs "Enabled\n", ahc_name(ahc)); 173865942Sgibbs else 173965942Sgibbs printf("%s: %sHigh byte termination " 174065942Sgibbs "Enabled\n", ahc_name(ahc), 174165942Sgibbs enableSEC_high ? "Secondary " 174265942Sgibbs : ""); 174365942Sgibbs } 174465942Sgibbs } 174565942Sgibbs 174671390Sgibbs sum = internal50_present + internal68_present 174771390Sgibbs + externalcable_present; 174871390Sgibbs if (sum < 2 || (enableSEC_low != 0)) { 174965942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 175065942Sgibbs brddat |= BRDDAT5; 175165942Sgibbs else 175265942Sgibbs *sxfrctl1 |= STPWEN; 175365942Sgibbs if (bootverbose) { 175465942Sgibbs if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 175565942Sgibbs printf("%s: 50 pin termination " 175665942Sgibbs "Enabled\n", ahc_name(ahc)); 175765942Sgibbs else 175865942Sgibbs printf("%s: %sLow byte termination " 175965942Sgibbs "Enabled\n", ahc_name(ahc), 176065942Sgibbs enableSEC_low ? "Secondary " 176165942Sgibbs : ""); 176265942Sgibbs } 176365942Sgibbs } 176465942Sgibbs 176565942Sgibbs if (enablePRI_low != 0) { 176665942Sgibbs *sxfrctl1 |= STPWEN; 176765942Sgibbs if (bootverbose) 176865942Sgibbs printf("%s: Primary Low Byte termination " 176965942Sgibbs "Enabled\n", ahc_name(ahc)); 177065942Sgibbs } 177165942Sgibbs 177265942Sgibbs /* 177365942Sgibbs * Setup STPWEN before setting up the rest of 177465942Sgibbs * the termination per the tech note on the U160 cards. 177565942Sgibbs */ 177665942Sgibbs ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 177765942Sgibbs 177865942Sgibbs if (enablePRI_high != 0) { 177965942Sgibbs brddat |= BRDDAT4; 178065942Sgibbs if (bootverbose) 178165942Sgibbs printf("%s: Primary High Byte " 178265942Sgibbs "termination Enabled\n", 178365942Sgibbs ahc_name(ahc)); 178465942Sgibbs } 178565942Sgibbs 178665942Sgibbs write_brdctl(ahc, brddat); 178765942Sgibbs 178865942Sgibbs } else { 178965942Sgibbs if ((adapter_control & CFSTERM) != 0) { 179065942Sgibbs *sxfrctl1 |= STPWEN; 179165942Sgibbs 179265942Sgibbs if (bootverbose) 179365942Sgibbs printf("%s: %sLow byte termination Enabled\n", 179465942Sgibbs ahc_name(ahc), 179565942Sgibbs (ahc->features & AHC_ULTRA2) ? "Primary " 179665942Sgibbs : ""); 179765942Sgibbs } 179865942Sgibbs 179971390Sgibbs if ((adapter_control & CFWSTERM) != 0 180071390Sgibbs && (ahc->features & AHC_WIDE) != 0) { 180165942Sgibbs brddat |= BRDDAT6; 180265942Sgibbs if (bootverbose) 180365942Sgibbs printf("%s: %sHigh byte termination Enabled\n", 180465942Sgibbs ahc_name(ahc), 180565942Sgibbs (ahc->features & AHC_ULTRA2) 180665942Sgibbs ? "Secondary " : ""); 180765942Sgibbs } 180865942Sgibbs 180965942Sgibbs /* 181065942Sgibbs * Setup STPWEN before setting up the rest of 181165942Sgibbs * the termination per the tech note on the U160 cards. 181265942Sgibbs */ 181365942Sgibbs ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 181465942Sgibbs 181571390Sgibbs if ((ahc->features & AHC_WIDE) != 0) 181671390Sgibbs write_brdctl(ahc, brddat); 181765942Sgibbs } 181865942Sgibbs SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */ 181965942Sgibbs} 182065942Sgibbs 182165942Sgibbsstatic void 182265942Sgibbsahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low, 182365942Sgibbs int *enableSEC_high, int *enablePRI_low, 182465942Sgibbs int *enablePRI_high, int *eeprom_present) 182565942Sgibbs{ 182665942Sgibbs uint8_t brdctl; 182765942Sgibbs 182865942Sgibbs /* 182965942Sgibbs * BRDDAT7 = Eeprom 183065942Sgibbs * BRDDAT6 = Enable Secondary High Byte termination 183165942Sgibbs * BRDDAT5 = Enable Secondary Low Byte termination 183265942Sgibbs * BRDDAT4 = Enable Primary high byte termination 183365942Sgibbs * BRDDAT3 = Enable Primary low byte termination 183465942Sgibbs */ 183565942Sgibbs brdctl = read_brdctl(ahc); 183665942Sgibbs *eeprom_present = brdctl & BRDDAT7; 183765942Sgibbs *enableSEC_high = (brdctl & BRDDAT6); 183865942Sgibbs *enableSEC_low = (brdctl & BRDDAT5); 183965942Sgibbs *enablePRI_high = (brdctl & BRDDAT4); 184065942Sgibbs *enablePRI_low = (brdctl & BRDDAT3); 184165942Sgibbs} 184265942Sgibbs 184365942Sgibbsstatic void 184465942Sgibbsaic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 184565942Sgibbs int *internal68_present, int *externalcable_present, 184665942Sgibbs int *eeprom_present) 184765942Sgibbs{ 184865942Sgibbs uint8_t brdctl; 184965942Sgibbs 185065942Sgibbs /* 185165942Sgibbs * First read the status of our cables. 185265942Sgibbs * Set the rom bank to 0 since the 185365942Sgibbs * bank setting serves as a multiplexor 185465942Sgibbs * for the cable detection logic. 185565942Sgibbs * BRDDAT5 controls the bank switch. 185665942Sgibbs */ 185765942Sgibbs write_brdctl(ahc, 0); 185865942Sgibbs 185965942Sgibbs /* 186065942Sgibbs * Now read the state of the internal 186165942Sgibbs * connectors. BRDDAT6 is INT50 and 186265942Sgibbs * BRDDAT7 is INT68. 186365942Sgibbs */ 186465942Sgibbs brdctl = read_brdctl(ahc); 186571390Sgibbs *internal50_present = (brdctl & BRDDAT6) ? 0 : 1; 186671390Sgibbs *internal68_present = (brdctl & BRDDAT7) ? 0 : 1; 186765942Sgibbs 186865942Sgibbs /* 186965942Sgibbs * Set the rom bank to 1 and determine 187065942Sgibbs * the other signals. 187165942Sgibbs */ 187265942Sgibbs write_brdctl(ahc, BRDDAT5); 187365942Sgibbs 187465942Sgibbs /* 187565942Sgibbs * Now read the state of the external 187665942Sgibbs * connectors. BRDDAT6 is EXT68 and 187765942Sgibbs * BRDDAT7 is EPROMPS. 187865942Sgibbs */ 187965942Sgibbs brdctl = read_brdctl(ahc); 188071390Sgibbs *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 188171390Sgibbs *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0; 188265942Sgibbs} 188365942Sgibbs 188465942Sgibbsstatic void 188565942Sgibbsaic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 188665942Sgibbs int *externalcable_present, int *eeprom_present) 188765942Sgibbs{ 188865942Sgibbs uint8_t brdctl; 1889102676Sgibbs uint8_t spiocap; 189065942Sgibbs 1891102676Sgibbs spiocap = ahc_inb(ahc, SPIOCAP); 1892102676Sgibbs spiocap &= ~SOFTCMDEN; 1893102676Sgibbs spiocap |= EXT_BRDCTL; 1894102676Sgibbs ahc_outb(ahc, SPIOCAP, spiocap); 189565942Sgibbs ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); 1896114621Sgibbs ahc_flush_device_writes(ahc); 1897114621Sgibbs ahc_delay(500); 189865942Sgibbs ahc_outb(ahc, BRDCTL, 0); 1899114621Sgibbs ahc_flush_device_writes(ahc); 1900114621Sgibbs ahc_delay(500); 190165942Sgibbs brdctl = ahc_inb(ahc, BRDCTL); 190271390Sgibbs *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; 190371390Sgibbs *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 190471390Sgibbs *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0; 190565942Sgibbs} 190665942Sgibbs 190795378Sgibbsint 190895378Sgibbsahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd) 190965942Sgibbs{ 191065942Sgibbs int wait; 191165942Sgibbs 191265942Sgibbs if ((ahc->features & AHC_SPIOCAP) != 0 191365942Sgibbs && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0) 191465942Sgibbs return (0); 191565942Sgibbs 191665942Sgibbs /* 191765942Sgibbs * Request access of the memory port. When access is 191865942Sgibbs * granted, SEERDY will go high. We use a 1 second 191965942Sgibbs * timeout which should be near 1 second more than 192065942Sgibbs * is needed. Reason: after the chip reset, there 192165942Sgibbs * should be no contention. 192265942Sgibbs */ 192365942Sgibbs SEEPROM_OUTB(sd, sd->sd_MS); 192465942Sgibbs wait = 1000; /* 1 second timeout in msec */ 192565942Sgibbs while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { 192665942Sgibbs ahc_delay(1000); /* delay 1 msec */ 192765942Sgibbs } 192865942Sgibbs if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { 192965942Sgibbs SEEPROM_OUTB(sd, 0); 193065942Sgibbs return (0); 193165942Sgibbs } 193265942Sgibbs return(1); 193365942Sgibbs} 193465942Sgibbs 193595378Sgibbsvoid 193695378Sgibbsahc_release_seeprom(struct seeprom_descriptor *sd) 193765942Sgibbs{ 193865942Sgibbs /* Release access to the memory port and the serial EEPROM. */ 193965942Sgibbs SEEPROM_OUTB(sd, 0); 194065942Sgibbs} 194165942Sgibbs 194265942Sgibbsstatic void 194365942Sgibbswrite_brdctl(struct ahc_softc *ahc, uint8_t value) 194465942Sgibbs{ 194565942Sgibbs uint8_t brdctl; 194665942Sgibbs 194765942Sgibbs if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 194865942Sgibbs brdctl = BRDSTB; 194965942Sgibbs if (ahc->channel == 'B') 195065942Sgibbs brdctl |= BRDCS; 195165942Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 195265942Sgibbs brdctl = 0; 195365942Sgibbs } else { 195465942Sgibbs brdctl = BRDSTB|BRDCS; 195565942Sgibbs } 195665942Sgibbs ahc_outb(ahc, BRDCTL, brdctl); 195771390Sgibbs ahc_flush_device_writes(ahc); 195865942Sgibbs brdctl |= value; 195965942Sgibbs ahc_outb(ahc, BRDCTL, brdctl); 196071390Sgibbs ahc_flush_device_writes(ahc); 196165942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 196265942Sgibbs brdctl |= BRDSTB_ULTRA2; 196365942Sgibbs else 196465942Sgibbs brdctl &= ~BRDSTB; 196565942Sgibbs ahc_outb(ahc, BRDCTL, brdctl); 196671390Sgibbs ahc_flush_device_writes(ahc); 196765942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 196865942Sgibbs brdctl = 0; 196965942Sgibbs else 197065942Sgibbs brdctl &= ~BRDCS; 197165942Sgibbs ahc_outb(ahc, BRDCTL, brdctl); 197265942Sgibbs} 197365942Sgibbs 197465942Sgibbsstatic uint8_t 1975115328Sgibbsread_brdctl(struct ahc_softc *ahc) 197665942Sgibbs{ 197765942Sgibbs uint8_t brdctl; 197865942Sgibbs uint8_t value; 197965942Sgibbs 198065942Sgibbs if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 198165942Sgibbs brdctl = BRDRW; 198265942Sgibbs if (ahc->channel == 'B') 198365942Sgibbs brdctl |= BRDCS; 198465942Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 198565942Sgibbs brdctl = BRDRW_ULTRA2; 198665942Sgibbs } else { 198765942Sgibbs brdctl = BRDRW|BRDCS; 198865942Sgibbs } 198965942Sgibbs ahc_outb(ahc, BRDCTL, brdctl); 199071390Sgibbs ahc_flush_device_writes(ahc); 199165942Sgibbs value = ahc_inb(ahc, BRDCTL); 199265942Sgibbs ahc_outb(ahc, BRDCTL, 0); 199365942Sgibbs return (value); 199465942Sgibbs} 199565942Sgibbs 1996114621Sgibbsstatic void 199765942Sgibbsahc_pci_intr(struct ahc_softc *ahc) 199865942Sgibbs{ 199966269Sgibbs u_int error; 200066269Sgibbs u_int status1; 200165942Sgibbs 200266269Sgibbs error = ahc_inb(ahc, ERROR); 200366269Sgibbs if ((error & PCIERRSTAT) == 0) 200466269Sgibbs return; 200566269Sgibbs 200665942Sgibbs status1 = ahc_pci_read_config(ahc->dev_softc, 200765942Sgibbs PCIR_STATUS + 1, /*bytes*/1); 200865942Sgibbs 200966269Sgibbs printf("%s: PCI error Interrupt at seqaddr = 0x%x\n", 201066269Sgibbs ahc_name(ahc), 201166269Sgibbs ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); 201266269Sgibbs 201365942Sgibbs if (status1 & DPE) { 2014114621Sgibbs ahc->pci_target_perr_count++; 201565942Sgibbs printf("%s: Data Parity Error Detected during address " 201665942Sgibbs "or write data phase\n", ahc_name(ahc)); 201765942Sgibbs } 201865942Sgibbs if (status1 & SSE) { 201966647Sgibbs printf("%s: Signal System Error Detected\n", ahc_name(ahc)); 202065942Sgibbs } 202165942Sgibbs if (status1 & RMA) { 202266647Sgibbs printf("%s: Received a Master Abort\n", ahc_name(ahc)); 202365942Sgibbs } 202465942Sgibbs if (status1 & RTA) { 202565942Sgibbs printf("%s: Received a Target Abort\n", ahc_name(ahc)); 202665942Sgibbs } 202765942Sgibbs if (status1 & STA) { 202865942Sgibbs printf("%s: Signaled a Target Abort\n", ahc_name(ahc)); 202965942Sgibbs } 203065942Sgibbs if (status1 & DPR) { 203165942Sgibbs printf("%s: Data Parity Error has been reported via PERR#\n", 203265942Sgibbs ahc_name(ahc)); 203365942Sgibbs } 203479874Sgibbs 203579874Sgibbs /* Clear latched errors. */ 203679874Sgibbs ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 203779874Sgibbs status1, /*bytes*/1); 203879874Sgibbs 203965942Sgibbs if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { 204065942Sgibbs printf("%s: Latched PCIERR interrupt with " 204165942Sgibbs "no status bits set\n", ahc_name(ahc)); 204279874Sgibbs } else { 204365942Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 204465942Sgibbs } 204566269Sgibbs 2046114621Sgibbs if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) { 2047114621Sgibbs printf( 2048114621Sgibbs"%s: WARNING WARNING WARNING WARNING\n" 2049114621Sgibbs"%s: Too many PCI parity errors observed as a target.\n" 2050114621Sgibbs"%s: Some device on this bus is generating bad parity.\n" 2051114621Sgibbs"%s: This is an error *observed by*, not *generated by*, this controller.\n" 2052114621Sgibbs"%s: PCI parity error checking has been disabled.\n" 2053114621Sgibbs"%s: WARNING WARNING WARNING WARNING\n", 2054114621Sgibbs ahc_name(ahc), ahc_name(ahc), ahc_name(ahc), 2055114621Sgibbs ahc_name(ahc), ahc_name(ahc), ahc_name(ahc)); 2056115332Sgibbs ahc->seqctl |= FAILDIS; 2057115332Sgibbs ahc_outb(ahc, SEQCTL, ahc->seqctl); 2058114621Sgibbs } 205974094Sgibbs ahc_unpause(ahc); 206065942Sgibbs} 206165942Sgibbs 206265942Sgibbsstatic int 2063114621Sgibbsahc_pci_chip_init(struct ahc_softc *ahc) 2064114621Sgibbs{ 2065114621Sgibbs ahc_outb(ahc, DSCOMMAND0, ahc->bus_softc.pci_softc.dscommand0); 2066114621Sgibbs ahc_outb(ahc, DSPCISTATUS, ahc->bus_softc.pci_softc.dspcistatus); 2067114621Sgibbs if ((ahc->features & AHC_DT) != 0) { 2068114621Sgibbs u_int sfunct; 2069114621Sgibbs 2070114621Sgibbs sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 2071114621Sgibbs ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 2072114621Sgibbs ahc_outb(ahc, OPTIONMODE, ahc->bus_softc.pci_softc.optionmode); 2073114621Sgibbs ahc_outw(ahc, TARGCRCCNT, ahc->bus_softc.pci_softc.targcrccnt); 2074114621Sgibbs ahc_outb(ahc, SFUNCT, sfunct); 2075114621Sgibbs ahc_outb(ahc, CRCCONTROL1, 2076114621Sgibbs ahc->bus_softc.pci_softc.crccontrol1); 2077114621Sgibbs } 2078114621Sgibbs if ((ahc->features & AHC_MULTI_FUNC) != 0) 2079114621Sgibbs ahc_outb(ahc, SCBBADDR, ahc->bus_softc.pci_softc.scbbaddr); 2080114621Sgibbs 2081114621Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 2082114621Sgibbs ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh); 2083114621Sgibbs 2084114621Sgibbs return (ahc_chip_init(ahc)); 2085114621Sgibbs} 2086114621Sgibbs 2087114621Sgibbsstatic int 2088114621Sgibbsahc_pci_suspend(struct ahc_softc *ahc) 2089114621Sgibbs{ 2090114621Sgibbs return (ahc_suspend(ahc)); 2091114621Sgibbs} 2092114621Sgibbs 2093114621Sgibbsstatic int 2094114621Sgibbsahc_pci_resume(struct ahc_softc *ahc) 2095114621Sgibbs{ 2096114621Sgibbs 2097114621Sgibbs ahc_power_state_change(ahc, AHC_POWER_STATE_D0); 2098114621Sgibbs 2099114621Sgibbs /* 2100114621Sgibbs * We assume that the OS has restored our register 2101114621Sgibbs * mappings, etc. Just update the config space registers 2102114621Sgibbs * that the OS doesn't know about and rely on our chip 2103114621Sgibbs * reset handler to handle the rest. 2104114621Sgibbs */ 2105114621Sgibbs ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4, 2106114621Sgibbs ahc->bus_softc.pci_softc.devconfig); 2107114621Sgibbs ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1, 2108114621Sgibbs ahc->bus_softc.pci_softc.command); 2109114621Sgibbs ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1, 2110114621Sgibbs ahc->bus_softc.pci_softc.csize_lattime); 2111114621Sgibbs if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) { 2112114621Sgibbs struct seeprom_descriptor sd; 2113114621Sgibbs u_int sxfrctl1; 2114114621Sgibbs 2115114621Sgibbs sd.sd_ahc = ahc; 2116114621Sgibbs sd.sd_control_offset = SEECTL; 2117114621Sgibbs sd.sd_status_offset = SEECTL; 2118114621Sgibbs sd.sd_dataout_offset = SEECTL; 2119114621Sgibbs 2120114621Sgibbs ahc_acquire_seeprom(ahc, &sd); 2121114621Sgibbs configure_termination(ahc, &sd, 2122114621Sgibbs ahc->seep_config->adapter_control, 2123114621Sgibbs &sxfrctl1); 2124114621Sgibbs ahc_release_seeprom(&sd); 2125114621Sgibbs } 2126114621Sgibbs return (ahc_resume(ahc)); 2127114621Sgibbs} 2128114621Sgibbs 2129114621Sgibbsstatic int 213079874Sgibbsahc_aic785X_setup(struct ahc_softc *ahc) 213165942Sgibbs{ 213279874Sgibbs ahc_dev_softc_t pci; 213374094Sgibbs uint8_t rev; 213474094Sgibbs 213579874Sgibbs pci = ahc->dev_softc; 213679874Sgibbs ahc->channel = 'A'; 213779874Sgibbs ahc->chip = AHC_AIC7850; 213879874Sgibbs ahc->features = AHC_AIC7850_FE; 213979874Sgibbs ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 214074094Sgibbs rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 214174094Sgibbs if (rev >= 1) 214279874Sgibbs ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 2143114621Sgibbs ahc->instruction_ram_size = 512; 214465942Sgibbs return (0); 214565942Sgibbs} 214665942Sgibbs 214765942Sgibbsstatic int 214879874Sgibbsahc_aic7860_setup(struct ahc_softc *ahc) 214965942Sgibbs{ 215079874Sgibbs ahc_dev_softc_t pci; 215165942Sgibbs uint8_t rev; 215265942Sgibbs 215379874Sgibbs pci = ahc->dev_softc; 215479874Sgibbs ahc->channel = 'A'; 215579874Sgibbs ahc->chip = AHC_AIC7860; 215679874Sgibbs ahc->features = AHC_AIC7860_FE; 215779874Sgibbs ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 215865942Sgibbs rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 215965942Sgibbs if (rev >= 1) 216079874Sgibbs ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 2161114621Sgibbs ahc->instruction_ram_size = 512; 216265942Sgibbs return (0); 216365942Sgibbs} 216465942Sgibbs 216565942Sgibbsstatic int 216679874Sgibbsahc_apa1480_setup(struct ahc_softc *ahc) 216771390Sgibbs{ 216871390Sgibbs int error; 216971390Sgibbs 217079874Sgibbs error = ahc_aic7860_setup(ahc); 217171390Sgibbs if (error != 0) 217271390Sgibbs return (error); 217379874Sgibbs ahc->features |= AHC_REMOVABLE; 217471390Sgibbs return (0); 217571390Sgibbs} 217671390Sgibbs 217771390Sgibbsstatic int 217879874Sgibbsahc_aic7870_setup(struct ahc_softc *ahc) 217965942Sgibbs{ 218079874Sgibbs 218179874Sgibbs ahc->channel = 'A'; 218279874Sgibbs ahc->chip = AHC_AIC7870; 218379874Sgibbs ahc->features = AHC_AIC7870_FE; 218479874Sgibbs ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 2185114621Sgibbs ahc->instruction_ram_size = 512; 218665942Sgibbs return (0); 218765942Sgibbs} 218865942Sgibbs 218965942Sgibbsstatic int 219079874Sgibbsahc_aha394X_setup(struct ahc_softc *ahc) 219165942Sgibbs{ 219265942Sgibbs int error; 219365942Sgibbs 219479874Sgibbs error = ahc_aic7870_setup(ahc); 219565942Sgibbs if (error == 0) 219679874Sgibbs error = ahc_aha394XX_setup(ahc); 219765942Sgibbs return (error); 219865942Sgibbs} 219965942Sgibbs 220065942Sgibbsstatic int 220179874Sgibbsahc_aha398X_setup(struct ahc_softc *ahc) 220265942Sgibbs{ 220365942Sgibbs int error; 220465942Sgibbs 220579874Sgibbs error = ahc_aic7870_setup(ahc); 220665942Sgibbs if (error == 0) 220779874Sgibbs error = ahc_aha398XX_setup(ahc); 220865942Sgibbs return (error); 220965942Sgibbs} 221065942Sgibbs 221165942Sgibbsstatic int 221279874Sgibbsahc_aha494X_setup(struct ahc_softc *ahc) 221365942Sgibbs{ 221465942Sgibbs int error; 221565942Sgibbs 221679874Sgibbs error = ahc_aic7870_setup(ahc); 221765942Sgibbs if (error == 0) 221879874Sgibbs error = ahc_aha494XX_setup(ahc); 221965942Sgibbs return (error); 222065942Sgibbs} 222165942Sgibbs 222265942Sgibbsstatic int 222379874Sgibbsahc_aic7880_setup(struct ahc_softc *ahc) 222465942Sgibbs{ 222579874Sgibbs ahc_dev_softc_t pci; 222665942Sgibbs uint8_t rev; 222765942Sgibbs 222879874Sgibbs pci = ahc->dev_softc; 222979874Sgibbs ahc->channel = 'A'; 223079874Sgibbs ahc->chip = AHC_AIC7880; 223179874Sgibbs ahc->features = AHC_AIC7880_FE; 223279874Sgibbs ahc->bugs |= AHC_TMODE_WIDEODD_BUG; 223365942Sgibbs rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 223465942Sgibbs if (rev >= 1) { 223579874Sgibbs ahc->bugs |= AHC_PCI_2_1_RETRY_BUG; 223665942Sgibbs } else { 223779874Sgibbs ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 223865942Sgibbs } 2239114621Sgibbs ahc->instruction_ram_size = 512; 224065942Sgibbs return (0); 224165942Sgibbs} 224265942Sgibbs 224365942Sgibbsstatic int 224479874Sgibbsahc_aha2940Pro_setup(struct ahc_softc *ahc) 224565942Sgibbs{ 224665942Sgibbs 224779874Sgibbs ahc->flags |= AHC_INT50_SPEEDFLEX; 2248102676Sgibbs return (ahc_aic7880_setup(ahc)); 224965942Sgibbs} 225065942Sgibbs 225165942Sgibbsstatic int 225279874Sgibbsahc_aha394XU_setup(struct ahc_softc *ahc) 225365942Sgibbs{ 225465942Sgibbs int error; 225565942Sgibbs 225679874Sgibbs error = ahc_aic7880_setup(ahc); 225765942Sgibbs if (error == 0) 225879874Sgibbs error = ahc_aha394XX_setup(ahc); 225965942Sgibbs return (error); 226065942Sgibbs} 226165942Sgibbs 226265942Sgibbsstatic int 226379874Sgibbsahc_aha398XU_setup(struct ahc_softc *ahc) 226465942Sgibbs{ 226565942Sgibbs int error; 226665942Sgibbs 226779874Sgibbs error = ahc_aic7880_setup(ahc); 226865942Sgibbs if (error == 0) 226979874Sgibbs error = ahc_aha398XX_setup(ahc); 227065942Sgibbs return (error); 227165942Sgibbs} 227265942Sgibbs 227365942Sgibbsstatic int 227479874Sgibbsahc_aic7890_setup(struct ahc_softc *ahc) 227565942Sgibbs{ 227679874Sgibbs ahc_dev_softc_t pci; 227765942Sgibbs uint8_t rev; 227865942Sgibbs 227979874Sgibbs pci = ahc->dev_softc; 228079874Sgibbs ahc->channel = 'A'; 228179874Sgibbs ahc->chip = AHC_AIC7890; 228279874Sgibbs ahc->features = AHC_AIC7890_FE; 228379874Sgibbs ahc->flags |= AHC_NEWEEPROM_FMT; 228465942Sgibbs rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 228565942Sgibbs if (rev == 0) 228679874Sgibbs ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; 2287114621Sgibbs ahc->instruction_ram_size = 768; 228865942Sgibbs return (0); 228965942Sgibbs} 229065942Sgibbs 229165942Sgibbsstatic int 229279874Sgibbsahc_aic7892_setup(struct ahc_softc *ahc) 229365942Sgibbs{ 229479874Sgibbs 229579874Sgibbs ahc->channel = 'A'; 229679874Sgibbs ahc->chip = AHC_AIC7892; 229779874Sgibbs ahc->features = AHC_AIC7892_FE; 229879874Sgibbs ahc->flags |= AHC_NEWEEPROM_FMT; 229979874Sgibbs ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; 2300114621Sgibbs ahc->instruction_ram_size = 1024; 230165942Sgibbs return (0); 230265942Sgibbs} 230365942Sgibbs 230465942Sgibbsstatic int 230579874Sgibbsahc_aic7895_setup(struct ahc_softc *ahc) 230665942Sgibbs{ 230779874Sgibbs ahc_dev_softc_t pci; 230865942Sgibbs uint8_t rev; 230965942Sgibbs 231079874Sgibbs pci = ahc->dev_softc; 231179874Sgibbs ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 231265942Sgibbs /* 231365942Sgibbs * The 'C' revision of the aic7895 has a few additional features. 231465942Sgibbs */ 231565942Sgibbs rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 231665942Sgibbs if (rev >= 4) { 231779874Sgibbs ahc->chip = AHC_AIC7895C; 231879874Sgibbs ahc->features = AHC_AIC7895C_FE; 231965942Sgibbs } else { 232065942Sgibbs u_int command; 232165942Sgibbs 232279874Sgibbs ahc->chip = AHC_AIC7895; 232379874Sgibbs ahc->features = AHC_AIC7895_FE; 232465942Sgibbs 232565942Sgibbs /* 232665942Sgibbs * The BIOS disables the use of MWI transactions 232765942Sgibbs * since it does not have the MWI bug work around 232865942Sgibbs * we have. Disabling MWI reduces performance, so 232965942Sgibbs * turn it on again. 233065942Sgibbs */ 233165942Sgibbs command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); 233265942Sgibbs command |= PCIM_CMD_MWRICEN; 233365942Sgibbs ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); 233479874Sgibbs ahc->bugs |= AHC_PCI_MWI_BUG; 233565942Sgibbs } 233665942Sgibbs /* 233765942Sgibbs * XXX Does CACHETHEN really not work??? What about PCI retry? 233865942Sgibbs * on C level chips. Need to test, but for now, play it safe. 233965942Sgibbs */ 234079874Sgibbs ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG 234179874Sgibbs | AHC_CACHETHEN_BUG; 234265942Sgibbs 234365942Sgibbs#if 0 234465942Sgibbs uint32_t devconfig; 234565942Sgibbs 234665942Sgibbs /* 234765942Sgibbs * Cachesize must also be zero due to stray DAC 234865942Sgibbs * problem when sitting behind some bridges. 234965942Sgibbs */ 235065942Sgibbs ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); 235165942Sgibbs devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1); 235265942Sgibbs devconfig |= MRDCEN; 235365942Sgibbs ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); 235465942Sgibbs#endif 235579874Sgibbs ahc->flags |= AHC_NEWEEPROM_FMT; 2356114621Sgibbs ahc->instruction_ram_size = 512; 235765942Sgibbs return (0); 235865942Sgibbs} 235965942Sgibbs 236065942Sgibbsstatic int 236179874Sgibbsahc_aic7896_setup(struct ahc_softc *ahc) 236265942Sgibbs{ 236379874Sgibbs ahc_dev_softc_t pci; 236479874Sgibbs 236579874Sgibbs pci = ahc->dev_softc; 236679874Sgibbs ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 236779874Sgibbs ahc->chip = AHC_AIC7896; 236879874Sgibbs ahc->features = AHC_AIC7896_FE; 236979874Sgibbs ahc->flags |= AHC_NEWEEPROM_FMT; 237079874Sgibbs ahc->bugs |= AHC_CACHETHEN_DIS_BUG; 2371114621Sgibbs ahc->instruction_ram_size = 768; 237265942Sgibbs return (0); 237365942Sgibbs} 237465942Sgibbs 237565942Sgibbsstatic int 237679874Sgibbsahc_aic7899_setup(struct ahc_softc *ahc) 237765942Sgibbs{ 237879874Sgibbs ahc_dev_softc_t pci; 237979874Sgibbs 238079874Sgibbs pci = ahc->dev_softc; 238179874Sgibbs ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 238279874Sgibbs ahc->chip = AHC_AIC7899; 238379874Sgibbs ahc->features = AHC_AIC7899_FE; 238479874Sgibbs ahc->flags |= AHC_NEWEEPROM_FMT; 238579874Sgibbs ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG; 2386114621Sgibbs ahc->instruction_ram_size = 1024; 238765942Sgibbs return (0); 238865942Sgibbs} 238965942Sgibbs 239065942Sgibbsstatic int 239179874Sgibbsahc_aha29160C_setup(struct ahc_softc *ahc) 239271390Sgibbs{ 239371390Sgibbs int error; 239471390Sgibbs 239579874Sgibbs error = ahc_aic7899_setup(ahc); 239671390Sgibbs if (error != 0) 239771390Sgibbs return (error); 239879874Sgibbs ahc->features |= AHC_REMOVABLE; 239971390Sgibbs return (0); 240071390Sgibbs} 240171390Sgibbs 240271390Sgibbsstatic int 240379874Sgibbsahc_raid_setup(struct ahc_softc *ahc) 240465942Sgibbs{ 240565942Sgibbs printf("RAID functionality unsupported\n"); 240665942Sgibbs return (ENXIO); 240765942Sgibbs} 240865942Sgibbs 240965942Sgibbsstatic int 241079874Sgibbsahc_aha394XX_setup(struct ahc_softc *ahc) 241165942Sgibbs{ 241279874Sgibbs ahc_dev_softc_t pci; 241379874Sgibbs 241479874Sgibbs pci = ahc->dev_softc; 241565942Sgibbs switch (ahc_get_pci_slot(pci)) { 241665942Sgibbs case AHC_394X_SLOT_CHANNEL_A: 241779874Sgibbs ahc->channel = 'A'; 241865942Sgibbs break; 241965942Sgibbs case AHC_394X_SLOT_CHANNEL_B: 242079874Sgibbs ahc->channel = 'B'; 242165942Sgibbs break; 242265942Sgibbs default: 242365942Sgibbs printf("adapter at unexpected slot %d\n" 242465942Sgibbs "unable to map to a channel\n", 242565942Sgibbs ahc_get_pci_slot(pci)); 242679874Sgibbs ahc->channel = 'A'; 242765942Sgibbs } 242865942Sgibbs return (0); 242965942Sgibbs} 243065942Sgibbs 243165942Sgibbsstatic int 243279874Sgibbsahc_aha398XX_setup(struct ahc_softc *ahc) 243365942Sgibbs{ 243479874Sgibbs ahc_dev_softc_t pci; 243579874Sgibbs 243679874Sgibbs pci = ahc->dev_softc; 243765942Sgibbs switch (ahc_get_pci_slot(pci)) { 243865942Sgibbs case AHC_398X_SLOT_CHANNEL_A: 243979874Sgibbs ahc->channel = 'A'; 244065942Sgibbs break; 244165942Sgibbs case AHC_398X_SLOT_CHANNEL_B: 244279874Sgibbs ahc->channel = 'B'; 244365942Sgibbs break; 244465942Sgibbs case AHC_398X_SLOT_CHANNEL_C: 244579874Sgibbs ahc->channel = 'C'; 244665942Sgibbs break; 244765942Sgibbs default: 244865942Sgibbs printf("adapter at unexpected slot %d\n" 244965942Sgibbs "unable to map to a channel\n", 245065942Sgibbs ahc_get_pci_slot(pci)); 245179874Sgibbs ahc->channel = 'A'; 245265942Sgibbs break; 245365942Sgibbs } 245479874Sgibbs ahc->flags |= AHC_LARGE_SEEPROM; 245565942Sgibbs return (0); 245665942Sgibbs} 245765942Sgibbs 245865942Sgibbsstatic int 245979874Sgibbsahc_aha494XX_setup(struct ahc_softc *ahc) 246065942Sgibbs{ 246179874Sgibbs ahc_dev_softc_t pci; 246279874Sgibbs 246379874Sgibbs pci = ahc->dev_softc; 246465942Sgibbs switch (ahc_get_pci_slot(pci)) { 246565942Sgibbs case AHC_494X_SLOT_CHANNEL_A: 246679874Sgibbs ahc->channel = 'A'; 246765942Sgibbs break; 246865942Sgibbs case AHC_494X_SLOT_CHANNEL_B: 246979874Sgibbs ahc->channel = 'B'; 247065942Sgibbs break; 247165942Sgibbs case AHC_494X_SLOT_CHANNEL_C: 247279874Sgibbs ahc->channel = 'C'; 247365942Sgibbs break; 247465942Sgibbs case AHC_494X_SLOT_CHANNEL_D: 247579874Sgibbs ahc->channel = 'D'; 247665942Sgibbs break; 247765942Sgibbs default: 247865942Sgibbs printf("adapter at unexpected slot %d\n" 247965942Sgibbs "unable to map to a channel\n", 248065942Sgibbs ahc_get_pci_slot(pci)); 248179874Sgibbs ahc->channel = 'A'; 248265942Sgibbs } 248379874Sgibbs ahc->flags |= AHC_LARGE_SEEPROM; 248465942Sgibbs return (0); 248565942Sgibbs} 2486