1098ca2bdSWarner Losh /*- 217d24755SJustin T. Gibbs * Product specific probe and attach routines for: 317d24755SJustin T. Gibbs * aic7901 and aic7902 SCSI controllers 417d24755SJustin T. Gibbs * 5*718cf2ccSPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 6*718cf2ccSPedro F. Giffuni * 717d24755SJustin T. Gibbs * Copyright (c) 1994-2001 Justin T. Gibbs. 81a1fbd0bSJustin T. Gibbs * Copyright (c) 2000-2002 Adaptec Inc. 917d24755SJustin T. Gibbs * All rights reserved. 1017d24755SJustin T. Gibbs * 1117d24755SJustin T. Gibbs * Redistribution and use in source and binary forms, with or without 1217d24755SJustin T. Gibbs * modification, are permitted provided that the following conditions 1317d24755SJustin T. Gibbs * are met: 1417d24755SJustin T. Gibbs * 1. Redistributions of source code must retain the above copyright 1517d24755SJustin T. Gibbs * notice, this list of conditions, and the following disclaimer, 1617d24755SJustin T. Gibbs * without modification. 1717d24755SJustin T. Gibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1817d24755SJustin T. Gibbs * substantially similar to the "NO WARRANTY" disclaimer below 1917d24755SJustin T. Gibbs * ("Disclaimer") and any redistribution must be conditioned upon 2017d24755SJustin T. Gibbs * including a substantially similar Disclaimer requirement for further 2117d24755SJustin T. Gibbs * binary redistribution. 2217d24755SJustin T. Gibbs * 3. Neither the names of the above-listed copyright holders nor the names 2317d24755SJustin T. Gibbs * of any contributors may be used to endorse or promote products derived 2417d24755SJustin T. Gibbs * from this software without specific prior written permission. 2517d24755SJustin T. Gibbs * 2617d24755SJustin T. Gibbs * Alternatively, this software may be distributed under the terms of the 2717d24755SJustin T. Gibbs * GNU General Public License ("GPL") version 2 as published by the Free 2817d24755SJustin T. Gibbs * Software Foundation. 2917d24755SJustin T. Gibbs * 3017d24755SJustin T. Gibbs * NO WARRANTY 3117d24755SJustin T. Gibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3217d24755SJustin T. Gibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3317d24755SJustin T. Gibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3417d24755SJustin T. Gibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3517d24755SJustin T. Gibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3617d24755SJustin T. Gibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3717d24755SJustin T. Gibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3817d24755SJustin T. Gibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3917d24755SJustin T. Gibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4017d24755SJustin T. Gibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4117d24755SJustin T. Gibbs * POSSIBILITY OF SUCH DAMAGES. 4217d24755SJustin T. Gibbs * 4322dbd4c6SJustin T. Gibbs * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#88 $ 4417d24755SJustin T. Gibbs */ 4517d24755SJustin T. Gibbs 4617d24755SJustin T. Gibbs #ifdef __linux__ 4717d24755SJustin T. Gibbs #include "aic79xx_osm.h" 4817d24755SJustin T. Gibbs #include "aic79xx_inline.h" 4917d24755SJustin T. Gibbs #else 50b3b25f2cSJustin T. Gibbs #include <sys/cdefs.h> 51b3b25f2cSJustin T. Gibbs __FBSDID("$FreeBSD$"); 5217d24755SJustin T. Gibbs #include <dev/aic7xxx/aic79xx_osm.h> 5317d24755SJustin T. Gibbs #include <dev/aic7xxx/aic79xx_inline.h> 5417d24755SJustin T. Gibbs #endif 5517d24755SJustin T. Gibbs 5617d24755SJustin T. Gibbs static __inline uint64_t 5717d24755SJustin T. Gibbs ahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor) 5817d24755SJustin T. Gibbs { 5917d24755SJustin T. Gibbs uint64_t id; 6017d24755SJustin T. Gibbs 6117d24755SJustin T. Gibbs id = subvendor 6217d24755SJustin T. Gibbs | (subdevice << 16) 6317d24755SJustin T. Gibbs | ((uint64_t)vendor << 32) 6417d24755SJustin T. Gibbs | ((uint64_t)device << 48); 6517d24755SJustin T. Gibbs 6617d24755SJustin T. Gibbs return (id); 6717d24755SJustin T. Gibbs } 6817d24755SJustin T. Gibbs 6917d24755SJustin T. Gibbs #define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull 704164174aSJustin T. Gibbs #define ID_ALL_IROC_MASK 0xFF7FFFFFFFFFFFFFull 7117d24755SJustin T. Gibbs #define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull 7217d24755SJustin T. Gibbs #define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull 734164174aSJustin T. Gibbs #define ID_9005_GENERIC_IROC_MASK 0xFF70FFFF00000000ull 7417d24755SJustin T. Gibbs 7517d24755SJustin T. Gibbs #define ID_AIC7901 0x800F9005FFFF9005ull 761a1fbd0bSJustin T. Gibbs #define ID_AHA_29320A 0x8000900500609005ull 77197696e9SJustin T. Gibbs #define ID_AHA_29320ALP 0x8017900500449005ull 78197696e9SJustin T. Gibbs 79197696e9SJustin T. Gibbs #define ID_AIC7901A 0x801E9005FFFF9005ull 80454bf169SScott Long #define ID_AHA_29320LP 0x8014900500449005ull 8117d24755SJustin T. Gibbs 8217d24755SJustin T. Gibbs #define ID_AIC7902 0x801F9005FFFF9005ull 83454bf169SScott Long #define ID_AIC7902_B 0x801D9005FFFF9005ull 8417d24755SJustin T. Gibbs #define ID_AHA_39320 0x8010900500409005ull 85b3b25f2cSJustin T. Gibbs #define ID_AHA_29320 0x8012900500429005ull 86b3b25f2cSJustin T. Gibbs #define ID_AHA_29320B 0x8013900500439005ull 87197696e9SJustin T. Gibbs #define ID_AHA_39320_B 0x8015900500409005ull 8822dbd4c6SJustin T. Gibbs #define ID_AHA_39320_B_DELL 0x8015900501681028ull 89acae33b0SJustin T. Gibbs #define ID_AHA_39320A 0x8016900500409005ull 9017d24755SJustin T. Gibbs #define ID_AHA_39320D 0x8011900500419005ull 91454bf169SScott Long #define ID_AHA_39320D_B 0x801C900500419005ull 92454bf169SScott Long #define ID_AHA_39320D_HP 0x8011900500AC0E11ull 93454bf169SScott Long #define ID_AHA_39320D_B_HP 0x801C900500AC0E11ull 94a4522488SChristian Brueffer #define ID_AHA_39320LPE 0x8017900500459005ull 9517d24755SJustin T. Gibbs #define ID_AIC7902_PCI_REV_A4 0x3 961a1fbd0bSJustin T. Gibbs #define ID_AIC7902_PCI_REV_B0 0x10 97454bf169SScott Long #define SUBID_HP 0x0E11 987cfc62d8SAchim Leubner #define DEVICE8081 0x8081 997cfc62d8SAchim Leubner #define DEVICE8088 0x8088 1007cfc62d8SAchim Leubner #define DEVICE8089 0x8089 1017cfc62d8SAchim Leubner #define ADAPTECVENDORID 0x9005 1027cfc62d8SAchim Leubner #define SUBVENDOR9005 0x9005 10317d24755SJustin T. Gibbs 1044164174aSJustin T. Gibbs #define DEVID_9005_HOSTRAID(id) ((id) & 0x80) 1054164174aSJustin T. Gibbs 10617d24755SJustin T. Gibbs #define DEVID_9005_TYPE(id) ((id) & 0xF) 10717d24755SJustin T. Gibbs #define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */ 10817d24755SJustin T. Gibbs #define DEVID_9005_TYPE_HBA_2EXT 0x1 /* 2 External Ports */ 10917d24755SJustin T. Gibbs #define DEVID_9005_TYPE_MB 0xF /* On Motherboard */ 11017d24755SJustin T. Gibbs 11117d24755SJustin T. Gibbs #define DEVID_9005_MFUNC(id) ((id) & 0x10) 11217d24755SJustin T. Gibbs 11317d24755SJustin T. Gibbs #define DEVID_9005_PACKETIZED(id) ((id) & 0x8000) 11417d24755SJustin T. Gibbs 11517d24755SJustin T. Gibbs #define SUBID_9005_TYPE(id) ((id) & 0xF) 11617d24755SJustin T. Gibbs #define SUBID_9005_TYPE_HBA 0x0 /* Standard Card */ 11717d24755SJustin T. Gibbs #define SUBID_9005_TYPE_MB 0xF /* On Motherboard */ 11817d24755SJustin T. Gibbs 11917d24755SJustin T. Gibbs #define SUBID_9005_AUTOTERM(id) (((id) & 0x10) == 0) 12017d24755SJustin T. Gibbs 12117d24755SJustin T. Gibbs #define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20) 12217d24755SJustin T. Gibbs 12317d24755SJustin T. Gibbs #define SUBID_9005_SEEPTYPE(id) ((id) & 0x0C0) >> 6) 12417d24755SJustin T. Gibbs #define SUBID_9005_SEEPTYPE_NONE 0x0 12517d24755SJustin T. Gibbs #define SUBID_9005_SEEPTYPE_4K 0x1 12617d24755SJustin T. Gibbs 127197696e9SJustin T. Gibbs static ahd_device_setup_t ahd_aic7901_setup; 1281a1fbd0bSJustin T. Gibbs static ahd_device_setup_t ahd_aic7901A_setup; 129454bf169SScott Long static ahd_device_setup_t ahd_aic7902_setup; 130c8ee7177SJustin T. Gibbs static ahd_device_setup_t ahd_aic790X_setup; 13117d24755SJustin T. Gibbs 13217d24755SJustin T. Gibbs struct ahd_pci_identity ahd_pci_ident_table [] = 13317d24755SJustin T. Gibbs { 134197696e9SJustin T. Gibbs /* aic7901 based controllers */ 135197696e9SJustin T. Gibbs { 136197696e9SJustin T. Gibbs ID_AHA_29320A, 137197696e9SJustin T. Gibbs ID_ALL_MASK, 138197696e9SJustin T. Gibbs "Adaptec 29320A Ultra320 SCSI adapter", 139197696e9SJustin T. Gibbs ahd_aic7901_setup 140197696e9SJustin T. Gibbs }, 141197696e9SJustin T. Gibbs { 142197696e9SJustin T. Gibbs ID_AHA_29320ALP, 143197696e9SJustin T. Gibbs ID_ALL_MASK, 144197696e9SJustin T. Gibbs "Adaptec 29320ALP Ultra320 SCSI adapter", 145197696e9SJustin T. Gibbs ahd_aic7901_setup 146197696e9SJustin T. Gibbs }, 147454bf169SScott Long /* aic7901A based controllers */ 148454bf169SScott Long { 149454bf169SScott Long ID_AHA_29320LP, 150454bf169SScott Long ID_ALL_MASK, 151454bf169SScott Long "Adaptec 29320LP Ultra320 SCSI adapter", 152454bf169SScott Long ahd_aic7901A_setup 153454bf169SScott Long }, 15417d24755SJustin T. Gibbs /* aic7902 based controllers */ 15517d24755SJustin T. Gibbs { 156b3b25f2cSJustin T. Gibbs ID_AHA_29320, 157b3b25f2cSJustin T. Gibbs ID_ALL_MASK, 158b3b25f2cSJustin T. Gibbs "Adaptec 29320 Ultra320 SCSI adapter", 159b3b25f2cSJustin T. Gibbs ahd_aic7902_setup 160b3b25f2cSJustin T. Gibbs }, 161b3b25f2cSJustin T. Gibbs { 162b3b25f2cSJustin T. Gibbs ID_AHA_29320B, 163b3b25f2cSJustin T. Gibbs ID_ALL_MASK, 164b3b25f2cSJustin T. Gibbs "Adaptec 29320B Ultra320 SCSI adapter", 165b3b25f2cSJustin T. Gibbs ahd_aic7902_setup 166b3b25f2cSJustin T. Gibbs }, 167b3b25f2cSJustin T. Gibbs { 16817d24755SJustin T. Gibbs ID_AHA_39320, 16917d24755SJustin T. Gibbs ID_ALL_MASK, 17017d24755SJustin T. Gibbs "Adaptec 39320 Ultra320 SCSI adapter", 17117d24755SJustin T. Gibbs ahd_aic7902_setup 17217d24755SJustin T. Gibbs }, 17317d24755SJustin T. Gibbs { 174197696e9SJustin T. Gibbs ID_AHA_39320_B, 175197696e9SJustin T. Gibbs ID_ALL_MASK, 176197696e9SJustin T. Gibbs "Adaptec 39320 Ultra320 SCSI adapter", 177197696e9SJustin T. Gibbs ahd_aic7902_setup 178197696e9SJustin T. Gibbs }, 179197696e9SJustin T. Gibbs { 18022dbd4c6SJustin T. Gibbs ID_AHA_39320_B_DELL, 18122dbd4c6SJustin T. Gibbs ID_ALL_MASK, 18222dbd4c6SJustin T. Gibbs "Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter", 18322dbd4c6SJustin T. Gibbs ahd_aic7902_setup 18422dbd4c6SJustin T. Gibbs }, 18522dbd4c6SJustin T. Gibbs { 186acae33b0SJustin T. Gibbs ID_AHA_39320A, 187acae33b0SJustin T. Gibbs ID_ALL_MASK, 188acae33b0SJustin T. Gibbs "Adaptec 39320A Ultra320 SCSI adapter", 189acae33b0SJustin T. Gibbs ahd_aic7902_setup 190acae33b0SJustin T. Gibbs }, 191acae33b0SJustin T. Gibbs { 19217d24755SJustin T. Gibbs ID_AHA_39320D, 19317d24755SJustin T. Gibbs ID_ALL_MASK, 19417d24755SJustin T. Gibbs "Adaptec 39320D Ultra320 SCSI adapter", 19517d24755SJustin T. Gibbs ahd_aic7902_setup 19617d24755SJustin T. Gibbs }, 19717d24755SJustin T. Gibbs { 198454bf169SScott Long ID_AHA_39320D_HP, 19917d24755SJustin T. Gibbs ID_ALL_MASK, 200454bf169SScott Long "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter", 201454bf169SScott Long ahd_aic7902_setup 202454bf169SScott Long }, 203454bf169SScott Long { 204454bf169SScott Long ID_AHA_39320D_B, 205454bf169SScott Long ID_ALL_MASK, 206454bf169SScott Long "Adaptec 39320D Ultra320 SCSI adapter", 207454bf169SScott Long ahd_aic7902_setup 208454bf169SScott Long }, 209454bf169SScott Long { 210454bf169SScott Long ID_AHA_39320D_B_HP, 211454bf169SScott Long ID_ALL_MASK, 212454bf169SScott Long "Adaptec (HP OEM) 39320D Ultra320 SCSI adapter", 21317d24755SJustin T. Gibbs ahd_aic7902_setup 21417d24755SJustin T. Gibbs }, 215a4522488SChristian Brueffer { 216a4522488SChristian Brueffer ID_AHA_39320LPE, 217a4522488SChristian Brueffer ID_ALL_MASK, 218a4522488SChristian Brueffer "Adaptec 39320LPE Ultra320 SCSI adapter", 219a4522488SChristian Brueffer ahd_aic7902_setup 220a4522488SChristian Brueffer }, 22117d24755SJustin T. Gibbs /* Generic chip probes for devices we don't know 'exactly' */ 22217d24755SJustin T. Gibbs { 2234164174aSJustin T. Gibbs ID_AIC7901 & ID_9005_GENERIC_MASK, 22422dbd4c6SJustin T. Gibbs ID_9005_GENERIC_MASK, 225197696e9SJustin T. Gibbs "Adaptec AIC7901 Ultra320 SCSI adapter", 226197696e9SJustin T. Gibbs ahd_aic7901_setup 227197696e9SJustin T. Gibbs }, 228197696e9SJustin T. Gibbs { 22997cae63dSScott Long ID_AIC7901A & ID_DEV_VENDOR_MASK, 23097cae63dSScott Long ID_DEV_VENDOR_MASK, 231454bf169SScott Long "Adaptec AIC7901A Ultra320 SCSI adapter", 232454bf169SScott Long ahd_aic7901A_setup 23317d24755SJustin T. Gibbs }, 23417d24755SJustin T. Gibbs { 23517d24755SJustin T. Gibbs ID_AIC7902 & ID_9005_GENERIC_MASK, 23617d24755SJustin T. Gibbs ID_9005_GENERIC_MASK, 237454bf169SScott Long "Adaptec AIC7902 Ultra320 SCSI adapter", 23817d24755SJustin T. Gibbs ahd_aic7902_setup 23917d24755SJustin T. Gibbs } 24017d24755SJustin T. Gibbs }; 24117d24755SJustin T. Gibbs 24217d24755SJustin T. Gibbs const u_int ahd_num_pci_devs = NUM_ELEMENTS(ahd_pci_ident_table); 24317d24755SJustin T. Gibbs 24417d24755SJustin T. Gibbs #define DEVCONFIG 0x40 24517d24755SJustin T. Gibbs #define PCIXINITPAT 0x0000E000ul 24617d24755SJustin T. Gibbs #define PCIXINIT_PCI33_66 0x0000E000ul 24717d24755SJustin T. Gibbs #define PCIXINIT_PCIX50_66 0x0000C000ul 24817d24755SJustin T. Gibbs #define PCIXINIT_PCIX66_100 0x0000A000ul 24917d24755SJustin T. Gibbs #define PCIXINIT_PCIX100_133 0x00008000ul 25017d24755SJustin T. Gibbs #define PCI_BUS_MODES_INDEX(devconfig) \ 25117d24755SJustin T. Gibbs (((devconfig) & PCIXINITPAT) >> 13) 25217d24755SJustin T. Gibbs static const char *pci_bus_modes[] = 25317d24755SJustin T. Gibbs { 25417d24755SJustin T. Gibbs "PCI bus mode unknown", 25517d24755SJustin T. Gibbs "PCI bus mode unknown", 25617d24755SJustin T. Gibbs "PCI bus mode unknown", 25717d24755SJustin T. Gibbs "PCI bus mode unknown", 25879649302SGavin Atkinson "PCI-X 101-133MHz", 25979649302SGavin Atkinson "PCI-X 67-100MHz", 26079649302SGavin Atkinson "PCI-X 50-66MHz", 26179649302SGavin Atkinson "PCI 33 or 66MHz" 26217d24755SJustin T. Gibbs }; 26317d24755SJustin T. Gibbs 26417d24755SJustin T. Gibbs #define TESTMODE 0x00000800ul 26517d24755SJustin T. Gibbs #define IRDY_RST 0x00000200ul 26617d24755SJustin T. Gibbs #define FRAME_RST 0x00000100ul 26717d24755SJustin T. Gibbs #define PCI64BIT 0x00000080ul 26817d24755SJustin T. Gibbs #define MRDCEN 0x00000040ul 26917d24755SJustin T. Gibbs #define ENDIANSEL 0x00000020ul 27017d24755SJustin T. Gibbs #define MIXQWENDIANEN 0x00000008ul 27117d24755SJustin T. Gibbs #define DACEN 0x00000004ul 27217d24755SJustin T. Gibbs #define STPWLEVEL 0x00000002ul 27317d24755SJustin T. Gibbs #define QWENDIANSEL 0x00000001ul 27417d24755SJustin T. Gibbs 27517d24755SJustin T. Gibbs #define DEVCONFIG1 0x44 27617d24755SJustin T. Gibbs #define PREQDIS 0x01 27717d24755SJustin T. Gibbs 27817d24755SJustin T. Gibbs #define CSIZE_LATTIME 0x0c 27917d24755SJustin T. Gibbs #define CACHESIZE 0x000000fful 28017d24755SJustin T. Gibbs #define LATTIME 0x0000ff00ul 28117d24755SJustin T. Gibbs 28217d24755SJustin T. Gibbs static int ahd_check_extport(struct ahd_softc *ahd); 28317d24755SJustin T. Gibbs static void ahd_configure_termination(struct ahd_softc *ahd, 28417d24755SJustin T. Gibbs u_int adapter_control); 28517d24755SJustin T. Gibbs static void ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat); 28617d24755SJustin T. Gibbs 28717d24755SJustin T. Gibbs struct ahd_pci_identity * 288b3b25f2cSJustin T. Gibbs ahd_find_pci_device(aic_dev_softc_t pci) 28917d24755SJustin T. Gibbs { 29017d24755SJustin T. Gibbs uint64_t full_id; 29117d24755SJustin T. Gibbs uint16_t device; 29217d24755SJustin T. Gibbs uint16_t vendor; 29317d24755SJustin T. Gibbs uint16_t subdevice; 29417d24755SJustin T. Gibbs uint16_t subvendor; 29517d24755SJustin T. Gibbs struct ahd_pci_identity *entry; 29617d24755SJustin T. Gibbs u_int i; 29717d24755SJustin T. Gibbs 298b3b25f2cSJustin T. Gibbs vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2); 299b3b25f2cSJustin T. Gibbs device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2); 300b3b25f2cSJustin T. Gibbs subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2); 301b3b25f2cSJustin T. Gibbs subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2); 3027cfc62d8SAchim Leubner 3037cfc62d8SAchim Leubner if ((vendor == ADAPTECVENDORID) && (subvendor == SUBVENDOR9005)) { 3047cfc62d8SAchim Leubner if ((device == DEVICE8081) || (device == DEVICE8088) || 3057cfc62d8SAchim Leubner (device == DEVICE8089)) { 3067cfc62d8SAchim Leubner printf("Controller device ID conflict with PMC Adaptec HBA\n"); 3077cfc62d8SAchim Leubner return (NULL); 3087cfc62d8SAchim Leubner } 3097cfc62d8SAchim Leubner } 3107cfc62d8SAchim Leubner 31117d24755SJustin T. Gibbs full_id = ahd_compose_id(device, 31217d24755SJustin T. Gibbs vendor, 31317d24755SJustin T. Gibbs subdevice, 31417d24755SJustin T. Gibbs subvendor); 31517d24755SJustin T. Gibbs 3164164174aSJustin T. Gibbs /* 3174164174aSJustin T. Gibbs * If we are configured to attach to HostRAID 3184164174aSJustin T. Gibbs * controllers, mask out the IROC/HostRAID bit 3194164174aSJustin T. Gibbs * in the 3204164174aSJustin T. Gibbs */ 3214164174aSJustin T. Gibbs if (ahd_attach_to_HostRAID_controllers) 3224164174aSJustin T. Gibbs full_id &= ID_ALL_IROC_MASK; 3234164174aSJustin T. Gibbs 32417d24755SJustin T. Gibbs for (i = 0; i < ahd_num_pci_devs; i++) { 32517d24755SJustin T. Gibbs entry = &ahd_pci_ident_table[i]; 32617d24755SJustin T. Gibbs if (entry->full_id == (full_id & entry->id_mask)) { 32717d24755SJustin T. Gibbs /* Honor exclusion entries. */ 32817d24755SJustin T. Gibbs if (entry->name == NULL) 32917d24755SJustin T. Gibbs return (NULL); 33017d24755SJustin T. Gibbs return (entry); 33117d24755SJustin T. Gibbs } 33217d24755SJustin T. Gibbs } 33317d24755SJustin T. Gibbs return (NULL); 33417d24755SJustin T. Gibbs } 33517d24755SJustin T. Gibbs 33617d24755SJustin T. Gibbs int 33717d24755SJustin T. Gibbs ahd_pci_config(struct ahd_softc *ahd, struct ahd_pci_identity *entry) 33817d24755SJustin T. Gibbs { 33917d24755SJustin T. Gibbs u_int command; 34017d24755SJustin T. Gibbs uint32_t devconfig; 3414164174aSJustin T. Gibbs uint16_t device; 34217d24755SJustin T. Gibbs uint16_t subvendor; 34317d24755SJustin T. Gibbs int error; 34417d24755SJustin T. Gibbs 345454bf169SScott Long ahd->description = entry->name; 346454bf169SScott Long /* 3474164174aSJustin T. Gibbs * Record if this is a HostRAID board. 3484164174aSJustin T. Gibbs */ 3494164174aSJustin T. Gibbs device = aic_pci_read_config(ahd->dev_softc, 3504164174aSJustin T. Gibbs PCIR_DEVICE, /*bytes*/2); 3514164174aSJustin T. Gibbs if (DEVID_9005_HOSTRAID(device)) 3524164174aSJustin T. Gibbs ahd->flags |= AHD_HOSTRAID_BOARD; 3534164174aSJustin T. Gibbs 3544164174aSJustin T. Gibbs /* 355454bf169SScott Long * Record if this is an HP board. 356454bf169SScott Long */ 357b3b25f2cSJustin T. Gibbs subvendor = aic_pci_read_config(ahd->dev_softc, 358454bf169SScott Long PCIR_SUBVEND_0, /*bytes*/2); 359454bf169SScott Long if (subvendor == SUBID_HP) 360454bf169SScott Long ahd->flags |= AHD_HP_BOARD; 361454bf169SScott Long 36217d24755SJustin T. Gibbs error = entry->setup(ahd); 36317d24755SJustin T. Gibbs if (error != 0) 36417d24755SJustin T. Gibbs return (error); 36517d24755SJustin T. Gibbs 3666eb7ebfeSJohn Baldwin /* 3676eb7ebfeSJohn Baldwin * Find the PCI-X cap pointer. If we don't find it, 3686eb7ebfeSJohn Baldwin * pcix_ptr will be 0. 3696eb7ebfeSJohn Baldwin */ 3703b0a4aefSJohn Baldwin pci_find_cap(ahd->dev_softc, PCIY_PCIX, &ahd->pcix_ptr); 371b3b25f2cSJustin T. Gibbs devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); 37217d24755SJustin T. Gibbs if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) { 37317d24755SJustin T. Gibbs ahd->chip |= AHD_PCI; 37417d24755SJustin T. Gibbs /* Disable PCIX workarounds when running in PCI mode. */ 37517d24755SJustin T. Gibbs ahd->bugs &= ~AHD_PCIX_BUG_MASK; 37617d24755SJustin T. Gibbs } else { 37717d24755SJustin T. Gibbs ahd->chip |= AHD_PCIX; 3786eb7ebfeSJohn Baldwin if (ahd->pcix_ptr == 0) 3796eb7ebfeSJohn Baldwin return (ENXIO); 38017d24755SJustin T. Gibbs } 38117d24755SJustin T. Gibbs ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)]; 38217d24755SJustin T. Gibbs 383b3b25f2cSJustin T. Gibbs aic_power_state_change(ahd, AIC_POWER_STATE_D0); 38417d24755SJustin T. Gibbs 38517d24755SJustin T. Gibbs error = ahd_pci_map_registers(ahd); 38617d24755SJustin T. Gibbs if (error != 0) 38717d24755SJustin T. Gibbs return (error); 38817d24755SJustin T. Gibbs 38917d24755SJustin T. Gibbs /* 39017d24755SJustin T. Gibbs * If we need to support high memory, enable dual 39117d24755SJustin T. Gibbs * address cycles. This bit must be set to enable 39217d24755SJustin T. Gibbs * high address bit generation even if we are on a 39317d24755SJustin T. Gibbs * 64bit bus (PCI64BIT set in devconfig). 39417d24755SJustin T. Gibbs */ 39517d24755SJustin T. Gibbs if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) { 39617d24755SJustin T. Gibbs uint32_t devconfig; 39717d24755SJustin T. Gibbs 39817d24755SJustin T. Gibbs if (bootverbose) 39917d24755SJustin T. Gibbs printf("%s: Enabling 39Bit Addressing\n", 40017d24755SJustin T. Gibbs ahd_name(ahd)); 401b3b25f2cSJustin T. Gibbs devconfig = aic_pci_read_config(ahd->dev_softc, 40217d24755SJustin T. Gibbs DEVCONFIG, /*bytes*/4); 40317d24755SJustin T. Gibbs devconfig |= DACEN; 404b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahd->dev_softc, DEVCONFIG, 40517d24755SJustin T. Gibbs devconfig, /*bytes*/4); 40617d24755SJustin T. Gibbs } 40717d24755SJustin T. Gibbs 40817d24755SJustin T. Gibbs /* Ensure busmastering is enabled */ 409b3b25f2cSJustin T. Gibbs command = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); 41017d24755SJustin T. Gibbs command |= PCIM_CMD_BUSMASTEREN; 411b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2); 41217d24755SJustin T. Gibbs 41317d24755SJustin T. Gibbs error = ahd_softc_init(ahd); 41417d24755SJustin T. Gibbs if (error != 0) 41517d24755SJustin T. Gibbs return (error); 41617d24755SJustin T. Gibbs 41717d24755SJustin T. Gibbs ahd->bus_intr = ahd_pci_intr; 41817d24755SJustin T. Gibbs 4191d528d67SJustin T. Gibbs error = ahd_reset(ahd, /*reinit*/FALSE); 42017d24755SJustin T. Gibbs if (error != 0) 42117d24755SJustin T. Gibbs return (ENXIO); 42217d24755SJustin T. Gibbs 42317d24755SJustin T. Gibbs ahd->pci_cachesize = 424b3b25f2cSJustin T. Gibbs aic_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, 42517d24755SJustin T. Gibbs /*bytes*/1) & CACHESIZE; 42617d24755SJustin T. Gibbs ahd->pci_cachesize *= 4; 42717d24755SJustin T. Gibbs 42817d24755SJustin T. Gibbs ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 42917d24755SJustin T. Gibbs /* See if we have a SEEPROM and perform auto-term */ 43017d24755SJustin T. Gibbs error = ahd_check_extport(ahd); 43117d24755SJustin T. Gibbs if (error != 0) 43217d24755SJustin T. Gibbs return (error); 43317d24755SJustin T. Gibbs 43417d24755SJustin T. Gibbs /* Core initialization */ 43517d24755SJustin T. Gibbs error = ahd_init(ahd); 43617d24755SJustin T. Gibbs if (error != 0) 43717d24755SJustin T. Gibbs return (error); 43817d24755SJustin T. Gibbs 43917d24755SJustin T. Gibbs /* 44017d24755SJustin T. Gibbs * Allow interrupts now that we are completely setup. 44117d24755SJustin T. Gibbs */ 44217d24755SJustin T. Gibbs error = ahd_pci_map_int(ahd); 44317d24755SJustin T. Gibbs if (error != 0) 44417d24755SJustin T. Gibbs return (error); 44517d24755SJustin T. Gibbs 446032b0a17SScott Long ahd_lock(ahd); 44717d24755SJustin T. Gibbs /* 44817d24755SJustin T. Gibbs * Link this softc in with all other ahd instances. 44917d24755SJustin T. Gibbs */ 45017d24755SJustin T. Gibbs ahd_softc_insert(ahd); 451032b0a17SScott Long ahd_unlock(ahd); 45217d24755SJustin T. Gibbs return (0); 45317d24755SJustin T. Gibbs } 45417d24755SJustin T. Gibbs 45517d24755SJustin T. Gibbs /* 456454bf169SScott Long * Perform some simple tests that should catch situations where 457454bf169SScott Long * our registers are invalidly mapped. 458454bf169SScott Long */ 459454bf169SScott Long int 460454bf169SScott Long ahd_pci_test_register_access(struct ahd_softc *ahd) 461454bf169SScott Long { 4620794987dSJustin T. Gibbs uint32_t cmd; 463176b648eSJustin T. Gibbs u_int targpcistat; 464176b648eSJustin T. Gibbs u_int pci_status1; 46597cae63dSScott Long int error; 4660794987dSJustin T. Gibbs uint8_t hcntrl; 46797cae63dSScott Long 46897cae63dSScott Long error = EIO; 46997cae63dSScott Long 4700794987dSJustin T. Gibbs /* 4710794987dSJustin T. Gibbs * Enable PCI error interrupt status, but suppress NMIs 4720794987dSJustin T. Gibbs * generated by SERR raised due to target aborts. 4730794987dSJustin T. Gibbs */ 474b3b25f2cSJustin T. Gibbs cmd = aic_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2); 475b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, 4760794987dSJustin T. Gibbs cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2); 477454bf169SScott Long 478454bf169SScott Long /* 479454bf169SScott Long * First a simple test to see if any 480454bf169SScott Long * registers can be read. Reading 481454bf169SScott Long * HCNTRL has no side effects and has 482454bf169SScott Long * at least one bit that is guaranteed to 483454bf169SScott Long * be zero so it is a good register to 484454bf169SScott Long * use for this test. 485454bf169SScott Long */ 4860794987dSJustin T. Gibbs hcntrl = ahd_inb(ahd, HCNTRL); 4870794987dSJustin T. Gibbs if (hcntrl == 0xFF) 48897cae63dSScott Long goto fail; 489454bf169SScott Long 490454bf169SScott Long /* 491454bf169SScott Long * Next create a situation where write combining 492454bf169SScott Long * or read prefetching could be initiated by the 493454bf169SScott Long * CPU or host bridge. Our device does not support 494594c945aSPedro F. Giffuni * either, so look for data corruption and/or flagged 495ba079c0dSScott Long * PCI errors. First pause without causing another 496ba079c0dSScott Long * chip reset. 497454bf169SScott Long */ 498ba079c0dSScott Long hcntrl &= ~CHIPRST; 4990794987dSJustin T. Gibbs ahd_outb(ahd, HCNTRL, hcntrl|PAUSE); 5000794987dSJustin T. Gibbs while (ahd_is_paused(ahd) == 0) 5010794987dSJustin T. Gibbs ; 502176b648eSJustin T. Gibbs 503176b648eSJustin T. Gibbs /* Clear any PCI errors that occurred before our driver attached. */ 504176b648eSJustin T. Gibbs ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); 505176b648eSJustin T. Gibbs targpcistat = ahd_inb(ahd, TARGPCISTAT); 506176b648eSJustin T. Gibbs ahd_outb(ahd, TARGPCISTAT, targpcistat); 507b3b25f2cSJustin T. Gibbs pci_status1 = aic_pci_read_config(ahd->dev_softc, 508176b648eSJustin T. Gibbs PCIR_STATUS + 1, /*bytes*/1); 509b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, 510176b648eSJustin T. Gibbs pci_status1, /*bytes*/1); 511176b648eSJustin T. Gibbs ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI); 512176b648eSJustin T. Gibbs ahd_outb(ahd, CLRINT, CLRPCIINT); 513176b648eSJustin T. Gibbs 5140794987dSJustin T. Gibbs ahd_outb(ahd, SEQCTL0, PERRORDIS); 51597cae63dSScott Long ahd_outl(ahd, SRAM_BASE, 0x5aa555aa); 51697cae63dSScott Long if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa) 51797cae63dSScott Long goto fail; 518454bf169SScott Long 519454bf169SScott Long if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) { 52097cae63dSScott Long u_int targpcistat; 52197cae63dSScott Long 52297cae63dSScott Long ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); 52397cae63dSScott Long targpcistat = ahd_inb(ahd, TARGPCISTAT); 52497cae63dSScott Long if ((targpcistat & STA) != 0) 52597cae63dSScott Long goto fail; 52697cae63dSScott Long } 52797cae63dSScott Long 52897cae63dSScott Long error = 0; 52997cae63dSScott Long 53097cae63dSScott Long fail: 53197cae63dSScott Long if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) { 532454bf169SScott Long 533454bf169SScott Long ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); 534454bf169SScott Long targpcistat = ahd_inb(ahd, TARGPCISTAT); 535454bf169SScott Long 536454bf169SScott Long /* Silently clear any latched errors. */ 537454bf169SScott Long ahd_outb(ahd, TARGPCISTAT, targpcistat); 538b3b25f2cSJustin T. Gibbs pci_status1 = aic_pci_read_config(ahd->dev_softc, 539454bf169SScott Long PCIR_STATUS + 1, /*bytes*/1); 540b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, 541454bf169SScott Long pci_status1, /*bytes*/1); 54297cae63dSScott Long ahd_outb(ahd, CLRINT, CLRPCIINT); 543454bf169SScott Long } 5440794987dSJustin T. Gibbs ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS); 545b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2); 54697cae63dSScott Long return (error); 547454bf169SScott Long } 548454bf169SScott Long 549454bf169SScott Long /* 55017d24755SJustin T. Gibbs * Check the external port logic for a serial eeprom 55117d24755SJustin T. Gibbs * and termination/cable detection contrls. 55217d24755SJustin T. Gibbs */ 55317d24755SJustin T. Gibbs static int 55417d24755SJustin T. Gibbs ahd_check_extport(struct ahd_softc *ahd) 55517d24755SJustin T. Gibbs { 556d7cff4abSJustin T. Gibbs struct vpd_config vpd; 55717d24755SJustin T. Gibbs struct seeprom_config *sc; 55817d24755SJustin T. Gibbs u_int adapter_control; 55917d24755SJustin T. Gibbs int have_seeprom; 56017d24755SJustin T. Gibbs int error; 56117d24755SJustin T. Gibbs 56217d24755SJustin T. Gibbs sc = ahd->seep_config; 56317d24755SJustin T. Gibbs have_seeprom = ahd_acquire_seeprom(ahd); 56417d24755SJustin T. Gibbs if (have_seeprom) { 56517d24755SJustin T. Gibbs u_int start_addr; 56617d24755SJustin T. Gibbs 567d7cff4abSJustin T. Gibbs /* 568d7cff4abSJustin T. Gibbs * Fetch VPD for this function and parse it. 569d7cff4abSJustin T. Gibbs */ 570d7cff4abSJustin T. Gibbs if (bootverbose) 571d7cff4abSJustin T. Gibbs printf("%s: Reading VPD from SEEPROM...", 572d7cff4abSJustin T. Gibbs ahd_name(ahd)); 573d7cff4abSJustin T. Gibbs 574d7cff4abSJustin T. Gibbs /* Address is always in units of 16bit words */ 575d7cff4abSJustin T. Gibbs start_addr = ((2 * sizeof(*sc)) 576d7cff4abSJustin T. Gibbs + (sizeof(vpd) * (ahd->channel - 'A'))) / 2; 577d7cff4abSJustin T. Gibbs 578d7cff4abSJustin T. Gibbs error = ahd_read_seeprom(ahd, (uint16_t *)&vpd, 579d7cff4abSJustin T. Gibbs start_addr, sizeof(vpd)/2, 580d7cff4abSJustin T. Gibbs /*bytestream*/TRUE); 581d7cff4abSJustin T. Gibbs if (error == 0) 582d7cff4abSJustin T. Gibbs error = ahd_parse_vpddata(ahd, &vpd); 583d7cff4abSJustin T. Gibbs if (bootverbose) 584d7cff4abSJustin T. Gibbs printf("%s: VPD parsing %s\n", 585d7cff4abSJustin T. Gibbs ahd_name(ahd), 586d7cff4abSJustin T. Gibbs error == 0 ? "successful" : "failed"); 587d7cff4abSJustin T. Gibbs 58817d24755SJustin T. Gibbs if (bootverbose) 58917d24755SJustin T. Gibbs printf("%s: Reading SEEPROM...", ahd_name(ahd)); 59017d24755SJustin T. Gibbs 59117d24755SJustin T. Gibbs /* Address is always in units of 16bit words */ 59217d24755SJustin T. Gibbs start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A'); 59317d24755SJustin T. Gibbs 59417d24755SJustin T. Gibbs error = ahd_read_seeprom(ahd, (uint16_t *)sc, 595d7cff4abSJustin T. Gibbs start_addr, sizeof(*sc)/2, 596d7cff4abSJustin T. Gibbs /*bytestream*/FALSE); 59717d24755SJustin T. Gibbs 59817d24755SJustin T. Gibbs if (error != 0) { 59917d24755SJustin T. Gibbs printf("Unable to read SEEPROM\n"); 60017d24755SJustin T. Gibbs have_seeprom = 0; 60117d24755SJustin T. Gibbs } else { 60217d24755SJustin T. Gibbs have_seeprom = ahd_verify_cksum(sc); 60317d24755SJustin T. Gibbs 60417d24755SJustin T. Gibbs if (bootverbose) { 60517d24755SJustin T. Gibbs if (have_seeprom == 0) 60617d24755SJustin T. Gibbs printf ("checksum error\n"); 60717d24755SJustin T. Gibbs else 60817d24755SJustin T. Gibbs printf ("done.\n"); 60917d24755SJustin T. Gibbs } 61017d24755SJustin T. Gibbs } 61117d24755SJustin T. Gibbs ahd_release_seeprom(ahd); 61217d24755SJustin T. Gibbs } 61317d24755SJustin T. Gibbs 61417d24755SJustin T. Gibbs if (!have_seeprom) { 61517d24755SJustin T. Gibbs u_int nvram_scb; 61617d24755SJustin T. Gibbs 61717d24755SJustin T. Gibbs /* 61817d24755SJustin T. Gibbs * Pull scratch ram settings and treat them as 61917d24755SJustin T. Gibbs * if they are the contents of an seeprom if 62017d24755SJustin T. Gibbs * the 'ADPT', 'BIOS', or 'ASPI' signature is found 62117d24755SJustin T. Gibbs * in SCB 0xFF. We manually compose the data as 16bit 62217d24755SJustin T. Gibbs * values to avoid endian issues. 62317d24755SJustin T. Gibbs */ 62417d24755SJustin T. Gibbs ahd_set_scbptr(ahd, 0xFF); 62517d24755SJustin T. Gibbs nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET); 62617d24755SJustin T. Gibbs if (nvram_scb != 0xFF 62717d24755SJustin T. Gibbs && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A' 62817d24755SJustin T. Gibbs && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D' 62917d24755SJustin T. Gibbs && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P' 63017d24755SJustin T. Gibbs && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T') 63117d24755SJustin T. Gibbs || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B' 63217d24755SJustin T. Gibbs && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I' 63317d24755SJustin T. Gibbs && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O' 63417d24755SJustin T. Gibbs && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S') 63517d24755SJustin T. Gibbs || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A' 63617d24755SJustin T. Gibbs && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S' 63717d24755SJustin T. Gibbs && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P' 63817d24755SJustin T. Gibbs && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) { 63917d24755SJustin T. Gibbs uint16_t *sc_data; 64017d24755SJustin T. Gibbs int i; 64117d24755SJustin T. Gibbs 64217d24755SJustin T. Gibbs ahd_set_scbptr(ahd, nvram_scb); 64317d24755SJustin T. Gibbs sc_data = (uint16_t *)sc; 64417d24755SJustin T. Gibbs for (i = 0; i < 64; i += 2) 64517d24755SJustin T. Gibbs *sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i); 64617d24755SJustin T. Gibbs have_seeprom = ahd_verify_cksum(sc); 64717d24755SJustin T. Gibbs if (have_seeprom) 64817d24755SJustin T. Gibbs ahd->flags |= AHD_SCB_CONFIG_USED; 64917d24755SJustin T. Gibbs } 65017d24755SJustin T. Gibbs } 65117d24755SJustin T. Gibbs 652f4e98881SRuslan Ermilov #ifdef AHD_DEBUG 65317d24755SJustin T. Gibbs if (have_seeprom != 0 65417d24755SJustin T. Gibbs && (ahd_debug & AHD_DUMP_SEEPROM) != 0) { 655d7cff4abSJustin T. Gibbs uint16_t *sc_data; 65617d24755SJustin T. Gibbs int i; 65717d24755SJustin T. Gibbs 65817d24755SJustin T. Gibbs printf("%s: Seeprom Contents:", ahd_name(ahd)); 659d7cff4abSJustin T. Gibbs sc_data = (uint16_t *)sc; 66017d24755SJustin T. Gibbs for (i = 0; i < (sizeof(*sc)); i += 2) 661d7cff4abSJustin T. Gibbs printf("\n\t0x%.4x", sc_data[i]); 66217d24755SJustin T. Gibbs printf("\n"); 66317d24755SJustin T. Gibbs } 66417d24755SJustin T. Gibbs #endif 66517d24755SJustin T. Gibbs 66617d24755SJustin T. Gibbs if (!have_seeprom) { 66717d24755SJustin T. Gibbs if (bootverbose) 66817d24755SJustin T. Gibbs printf("%s: No SEEPROM available.\n", ahd_name(ahd)); 66917d24755SJustin T. Gibbs ahd->flags |= AHD_USEDEFAULTS; 67017d24755SJustin T. Gibbs error = ahd_default_config(ahd); 67117d24755SJustin T. Gibbs adapter_control = CFAUTOTERM|CFSEAUTOTERM; 67217d24755SJustin T. Gibbs free(ahd->seep_config, M_DEVBUF); 67317d24755SJustin T. Gibbs ahd->seep_config = NULL; 67417d24755SJustin T. Gibbs } else { 67517d24755SJustin T. Gibbs error = ahd_parse_cfgdata(ahd, sc); 67617d24755SJustin T. Gibbs adapter_control = sc->adapter_control; 67717d24755SJustin T. Gibbs } 67817d24755SJustin T. Gibbs if (error != 0) 67917d24755SJustin T. Gibbs return (error); 68017d24755SJustin T. Gibbs 68117d24755SJustin T. Gibbs ahd_configure_termination(ahd, adapter_control); 68217d24755SJustin T. Gibbs 68317d24755SJustin T. Gibbs return (0); 68417d24755SJustin T. Gibbs } 68517d24755SJustin T. Gibbs 68617d24755SJustin T. Gibbs static void 68717d24755SJustin T. Gibbs ahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control) 68817d24755SJustin T. Gibbs { 68917d24755SJustin T. Gibbs int error; 69017d24755SJustin T. Gibbs u_int sxfrctl1; 69117d24755SJustin T. Gibbs uint8_t termctl; 69217d24755SJustin T. Gibbs uint32_t devconfig; 69317d24755SJustin T. Gibbs 694b3b25f2cSJustin T. Gibbs devconfig = aic_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4); 69517d24755SJustin T. Gibbs devconfig &= ~STPWLEVEL; 6961a1fbd0bSJustin T. Gibbs if ((ahd->flags & AHD_STPWLEVEL_A) != 0) 69717d24755SJustin T. Gibbs devconfig |= STPWLEVEL; 6981a1fbd0bSJustin T. Gibbs if (bootverbose) 6991a1fbd0bSJustin T. Gibbs printf("%s: STPWLEVEL is %s\n", 7001a1fbd0bSJustin T. Gibbs ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off"); 701b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4); 70217d24755SJustin T. Gibbs 70317d24755SJustin T. Gibbs /* Make sure current sensing is off. */ 70417d24755SJustin T. Gibbs if ((ahd->flags & AHD_CURRENT_SENSING) != 0) { 70517d24755SJustin T. Gibbs (void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0); 70617d24755SJustin T. Gibbs } 70717d24755SJustin T. Gibbs 70817d24755SJustin T. Gibbs /* 70917d24755SJustin T. Gibbs * Read to sense. Write to set. 71017d24755SJustin T. Gibbs */ 71117d24755SJustin T. Gibbs error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl); 71217d24755SJustin T. Gibbs if ((adapter_control & CFAUTOTERM) == 0) { 71317d24755SJustin T. Gibbs if (bootverbose) 71417d24755SJustin T. Gibbs printf("%s: Manual Primary Termination\n", 71517d24755SJustin T. Gibbs ahd_name(ahd)); 71617d24755SJustin T. Gibbs termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH); 71717d24755SJustin T. Gibbs if ((adapter_control & CFSTERM) != 0) 71817d24755SJustin T. Gibbs termctl |= FLX_TERMCTL_ENPRILOW; 71917d24755SJustin T. Gibbs if ((adapter_control & CFWSTERM) != 0) 72017d24755SJustin T. Gibbs termctl |= FLX_TERMCTL_ENPRIHIGH; 72117d24755SJustin T. Gibbs } else if (error != 0) { 72217d24755SJustin T. Gibbs printf("%s: Primary Auto-Term Sensing failed! " 72317d24755SJustin T. Gibbs "Using Defaults.\n", ahd_name(ahd)); 72417d24755SJustin T. Gibbs termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH; 72517d24755SJustin T. Gibbs } 72617d24755SJustin T. Gibbs 72717d24755SJustin T. Gibbs if ((adapter_control & CFSEAUTOTERM) == 0) { 72817d24755SJustin T. Gibbs if (bootverbose) 72917d24755SJustin T. Gibbs printf("%s: Manual Secondary Termination\n", 73017d24755SJustin T. Gibbs ahd_name(ahd)); 73117d24755SJustin T. Gibbs termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH); 73217d24755SJustin T. Gibbs if ((adapter_control & CFSELOWTERM) != 0) 73317d24755SJustin T. Gibbs termctl |= FLX_TERMCTL_ENSECLOW; 73417d24755SJustin T. Gibbs if ((adapter_control & CFSEHIGHTERM) != 0) 73517d24755SJustin T. Gibbs termctl |= FLX_TERMCTL_ENSECHIGH; 73617d24755SJustin T. Gibbs } else if (error != 0) { 73717d24755SJustin T. Gibbs printf("%s: Secondary Auto-Term Sensing failed! " 73817d24755SJustin T. Gibbs "Using Defaults.\n", ahd_name(ahd)); 73917d24755SJustin T. Gibbs termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH; 74017d24755SJustin T. Gibbs } 74117d24755SJustin T. Gibbs 74217d24755SJustin T. Gibbs /* 74317d24755SJustin T. Gibbs * Now set the termination based on what we found. 74417d24755SJustin T. Gibbs */ 74517d24755SJustin T. Gibbs sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN; 746b3b25f2cSJustin T. Gibbs ahd->flags &= ~AHD_TERM_ENB_A; 74717d24755SJustin T. Gibbs if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) { 74817d24755SJustin T. Gibbs ahd->flags |= AHD_TERM_ENB_A; 74917d24755SJustin T. Gibbs sxfrctl1 |= STPWEN; 75017d24755SJustin T. Gibbs } 75117d24755SJustin T. Gibbs /* Must set the latch once in order to be effective. */ 75217d24755SJustin T. Gibbs ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN); 75317d24755SJustin T. Gibbs ahd_outb(ahd, SXFRCTL1, sxfrctl1); 75417d24755SJustin T. Gibbs 75517d24755SJustin T. Gibbs error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl); 75617d24755SJustin T. Gibbs if (error != 0) { 75717d24755SJustin T. Gibbs printf("%s: Unable to set termination settings!\n", 75817d24755SJustin T. Gibbs ahd_name(ahd)); 75917d24755SJustin T. Gibbs } else if (bootverbose) { 76017d24755SJustin T. Gibbs printf("%s: Primary High byte termination %sabled\n", 76117d24755SJustin T. Gibbs ahd_name(ahd), 76217d24755SJustin T. Gibbs (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis"); 76317d24755SJustin T. Gibbs 76417d24755SJustin T. Gibbs printf("%s: Primary Low byte termination %sabled\n", 76517d24755SJustin T. Gibbs ahd_name(ahd), 76617d24755SJustin T. Gibbs (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis"); 76717d24755SJustin T. Gibbs 76817d24755SJustin T. Gibbs printf("%s: Secondary High byte termination %sabled\n", 76917d24755SJustin T. Gibbs ahd_name(ahd), 77017d24755SJustin T. Gibbs (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis"); 77117d24755SJustin T. Gibbs 77217d24755SJustin T. Gibbs printf("%s: Secondary Low byte termination %sabled\n", 77317d24755SJustin T. Gibbs ahd_name(ahd), 77417d24755SJustin T. Gibbs (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis"); 77517d24755SJustin T. Gibbs } 77617d24755SJustin T. Gibbs return; 77717d24755SJustin T. Gibbs } 77817d24755SJustin T. Gibbs 77917d24755SJustin T. Gibbs #define DPE 0x80 78017d24755SJustin T. Gibbs #define SSE 0x40 78117d24755SJustin T. Gibbs #define RMA 0x20 78217d24755SJustin T. Gibbs #define RTA 0x10 78317d24755SJustin T. Gibbs #define STA 0x08 78417d24755SJustin T. Gibbs #define DPR 0x01 78517d24755SJustin T. Gibbs 78617d24755SJustin T. Gibbs static const char *split_status_source[] = 78717d24755SJustin T. Gibbs { 78817d24755SJustin T. Gibbs "DFF0", 78917d24755SJustin T. Gibbs "DFF1", 79017d24755SJustin T. Gibbs "OVLY", 79117d24755SJustin T. Gibbs "CMC", 79217d24755SJustin T. Gibbs }; 79317d24755SJustin T. Gibbs 79417d24755SJustin T. Gibbs static const char *pci_status_source[] = 79517d24755SJustin T. Gibbs { 79617d24755SJustin T. Gibbs "DFF0", 79717d24755SJustin T. Gibbs "DFF1", 79817d24755SJustin T. Gibbs "SG", 79917d24755SJustin T. Gibbs "CMC", 80017d24755SJustin T. Gibbs "OVLY", 80117d24755SJustin T. Gibbs "NONE", 80217d24755SJustin T. Gibbs "MSI", 80317d24755SJustin T. Gibbs "TARG" 80417d24755SJustin T. Gibbs }; 80517d24755SJustin T. Gibbs 80617d24755SJustin T. Gibbs static const char *split_status_strings[] = 80717d24755SJustin T. Gibbs { 808acae33b0SJustin T. Gibbs "%s: Received split response in %s.\n", 80917d24755SJustin T. Gibbs "%s: Received split completion error message in %s\n", 81017d24755SJustin T. Gibbs "%s: Receive overrun in %s\n", 81117d24755SJustin T. Gibbs "%s: Count not complete in %s\n", 81217d24755SJustin T. Gibbs "%s: Split completion data bucket in %s\n", 81317d24755SJustin T. Gibbs "%s: Split completion address error in %s\n", 81417d24755SJustin T. Gibbs "%s: Split completion byte count error in %s\n", 815acae33b0SJustin T. Gibbs "%s: Signaled Target-abort to early terminate a split in %s\n" 81617d24755SJustin T. Gibbs }; 81717d24755SJustin T. Gibbs 81817d24755SJustin T. Gibbs static const char *pci_status_strings[] = 81917d24755SJustin T. Gibbs { 82017d24755SJustin T. Gibbs "%s: Data Parity Error has been reported via PERR# in %s\n", 82117d24755SJustin T. Gibbs "%s: Target initial wait state error in %s\n", 82217d24755SJustin T. Gibbs "%s: Split completion read data parity error in %s\n", 82317d24755SJustin T. Gibbs "%s: Split completion address attribute parity error in %s\n", 82417d24755SJustin T. Gibbs "%s: Received a Target Abort in %s\n", 82517d24755SJustin T. Gibbs "%s: Received a Master Abort in %s\n", 82617d24755SJustin T. Gibbs "%s: Signal System Error Detected in %s\n", 82717d24755SJustin T. Gibbs "%s: Address or Write Phase Parity Error Detected in %s.\n" 82817d24755SJustin T. Gibbs }; 82917d24755SJustin T. Gibbs 83017d24755SJustin T. Gibbs void 83117d24755SJustin T. Gibbs ahd_pci_intr(struct ahd_softc *ahd) 83217d24755SJustin T. Gibbs { 83317d24755SJustin T. Gibbs uint8_t pci_status[8]; 83417d24755SJustin T. Gibbs ahd_mode_state saved_modes; 83517d24755SJustin T. Gibbs u_int pci_status1; 83617d24755SJustin T. Gibbs u_int intstat; 83717d24755SJustin T. Gibbs u_int i; 83817d24755SJustin T. Gibbs u_int reg; 83917d24755SJustin T. Gibbs 84017d24755SJustin T. Gibbs intstat = ahd_inb(ahd, INTSTAT); 84117d24755SJustin T. Gibbs 84217d24755SJustin T. Gibbs if ((intstat & SPLTINT) != 0) 84317d24755SJustin T. Gibbs ahd_pci_split_intr(ahd, intstat); 84417d24755SJustin T. Gibbs 84517d24755SJustin T. Gibbs if ((intstat & PCIINT) == 0) 84617d24755SJustin T. Gibbs return; 84717d24755SJustin T. Gibbs 84817d24755SJustin T. Gibbs printf("%s: PCI error Interrupt\n", ahd_name(ahd)); 84917d24755SJustin T. Gibbs saved_modes = ahd_save_modes(ahd); 85017d24755SJustin T. Gibbs ahd_dump_card_state(ahd); 85117d24755SJustin T. Gibbs ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG); 85217d24755SJustin T. Gibbs for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) { 85317d24755SJustin T. Gibbs 85417d24755SJustin T. Gibbs if (i == 5) 85517d24755SJustin T. Gibbs continue; 85617d24755SJustin T. Gibbs pci_status[i] = ahd_inb(ahd, reg); 857acae33b0SJustin T. Gibbs /* Clear latched errors. So our interrupt deasserts. */ 85817d24755SJustin T. Gibbs ahd_outb(ahd, reg, pci_status[i]); 85917d24755SJustin T. Gibbs } 86017d24755SJustin T. Gibbs 86117d24755SJustin T. Gibbs for (i = 0; i < 8; i++) { 86217d24755SJustin T. Gibbs u_int bit; 86317d24755SJustin T. Gibbs 86417d24755SJustin T. Gibbs if (i == 5) 86517d24755SJustin T. Gibbs continue; 86617d24755SJustin T. Gibbs 86717d24755SJustin T. Gibbs for (bit = 0; bit < 8; bit++) { 86817d24755SJustin T. Gibbs 86917d24755SJustin T. Gibbs if ((pci_status[i] & (0x1 << bit)) != 0) { 87017d24755SJustin T. Gibbs static const char *s; 87117d24755SJustin T. Gibbs 87217d24755SJustin T. Gibbs s = pci_status_strings[bit]; 87317d24755SJustin T. Gibbs if (i == 7/*TARG*/ && bit == 3) 87497cae63dSScott Long s = "%s: Signaled Target Abort\n"; 87517d24755SJustin T. Gibbs printf(s, ahd_name(ahd), pci_status_source[i]); 87617d24755SJustin T. Gibbs } 87717d24755SJustin T. Gibbs } 87817d24755SJustin T. Gibbs } 879b3b25f2cSJustin T. Gibbs pci_status1 = aic_pci_read_config(ahd->dev_softc, 88017d24755SJustin T. Gibbs PCIR_STATUS + 1, /*bytes*/1); 881b3b25f2cSJustin T. Gibbs aic_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1, 88217d24755SJustin T. Gibbs pci_status1, /*bytes*/1); 88317d24755SJustin T. Gibbs ahd_restore_modes(ahd, saved_modes); 88497cae63dSScott Long ahd_outb(ahd, CLRINT, CLRPCIINT); 88517d24755SJustin T. Gibbs ahd_unpause(ahd); 88617d24755SJustin T. Gibbs } 88717d24755SJustin T. Gibbs 88817d24755SJustin T. Gibbs static void 88917d24755SJustin T. Gibbs ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat) 89017d24755SJustin T. Gibbs { 89117d24755SJustin T. Gibbs uint8_t split_status[4]; 89217d24755SJustin T. Gibbs uint8_t split_status1[4]; 89317d24755SJustin T. Gibbs uint8_t sg_split_status[2]; 89417d24755SJustin T. Gibbs uint8_t sg_split_status1[2]; 89517d24755SJustin T. Gibbs ahd_mode_state saved_modes; 89617d24755SJustin T. Gibbs u_int i; 8976eb7ebfeSJohn Baldwin uint32_t pcix_status; 89817d24755SJustin T. Gibbs 89917d24755SJustin T. Gibbs /* 90017d24755SJustin T. Gibbs * Check for splits in all modes. Modes 0 and 1 90117d24755SJustin T. Gibbs * additionally have SG engine splits to look at. 90217d24755SJustin T. Gibbs */ 9036eb7ebfeSJohn Baldwin pcix_status = aic_pci_read_config(ahd->dev_softc, 9046eb7ebfeSJohn Baldwin ahd->pcix_ptr + PCIXR_STATUS, /*bytes*/ 4); 90517d24755SJustin T. Gibbs printf("%s: PCI Split Interrupt - PCI-X status = 0x%x\n", 9066eb7ebfeSJohn Baldwin ahd_name(ahd), pcix_status >> 16); 90717d24755SJustin T. Gibbs saved_modes = ahd_save_modes(ahd); 90817d24755SJustin T. Gibbs for (i = 0; i < 4; i++) { 90917d24755SJustin T. Gibbs ahd_set_modes(ahd, i, i); 91017d24755SJustin T. Gibbs 91117d24755SJustin T. Gibbs split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0); 91217d24755SJustin T. Gibbs split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1); 913acae33b0SJustin T. Gibbs /* Clear latched errors. So our interrupt deasserts. */ 91417d24755SJustin T. Gibbs ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]); 91517d24755SJustin T. Gibbs ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]); 916d7cff4abSJustin T. Gibbs if (i > 1) 91717d24755SJustin T. Gibbs continue; 91817d24755SJustin T. Gibbs sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0); 91917d24755SJustin T. Gibbs sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1); 920acae33b0SJustin T. Gibbs /* Clear latched errors. So our interrupt deasserts. */ 92117d24755SJustin T. Gibbs ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]); 92217d24755SJustin T. Gibbs ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]); 92317d24755SJustin T. Gibbs } 92417d24755SJustin T. Gibbs 92517d24755SJustin T. Gibbs for (i = 0; i < 4; i++) { 92617d24755SJustin T. Gibbs u_int bit; 92717d24755SJustin T. Gibbs 92817d24755SJustin T. Gibbs for (bit = 0; bit < 8; bit++) { 92917d24755SJustin T. Gibbs 93017d24755SJustin T. Gibbs if ((split_status[i] & (0x1 << bit)) != 0) { 93117d24755SJustin T. Gibbs static const char *s; 93217d24755SJustin T. Gibbs 93317d24755SJustin T. Gibbs s = split_status_strings[bit]; 93417d24755SJustin T. Gibbs printf(s, ahd_name(ahd), 93517d24755SJustin T. Gibbs split_status_source[i]); 93617d24755SJustin T. Gibbs } 93717d24755SJustin T. Gibbs 938d7cff4abSJustin T. Gibbs if (i > 1) 93917d24755SJustin T. Gibbs continue; 94017d24755SJustin T. Gibbs 94117d24755SJustin T. Gibbs if ((sg_split_status[i] & (0x1 << bit)) != 0) { 94217d24755SJustin T. Gibbs static const char *s; 94317d24755SJustin T. Gibbs 94417d24755SJustin T. Gibbs s = split_status_strings[bit]; 94517d24755SJustin T. Gibbs printf(s, ahd_name(ahd), "SG"); 94617d24755SJustin T. Gibbs } 94717d24755SJustin T. Gibbs } 94817d24755SJustin T. Gibbs } 94917d24755SJustin T. Gibbs /* 95017d24755SJustin T. Gibbs * Clear PCI-X status bits. 95117d24755SJustin T. Gibbs */ 9526eb7ebfeSJohn Baldwin aic_pci_write_config(ahd->dev_softc, ahd->pcix_ptr + PCIXR_STATUS, 9536eb7ebfeSJohn Baldwin pcix_status, /*bytes*/4); 95497cae63dSScott Long ahd_outb(ahd, CLRINT, CLRSPLTINT); 95517d24755SJustin T. Gibbs ahd_restore_modes(ahd, saved_modes); 95617d24755SJustin T. Gibbs } 95717d24755SJustin T. Gibbs 95817d24755SJustin T. Gibbs static int 959197696e9SJustin T. Gibbs ahd_aic7901_setup(struct ahd_softc *ahd) 960197696e9SJustin T. Gibbs { 961197696e9SJustin T. Gibbs 962197696e9SJustin T. Gibbs ahd->chip = AHD_AIC7901; 963c8ee7177SJustin T. Gibbs ahd->features = AHD_AIC7901_FE; 964c8ee7177SJustin T. Gibbs return (ahd_aic790X_setup(ahd)); 965197696e9SJustin T. Gibbs } 966197696e9SJustin T. Gibbs 967197696e9SJustin T. Gibbs static int 9681a1fbd0bSJustin T. Gibbs ahd_aic7901A_setup(struct ahd_softc *ahd) 9691a1fbd0bSJustin T. Gibbs { 9701a1fbd0bSJustin T. Gibbs 9711a1fbd0bSJustin T. Gibbs ahd->chip = AHD_AIC7901A; 972c8ee7177SJustin T. Gibbs ahd->features = AHD_AIC7901A_FE; 973c8ee7177SJustin T. Gibbs return (ahd_aic790X_setup(ahd)); 9741a1fbd0bSJustin T. Gibbs } 9751a1fbd0bSJustin T. Gibbs 976454bf169SScott Long static int 977454bf169SScott Long ahd_aic7902_setup(struct ahd_softc *ahd) 978454bf169SScott Long { 979c8ee7177SJustin T. Gibbs ahd->chip = AHD_AIC7902; 980c8ee7177SJustin T. Gibbs ahd->features = AHD_AIC7902_FE; 981c8ee7177SJustin T. Gibbs return (ahd_aic790X_setup(ahd)); 982c8ee7177SJustin T. Gibbs } 983c8ee7177SJustin T. Gibbs 984c8ee7177SJustin T. Gibbs static int 985c8ee7177SJustin T. Gibbs ahd_aic790X_setup(struct ahd_softc *ahd) 986c8ee7177SJustin T. Gibbs { 987b3b25f2cSJustin T. Gibbs aic_dev_softc_t pci; 988454bf169SScott Long u_int rev; 989454bf169SScott Long 990454bf169SScott Long pci = ahd->dev_softc; 991b3b25f2cSJustin T. Gibbs rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1); 992454bf169SScott Long if (rev < ID_AIC7902_PCI_REV_A4) { 993454bf169SScott Long printf("%s: Unable to attach to unsupported chip revision %d\n", 994454bf169SScott Long ahd_name(ahd), rev); 995b3b25f2cSJustin T. Gibbs aic_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2); 996454bf169SScott Long return (ENXIO); 997454bf169SScott Long } 998b3b25f2cSJustin T. Gibbs ahd->channel = aic_get_pci_function(pci) + 'A'; 999454bf169SScott Long if (rev < ID_AIC7902_PCI_REV_B0) { 1000454bf169SScott Long /* 1001454bf169SScott Long * Enable A series workarounds. 1002454bf169SScott Long */ 1003454bf169SScott Long ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG 1004454bf169SScott Long | AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG 1005454bf169SScott Long | AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG 1006454bf169SScott Long | AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG 1007454bf169SScott Long | AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG 10082cd3cc37SJustin T. Gibbs | AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG 10092cd3cc37SJustin T. Gibbs | AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG 10102cd3cc37SJustin T. Gibbs | AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG 10112cd3cc37SJustin T. Gibbs | AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG 1012d7cff4abSJustin T. Gibbs | AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG 1013d7cff4abSJustin T. Gibbs | AHD_FAINT_LED_BUG; 1014454bf169SScott Long 1015454bf169SScott Long /* 1016594c945aSPedro F. Giffuni * IO Cell parameter setup. 1017454bf169SScott Long */ 1018454bf169SScott Long AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29); 1019454bf169SScott Long 1020454bf169SScott Long if ((ahd->flags & AHD_HP_BOARD) == 0) 1021454bf169SScott Long AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA); 1022454bf169SScott Long } else { 1023454bf169SScott Long u_int devconfig1; 1024454bf169SScott Long 1025454bf169SScott Long ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS 10264ddea3e2SJustin T. Gibbs | AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY; 102705899a48SJustin T. Gibbs ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG; 1028c8ee7177SJustin T. Gibbs 1029c8ee7177SJustin T. Gibbs /* 1030c8ee7177SJustin T. Gibbs * Some issues have been resolved in the 7901B. 1031c8ee7177SJustin T. Gibbs */ 1032c8ee7177SJustin T. Gibbs if ((ahd->features & AHD_MULTI_FUNC) != 0) 103305899a48SJustin T. Gibbs ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG 103405899a48SJustin T. Gibbs | AHD_BUSFREEREV_BUG; 1035454bf169SScott Long 1036454bf169SScott Long /* 1037594c945aSPedro F. Giffuni * IO Cell parameter setup. 1038454bf169SScott Long */ 1039454bf169SScott Long AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29); 1040454bf169SScott Long AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB); 1041454bf169SScott Long AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF); 1042454bf169SScott Long 1043454bf169SScott Long /* 1044454bf169SScott Long * Set the PREQDIS bit for H2B which disables some workaround 1045454bf169SScott Long * that doesn't work on regular PCI busses. 1046454bf169SScott Long * XXX - Find out exactly what this does from the hardware 1047454bf169SScott Long * folks! 1048454bf169SScott Long */ 1049b3b25f2cSJustin T. Gibbs devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); 1050b3b25f2cSJustin T. Gibbs aic_pci_write_config(pci, DEVCONFIG1, 1051454bf169SScott Long devconfig1|PREQDIS, /*bytes*/1); 1052b3b25f2cSJustin T. Gibbs devconfig1 = aic_pci_read_config(pci, DEVCONFIG1, /*bytes*/1); 1053454bf169SScott Long } 1054454bf169SScott Long 1055454bf169SScott Long return (0); 1056454bf169SScott Long } 1057