aic7xxx_pci.c revision 72325
165942Sgibbs/* 265942Sgibbs * Product specific probe and attach routines for: 365942Sgibbs * 3940, 2940, aic7895, aic7890, aic7880, 465942Sgibbs * aic7870, aic7860 and aic7850 SCSI controllers 565942Sgibbs * 671717Sgibbs * Copyright (c) 1995-2000 Justin T. Gibbs 765942Sgibbs * All rights reserved. 865942Sgibbs * 965942Sgibbs * Redistribution and use in source and binary forms, with or without 1065942Sgibbs * modification, are permitted provided that the following conditions 1165942Sgibbs * are met: 1265942Sgibbs * 1. Redistributions of source code must retain the above copyright 1365942Sgibbs * notice, this list of conditions, and the following disclaimer, 1465942Sgibbs * without modification, immediately at the beginning of the file. 1565942Sgibbs * 2. The name of the author may not be used to endorse or promote products 1665942Sgibbs * derived from this software without specific prior written permission. 1765942Sgibbs * 1865942Sgibbs * Alternatively, this software may be distributed under the terms of the 1965942Sgibbs * GNU Public License ("GPL"). 2065942Sgibbs * 2165942Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 2265942Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2365942Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2465942Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR 2565942Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2665942Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2765942Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2865942Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2965942Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3065942Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3165942Sgibbs * SUCH DAMAGE. 3265942Sgibbs * 3371390Sgibbs * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#12 $ 3465942Sgibbs * 3565942Sgibbs * $FreeBSD: head/sys/dev/aic7xxx/aic7xxx_pci.c 72325 2001-02-10 18:04:27Z gibbs $ 3665942Sgibbs */ 3765942Sgibbs 3865942Sgibbs#ifdef __linux__ 3965942Sgibbs#include "aic7xxx_linux.h" 4065942Sgibbs#include "aic7xxx_inline.h" 4165942Sgibbs#include "aic7xxx_93cx6.h" 4265942Sgibbs#endif 4365942Sgibbs 4465942Sgibbs#ifdef __FreeBSD__ 4565942Sgibbs#include <dev/aic7xxx/aic7xxx_freebsd.h> 4665942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h> 4765942Sgibbs#include <dev/aic7xxx/aic7xxx_93cx6.h> 4865942Sgibbs#endif 4965942Sgibbs 5065942Sgibbs#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */ 5165942Sgibbs#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */ 5265942Sgibbs 5365942Sgibbsstatic __inline uint64_t 5465942Sgibbsahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) 5565942Sgibbs{ 5665942Sgibbs uint64_t id; 5765942Sgibbs 5865942Sgibbs id = subvendor 5965942Sgibbs | (subdevice << 16) 6065942Sgibbs | ((uint64_t)vendor << 32) 6165942Sgibbs | ((uint64_t)device << 48); 6265942Sgibbs 6365942Sgibbs return (id); 6465942Sgibbs} 6565942Sgibbs 6665942Sgibbs#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull 6765942Sgibbs#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull 6872325Sgibbs#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull 6965942Sgibbs#define ID_AIC7850 0x5078900400000000ull 7065942Sgibbs#define ID_AHA_2910_15_20_30C 0x5078900478509004ull 7165942Sgibbs#define ID_AIC7855 0x5578900400000000ull 7265942Sgibbs#define ID_AIC7859 0x3860900400000000ull 7365942Sgibbs#define ID_AHA_2930CU 0x3860900438699004ull 7465942Sgibbs#define ID_AIC7860 0x6078900400000000ull 7565942Sgibbs#define ID_AIC7860C 0x6078900478609004ull 7665942Sgibbs#define ID_AHA_1480A 0x6075900400000000ull 7765942Sgibbs#define ID_AHA_2940AU_0 0x6178900400000000ull 7865942Sgibbs#define ID_AHA_2940AU_1 0x6178900478619004ull 7965942Sgibbs#define ID_AHA_2940AU_CN 0x2178900478219004ull 8065942Sgibbs#define ID_AHA_2930C_VAR 0x6038900438689004ull 8165942Sgibbs 8265942Sgibbs#define ID_AIC7870 0x7078900400000000ull 8365942Sgibbs#define ID_AHA_2940 0x7178900400000000ull 8465942Sgibbs#define ID_AHA_3940 0x7278900400000000ull 8565942Sgibbs#define ID_AHA_398X 0x7378900400000000ull 8665942Sgibbs#define ID_AHA_2944 0x7478900400000000ull 8765942Sgibbs#define ID_AHA_3944 0x7578900400000000ull 8865942Sgibbs#define ID_AHA_4944 0x7678900400000000ull 8965942Sgibbs 9065942Sgibbs#define ID_AIC7880 0x8078900400000000ull 9165942Sgibbs#define ID_AIC7880_B 0x8078900478809004ull 9265942Sgibbs#define ID_AHA_2940U 0x8178900400000000ull 9365942Sgibbs#define ID_AHA_3940U 0x8278900400000000ull 9465942Sgibbs#define ID_AHA_2944U 0x8478900400000000ull 9565942Sgibbs#define ID_AHA_3944U 0x8578900400000000ull 9665942Sgibbs#define ID_AHA_398XU 0x8378900400000000ull 9765942Sgibbs#define ID_AHA_4944U 0x8678900400000000ull 9865942Sgibbs#define ID_AHA_2940UB 0x8178900478819004ull 9965942Sgibbs#define ID_AHA_2930U 0x8878900478889004ull 10065942Sgibbs#define ID_AHA_2940U_PRO 0x8778900478879004ull 10165942Sgibbs#define ID_AHA_2940U_CN 0x0078900478009004ull 10265942Sgibbs 10365942Sgibbs#define ID_AIC7895 0x7895900478959004ull 10465942Sgibbs#define ID_AIC7895_RAID_PORT 0x7893900478939004ull 10565942Sgibbs#define ID_AHA_2940U_DUAL 0x7895900478919004ull 10665942Sgibbs#define ID_AHA_3940AU 0x7895900478929004ull 10765942Sgibbs#define ID_AHA_3944AU 0x7895900478949004ull 10865942Sgibbs 10965942Sgibbs#define ID_AIC7890 0x001F9005000F9005ull 11065942Sgibbs#define ID_AAA_131U2 0x0013900500039005ull 11165942Sgibbs#define ID_AHA_2930U2 0x0011900501819005ull 11265942Sgibbs#define ID_AHA_2940U2B 0x00109005A1009005ull 11365942Sgibbs#define ID_AHA_2940U2_OEM 0x0010900521809005ull 11465942Sgibbs#define ID_AHA_2940U2 0x00109005A1809005ull 11565942Sgibbs#define ID_AHA_2950U2B 0x00109005E1009005ull 11665942Sgibbs 11765942Sgibbs#define ID_AIC7892 0x008F9005FFFF9005ull 11865942Sgibbs#define ID_AHA_29160 0x00809005E2A09005ull 11965942Sgibbs#define ID_AHA_29160_CPQ 0x00809005E2A00E11ull 12065942Sgibbs#define ID_AHA_29160N 0x0080900562A09005ull 12170204Sgibbs#define ID_AHA_29160C 0x0080900562209005ull 12265942Sgibbs#define ID_AHA_29160B 0x00809005E2209005ull 12365942Sgibbs#define ID_AHA_19160B 0x0081900562A19005ull 12465942Sgibbs 12565942Sgibbs#define ID_AIC7896 0x005F9005FFFF9005ull 12665942Sgibbs#define ID_AHA_3950U2B_0 0x00509005FFFF9005ull 12765942Sgibbs#define ID_AHA_3950U2B_1 0x00509005F5009005ull 12865942Sgibbs#define ID_AHA_3950U2D_0 0x00519005FFFF9005ull 12965942Sgibbs#define ID_AHA_3950U2D_1 0x00519005B5009005ull 13065942Sgibbs 13165942Sgibbs#define ID_AIC7899 0x00CF9005FFFF9005ull 13265942Sgibbs#define ID_AHA_3960D 0x00C09005F6209005ull /* AKA AHA-39160 */ 13365942Sgibbs#define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull 13465942Sgibbs 13565942Sgibbs#define ID_AIC7810 0x1078900400000000ull 13665942Sgibbs#define ID_AIC7815 0x7815900400000000ull 13765942Sgibbs 13872325Sgibbs#define DEVID_9005_TYPE(id) ((id) & 0xF) 13972325Sgibbs#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ 14072325Sgibbs#define DEVID_9005_TYPE_AAA 0x3 /* RAID Card */ 14172325Sgibbs#define DEVID_9005_TYPE_SISL 0x5 /* Low Cost Card */ 14272325Sgibbs#define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ 14372325Sgibbs 14472325Sgibbs#define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4) 14572325Sgibbs#define DEVID_9005_MAXRATE_U160 0x0 14672325Sgibbs#define DEVID_9005_MAXRATE_ULTRA2 0x1 14772325Sgibbs#define DEVID_9005_MAXRATE_ULTRA 0x2 14872325Sgibbs#define DEVID_9005_MAXRATE_FAST 0x3 14972325Sgibbs 15072325Sgibbs#define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6) 15172325Sgibbs 15272325Sgibbs#define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8) 15372325Sgibbs#define DEVID_9005_CLASS_SPI 0x0 /* Parallel SCSI */ 15472325Sgibbs 15570693Sgibbs#define SUBID_9005_TYPE(id) ((id) & 0xF) 15670693Sgibbs#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */ 15770693Sgibbs#define SUBID_9005_TYPE_CARD 0x0 /* Standard Card */ 15870693Sgibbs#define SUBID_9005_TYPE_LCCARD 0x1 /* Low Cost Card */ 15970693Sgibbs#define SUBID_9005_TYPE_RAID 0x3 /* Combined with Raid */ 16070204Sgibbs 16170693Sgibbs#define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4) 16270693Sgibbs#define SUBID_9005_MAXRATE_ULTRA2 0x0 16370693Sgibbs#define SUBID_9005_MAXRATE_ULTRA 0x1 16470693Sgibbs#define SUBID_9005_MAXRATE_U160 0x2 16570693Sgibbs#define SUBID_9005_MAXRATE_RESERVED 0x3 16670693Sgibbs 16770693Sgibbs#define SUBID_9005_SEEPTYPE(id) \ 16870693Sgibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 16970693Sgibbs ? ((id) & 0xC0) >> 6 \ 17070693Sgibbs : ((id) & 0x300) >> 8) 17170693Sgibbs#define SUBID_9005_SEEPTYPE_NONE 0x0 17270693Sgibbs#define SUBID_9005_SEEPTYPE_1K 0x1 17370693Sgibbs#define SUBID_9005_SEEPTYPE_2K_4K 0x2 17470693Sgibbs#define SUBID_9005_SEEPTYPE_RESERVED 0x3 17570693Sgibbs#define SUBID_9005_AUTOTERM(id) \ 17670693Sgibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 17770693Sgibbs ? (((id) & 0x400) >> 10) == 0 \ 17870693Sgibbs : (((id) & 0x40) >> 6) == 0) 17970693Sgibbs 18070693Sgibbs#define SUBID_9005_NUMCHAN(id) \ 18170693Sgibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 18270693Sgibbs ? ((id) & 0x300) >> 8 \ 18370693Sgibbs : ((id) & 0xC00) >> 10) 18470693Sgibbs 18570693Sgibbs#define SUBID_9005_LEGACYCONN(id) \ 18670693Sgibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 18770693Sgibbs ? 0 \ 18870693Sgibbs : ((id) & 0x80) >> 7) 18970693Sgibbs 19070693Sgibbs#define SUBID_9005_MFUNCENB(id) \ 19170693Sgibbs ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \ 19270693Sgibbs ? ((id) & 0x800) >> 11 \ 19370693Sgibbs : ((id) & 0x1000) >> 12) 19470693Sgibbs/* 19570693Sgibbs * Informational only. Should use chip register to be 19670693Sgibbs * ceratian, but may be use in identification strings. 19770693Sgibbs */ 19870693Sgibbs#define SUBID_9005_CARD_SCSIWIDTH_MASK 0x2000 19970693Sgibbs#define SUBID_9005_CARD_PCIWIDTH_MASK 0x4000 20070693Sgibbs#define SUBID_9005_CARD_SEDIFF_MASK 0x8000 20170693Sgibbs 20265942Sgibbsstatic ahc_device_setup_t ahc_aic7850_setup; 20365942Sgibbsstatic ahc_device_setup_t ahc_aic7855_setup; 20465942Sgibbsstatic ahc_device_setup_t ahc_aic7860_setup; 20571390Sgibbsstatic ahc_device_setup_t ahc_apa1480_setup; 20665942Sgibbsstatic ahc_device_setup_t ahc_aic7870_setup; 20765942Sgibbsstatic ahc_device_setup_t ahc_aha394X_setup; 20865942Sgibbsstatic ahc_device_setup_t ahc_aha494X_setup; 20965942Sgibbsstatic ahc_device_setup_t ahc_aha398X_setup; 21065942Sgibbsstatic ahc_device_setup_t ahc_aic7880_setup; 21171390Sgibbsstatic ahc_device_setup_t ahc_aha2940Pro_setup; 21265942Sgibbsstatic ahc_device_setup_t ahc_aha394XU_setup; 21365942Sgibbsstatic ahc_device_setup_t ahc_aha398XU_setup; 21465942Sgibbsstatic ahc_device_setup_t ahc_aic7890_setup; 21565942Sgibbsstatic ahc_device_setup_t ahc_aic7892_setup; 21665942Sgibbsstatic ahc_device_setup_t ahc_aic7895_setup; 21765942Sgibbsstatic ahc_device_setup_t ahc_aic7896_setup; 21865942Sgibbsstatic ahc_device_setup_t ahc_aic7899_setup; 21971390Sgibbsstatic ahc_device_setup_t ahc_aha29160C_setup; 22065942Sgibbsstatic ahc_device_setup_t ahc_raid_setup; 22165942Sgibbsstatic ahc_device_setup_t ahc_aha394XX_setup; 22265942Sgibbsstatic ahc_device_setup_t ahc_aha494XX_setup; 22365942Sgibbsstatic ahc_device_setup_t ahc_aha398XX_setup; 22465942Sgibbs 22565942Sgibbsstruct ahc_pci_identity ahc_pci_ident_table [] = 22665942Sgibbs{ 22765942Sgibbs /* aic7850 based controllers */ 22865942Sgibbs { 22965942Sgibbs ID_AHA_2910_15_20_30C, 23065942Sgibbs ID_ALL_MASK, 23165942Sgibbs "Adaptec 2910/15/20/30C SCSI adapter", 23265942Sgibbs ahc_aic7850_setup 23365942Sgibbs }, 23465942Sgibbs /* aic7860 based controllers */ 23565942Sgibbs { 23665942Sgibbs ID_AHA_2930CU, 23765942Sgibbs ID_ALL_MASK, 23865942Sgibbs "Adaptec 2930CU SCSI adapter", 23965942Sgibbs ahc_aic7860_setup 24065942Sgibbs }, 24165942Sgibbs { 24265942Sgibbs ID_AHA_1480A & ID_DEV_VENDOR_MASK, 24365942Sgibbs ID_DEV_VENDOR_MASK, 24465942Sgibbs "Adaptec 1480A Ultra SCSI adapter", 24571390Sgibbs ahc_apa1480_setup 24665942Sgibbs }, 24765942Sgibbs { 24865942Sgibbs ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK, 24965942Sgibbs ID_DEV_VENDOR_MASK, 25065942Sgibbs "Adaptec 2940A Ultra SCSI adapter", 25165942Sgibbs ahc_aic7860_setup 25265942Sgibbs }, 25365942Sgibbs { 25465942Sgibbs ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK, 25565942Sgibbs ID_DEV_VENDOR_MASK, 25665942Sgibbs "Adaptec 2940A/CN Ultra SCSI adapter", 25765942Sgibbs ahc_aic7860_setup 25865942Sgibbs }, 25965942Sgibbs { 26065942Sgibbs ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK, 26165942Sgibbs ID_DEV_VENDOR_MASK, 26265942Sgibbs "Adaptec 2930C SCSI adapter (VAR)", 26365942Sgibbs ahc_aic7860_setup 26465942Sgibbs }, 26565942Sgibbs /* aic7870 based controllers */ 26665942Sgibbs { 26765942Sgibbs ID_AHA_2940, 26865942Sgibbs ID_ALL_MASK, 26965942Sgibbs "Adaptec 2940 SCSI adapter", 27065942Sgibbs ahc_aic7870_setup 27165942Sgibbs }, 27265942Sgibbs { 27365942Sgibbs ID_AHA_3940, 27465942Sgibbs ID_ALL_MASK, 27565942Sgibbs "Adaptec 3940 SCSI adapter", 27665942Sgibbs ahc_aha394X_setup 27765942Sgibbs }, 27865942Sgibbs { 27965942Sgibbs ID_AHA_398X, 28065942Sgibbs ID_ALL_MASK, 28165942Sgibbs "Adaptec 398X SCSI RAID adapter", 28265942Sgibbs ahc_aha398X_setup 28365942Sgibbs }, 28465942Sgibbs { 28565942Sgibbs ID_AHA_2944, 28665942Sgibbs ID_ALL_MASK, 28765942Sgibbs "Adaptec 2944 SCSI adapter", 28865942Sgibbs ahc_aic7870_setup 28965942Sgibbs }, 29065942Sgibbs { 29165942Sgibbs ID_AHA_3944, 29265942Sgibbs ID_ALL_MASK, 29365942Sgibbs "Adaptec 3944 SCSI adapter", 29465942Sgibbs ahc_aha394X_setup 29565942Sgibbs }, 29665942Sgibbs { 29765942Sgibbs ID_AHA_4944, 29865942Sgibbs ID_ALL_MASK, 29965942Sgibbs "Adaptec 4944 SCSI adapter", 30065942Sgibbs ahc_aha494X_setup 30165942Sgibbs }, 30265942Sgibbs /* aic7880 based controllers */ 30365942Sgibbs { 30465942Sgibbs ID_AHA_2940U & ID_DEV_VENDOR_MASK, 30565942Sgibbs ID_DEV_VENDOR_MASK, 30665942Sgibbs "Adaptec 2940 Ultra SCSI adapter", 30765942Sgibbs ahc_aic7880_setup 30865942Sgibbs }, 30965942Sgibbs { 31065942Sgibbs ID_AHA_3940U & ID_DEV_VENDOR_MASK, 31165942Sgibbs ID_DEV_VENDOR_MASK, 31265942Sgibbs "Adaptec 3940 Ultra SCSI adapter", 31365942Sgibbs ahc_aha394XU_setup 31465942Sgibbs }, 31565942Sgibbs { 31665942Sgibbs ID_AHA_2944U & ID_DEV_VENDOR_MASK, 31765942Sgibbs ID_DEV_VENDOR_MASK, 31865942Sgibbs "Adaptec 2944 Ultra SCSI adapter", 31965942Sgibbs ahc_aic7880_setup 32065942Sgibbs }, 32165942Sgibbs { 32265942Sgibbs ID_AHA_3944U & ID_DEV_VENDOR_MASK, 32365942Sgibbs ID_DEV_VENDOR_MASK, 32465942Sgibbs "Adaptec 3944 Ultra SCSI adapter", 32565942Sgibbs ahc_aha394XU_setup 32665942Sgibbs }, 32765942Sgibbs { 32865942Sgibbs ID_AHA_398XU & ID_DEV_VENDOR_MASK, 32965942Sgibbs ID_DEV_VENDOR_MASK, 33065942Sgibbs "Adaptec 398X Ultra SCSI RAID adapter", 33165942Sgibbs ahc_aha398XU_setup 33265942Sgibbs }, 33365942Sgibbs { 33465942Sgibbs /* 33565942Sgibbs * XXX Don't know the slot numbers 33665942Sgibbs * so we can't identify channels 33765942Sgibbs */ 33865942Sgibbs ID_AHA_4944U & ID_DEV_VENDOR_MASK, 33965942Sgibbs ID_DEV_VENDOR_MASK, 34065942Sgibbs "Adaptec 4944 Ultra SCSI adapter", 34165942Sgibbs ahc_aic7880_setup 34265942Sgibbs }, 34365942Sgibbs { 34465942Sgibbs ID_AHA_2930U & ID_DEV_VENDOR_MASK, 34565942Sgibbs ID_DEV_VENDOR_MASK, 34665942Sgibbs "Adaptec 2930 Ultra SCSI adapter", 34765942Sgibbs ahc_aic7880_setup 34865942Sgibbs }, 34965942Sgibbs { 35065942Sgibbs ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK, 35165942Sgibbs ID_DEV_VENDOR_MASK, 35265942Sgibbs "Adaptec 2940 Pro Ultra SCSI adapter", 35371390Sgibbs ahc_aha2940Pro_setup 35465942Sgibbs }, 35565942Sgibbs { 35665942Sgibbs ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK, 35765942Sgibbs ID_DEV_VENDOR_MASK, 35865942Sgibbs "Adaptec 2940/CN Ultra SCSI adapter", 35965942Sgibbs ahc_aic7880_setup 36065942Sgibbs }, 36165942Sgibbs /* aic7890 based controllers */ 36265942Sgibbs { 36365942Sgibbs ID_AHA_2930U2, 36465942Sgibbs ID_ALL_MASK, 36565942Sgibbs "Adaptec 2930 Ultra2 SCSI adapter", 36665942Sgibbs ahc_aic7890_setup 36765942Sgibbs }, 36865942Sgibbs { 36965942Sgibbs ID_AHA_2940U2B, 37065942Sgibbs ID_ALL_MASK, 37165942Sgibbs "Adaptec 2940B Ultra2 SCSI adapter", 37265942Sgibbs ahc_aic7890_setup 37365942Sgibbs }, 37465942Sgibbs { 37565942Sgibbs ID_AHA_2940U2_OEM, 37665942Sgibbs ID_ALL_MASK, 37765942Sgibbs "Adaptec 2940 Ultra2 SCSI adapter (OEM)", 37865942Sgibbs ahc_aic7890_setup 37965942Sgibbs }, 38065942Sgibbs { 38165942Sgibbs ID_AHA_2940U2, 38265942Sgibbs ID_ALL_MASK, 38365942Sgibbs "Adaptec 2940 Ultra2 SCSI adapter", 38465942Sgibbs ahc_aic7890_setup 38565942Sgibbs }, 38665942Sgibbs { 38765942Sgibbs ID_AHA_2950U2B, 38865942Sgibbs ID_ALL_MASK, 38965942Sgibbs "Adaptec 2950 Ultra2 SCSI adapter", 39065942Sgibbs ahc_aic7890_setup 39165942Sgibbs }, 39265942Sgibbs { 39365942Sgibbs ID_AAA_131U2, 39465942Sgibbs ID_ALL_MASK, 39565942Sgibbs "Adaptec AAA-131 Ultra2 RAID adapter", 39665942Sgibbs ahc_aic7890_setup 39765942Sgibbs }, 39865942Sgibbs /* aic7892 based controllers */ 39965942Sgibbs { 40065942Sgibbs ID_AHA_29160, 40165942Sgibbs ID_ALL_MASK, 40265942Sgibbs "Adaptec 29160 Ultra160 SCSI adapter", 40365942Sgibbs ahc_aic7892_setup 40465942Sgibbs }, 40565942Sgibbs { 40665942Sgibbs ID_AHA_29160_CPQ, 40765942Sgibbs ID_ALL_MASK, 40865942Sgibbs "Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter", 40965942Sgibbs ahc_aic7892_setup 41065942Sgibbs }, 41165942Sgibbs { 41265942Sgibbs ID_AHA_29160N, 41365942Sgibbs ID_ALL_MASK, 41465942Sgibbs "Adaptec 29160N Ultra160 SCSI adapter", 41565942Sgibbs ahc_aic7892_setup 41665942Sgibbs }, 41765942Sgibbs { 41870204Sgibbs ID_AHA_29160C, 41970204Sgibbs ID_ALL_MASK, 42070204Sgibbs "Adaptec 29160C Ultra160 SCSI adapter", 42171390Sgibbs ahc_aha29160C_setup 42270204Sgibbs }, 42370204Sgibbs { 42465942Sgibbs ID_AHA_29160B, 42565942Sgibbs ID_ALL_MASK, 42665942Sgibbs "Adaptec 29160B Ultra160 SCSI adapter", 42765942Sgibbs ahc_aic7892_setup 42865942Sgibbs }, 42965942Sgibbs { 43065942Sgibbs ID_AHA_19160B, 43165942Sgibbs ID_ALL_MASK, 43265942Sgibbs "Adaptec 19160B Ultra160 SCSI adapter", 43365942Sgibbs ahc_aic7892_setup 43465942Sgibbs }, 43565942Sgibbs /* aic7895 based controllers */ 43665942Sgibbs { 43765942Sgibbs ID_AHA_2940U_DUAL, 43865942Sgibbs ID_ALL_MASK, 43965942Sgibbs "Adaptec 2940/DUAL Ultra SCSI adapter", 44065942Sgibbs ahc_aic7895_setup 44165942Sgibbs }, 44265942Sgibbs { 44365942Sgibbs ID_AHA_3940AU, 44465942Sgibbs ID_ALL_MASK, 44565942Sgibbs "Adaptec 3940A Ultra SCSI adapter", 44665942Sgibbs ahc_aic7895_setup 44765942Sgibbs }, 44865942Sgibbs { 44965942Sgibbs ID_AHA_3944AU, 45065942Sgibbs ID_ALL_MASK, 45165942Sgibbs "Adaptec 3944A Ultra SCSI adapter", 45265942Sgibbs ahc_aic7895_setup 45365942Sgibbs }, 45465942Sgibbs /* aic7896/97 based controllers */ 45565942Sgibbs { 45665942Sgibbs ID_AHA_3950U2B_0, 45765942Sgibbs ID_ALL_MASK, 45865942Sgibbs "Adaptec 3950B Ultra2 SCSI adapter", 45965942Sgibbs ahc_aic7896_setup 46065942Sgibbs }, 46165942Sgibbs { 46265942Sgibbs ID_AHA_3950U2B_1, 46365942Sgibbs ID_ALL_MASK, 46465942Sgibbs "Adaptec 3950B Ultra2 SCSI adapter", 46565942Sgibbs ahc_aic7896_setup 46665942Sgibbs }, 46765942Sgibbs { 46865942Sgibbs ID_AHA_3950U2D_0, 46965942Sgibbs ID_ALL_MASK, 47065942Sgibbs "Adaptec 3950D Ultra2 SCSI adapter", 47165942Sgibbs ahc_aic7896_setup 47265942Sgibbs }, 47365942Sgibbs { 47465942Sgibbs ID_AHA_3950U2D_1, 47565942Sgibbs ID_ALL_MASK, 47665942Sgibbs "Adaptec 3950D Ultra2 SCSI adapter", 47765942Sgibbs ahc_aic7896_setup 47865942Sgibbs }, 47965942Sgibbs /* aic7899 based controllers */ 48065942Sgibbs { 48165942Sgibbs ID_AHA_3960D, 48265942Sgibbs ID_ALL_MASK, 48365942Sgibbs "Adaptec 3960D Ultra160 SCSI adapter", 48465942Sgibbs ahc_aic7899_setup 48565942Sgibbs }, 48665942Sgibbs { 48765942Sgibbs ID_AHA_3960D_CPQ, 48865942Sgibbs ID_ALL_MASK, 48965942Sgibbs "Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter", 49065942Sgibbs ahc_aic7899_setup 49165942Sgibbs }, 49265942Sgibbs /* Generic chip probes for devices we don't know 'exactly' */ 49365942Sgibbs { 49465942Sgibbs ID_AIC7850 & ID_DEV_VENDOR_MASK, 49565942Sgibbs ID_DEV_VENDOR_MASK, 49665942Sgibbs "Adaptec aic7850 SCSI adapter", 49765942Sgibbs ahc_aic7850_setup 49865942Sgibbs }, 49965942Sgibbs { 50065942Sgibbs ID_AIC7855 & ID_DEV_VENDOR_MASK, 50165942Sgibbs ID_DEV_VENDOR_MASK, 50265942Sgibbs "Adaptec aic7855 SCSI adapter", 50365942Sgibbs ahc_aic7855_setup 50465942Sgibbs }, 50565942Sgibbs { 50665942Sgibbs ID_AIC7859 & ID_DEV_VENDOR_MASK, 50765942Sgibbs ID_DEV_VENDOR_MASK, 50865942Sgibbs "Adaptec aic7859 Ultra SCSI adapter", 50965942Sgibbs ahc_aic7860_setup 51065942Sgibbs }, 51165942Sgibbs { 51265942Sgibbs ID_AIC7860 & ID_DEV_VENDOR_MASK, 51365942Sgibbs ID_DEV_VENDOR_MASK, 51465942Sgibbs "Adaptec aic7860 SCSI adapter", 51565942Sgibbs ahc_aic7860_setup 51665942Sgibbs }, 51765942Sgibbs { 51865942Sgibbs ID_AIC7870 & ID_DEV_VENDOR_MASK, 51965942Sgibbs ID_DEV_VENDOR_MASK, 52065942Sgibbs "Adaptec aic7870 SCSI adapter", 52165942Sgibbs ahc_aic7870_setup 52265942Sgibbs }, 52365942Sgibbs { 52465942Sgibbs ID_AIC7880 & ID_DEV_VENDOR_MASK, 52565942Sgibbs ID_DEV_VENDOR_MASK, 52665942Sgibbs "Adaptec aic7880 Ultra SCSI adapter", 52765942Sgibbs ahc_aic7880_setup 52865942Sgibbs }, 52965942Sgibbs { 53072325Sgibbs ID_AIC7890 & ID_9005_GENERIC_MASK, 53172325Sgibbs ID_9005_GENERIC_MASK, 53265942Sgibbs "Adaptec aic7890/91 Ultra2 SCSI adapter", 53365942Sgibbs ahc_aic7890_setup 53465942Sgibbs }, 53565942Sgibbs { 53672325Sgibbs ID_AIC7892 & ID_9005_GENERIC_MASK, 53772325Sgibbs ID_9005_GENERIC_MASK, 53865942Sgibbs "Adaptec aic7892 Ultra160 SCSI adapter", 53965942Sgibbs ahc_aic7892_setup 54065942Sgibbs }, 54165942Sgibbs { 54265942Sgibbs ID_AIC7895 & ID_DEV_VENDOR_MASK, 54365942Sgibbs ID_DEV_VENDOR_MASK, 54465942Sgibbs "Adaptec aic7895 Ultra SCSI adapter", 54565942Sgibbs ahc_aic7895_setup 54665942Sgibbs }, 54765942Sgibbs { 54865942Sgibbs ID_AIC7895_RAID_PORT & ID_DEV_VENDOR_MASK, 54965942Sgibbs ID_DEV_VENDOR_MASK, 55065942Sgibbs "Adaptec aic7895 Ultra SCSI adapter (RAID PORT)", 55165942Sgibbs ahc_aic7895_setup 55265942Sgibbs }, 55365942Sgibbs { 55472325Sgibbs ID_AIC7896 & ID_9005_GENERIC_MASK, 55572325Sgibbs ID_9005_GENERIC_MASK, 55665942Sgibbs "Adaptec aic7896/97 Ultra2 SCSI adapter", 55765942Sgibbs ahc_aic7896_setup 55865942Sgibbs }, 55965942Sgibbs { 56072325Sgibbs ID_AIC7899 & ID_9005_GENERIC_MASK, 56172325Sgibbs ID_9005_GENERIC_MASK, 56265942Sgibbs "Adaptec aic7899 Ultra160 SCSI adapter", 56365942Sgibbs ahc_aic7899_setup 56465942Sgibbs }, 56565942Sgibbs { 56665942Sgibbs ID_AIC7810 & ID_DEV_VENDOR_MASK, 56765942Sgibbs ID_DEV_VENDOR_MASK, 56865942Sgibbs "Adaptec aic7810 RAID memory controller", 56965942Sgibbs ahc_raid_setup 57065942Sgibbs }, 57165942Sgibbs { 57265942Sgibbs ID_AIC7815 & ID_DEV_VENDOR_MASK, 57365942Sgibbs ID_DEV_VENDOR_MASK, 57465942Sgibbs "Adaptec aic7815 RAID memory controller", 57565942Sgibbs ahc_raid_setup 57665942Sgibbs } 57765942Sgibbs}; 57865942Sgibbs 57970204Sgibbsconst u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table); 58065942Sgibbs 58165942Sgibbs#define AHC_394X_SLOT_CHANNEL_A 4 58265942Sgibbs#define AHC_394X_SLOT_CHANNEL_B 5 58365942Sgibbs 58465942Sgibbs#define AHC_398X_SLOT_CHANNEL_A 4 58565942Sgibbs#define AHC_398X_SLOT_CHANNEL_B 8 58665942Sgibbs#define AHC_398X_SLOT_CHANNEL_C 12 58765942Sgibbs 58865942Sgibbs#define AHC_494X_SLOT_CHANNEL_A 4 58965942Sgibbs#define AHC_494X_SLOT_CHANNEL_B 5 59065942Sgibbs#define AHC_494X_SLOT_CHANNEL_C 6 59165942Sgibbs#define AHC_494X_SLOT_CHANNEL_D 7 59265942Sgibbs 59365942Sgibbs#define DEVCONFIG 0x40 59465942Sgibbs#define SCBSIZE32 0x00010000ul /* aic789X only */ 59565942Sgibbs#define MPORTMODE 0x00000400ul /* aic7870 only */ 59665942Sgibbs#define RAMPSM 0x00000200ul /* aic7870 only */ 59765942Sgibbs#define VOLSENSE 0x00000100ul 59865942Sgibbs#define SCBRAMSEL 0x00000080ul 59965942Sgibbs#define MRDCEN 0x00000040ul 60065942Sgibbs#define EXTSCBTIME 0x00000020ul /* aic7870 only */ 60165942Sgibbs#define EXTSCBPEN 0x00000010ul /* aic7870 only */ 60265942Sgibbs#define BERREN 0x00000008ul 60365942Sgibbs#define DACEN 0x00000004ul 60465942Sgibbs#define STPWLEVEL 0x00000002ul 60565942Sgibbs#define DIFACTNEGEN 0x00000001ul /* aic7870 only */ 60665942Sgibbs 60765942Sgibbs#define CSIZE_LATTIME 0x0c 60865942Sgibbs#define CACHESIZE 0x0000003ful /* only 5 bits */ 60965942Sgibbs#define LATTIME 0x0000ff00ul 61065942Sgibbs 61170204Sgibbstypedef enum 61270204Sgibbs{ 61370204Sgibbs AHC_POWER_STATE_D0, 61470204Sgibbs AHC_POWER_STATE_D1, 61570204Sgibbs AHC_POWER_STATE_D2, 61670204Sgibbs AHC_POWER_STATE_D3 61770204Sgibbs} ahc_power_state; 61870204Sgibbs 61970204Sgibbsstatic void ahc_power_state_change(struct ahc_softc *ahc, 62070204Sgibbs ahc_power_state new_state); 62165942Sgibbsstatic int ahc_ext_scbram_present(struct ahc_softc *ahc); 62265942Sgibbsstatic void ahc_scbram_config(struct ahc_softc *ahc, int enable, 62365942Sgibbs int pcheck, int fast, int large); 62465942Sgibbsstatic void ahc_probe_ext_scbram(struct ahc_softc *ahc); 62565942Sgibbsstatic void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1); 62665942Sgibbsstatic void configure_termination(struct ahc_softc *ahc, 62765942Sgibbs struct seeprom_descriptor *sd, 62865942Sgibbs u_int adapter_control, 62965942Sgibbs u_int *sxfrctl1); 63065942Sgibbs 63165942Sgibbsstatic void ahc_new_term_detect(struct ahc_softc *ahc, 63265942Sgibbs int *enableSEC_low, 63365942Sgibbs int *enableSEC_high, 63465942Sgibbs int *enablePRI_low, 63565942Sgibbs int *enablePRI_high, 63665942Sgibbs int *eeprom_present); 63765942Sgibbsstatic void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 63865942Sgibbs int *internal68_present, 63965942Sgibbs int *externalcable_present, 64065942Sgibbs int *eeprom_present); 64165942Sgibbsstatic void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 64265942Sgibbs int *externalcable_present, 64365942Sgibbs int *eeprom_present); 64465942Sgibbsstatic int acquire_seeprom(struct ahc_softc *ahc, 64565942Sgibbs struct seeprom_descriptor *sd); 64665942Sgibbsstatic void release_seeprom(struct seeprom_descriptor *sd); 64765942Sgibbsstatic void write_brdctl(struct ahc_softc *ahc, uint8_t value); 64865942Sgibbsstatic uint8_t read_brdctl(struct ahc_softc *ahc); 64965942Sgibbs 65065942Sgibbsstruct ahc_pci_identity * 65165942Sgibbsahc_find_pci_device(ahc_dev_softc_t pci) 65265942Sgibbs{ 65365942Sgibbs uint64_t full_id; 65465942Sgibbs uint16_t device; 65565942Sgibbs uint16_t vendor; 65665942Sgibbs uint16_t subdevice; 65765942Sgibbs uint16_t subvendor; 65865942Sgibbs struct ahc_pci_identity *entry; 65965942Sgibbs u_int i; 66065942Sgibbs 66165942Sgibbs vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); 66265942Sgibbs device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); 66365942Sgibbs subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); 66465942Sgibbs subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); 66565942Sgibbs full_id = ahc_compose_id(device, 66665942Sgibbs vendor, 66765942Sgibbs subdevice, 66865942Sgibbs subvendor); 66965942Sgibbs 67070204Sgibbs /* If the second function is not hooked up, ignore it. */ 67170204Sgibbs if (ahc_get_pci_function(pci) > 0 67270204Sgibbs && subvendor == 0x9005 67370693Sgibbs && SUBID_9005_MFUNCENB(subdevice) == 0) 67470204Sgibbs return (NULL); 67570204Sgibbs 67665942Sgibbs for (i = 0; i < ahc_num_pci_devs; i++) { 67765942Sgibbs entry = &ahc_pci_ident_table[i]; 67865942Sgibbs if (entry->full_id == (full_id & entry->id_mask)) 67965942Sgibbs return (entry); 68065942Sgibbs } 68165942Sgibbs return (NULL); 68265942Sgibbs} 68365942Sgibbs 68465942Sgibbsint 68565942Sgibbsahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry) 68665942Sgibbs{ 68765942Sgibbs struct ahc_probe_config probe_config; 68865942Sgibbs struct scb_data *shared_scb_data; 68965942Sgibbs u_int command; 69065942Sgibbs u_int our_id = 0; 69165942Sgibbs u_int sxfrctl1; 69265942Sgibbs u_int scsiseq; 69365942Sgibbs u_int dscommand0; 69465942Sgibbs int error; 69565942Sgibbs uint8_t sblkctl; 69665942Sgibbs 69765942Sgibbs shared_scb_data = NULL; 69865942Sgibbs ahc_init_probe_config(&probe_config); 69965942Sgibbs error = entry->setup(ahc->dev_softc, &probe_config); 70065942Sgibbs if (error != 0) 70165942Sgibbs return (error); 70265942Sgibbs probe_config.chip |= AHC_PCI; 70365942Sgibbs probe_config.description = entry->name; 70465942Sgibbs 70565942Sgibbs error = ahc_pci_map_registers(ahc); 70665942Sgibbs if (error != 0) 70765942Sgibbs return (error); 70865942Sgibbs 70970204Sgibbs ahc_power_state_change(ahc, AHC_POWER_STATE_D0); 71070204Sgibbs 71165942Sgibbs /* Ensure busmastering is enabled */ 71265942Sgibbs command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1); 71365942Sgibbs command |= PCIM_CMD_BUSMASTEREN; 71465942Sgibbs ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1); 71565942Sgibbs 71665942Sgibbs /* On all PCI adapters, we allow SCB paging */ 71765942Sgibbs probe_config.flags |= AHC_PAGESCBS; 71865942Sgibbs 71965942Sgibbs error = ahc_softc_init(ahc, &probe_config); 72065942Sgibbs if (error != 0) 72165942Sgibbs return (error); 72265942Sgibbs 72365942Sgibbs /* Remeber how the card was setup in case there is no SEEPROM */ 72470204Sgibbs if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) { 72570204Sgibbs pause_sequencer(ahc); 72670204Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 72770204Sgibbs our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID; 72870204Sgibbs else 72970204Sgibbs our_id = ahc_inb(ahc, SCSIID) & OID; 73070204Sgibbs sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN; 73170204Sgibbs scsiseq = ahc_inb(ahc, SCSISEQ); 73270204Sgibbs } else { 73370204Sgibbs sxfrctl1 = STPWEN; 73470204Sgibbs our_id = 7; 73570204Sgibbs scsiseq = 0; 73670204Sgibbs } 73765942Sgibbs 73865942Sgibbs error = ahc_reset(ahc); 73965942Sgibbs if (error != 0) 74065942Sgibbs return (ENXIO); 74165942Sgibbs 74265942Sgibbs if ((ahc->features & AHC_DT) != 0) { 74365942Sgibbs u_int sfunct; 74465942Sgibbs 74565942Sgibbs /* Perform ALT-Mode Setup */ 74665942Sgibbs sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE; 74765942Sgibbs ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE); 74865942Sgibbs ahc_outb(ahc, OPTIONMODE, OPTIONMODE_DEFAULTS); 74965942Sgibbs ahc_outb(ahc, SFUNCT, sfunct); 75065942Sgibbs 75165942Sgibbs /* Normal mode setup */ 75265942Sgibbs ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN 75370204Sgibbs |TARGCRCENDEN); 75465942Sgibbs } 75565942Sgibbs 75665942Sgibbs error = ahc_pci_map_int(ahc); 75765942Sgibbs if (error != 0) 75865942Sgibbs return (error); 75965942Sgibbs dscommand0 = ahc_inb(ahc, DSCOMMAND0); 76066647Sgibbs dscommand0 |= MPARCKEN|CACHETHEN; 76165942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 76265942Sgibbs 76365942Sgibbs /* 76465942Sgibbs * DPARCKEN doesn't work correctly on 76565942Sgibbs * some MBs so don't use it. 76665942Sgibbs */ 76765942Sgibbs dscommand0 &= ~DPARCKEN; 76865942Sgibbs } 76965942Sgibbs 77065942Sgibbs /* 77165942Sgibbs * Handle chips that must have cache line 77265942Sgibbs * streaming (dis/en)abled. 77365942Sgibbs */ 77465942Sgibbs if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0) 77565942Sgibbs dscommand0 |= CACHETHEN; 77665942Sgibbs 77765942Sgibbs if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0) 77865942Sgibbs dscommand0 &= ~CACHETHEN; 77965942Sgibbs 78065942Sgibbs ahc_outb(ahc, DSCOMMAND0, dscommand0); 78165942Sgibbs 78265942Sgibbs ahc->pci_cachesize = 78365942Sgibbs ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, 78465942Sgibbs /*bytes*/1) & CACHESIZE; 78565942Sgibbs ahc->pci_cachesize *= 4; 78665942Sgibbs 78765942Sgibbs /* See if we have a SEEPROM and perform auto-term */ 78865942Sgibbs check_extport(ahc, &sxfrctl1); 78965942Sgibbs 79065942Sgibbs /* 79165942Sgibbs * Take the LED out of diagnostic mode 79265942Sgibbs */ 79365942Sgibbs sblkctl = ahc_inb(ahc, SBLKCTL); 79465942Sgibbs ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON))); 79565942Sgibbs 79665942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 79768087Sgibbs ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX); 79865942Sgibbs } else { 79965942Sgibbs ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100); 80065942Sgibbs } 80165942Sgibbs 80265942Sgibbs if (ahc->flags & AHC_USEDEFAULTS) { 80365942Sgibbs /* 80465942Sgibbs * PCI Adapter default setup 80565942Sgibbs * Should only be used if the adapter does not have 80665942Sgibbs * a SEEPROM. 80765942Sgibbs */ 80865942Sgibbs /* See if someone else set us up already */ 80965942Sgibbs if (scsiseq != 0) { 81065942Sgibbs printf("%s: Using left over BIOS settings\n", 81165942Sgibbs ahc_name(ahc)); 81265942Sgibbs ahc->flags &= ~AHC_USEDEFAULTS; 81372325Sgibbs ahc->flags |= AHC_BIOS_ENABLED; 81465942Sgibbs } else { 81565942Sgibbs /* 81665942Sgibbs * Assume only one connector and always turn 81765942Sgibbs * on termination. 81865942Sgibbs */ 81965942Sgibbs our_id = 0x07; 82065942Sgibbs sxfrctl1 = STPWEN; 82165942Sgibbs } 82265942Sgibbs ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI); 82365942Sgibbs 82465942Sgibbs ahc->our_id = our_id; 82565942Sgibbs } 82665942Sgibbs 82765942Sgibbs /* 82865942Sgibbs * Take a look to see if we have external SRAM. 82965942Sgibbs * We currently do not attempt to use SRAM that is 83065942Sgibbs * shared among multiple controllers. 83165942Sgibbs */ 83265942Sgibbs ahc_probe_ext_scbram(ahc); 83365942Sgibbs 83465942Sgibbs /* 83565942Sgibbs * Record our termination setting for the 83665942Sgibbs * generic initialization routine. 83765942Sgibbs */ 83865942Sgibbs if ((sxfrctl1 & STPWEN) != 0) 83965942Sgibbs ahc->flags |= AHC_TERM_ENB_A; 84065942Sgibbs 84165942Sgibbs /* Core initialization */ 84265942Sgibbs error = ahc_init(ahc); 84365942Sgibbs if (error != 0) 84465942Sgibbs return (error); 84565942Sgibbs 84665942Sgibbs /* 84765942Sgibbs * Link this softc in with all other ahc instances. 84865942Sgibbs */ 84965942Sgibbs ahc_softc_insert(ahc); 85065942Sgibbs 85165942Sgibbs return (0); 85265942Sgibbs} 85365942Sgibbs 85470204Sgibbsstatic void 85570204Sgibbsahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state) 85670204Sgibbs{ 85770204Sgibbs uint32_t cap; 85870204Sgibbs u_int cap_offset; 85970204Sgibbs 86070204Sgibbs /* 86170204Sgibbs * Traverse the capability list looking for 86270204Sgibbs * the power management capability. 86370204Sgibbs */ 86470204Sgibbs cap = 0; 86570204Sgibbs cap_offset = ahc_pci_read_config(ahc->dev_softc, 86670204Sgibbs PCIR_CAP_PTR, /*bytes*/1); 86770204Sgibbs while (cap_offset != 0) { 86870204Sgibbs 86970204Sgibbs cap = ahc_pci_read_config(ahc->dev_softc, 87070204Sgibbs cap_offset, /*bytes*/4); 87170204Sgibbs if ((cap & 0xFF) == 1 87270204Sgibbs && ((cap >> 16) & 0x3) > 0) { 87370204Sgibbs uint32_t pm_control; 87470204Sgibbs 87570204Sgibbs pm_control = ahc_pci_read_config(ahc->dev_softc, 87670204Sgibbs cap_offset + 4, 87770204Sgibbs /*bytes*/4); 87870204Sgibbs pm_control &= ~0x3; 87970204Sgibbs pm_control |= new_state; 88070204Sgibbs ahc_pci_write_config(ahc->dev_softc, 88170204Sgibbs cap_offset + 4, 88270204Sgibbs pm_control, /*bytes*/2); 88370204Sgibbs break; 88470204Sgibbs } 88570204Sgibbs cap_offset = (cap >> 8) & 0xFF; 88670204Sgibbs } 88770204Sgibbs} 88870204Sgibbs 88965942Sgibbs/* 89065942Sgibbs * Test for the presense of external sram in an 89165942Sgibbs * "unshared" configuration. 89265942Sgibbs */ 89365942Sgibbsstatic int 89465942Sgibbsahc_ext_scbram_present(struct ahc_softc *ahc) 89565942Sgibbs{ 89668087Sgibbs u_int chip; 89765942Sgibbs int ramps; 89865942Sgibbs int single_user; 89965942Sgibbs uint32_t devconfig; 90065942Sgibbs 90168087Sgibbs chip = ahc->chip & AHC_CHIPID_MASK; 90265942Sgibbs devconfig = ahc_pci_read_config(ahc->dev_softc, 90365942Sgibbs DEVCONFIG, /*bytes*/4); 90465942Sgibbs single_user = (devconfig & MPORTMODE) != 0; 90565942Sgibbs 90665942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 90765942Sgibbs ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0; 90868087Sgibbs else if (chip >= AHC_AIC7870) 90965942Sgibbs ramps = (devconfig & RAMPSM) != 0; 91065942Sgibbs else 91165942Sgibbs ramps = 0; 91265942Sgibbs 91365942Sgibbs if (ramps && single_user) 91465942Sgibbs return (1); 91565942Sgibbs return (0); 91665942Sgibbs} 91765942Sgibbs 91865942Sgibbs/* 91965942Sgibbs * Enable external scbram. 92065942Sgibbs */ 92165942Sgibbsstatic void 92265942Sgibbsahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck, 92365942Sgibbs int fast, int large) 92465942Sgibbs{ 92565942Sgibbs uint32_t devconfig; 92665942Sgibbs 92765942Sgibbs if (ahc->features & AHC_MULTI_FUNC) { 92865942Sgibbs /* 92965942Sgibbs * Set the SCB Base addr (highest address bit) 93065942Sgibbs * depending on which channel we are. 93165942Sgibbs */ 93265942Sgibbs ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc)); 93365942Sgibbs } 93465942Sgibbs 93565942Sgibbs devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4); 93665942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 93765942Sgibbs u_int dscommand0; 93865942Sgibbs 93965942Sgibbs dscommand0 = ahc_inb(ahc, DSCOMMAND0); 94065942Sgibbs if (enable) 94165942Sgibbs dscommand0 &= ~INTSCBRAMSEL; 94265942Sgibbs else 94365942Sgibbs dscommand0 |= INTSCBRAMSEL; 94465942Sgibbs if (large) 94565942Sgibbs dscommand0 &= ~USCBSIZE32; 94665942Sgibbs else 94765942Sgibbs dscommand0 |= USCBSIZE32; 94865942Sgibbs ahc_outb(ahc, DSCOMMAND0, dscommand0); 94965942Sgibbs } else { 95065942Sgibbs if (fast) 95165942Sgibbs devconfig &= ~EXTSCBTIME; 95265942Sgibbs else 95365942Sgibbs devconfig |= EXTSCBTIME; 95465942Sgibbs if (enable) 95565942Sgibbs devconfig &= ~SCBRAMSEL; 95665942Sgibbs else 95765942Sgibbs devconfig |= SCBRAMSEL; 95865942Sgibbs if (large) 95965942Sgibbs devconfig &= ~SCBSIZE32; 96065942Sgibbs else 96165942Sgibbs devconfig |= SCBSIZE32; 96265942Sgibbs } 96365942Sgibbs if (pcheck) 96465942Sgibbs devconfig |= EXTSCBPEN; 96565942Sgibbs else 96665942Sgibbs devconfig &= ~EXTSCBPEN; 96765942Sgibbs 96865942Sgibbs ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 96965942Sgibbs} 97065942Sgibbs 97165942Sgibbs/* 97265942Sgibbs * Take a look to see if we have external SRAM. 97365942Sgibbs * We currently do not attempt to use SRAM that is 97465942Sgibbs * shared among multiple controllers. 97565942Sgibbs */ 97665942Sgibbsstatic void 97765942Sgibbsahc_probe_ext_scbram(struct ahc_softc *ahc) 97865942Sgibbs{ 97965942Sgibbs int num_scbs; 98065942Sgibbs int test_num_scbs; 98165942Sgibbs int enable; 98265942Sgibbs int pcheck; 98365942Sgibbs int fast; 98465942Sgibbs int large; 98565942Sgibbs 98665942Sgibbs enable = FALSE; 98765942Sgibbs pcheck = FALSE; 98865942Sgibbs fast = FALSE; 98965942Sgibbs large = FALSE; 99065942Sgibbs num_scbs = 0; 99165942Sgibbs 99265942Sgibbs if (ahc_ext_scbram_present(ahc) == 0) 99365942Sgibbs goto done; 99465942Sgibbs 99565942Sgibbs /* 99665942Sgibbs * Probe for the best parameters to use. 99765942Sgibbs */ 99865942Sgibbs ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large); 99965942Sgibbs num_scbs = ahc_probe_scbs(ahc); 100065942Sgibbs if (num_scbs == 0) { 100165942Sgibbs /* The SRAM wasn't really present. */ 100265942Sgibbs goto done; 100365942Sgibbs } 100465942Sgibbs enable = TRUE; 100565942Sgibbs 100665942Sgibbs /* 100765942Sgibbs * Clear any outstanding parity error 100865942Sgibbs * and ensure that parity error reporting 100965942Sgibbs * is enabled. 101065942Sgibbs */ 101165942Sgibbs ahc_outb(ahc, SEQCTL, 0); 101265942Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 101365942Sgibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 101465942Sgibbs 101565942Sgibbs /* Now see if we can do parity */ 101665942Sgibbs ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large); 101765942Sgibbs num_scbs = ahc_probe_scbs(ahc); 101865942Sgibbs if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 101965942Sgibbs || (ahc_inb(ahc, ERROR) & MPARERR) == 0) 102065942Sgibbs pcheck = TRUE; 102165942Sgibbs 102265942Sgibbs /* Clear any resulting parity error */ 102365942Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 102465942Sgibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 102565942Sgibbs 102665942Sgibbs /* Now see if we can do fast timing */ 102765942Sgibbs ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large); 102865942Sgibbs test_num_scbs = ahc_probe_scbs(ahc); 102965942Sgibbs if (test_num_scbs == num_scbs 103065942Sgibbs && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0 103165942Sgibbs || (ahc_inb(ahc, ERROR) & MPARERR) == 0)) 103265942Sgibbs fast = TRUE; 103365942Sgibbs 103465942Sgibbs /* 103565942Sgibbs * See if we can use large SCBs and still maintain 103665942Sgibbs * the same overall count of SCBs. 103765942Sgibbs */ 103865942Sgibbs if ((ahc->features & AHC_LARGE_SCBS) != 0) { 103965942Sgibbs ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE); 104065942Sgibbs test_num_scbs = ahc_probe_scbs(ahc); 104165942Sgibbs if (test_num_scbs >= num_scbs) { 104265942Sgibbs large = TRUE; 104365942Sgibbs num_scbs = test_num_scbs; 104465942Sgibbs if (num_scbs >= 64) { 104565942Sgibbs /* 104665942Sgibbs * We have enough space to move the 104765942Sgibbs * "busy targets table" into SCB space 104865942Sgibbs * and make it qualify all the way to the 104965942Sgibbs * lun level. 105065942Sgibbs */ 105165942Sgibbs ahc->flags |= AHC_SCB_BTT; 105265942Sgibbs } 105365942Sgibbs } 105465942Sgibbs } 105565942Sgibbsdone: 105665942Sgibbs /* 105765942Sgibbs * Disable parity error reporting until we 105865942Sgibbs * can load instruction ram. 105965942Sgibbs */ 106065942Sgibbs ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS); 106165942Sgibbs /* Clear any latched parity error */ 106265942Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 106365942Sgibbs ahc_outb(ahc, CLRINT, CLRBRKADRINT); 106465942Sgibbs if (bootverbose && enable) { 106565942Sgibbs printf("%s: External SRAM, %s access%s, %dbytes/SCB\n", 106665942Sgibbs ahc_name(ahc), fast ? "fast" : "slow", 106765942Sgibbs pcheck ? ", parity checking enabled" : "", 106865942Sgibbs large ? 64 : 32); 106965942Sgibbs } 107065942Sgibbs ahc_scbram_config(ahc, enable, pcheck, fast, large); 107165942Sgibbs} 107265942Sgibbs 107365942Sgibbs/* 107465942Sgibbs * Check the external port logic for a serial eeprom 107565942Sgibbs * and termination/cable detection contrls. 107665942Sgibbs */ 107765942Sgibbsstatic void 107865942Sgibbscheck_extport(struct ahc_softc *ahc, u_int *sxfrctl1) 107965942Sgibbs{ 108065942Sgibbs struct seeprom_descriptor sd; 108165942Sgibbs struct seeprom_config sc; 108265942Sgibbs u_int scsi_conf; 108365942Sgibbs u_int adapter_control; 108465942Sgibbs int have_seeprom; 108565942Sgibbs int have_autoterm; 108665942Sgibbs 108765942Sgibbs sd.sd_ahc = ahc; 108865942Sgibbs sd.sd_control_offset = SEECTL; 108965942Sgibbs sd.sd_status_offset = SEECTL; 109065942Sgibbs sd.sd_dataout_offset = SEECTL; 109165942Sgibbs 109265942Sgibbs /* 109365942Sgibbs * For some multi-channel devices, the c46 is simply too 109465942Sgibbs * small to work. For the other controller types, we can 109565942Sgibbs * get our information from either SEEPROM type. Set the 109665942Sgibbs * type to start our probe with accordingly. 109765942Sgibbs */ 109865942Sgibbs if (ahc->flags & AHC_LARGE_SEEPROM) 109965942Sgibbs sd.sd_chip = C56_66; 110065942Sgibbs else 110165942Sgibbs sd.sd_chip = C46; 110265942Sgibbs 110365942Sgibbs sd.sd_MS = SEEMS; 110465942Sgibbs sd.sd_RDY = SEERDY; 110565942Sgibbs sd.sd_CS = SEECS; 110665942Sgibbs sd.sd_CK = SEECK; 110765942Sgibbs sd.sd_DO = SEEDO; 110865942Sgibbs sd.sd_DI = SEEDI; 110965942Sgibbs 111065942Sgibbs have_seeprom = acquire_seeprom(ahc, &sd); 111165942Sgibbs if (have_seeprom) { 111265942Sgibbs 111365942Sgibbs if (bootverbose) 111465942Sgibbs printf("%s: Reading SEEPROM...", ahc_name(ahc)); 111565942Sgibbs 111665942Sgibbs for (;;) { 111765942Sgibbs u_int start_addr; 111865942Sgibbs 111965942Sgibbs start_addr = 32 * (ahc->channel - 'A'); 112065942Sgibbs 112165942Sgibbs have_seeprom = read_seeprom(&sd, (uint16_t *)&sc, 112265942Sgibbs start_addr, sizeof(sc)/2); 112365942Sgibbs 112465942Sgibbs if (have_seeprom) 112565942Sgibbs have_seeprom = verify_cksum(&sc); 112665942Sgibbs 112765942Sgibbs if (have_seeprom != 0 || sd.sd_chip == C56_66) { 112865942Sgibbs if (bootverbose) { 112965942Sgibbs if (have_seeprom == 0) 113065942Sgibbs printf ("checksum error\n"); 113165942Sgibbs else 113265942Sgibbs printf ("done.\n"); 113365942Sgibbs } 113465942Sgibbs break; 113565942Sgibbs } 113665942Sgibbs sd.sd_chip = C56_66; 113765942Sgibbs } 113865942Sgibbs } 113965942Sgibbs 114065942Sgibbs#if 0 114165942Sgibbs if (!have_seeprom) { 114265942Sgibbs /* 114365942Sgibbs * Pull scratch ram settings and treat them as 114465942Sgibbs * if they are the contents of an seeprom if 114565942Sgibbs * the 'ADPT' signature is found in SCB2. 114665942Sgibbs */ 114765942Sgibbs ahc_outb(ahc, SCBPTR, 2); 114865942Sgibbs if (ahc_inb(ahc, SCB_BASE) == 'A' 114965942Sgibbs && ahc_inb(ahc, SCB_BASE + 1) == 'D' 115065942Sgibbs && ahc_inb(ahc, SCB_BASE + 2) == 'P' 115165942Sgibbs && ahc_inb(ahc, SCB_BASE + 3) == 'T') { 115265942Sgibbs uint8_t *sc_bytes; 115365942Sgibbs int i; 115465942Sgibbs 115565942Sgibbs sc_bytes = (uint8_t *)≻ 115665942Sgibbs for (i = 0; i < 64; i++) 115765942Sgibbs sc_bytes[i] = ahc_inb(ahc, TARG_SCSIRATE + i); 115865942Sgibbs /* Byte 0x1c is stored in byte 4 of SCB2 */ 115965942Sgibbs sc_bytes[0x1c] = ahc_inb(ahc, SCB_BASE + 4); 116065942Sgibbs have_seeprom = verify_cksum(&sc); 116165942Sgibbs } 116265942Sgibbs } 116365942Sgibbs#endif 116465942Sgibbs 116565942Sgibbs if (!have_seeprom) { 116665942Sgibbs if (bootverbose) 116765942Sgibbs printf("%s: No SEEPROM available.\n", ahc_name(ahc)); 116865942Sgibbs ahc->flags |= AHC_USEDEFAULTS; 116965942Sgibbs } else { 117065942Sgibbs /* 117165942Sgibbs * Put the data we've collected down into SRAM 117265942Sgibbs * where ahc_init will find it. 117365942Sgibbs */ 117465942Sgibbs int i; 117565942Sgibbs int max_targ = sc.max_targets & CFMAXTARG; 117665942Sgibbs uint16_t discenable; 117765942Sgibbs uint16_t ultraenb; 117865942Sgibbs 117965942Sgibbs discenable = 0; 118065942Sgibbs ultraenb = 0; 118165942Sgibbs if ((sc.adapter_control & CFULTRAEN) != 0) { 118265942Sgibbs /* 118365942Sgibbs * Determine if this adapter has a "newstyle" 118465942Sgibbs * SEEPROM format. 118565942Sgibbs */ 118665942Sgibbs for (i = 0; i < max_targ; i++) { 118765942Sgibbs if ((sc.device_flags[i] & CFSYNCHISULTRA) != 0){ 118865942Sgibbs ahc->flags |= AHC_NEWEEPROM_FMT; 118965942Sgibbs break; 119065942Sgibbs } 119165942Sgibbs } 119265942Sgibbs } 119365942Sgibbs 119465942Sgibbs for (i = 0; i < max_targ; i++) { 119565942Sgibbs u_int scsirate; 119665942Sgibbs uint16_t target_mask; 119765942Sgibbs 119865942Sgibbs target_mask = 0x01 << i; 119965942Sgibbs if (sc.device_flags[i] & CFDISC) 120065942Sgibbs discenable |= target_mask; 120165942Sgibbs if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) { 120265942Sgibbs if ((sc.device_flags[i] & CFSYNCHISULTRA) != 0) 120365942Sgibbs ultraenb |= target_mask; 120465942Sgibbs } else if ((sc.adapter_control & CFULTRAEN) != 0) { 120565942Sgibbs ultraenb |= target_mask; 120665942Sgibbs } 120765942Sgibbs if ((sc.device_flags[i] & CFXFER) == 0x04 120865942Sgibbs && (ultraenb & target_mask) != 0) { 120965942Sgibbs /* Treat 10MHz as a non-ultra speed */ 121065942Sgibbs sc.device_flags[i] &= ~CFXFER; 121165942Sgibbs ultraenb &= ~target_mask; 121265942Sgibbs } 121365942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) { 121465942Sgibbs u_int offset; 121565942Sgibbs 121665942Sgibbs if (sc.device_flags[i] & CFSYNCH) 121765942Sgibbs offset = MAX_OFFSET_ULTRA2; 121865942Sgibbs else 121965942Sgibbs offset = 0; 122065942Sgibbs ahc_outb(ahc, TARG_OFFSET + i, offset); 122165942Sgibbs 122265942Sgibbs /* 122365942Sgibbs * The ultra enable bits contain the 122465942Sgibbs * high bit of the ultra2 sync rate 122565942Sgibbs * field. 122665942Sgibbs */ 122765942Sgibbs scsirate = (sc.device_flags[i] & CFXFER) 122865942Sgibbs | ((ultraenb & target_mask) 122965942Sgibbs ? 0x8 : 0x0); 123065942Sgibbs if (sc.device_flags[i] & CFWIDEB) 123165942Sgibbs scsirate |= WIDEXFER; 123265942Sgibbs } else { 123365942Sgibbs scsirate = (sc.device_flags[i] & CFXFER) << 4; 123465942Sgibbs if (sc.device_flags[i] & CFSYNCH) 123565942Sgibbs scsirate |= SOFS; 123665942Sgibbs if (sc.device_flags[i] & CFWIDEB) 123765942Sgibbs scsirate |= WIDEXFER; 123865942Sgibbs } 123965942Sgibbs ahc_outb(ahc, TARG_SCSIRATE + i, scsirate); 124065942Sgibbs } 124165942Sgibbs ahc->our_id = sc.brtime_id & CFSCSIID; 124265942Sgibbs 124365942Sgibbs scsi_conf = (ahc->our_id & 0x7); 124465942Sgibbs if (sc.adapter_control & CFSPARITY) 124565942Sgibbs scsi_conf |= ENSPCHK; 124665942Sgibbs if (sc.adapter_control & CFRESETB) 124765942Sgibbs scsi_conf |= RESET_SCSI; 124865942Sgibbs 124972325Sgibbs if ((sc.adapter_control & CFCHNLBPRIMARY) != 0 125072325Sgibbs && (ahc->features & AHC_MULTI_FUNC) != 0) 125172325Sgibbs ahc->flags |= AHC_CHANNEL_B_PRIMARY; 125272325Sgibbs 125365942Sgibbs if (sc.bios_control & CFEXTEND) 125465942Sgibbs ahc->flags |= AHC_EXTENDED_TRANS_A; 125572325Sgibbs 125672325Sgibbs if (sc.bios_control & CFBIOSEN) 125772325Sgibbs ahc->flags |= AHC_BIOS_ENABLED; 125865942Sgibbs if (ahc->features & AHC_ULTRA 125965942Sgibbs && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) { 126065942Sgibbs /* Should we enable Ultra mode? */ 126165942Sgibbs if (!(sc.adapter_control & CFULTRAEN)) 126265942Sgibbs /* Treat us as a non-ultra card */ 126365942Sgibbs ultraenb = 0; 126465942Sgibbs } 126565942Sgibbs 126665942Sgibbs if (sc.signature == CFSIGNATURE) { 126765942Sgibbs uint32_t devconfig; 126865942Sgibbs 126965942Sgibbs /* Honor the STPWLEVEL settings */ 127065942Sgibbs devconfig = ahc_pci_read_config(ahc->dev_softc, 127165942Sgibbs DEVCONFIG, /*bytes*/4); 127265942Sgibbs devconfig &= ~STPWLEVEL; 127365942Sgibbs if ((sc.bios_control & CFSTPWLEVEL) != 0) 127465942Sgibbs devconfig |= STPWLEVEL; 127565942Sgibbs ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, 127665942Sgibbs devconfig, /*bytes*/4); 127765942Sgibbs } 127865942Sgibbs /* Set SCSICONF info */ 127965942Sgibbs ahc_outb(ahc, SCSICONF, scsi_conf); 128065942Sgibbs ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff)); 128165942Sgibbs ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff)); 128265942Sgibbs ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff); 128365942Sgibbs ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff); 128465942Sgibbs } 128565942Sgibbs 128665942Sgibbs /* 128765942Sgibbs * Cards that have the external logic necessary to talk to 128865942Sgibbs * a SEEPROM, are almost certain to have the remaining logic 128965942Sgibbs * necessary for auto-termination control. This assumption 129065942Sgibbs * hasn't failed yet... 129165942Sgibbs */ 129265942Sgibbs have_autoterm = have_seeprom; 129365942Sgibbs if (have_seeprom) 129465942Sgibbs adapter_control = sc.adapter_control; 129565942Sgibbs else 129665942Sgibbs adapter_control = CFAUTOTERM; 129765942Sgibbs 129865942Sgibbs /* 129965942Sgibbs * Some low-cost chips have SEEPROM and auto-term control built 130065942Sgibbs * in, instead of using a GAL. They can tell us directly 130165942Sgibbs * if the termination logic is enabled. 130265942Sgibbs */ 130365942Sgibbs if ((ahc->features & AHC_SPIOCAP) != 0) { 130465942Sgibbs if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) != 0) 130565942Sgibbs have_autoterm = TRUE; 130665942Sgibbs else 130765942Sgibbs have_autoterm = FALSE; 130865942Sgibbs } 130965942Sgibbs 131065942Sgibbs if (have_autoterm) 131165942Sgibbs configure_termination(ahc, &sd, adapter_control, sxfrctl1); 131265942Sgibbs 131365942Sgibbs release_seeprom(&sd); 131465942Sgibbs} 131565942Sgibbs 131665942Sgibbsstatic void 131765942Sgibbsconfigure_termination(struct ahc_softc *ahc, 131865942Sgibbs struct seeprom_descriptor *sd, 131965942Sgibbs u_int adapter_control, 132065942Sgibbs u_int *sxfrctl1) 132165942Sgibbs{ 132265942Sgibbs uint8_t brddat; 132365942Sgibbs 132465942Sgibbs brddat = 0; 132565942Sgibbs 132665942Sgibbs /* 132765942Sgibbs * Update the settings in sxfrctl1 to match the 132865942Sgibbs * termination settings 132965942Sgibbs */ 133065942Sgibbs *sxfrctl1 = 0; 133165942Sgibbs 133265942Sgibbs /* 133365942Sgibbs * SEECS must be on for the GALS to latch 133465942Sgibbs * the data properly. Be sure to leave MS 133565942Sgibbs * on or we will release the seeprom. 133665942Sgibbs */ 133765942Sgibbs SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS); 133865942Sgibbs if ((adapter_control & CFAUTOTERM) != 0 133965942Sgibbs || (ahc->features & AHC_NEW_TERMCTL) != 0) { 134065942Sgibbs int internal50_present; 134165942Sgibbs int internal68_present; 134265942Sgibbs int externalcable_present; 134365942Sgibbs int eeprom_present; 134465942Sgibbs int enableSEC_low; 134565942Sgibbs int enableSEC_high; 134665942Sgibbs int enablePRI_low; 134765942Sgibbs int enablePRI_high; 134871390Sgibbs int sum; 134965942Sgibbs 135065942Sgibbs enableSEC_low = 0; 135165942Sgibbs enableSEC_high = 0; 135265942Sgibbs enablePRI_low = 0; 135365942Sgibbs enablePRI_high = 0; 135465942Sgibbs if ((ahc->features & AHC_NEW_TERMCTL) != 0) { 135565942Sgibbs ahc_new_term_detect(ahc, &enableSEC_low, 135665942Sgibbs &enableSEC_high, 135765942Sgibbs &enablePRI_low, 135865942Sgibbs &enablePRI_high, 135965942Sgibbs &eeprom_present); 136065942Sgibbs if ((adapter_control & CFSEAUTOTERM) == 0) { 136165942Sgibbs if (bootverbose) 136265942Sgibbs printf("%s: Manual SE Termination\n", 136365942Sgibbs ahc_name(ahc)); 136465942Sgibbs enableSEC_low = (adapter_control & CFSELOWTERM); 136565942Sgibbs enableSEC_high = 136665942Sgibbs (adapter_control & CFSEHIGHTERM); 136765942Sgibbs } 136865942Sgibbs if ((adapter_control & CFAUTOTERM) == 0) { 136965942Sgibbs if (bootverbose) 137065942Sgibbs printf("%s: Manual LVD Termination\n", 137165942Sgibbs ahc_name(ahc)); 137265942Sgibbs enablePRI_low = (adapter_control & CFSTERM); 137365942Sgibbs enablePRI_high = (adapter_control & CFWSTERM); 137465942Sgibbs } 137565942Sgibbs /* Make the table calculations below happy */ 137665942Sgibbs internal50_present = 0; 137765942Sgibbs internal68_present = 1; 137865942Sgibbs externalcable_present = 1; 137965942Sgibbs } else if ((ahc->features & AHC_SPIOCAP) != 0) { 138065942Sgibbs aic785X_cable_detect(ahc, &internal50_present, 138165942Sgibbs &externalcable_present, 138265942Sgibbs &eeprom_present); 138365942Sgibbs } else { 138465942Sgibbs aic787X_cable_detect(ahc, &internal50_present, 138565942Sgibbs &internal68_present, 138665942Sgibbs &externalcable_present, 138765942Sgibbs &eeprom_present); 138865942Sgibbs } 138965942Sgibbs 139065942Sgibbs if ((ahc->features & AHC_WIDE) == 0) 139165942Sgibbs internal68_present = 0; 139265942Sgibbs 139371390Sgibbs if (bootverbose 139471390Sgibbs && (ahc->features & AHC_ULTRA2) == 0) { 139571390Sgibbs printf("%s: internal 50 cable %s present", 139671390Sgibbs ahc_name(ahc), 139771390Sgibbs internal50_present ? "is":"not"); 139871390Sgibbs 139971390Sgibbs if ((ahc->features & AHC_WIDE) != 0) 140071390Sgibbs printf(", internal 68 cable %s present", 140165942Sgibbs internal68_present ? "is":"not"); 140271390Sgibbs printf("\n%s: external cable %s present\n", 140371390Sgibbs ahc_name(ahc), 140471390Sgibbs externalcable_present ? "is":"not"); 140571390Sgibbs } 140671390Sgibbs if (bootverbose) 140765942Sgibbs printf("%s: BIOS eeprom %s present\n", 140865942Sgibbs ahc_name(ahc), eeprom_present ? "is" : "not"); 140965942Sgibbs 141065942Sgibbs if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) { 141165942Sgibbs /* 141265942Sgibbs * The 50 pin connector is a separate bus, 141365942Sgibbs * so force it to always be terminated. 141465942Sgibbs * In the future, perform current sensing 141565942Sgibbs * to determine if we are in the middle of 141665942Sgibbs * a properly terminated bus. 141765942Sgibbs */ 141865942Sgibbs internal50_present = 0; 141965942Sgibbs } 142065942Sgibbs 142165942Sgibbs /* 142265942Sgibbs * Now set the termination based on what 142365942Sgibbs * we found. 142465942Sgibbs * Flash Enable = BRDDAT7 142565942Sgibbs * Secondary High Term Enable = BRDDAT6 142665942Sgibbs * Secondary Low Term Enable = BRDDAT5 (7890) 142765942Sgibbs * Primary High Term Enable = BRDDAT4 (7890) 142865942Sgibbs */ 142965942Sgibbs if ((ahc->features & AHC_ULTRA2) == 0 143071390Sgibbs && (internal50_present != 0) 143171390Sgibbs && (internal68_present != 0) 143271390Sgibbs && (externalcable_present != 0)) { 143365942Sgibbs printf("%s: Illegal cable configuration!!. " 143465942Sgibbs "Only two connectors on the " 143565942Sgibbs "adapter may be used at a " 143665942Sgibbs "time!\n", ahc_name(ahc)); 143765942Sgibbs } 143865942Sgibbs 143965942Sgibbs if ((ahc->features & AHC_WIDE) != 0 144065942Sgibbs && ((externalcable_present == 0) 144165942Sgibbs || (internal68_present == 0) 144265942Sgibbs || (enableSEC_high != 0))) { 144365942Sgibbs brddat |= BRDDAT6; 144465942Sgibbs if (bootverbose) { 144565942Sgibbs if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 144665942Sgibbs printf("%s: 68 pin termination " 144765942Sgibbs "Enabled\n", ahc_name(ahc)); 144865942Sgibbs else 144965942Sgibbs printf("%s: %sHigh byte termination " 145065942Sgibbs "Enabled\n", ahc_name(ahc), 145165942Sgibbs enableSEC_high ? "Secondary " 145265942Sgibbs : ""); 145365942Sgibbs } 145465942Sgibbs } 145565942Sgibbs 145671390Sgibbs sum = internal50_present + internal68_present 145771390Sgibbs + externalcable_present; 145871390Sgibbs if (sum < 2 || (enableSEC_low != 0)) { 145965942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 146065942Sgibbs brddat |= BRDDAT5; 146165942Sgibbs else 146265942Sgibbs *sxfrctl1 |= STPWEN; 146365942Sgibbs if (bootverbose) { 146465942Sgibbs if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) 146565942Sgibbs printf("%s: 50 pin termination " 146665942Sgibbs "Enabled\n", ahc_name(ahc)); 146765942Sgibbs else 146865942Sgibbs printf("%s: %sLow byte termination " 146965942Sgibbs "Enabled\n", ahc_name(ahc), 147065942Sgibbs enableSEC_low ? "Secondary " 147165942Sgibbs : ""); 147265942Sgibbs } 147365942Sgibbs } 147465942Sgibbs 147565942Sgibbs if (enablePRI_low != 0) { 147665942Sgibbs *sxfrctl1 |= STPWEN; 147765942Sgibbs if (bootverbose) 147865942Sgibbs printf("%s: Primary Low Byte termination " 147965942Sgibbs "Enabled\n", ahc_name(ahc)); 148065942Sgibbs } 148165942Sgibbs 148265942Sgibbs /* 148365942Sgibbs * Setup STPWEN before setting up the rest of 148465942Sgibbs * the termination per the tech note on the U160 cards. 148565942Sgibbs */ 148665942Sgibbs ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 148765942Sgibbs 148865942Sgibbs if (enablePRI_high != 0) { 148965942Sgibbs brddat |= BRDDAT4; 149065942Sgibbs if (bootverbose) 149165942Sgibbs printf("%s: Primary High Byte " 149265942Sgibbs "termination Enabled\n", 149365942Sgibbs ahc_name(ahc)); 149465942Sgibbs } 149565942Sgibbs 149665942Sgibbs write_brdctl(ahc, brddat); 149765942Sgibbs 149865942Sgibbs } else { 149965942Sgibbs if ((adapter_control & CFSTERM) != 0) { 150065942Sgibbs *sxfrctl1 |= STPWEN; 150165942Sgibbs 150265942Sgibbs if (bootverbose) 150365942Sgibbs printf("%s: %sLow byte termination Enabled\n", 150465942Sgibbs ahc_name(ahc), 150565942Sgibbs (ahc->features & AHC_ULTRA2) ? "Primary " 150665942Sgibbs : ""); 150765942Sgibbs } 150865942Sgibbs 150971390Sgibbs if ((adapter_control & CFWSTERM) != 0 151071390Sgibbs && (ahc->features & AHC_WIDE) != 0) { 151165942Sgibbs brddat |= BRDDAT6; 151265942Sgibbs if (bootverbose) 151365942Sgibbs printf("%s: %sHigh byte termination Enabled\n", 151465942Sgibbs ahc_name(ahc), 151565942Sgibbs (ahc->features & AHC_ULTRA2) 151665942Sgibbs ? "Secondary " : ""); 151765942Sgibbs } 151865942Sgibbs 151965942Sgibbs /* 152065942Sgibbs * Setup STPWEN before setting up the rest of 152165942Sgibbs * the termination per the tech note on the U160 cards. 152265942Sgibbs */ 152365942Sgibbs ahc_outb(ahc, SXFRCTL1, *sxfrctl1); 152465942Sgibbs 152571390Sgibbs if ((ahc->features & AHC_WIDE) != 0) 152671390Sgibbs write_brdctl(ahc, brddat); 152765942Sgibbs } 152865942Sgibbs SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */ 152965942Sgibbs} 153065942Sgibbs 153165942Sgibbsstatic void 153265942Sgibbsahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low, 153365942Sgibbs int *enableSEC_high, int *enablePRI_low, 153465942Sgibbs int *enablePRI_high, int *eeprom_present) 153565942Sgibbs{ 153665942Sgibbs uint8_t brdctl; 153765942Sgibbs 153865942Sgibbs /* 153965942Sgibbs * BRDDAT7 = Eeprom 154065942Sgibbs * BRDDAT6 = Enable Secondary High Byte termination 154165942Sgibbs * BRDDAT5 = Enable Secondary Low Byte termination 154265942Sgibbs * BRDDAT4 = Enable Primary high byte termination 154365942Sgibbs * BRDDAT3 = Enable Primary low byte termination 154465942Sgibbs */ 154565942Sgibbs brdctl = read_brdctl(ahc); 154665942Sgibbs *eeprom_present = brdctl & BRDDAT7; 154765942Sgibbs *enableSEC_high = (brdctl & BRDDAT6); 154865942Sgibbs *enableSEC_low = (brdctl & BRDDAT5); 154965942Sgibbs *enablePRI_high = (brdctl & BRDDAT4); 155065942Sgibbs *enablePRI_low = (brdctl & BRDDAT3); 155165942Sgibbs} 155265942Sgibbs 155365942Sgibbsstatic void 155465942Sgibbsaic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 155565942Sgibbs int *internal68_present, int *externalcable_present, 155665942Sgibbs int *eeprom_present) 155765942Sgibbs{ 155865942Sgibbs uint8_t brdctl; 155965942Sgibbs 156065942Sgibbs /* 156165942Sgibbs * First read the status of our cables. 156265942Sgibbs * Set the rom bank to 0 since the 156365942Sgibbs * bank setting serves as a multiplexor 156465942Sgibbs * for the cable detection logic. 156565942Sgibbs * BRDDAT5 controls the bank switch. 156665942Sgibbs */ 156765942Sgibbs write_brdctl(ahc, 0); 156865942Sgibbs 156965942Sgibbs /* 157065942Sgibbs * Now read the state of the internal 157165942Sgibbs * connectors. BRDDAT6 is INT50 and 157265942Sgibbs * BRDDAT7 is INT68. 157365942Sgibbs */ 157465942Sgibbs brdctl = read_brdctl(ahc); 157571390Sgibbs *internal50_present = (brdctl & BRDDAT6) ? 0 : 1; 157671390Sgibbs *internal68_present = (brdctl & BRDDAT7) ? 0 : 1; 157765942Sgibbs 157865942Sgibbs /* 157965942Sgibbs * Set the rom bank to 1 and determine 158065942Sgibbs * the other signals. 158165942Sgibbs */ 158265942Sgibbs write_brdctl(ahc, BRDDAT5); 158365942Sgibbs 158465942Sgibbs /* 158565942Sgibbs * Now read the state of the external 158665942Sgibbs * connectors. BRDDAT6 is EXT68 and 158765942Sgibbs * BRDDAT7 is EPROMPS. 158865942Sgibbs */ 158965942Sgibbs brdctl = read_brdctl(ahc); 159071390Sgibbs *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 159171390Sgibbs *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0; 159265942Sgibbs} 159365942Sgibbs 159465942Sgibbsstatic void 159565942Sgibbsaic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present, 159665942Sgibbs int *externalcable_present, int *eeprom_present) 159765942Sgibbs{ 159865942Sgibbs uint8_t brdctl; 159965942Sgibbs 160065942Sgibbs ahc_outb(ahc, BRDCTL, BRDRW|BRDCS); 160165942Sgibbs ahc_outb(ahc, BRDCTL, 0); 160265942Sgibbs brdctl = ahc_inb(ahc, BRDCTL); 160371390Sgibbs *internal50_present = (brdctl & BRDDAT5) ? 0 : 1; 160471390Sgibbs *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1; 160565942Sgibbs 160671390Sgibbs *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0; 160765942Sgibbs} 160865942Sgibbs 160965942Sgibbsstatic int 161065942Sgibbsacquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd) 161165942Sgibbs{ 161265942Sgibbs int wait; 161365942Sgibbs 161465942Sgibbs if ((ahc->features & AHC_SPIOCAP) != 0 161565942Sgibbs && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0) 161665942Sgibbs return (0); 161765942Sgibbs 161865942Sgibbs /* 161965942Sgibbs * Request access of the memory port. When access is 162065942Sgibbs * granted, SEERDY will go high. We use a 1 second 162165942Sgibbs * timeout which should be near 1 second more than 162265942Sgibbs * is needed. Reason: after the chip reset, there 162365942Sgibbs * should be no contention. 162465942Sgibbs */ 162565942Sgibbs SEEPROM_OUTB(sd, sd->sd_MS); 162665942Sgibbs wait = 1000; /* 1 second timeout in msec */ 162765942Sgibbs while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) { 162865942Sgibbs ahc_delay(1000); /* delay 1 msec */ 162965942Sgibbs } 163065942Sgibbs if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) { 163165942Sgibbs SEEPROM_OUTB(sd, 0); 163265942Sgibbs return (0); 163365942Sgibbs } 163465942Sgibbs return(1); 163565942Sgibbs} 163665942Sgibbs 163765942Sgibbsstatic void 163865942Sgibbsrelease_seeprom(struct seeprom_descriptor *sd) 163965942Sgibbs{ 164065942Sgibbs /* Release access to the memory port and the serial EEPROM. */ 164165942Sgibbs SEEPROM_OUTB(sd, 0); 164265942Sgibbs} 164365942Sgibbs 164465942Sgibbsstatic void 164565942Sgibbswrite_brdctl(struct ahc_softc *ahc, uint8_t value) 164665942Sgibbs{ 164765942Sgibbs uint8_t brdctl; 164865942Sgibbs 164965942Sgibbs if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 165065942Sgibbs brdctl = BRDSTB; 165165942Sgibbs if (ahc->channel == 'B') 165265942Sgibbs brdctl |= BRDCS; 165365942Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 165465942Sgibbs brdctl = 0; 165565942Sgibbs } else { 165665942Sgibbs brdctl = BRDSTB|BRDCS; 165765942Sgibbs } 165865942Sgibbs ahc_outb(ahc, BRDCTL, brdctl); 165971390Sgibbs ahc_flush_device_writes(ahc); 166065942Sgibbs brdctl |= value; 166165942Sgibbs ahc_outb(ahc, BRDCTL, brdctl); 166271390Sgibbs ahc_flush_device_writes(ahc); 166365942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 166465942Sgibbs brdctl |= BRDSTB_ULTRA2; 166565942Sgibbs else 166665942Sgibbs brdctl &= ~BRDSTB; 166765942Sgibbs ahc_outb(ahc, BRDCTL, brdctl); 166871390Sgibbs ahc_flush_device_writes(ahc); 166965942Sgibbs if ((ahc->features & AHC_ULTRA2) != 0) 167065942Sgibbs brdctl = 0; 167165942Sgibbs else 167265942Sgibbs brdctl &= ~BRDCS; 167365942Sgibbs ahc_outb(ahc, BRDCTL, brdctl); 167465942Sgibbs} 167565942Sgibbs 167665942Sgibbsstatic uint8_t 167765942Sgibbsread_brdctl(ahc) 167865942Sgibbs struct ahc_softc *ahc; 167965942Sgibbs{ 168065942Sgibbs uint8_t brdctl; 168165942Sgibbs uint8_t value; 168265942Sgibbs 168365942Sgibbs if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) { 168465942Sgibbs brdctl = BRDRW; 168565942Sgibbs if (ahc->channel == 'B') 168665942Sgibbs brdctl |= BRDCS; 168765942Sgibbs } else if ((ahc->features & AHC_ULTRA2) != 0) { 168865942Sgibbs brdctl = BRDRW_ULTRA2; 168965942Sgibbs } else { 169065942Sgibbs brdctl = BRDRW|BRDCS; 169165942Sgibbs } 169265942Sgibbs ahc_outb(ahc, BRDCTL, brdctl); 169371390Sgibbs ahc_flush_device_writes(ahc); 169465942Sgibbs value = ahc_inb(ahc, BRDCTL); 169565942Sgibbs ahc_outb(ahc, BRDCTL, 0); 169665942Sgibbs return (value); 169765942Sgibbs} 169865942Sgibbs 169965942Sgibbs#define DPE 0x80 170065942Sgibbs#define SSE 0x40 170165942Sgibbs#define RMA 0x20 170265942Sgibbs#define RTA 0x10 170365942Sgibbs#define STA 0x08 170465942Sgibbs#define DPR 0x01 170565942Sgibbs 170665942Sgibbsvoid 170765942Sgibbsahc_pci_intr(struct ahc_softc *ahc) 170865942Sgibbs{ 170966269Sgibbs u_int error; 171066269Sgibbs u_int status1; 171165942Sgibbs 171266269Sgibbs error = ahc_inb(ahc, ERROR); 171366269Sgibbs if ((error & PCIERRSTAT) == 0) 171466269Sgibbs return; 171566269Sgibbs 171665942Sgibbs status1 = ahc_pci_read_config(ahc->dev_softc, 171765942Sgibbs PCIR_STATUS + 1, /*bytes*/1); 171865942Sgibbs 171966269Sgibbs printf("%s: PCI error Interrupt at seqaddr = 0x%x\n", 172066269Sgibbs ahc_name(ahc), 172166269Sgibbs ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)); 172266269Sgibbs 172365942Sgibbs if (status1 & DPE) { 172465942Sgibbs printf("%s: Data Parity Error Detected during address " 172565942Sgibbs "or write data phase\n", ahc_name(ahc)); 172665942Sgibbs } 172765942Sgibbs if (status1 & SSE) { 172866647Sgibbs printf("%s: Signal System Error Detected\n", ahc_name(ahc)); 172965942Sgibbs } 173065942Sgibbs if (status1 & RMA) { 173166647Sgibbs printf("%s: Received a Master Abort\n", ahc_name(ahc)); 173265942Sgibbs } 173365942Sgibbs if (status1 & RTA) { 173465942Sgibbs printf("%s: Received a Target Abort\n", ahc_name(ahc)); 173565942Sgibbs } 173665942Sgibbs if (status1 & STA) { 173765942Sgibbs printf("%s: Signaled a Target Abort\n", ahc_name(ahc)); 173865942Sgibbs } 173965942Sgibbs if (status1 & DPR) { 174065942Sgibbs printf("%s: Data Parity Error has been reported via PERR#\n", 174165942Sgibbs ahc_name(ahc)); 174265942Sgibbs } 174365942Sgibbs if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) { 174465942Sgibbs printf("%s: Latched PCIERR interrupt with " 174565942Sgibbs "no status bits set\n", ahc_name(ahc)); 174665942Sgibbs } 174765942Sgibbs ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1, 174865942Sgibbs status1, /*bytes*/1); 174965942Sgibbs 175065942Sgibbs if (status1 & (DPR|RMA|RTA)) { 175165942Sgibbs ahc_outb(ahc, CLRINT, CLRPARERR); 175265942Sgibbs } 175366269Sgibbs 175466269Sgibbs unpause_sequencer(ahc); 175565942Sgibbs} 175665942Sgibbs 175765942Sgibbsstatic int 175865942Sgibbsahc_aic7850_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 175965942Sgibbs{ 176065942Sgibbs probe_config->channel = 'A'; 176165942Sgibbs probe_config->chip = AHC_AIC7850; 176265942Sgibbs probe_config->features = AHC_AIC7850_FE; 176365942Sgibbs probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG 176465942Sgibbs | AHC_PCI_MWI_BUG; 176565942Sgibbs return (0); 176665942Sgibbs} 176765942Sgibbs 176865942Sgibbsstatic int 176965942Sgibbsahc_aic7855_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 177065942Sgibbs{ 177165942Sgibbs probe_config->channel = 'A'; 177265942Sgibbs probe_config->chip = AHC_AIC7855; 177365942Sgibbs probe_config->features = AHC_AIC7855_FE; 177465942Sgibbs probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG 177565942Sgibbs | AHC_PCI_MWI_BUG; 177665942Sgibbs return (0); 177765942Sgibbs} 177865942Sgibbs 177965942Sgibbsstatic int 178065942Sgibbsahc_aic7860_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 178165942Sgibbs{ 178265942Sgibbs uint8_t rev; 178365942Sgibbs 178465942Sgibbs probe_config->channel = 'A'; 178565942Sgibbs probe_config->chip = AHC_AIC7860; 178665942Sgibbs probe_config->features = AHC_AIC7860_FE; 178765942Sgibbs probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG 178865942Sgibbs | AHC_PCI_MWI_BUG; 178965942Sgibbs rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 179065942Sgibbs if (rev >= 1) 179165942Sgibbs probe_config->bugs |= AHC_PCI_2_1_RETRY_BUG; 179265942Sgibbs return (0); 179365942Sgibbs} 179465942Sgibbs 179565942Sgibbsstatic int 179671390Sgibbsahc_apa1480_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 179771390Sgibbs{ 179871390Sgibbs int error; 179971390Sgibbs 180071390Sgibbs error = ahc_aic7860_setup(pci, probe_config); 180171390Sgibbs if (error != 0) 180271390Sgibbs return (error); 180371390Sgibbs probe_config->features |= AHC_REMOVABLE; 180471390Sgibbs return (0); 180571390Sgibbs} 180671390Sgibbs 180771390Sgibbsstatic int 180865942Sgibbsahc_aic7870_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 180965942Sgibbs{ 181065942Sgibbs probe_config->channel = 'A'; 181165942Sgibbs probe_config->chip = AHC_AIC7870; 181265942Sgibbs probe_config->features = AHC_AIC7870_FE; 181365942Sgibbs probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG 181465942Sgibbs | AHC_PCI_MWI_BUG; 181565942Sgibbs return (0); 181665942Sgibbs} 181765942Sgibbs 181865942Sgibbsstatic int 181965942Sgibbsahc_aha394X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 182065942Sgibbs{ 182165942Sgibbs int error; 182265942Sgibbs 182365942Sgibbs error = ahc_aic7870_setup(pci, probe_config); 182465942Sgibbs if (error == 0) 182565942Sgibbs error = ahc_aha394XX_setup(pci, probe_config); 182665942Sgibbs return (error); 182765942Sgibbs} 182865942Sgibbs 182965942Sgibbsstatic int 183065942Sgibbsahc_aha398X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 183165942Sgibbs{ 183265942Sgibbs int error; 183365942Sgibbs 183465942Sgibbs error = ahc_aic7870_setup(pci, probe_config); 183565942Sgibbs if (error == 0) 183665942Sgibbs error = ahc_aha398XX_setup(pci, probe_config); 183765942Sgibbs return (error); 183865942Sgibbs} 183965942Sgibbs 184065942Sgibbsstatic int 184165942Sgibbsahc_aha494X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 184265942Sgibbs{ 184365942Sgibbs int error; 184465942Sgibbs 184565942Sgibbs error = ahc_aic7870_setup(pci, probe_config); 184665942Sgibbs if (error == 0) 184765942Sgibbs error = ahc_aha494XX_setup(pci, probe_config); 184865942Sgibbs return (error); 184965942Sgibbs} 185065942Sgibbs 185165942Sgibbsstatic int 185265942Sgibbsahc_aic7880_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 185365942Sgibbs{ 185465942Sgibbs uint8_t rev; 185565942Sgibbs 185665942Sgibbs probe_config->channel = 'A'; 185765942Sgibbs probe_config->chip = AHC_AIC7880; 185865942Sgibbs probe_config->features = AHC_AIC7880_FE; 185965942Sgibbs probe_config->bugs |= AHC_TMODE_WIDEODD_BUG; 186065942Sgibbs rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 186165942Sgibbs if (rev >= 1) { 186265942Sgibbs probe_config->bugs |= AHC_PCI_2_1_RETRY_BUG; 186365942Sgibbs } else { 186466845Sgibbs probe_config->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG; 186565942Sgibbs } 186665942Sgibbs return (0); 186765942Sgibbs} 186865942Sgibbs 186965942Sgibbsstatic int 187071390Sgibbsahc_aha2940Pro_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 187165942Sgibbs{ 187265942Sgibbs int error; 187365942Sgibbs 187465942Sgibbs probe_config->flags |= AHC_INT50_SPEEDFLEX; 187565942Sgibbs error = ahc_aic7880_setup(pci, probe_config); 187665942Sgibbs return (0); 187765942Sgibbs} 187865942Sgibbs 187965942Sgibbsstatic int 188065942Sgibbsahc_aha394XU_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 188165942Sgibbs{ 188265942Sgibbs int error; 188365942Sgibbs 188465942Sgibbs error = ahc_aic7880_setup(pci, probe_config); 188565942Sgibbs if (error == 0) 188665942Sgibbs error = ahc_aha394XX_setup(pci, probe_config); 188765942Sgibbs return (error); 188865942Sgibbs} 188965942Sgibbs 189065942Sgibbsstatic int 189165942Sgibbsahc_aha398XU_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 189265942Sgibbs{ 189365942Sgibbs int error; 189465942Sgibbs 189565942Sgibbs error = ahc_aic7880_setup(pci, probe_config); 189665942Sgibbs if (error == 0) 189765942Sgibbs error = ahc_aha398XX_setup(pci, probe_config); 189865942Sgibbs return (error); 189965942Sgibbs} 190065942Sgibbs 190165942Sgibbsstatic int 190265942Sgibbsahc_aic7890_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 190365942Sgibbs{ 190465942Sgibbs uint8_t rev; 190565942Sgibbs 190665942Sgibbs probe_config->channel = 'A'; 190765942Sgibbs probe_config->chip = AHC_AIC7890; 190865942Sgibbs probe_config->features = AHC_AIC7890_FE; 190965942Sgibbs probe_config->flags |= AHC_NEWEEPROM_FMT; 191065942Sgibbs rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 191165942Sgibbs if (rev == 0) 191265942Sgibbs probe_config->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG; 191365942Sgibbs return (0); 191465942Sgibbs} 191565942Sgibbs 191665942Sgibbsstatic int 191765942Sgibbsahc_aic7892_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 191865942Sgibbs{ 191965942Sgibbs probe_config->channel = 'A'; 192065942Sgibbs probe_config->chip = AHC_AIC7892; 192165942Sgibbs probe_config->features = AHC_AIC7892_FE; 192265942Sgibbs probe_config->flags |= AHC_NEWEEPROM_FMT; 192365942Sgibbs probe_config->bugs |= AHC_SCBCHAN_UPLOAD_BUG; 192465942Sgibbs return (0); 192565942Sgibbs} 192665942Sgibbs 192765942Sgibbsstatic int 192865942Sgibbsahc_aic7895_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 192965942Sgibbs{ 193065942Sgibbs uint8_t rev; 193165942Sgibbs 193265942Sgibbs probe_config->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 193365942Sgibbs /* 193465942Sgibbs * The 'C' revision of the aic7895 has a few additional features. 193565942Sgibbs */ 193665942Sgibbs rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 193765942Sgibbs if (rev >= 4) { 193865942Sgibbs probe_config->chip = AHC_AIC7895C; 193965942Sgibbs probe_config->features = AHC_AIC7895C_FE; 194065942Sgibbs } else { 194165942Sgibbs u_int command; 194265942Sgibbs 194365942Sgibbs probe_config->chip = AHC_AIC7895; 194465942Sgibbs probe_config->features = AHC_AIC7895_FE; 194565942Sgibbs 194665942Sgibbs /* 194765942Sgibbs * The BIOS disables the use of MWI transactions 194865942Sgibbs * since it does not have the MWI bug work around 194965942Sgibbs * we have. Disabling MWI reduces performance, so 195065942Sgibbs * turn it on again. 195165942Sgibbs */ 195265942Sgibbs command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1); 195365942Sgibbs command |= PCIM_CMD_MWRICEN; 195465942Sgibbs ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1); 195565942Sgibbs probe_config->bugs |= AHC_PCI_MWI_BUG; 195665942Sgibbs } 195765942Sgibbs /* 195865942Sgibbs * XXX Does CACHETHEN really not work??? What about PCI retry? 195965942Sgibbs * on C level chips. Need to test, but for now, play it safe. 196065942Sgibbs */ 196165942Sgibbs probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG 196265942Sgibbs | AHC_CACHETHEN_BUG; 196365942Sgibbs 196465942Sgibbs#if 0 196565942Sgibbs uint32_t devconfig; 196665942Sgibbs 196765942Sgibbs /* 196865942Sgibbs * Cachesize must also be zero due to stray DAC 196965942Sgibbs * problem when sitting behind some bridges. 197065942Sgibbs */ 197165942Sgibbs ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1); 197265942Sgibbs devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1); 197365942Sgibbs devconfig |= MRDCEN; 197465942Sgibbs ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1); 197565942Sgibbs#endif 197665942Sgibbs probe_config->flags |= AHC_NEWEEPROM_FMT; 197765942Sgibbs return (0); 197865942Sgibbs} 197965942Sgibbs 198065942Sgibbsstatic int 198165942Sgibbsahc_aic7896_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 198265942Sgibbs{ 198365942Sgibbs probe_config->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 198465942Sgibbs probe_config->chip = AHC_AIC7896; 198565942Sgibbs probe_config->features = AHC_AIC7896_FE; 198665942Sgibbs probe_config->flags |= AHC_NEWEEPROM_FMT; 198765942Sgibbs probe_config->bugs |= AHC_CACHETHEN_DIS_BUG; 198865942Sgibbs return (0); 198965942Sgibbs} 199065942Sgibbs 199165942Sgibbsstatic int 199265942Sgibbsahc_aic7899_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 199365942Sgibbs{ 199465942Sgibbs probe_config->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A'; 199565942Sgibbs probe_config->chip = AHC_AIC7899; 199665942Sgibbs probe_config->features = AHC_AIC7899_FE; 199765942Sgibbs probe_config->flags |= AHC_NEWEEPROM_FMT; 199865942Sgibbs probe_config->bugs |= AHC_SCBCHAN_UPLOAD_BUG; 199965942Sgibbs return (0); 200065942Sgibbs} 200165942Sgibbs 200265942Sgibbsstatic int 200371390Sgibbsahc_aha29160C_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 200471390Sgibbs{ 200571390Sgibbs int error; 200671390Sgibbs 200771390Sgibbs error = ahc_aic7899_setup(pci, probe_config); 200871390Sgibbs if (error != 0) 200971390Sgibbs return (error); 201071390Sgibbs probe_config->features |= AHC_REMOVABLE; 201171390Sgibbs return (0); 201271390Sgibbs} 201371390Sgibbs 201471390Sgibbsstatic int 201565942Sgibbsahc_raid_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 201665942Sgibbs{ 201765942Sgibbs printf("RAID functionality unsupported\n"); 201865942Sgibbs return (ENXIO); 201965942Sgibbs} 202065942Sgibbs 202165942Sgibbsstatic int 202265942Sgibbsahc_aha394XX_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 202365942Sgibbs{ 202465942Sgibbs switch (ahc_get_pci_slot(pci)) { 202565942Sgibbs case AHC_394X_SLOT_CHANNEL_A: 202665942Sgibbs probe_config->channel = 'A'; 202765942Sgibbs break; 202865942Sgibbs case AHC_394X_SLOT_CHANNEL_B: 202965942Sgibbs probe_config->channel = 'B'; 203065942Sgibbs break; 203165942Sgibbs default: 203265942Sgibbs printf("adapter at unexpected slot %d\n" 203365942Sgibbs "unable to map to a channel\n", 203465942Sgibbs ahc_get_pci_slot(pci)); 203565942Sgibbs probe_config->channel = 'A'; 203665942Sgibbs } 203765942Sgibbs return (0); 203865942Sgibbs} 203965942Sgibbs 204065942Sgibbsstatic int 204165942Sgibbsahc_aha398XX_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 204265942Sgibbs{ 204365942Sgibbs switch (ahc_get_pci_slot(pci)) { 204465942Sgibbs case AHC_398X_SLOT_CHANNEL_A: 204565942Sgibbs probe_config->channel = 'A'; 204665942Sgibbs break; 204765942Sgibbs case AHC_398X_SLOT_CHANNEL_B: 204865942Sgibbs probe_config->channel = 'B'; 204965942Sgibbs break; 205065942Sgibbs case AHC_398X_SLOT_CHANNEL_C: 205165942Sgibbs probe_config->channel = 'C'; 205265942Sgibbs break; 205365942Sgibbs default: 205465942Sgibbs printf("adapter at unexpected slot %d\n" 205565942Sgibbs "unable to map to a channel\n", 205665942Sgibbs ahc_get_pci_slot(pci)); 205765942Sgibbs probe_config->channel = 'A'; 205865942Sgibbs break; 205965942Sgibbs } 206065942Sgibbs probe_config->flags |= AHC_LARGE_SEEPROM; 206165942Sgibbs return (0); 206265942Sgibbs} 206365942Sgibbs 206465942Sgibbsstatic int 206565942Sgibbsahc_aha494XX_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config) 206665942Sgibbs{ 206765942Sgibbs switch (ahc_get_pci_slot(pci)) { 206865942Sgibbs case AHC_494X_SLOT_CHANNEL_A: 206965942Sgibbs probe_config->channel = 'A'; 207065942Sgibbs break; 207165942Sgibbs case AHC_494X_SLOT_CHANNEL_B: 207265942Sgibbs probe_config->channel = 'B'; 207365942Sgibbs break; 207465942Sgibbs case AHC_494X_SLOT_CHANNEL_C: 207565942Sgibbs probe_config->channel = 'C'; 207665942Sgibbs break; 207765942Sgibbs case AHC_494X_SLOT_CHANNEL_D: 207865942Sgibbs probe_config->channel = 'D'; 207965942Sgibbs break; 208065942Sgibbs default: 208165942Sgibbs printf("adapter at unexpected slot %d\n" 208265942Sgibbs "unable to map to a channel\n", 208365942Sgibbs ahc_get_pci_slot(pci)); 208465942Sgibbs probe_config->channel = 'A'; 208565942Sgibbs } 208665942Sgibbs probe_config->flags |= AHC_LARGE_SEEPROM; 208765942Sgibbs return (0); 208865942Sgibbs} 2089