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