18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Product specific probe and attach routines for:
38c2ecf20Sopenharmony_ci *	aic7901 and aic7902 SCSI controllers
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Copyright (c) 1994-2001 Justin T. Gibbs.
68c2ecf20Sopenharmony_ci * Copyright (c) 2000-2002 Adaptec Inc.
78c2ecf20Sopenharmony_ci * All rights reserved.
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Redistribution and use in source and binary forms, with or without
108c2ecf20Sopenharmony_ci * modification, are permitted provided that the following conditions
118c2ecf20Sopenharmony_ci * are met:
128c2ecf20Sopenharmony_ci * 1. Redistributions of source code must retain the above copyright
138c2ecf20Sopenharmony_ci *    notice, this list of conditions, and the following disclaimer,
148c2ecf20Sopenharmony_ci *    without modification.
158c2ecf20Sopenharmony_ci * 2. Redistributions in binary form must reproduce at minimum a disclaimer
168c2ecf20Sopenharmony_ci *    substantially similar to the "NO WARRANTY" disclaimer below
178c2ecf20Sopenharmony_ci *    ("Disclaimer") and any redistribution must be conditioned upon
188c2ecf20Sopenharmony_ci *    including a substantially similar Disclaimer requirement for further
198c2ecf20Sopenharmony_ci *    binary redistribution.
208c2ecf20Sopenharmony_ci * 3. Neither the names of the above-listed copyright holders nor the names
218c2ecf20Sopenharmony_ci *    of any contributors may be used to endorse or promote products derived
228c2ecf20Sopenharmony_ci *    from this software without specific prior written permission.
238c2ecf20Sopenharmony_ci *
248c2ecf20Sopenharmony_ci * Alternatively, this software may be distributed under the terms of the
258c2ecf20Sopenharmony_ci * GNU General Public License ("GPL") version 2 as published by the Free
268c2ecf20Sopenharmony_ci * Software Foundation.
278c2ecf20Sopenharmony_ci *
288c2ecf20Sopenharmony_ci * NO WARRANTY
298c2ecf20Sopenharmony_ci * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
308c2ecf20Sopenharmony_ci * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
318c2ecf20Sopenharmony_ci * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
328c2ecf20Sopenharmony_ci * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
338c2ecf20Sopenharmony_ci * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
348c2ecf20Sopenharmony_ci * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
358c2ecf20Sopenharmony_ci * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
368c2ecf20Sopenharmony_ci * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
378c2ecf20Sopenharmony_ci * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
388c2ecf20Sopenharmony_ci * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
398c2ecf20Sopenharmony_ci * POSSIBILITY OF SUCH DAMAGES.
408c2ecf20Sopenharmony_ci *
418c2ecf20Sopenharmony_ci * $Id: //depot/aic7xxx/aic7xxx/aic79xx_pci.c#92 $
428c2ecf20Sopenharmony_ci */
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#include "aic79xx_osm.h"
458c2ecf20Sopenharmony_ci#include "aic79xx_inline.h"
468c2ecf20Sopenharmony_ci#include "aic79xx_pci.h"
478c2ecf20Sopenharmony_ci
488c2ecf20Sopenharmony_cistatic inline uint64_t
498c2ecf20Sopenharmony_ciahd_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
508c2ecf20Sopenharmony_ci{
518c2ecf20Sopenharmony_ci	uint64_t id;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	id = subvendor
548c2ecf20Sopenharmony_ci	   | (subdevice << 16)
558c2ecf20Sopenharmony_ci	   | ((uint64_t)vendor << 32)
568c2ecf20Sopenharmony_ci	   | ((uint64_t)device << 48);
578c2ecf20Sopenharmony_ci
588c2ecf20Sopenharmony_ci	return (id);
598c2ecf20Sopenharmony_ci}
608c2ecf20Sopenharmony_ci
618c2ecf20Sopenharmony_ci#define ID_AIC7902_PCI_REV_A4		0x3
628c2ecf20Sopenharmony_ci#define ID_AIC7902_PCI_REV_B0		0x10
638c2ecf20Sopenharmony_ci#define SUBID_HP			0x0E11
648c2ecf20Sopenharmony_ci
658c2ecf20Sopenharmony_ci#define DEVID_9005_HOSTRAID(id) ((id) & 0x80)
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci#define DEVID_9005_TYPE(id) ((id) & 0xF)
688c2ecf20Sopenharmony_ci#define		DEVID_9005_TYPE_HBA		0x0	/* Standard Card */
698c2ecf20Sopenharmony_ci#define		DEVID_9005_TYPE_HBA_2EXT	0x1	/* 2 External Ports */
708c2ecf20Sopenharmony_ci#define		DEVID_9005_TYPE_IROC		0x8	/* Raid(0,1,10) Card */
718c2ecf20Sopenharmony_ci#define		DEVID_9005_TYPE_MB		0xF	/* On Motherboard */
728c2ecf20Sopenharmony_ci
738c2ecf20Sopenharmony_ci#define DEVID_9005_MFUNC(id) ((id) & 0x10)
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#define DEVID_9005_PACKETIZED(id) ((id) & 0x8000)
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci#define SUBID_9005_TYPE(id) ((id) & 0xF)
788c2ecf20Sopenharmony_ci#define		SUBID_9005_TYPE_HBA		0x0	/* Standard Card */
798c2ecf20Sopenharmony_ci#define		SUBID_9005_TYPE_MB		0xF	/* On Motherboard */
808c2ecf20Sopenharmony_ci
818c2ecf20Sopenharmony_ci#define SUBID_9005_AUTOTERM(id)	(((id) & 0x10) == 0)
828c2ecf20Sopenharmony_ci
838c2ecf20Sopenharmony_ci#define SUBID_9005_LEGACYCONN_FUNC(id) ((id) & 0x20)
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_ci#define SUBID_9005_SEEPTYPE(id) (((id) & 0x0C0) >> 6)
868c2ecf20Sopenharmony_ci#define		SUBID_9005_SEEPTYPE_NONE	0x0
878c2ecf20Sopenharmony_ci#define		SUBID_9005_SEEPTYPE_4K		0x1
888c2ecf20Sopenharmony_ci
898c2ecf20Sopenharmony_cistatic ahd_device_setup_t ahd_aic7901_setup;
908c2ecf20Sopenharmony_cistatic ahd_device_setup_t ahd_aic7901A_setup;
918c2ecf20Sopenharmony_cistatic ahd_device_setup_t ahd_aic7902_setup;
928c2ecf20Sopenharmony_cistatic ahd_device_setup_t ahd_aic790X_setup;
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_cistatic const struct ahd_pci_identity ahd_pci_ident_table[] =
958c2ecf20Sopenharmony_ci{
968c2ecf20Sopenharmony_ci	/* aic7901 based controllers */
978c2ecf20Sopenharmony_ci	{
988c2ecf20Sopenharmony_ci		ID_AHA_29320A,
998c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1008c2ecf20Sopenharmony_ci		"Adaptec 29320A Ultra320 SCSI adapter",
1018c2ecf20Sopenharmony_ci		ahd_aic7901_setup
1028c2ecf20Sopenharmony_ci	},
1038c2ecf20Sopenharmony_ci	{
1048c2ecf20Sopenharmony_ci		ID_AHA_29320ALP,
1058c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1068c2ecf20Sopenharmony_ci		"Adaptec 29320ALP PCIx Ultra320 SCSI adapter",
1078c2ecf20Sopenharmony_ci		ahd_aic7901_setup
1088c2ecf20Sopenharmony_ci	},
1098c2ecf20Sopenharmony_ci	{
1108c2ecf20Sopenharmony_ci		ID_AHA_29320LPE,
1118c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1128c2ecf20Sopenharmony_ci		"Adaptec 29320LPE PCIe Ultra320 SCSI adapter",
1138c2ecf20Sopenharmony_ci		ahd_aic7901_setup
1148c2ecf20Sopenharmony_ci	},
1158c2ecf20Sopenharmony_ci	/* aic7901A based controllers */
1168c2ecf20Sopenharmony_ci	{
1178c2ecf20Sopenharmony_ci		ID_AHA_29320LP,
1188c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1198c2ecf20Sopenharmony_ci		"Adaptec 29320LP Ultra320 SCSI adapter",
1208c2ecf20Sopenharmony_ci		ahd_aic7901A_setup
1218c2ecf20Sopenharmony_ci	},
1228c2ecf20Sopenharmony_ci	/* aic7902 based controllers */
1238c2ecf20Sopenharmony_ci	{
1248c2ecf20Sopenharmony_ci		ID_AHA_29320,
1258c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1268c2ecf20Sopenharmony_ci		"Adaptec 29320 Ultra320 SCSI adapter",
1278c2ecf20Sopenharmony_ci		ahd_aic7902_setup
1288c2ecf20Sopenharmony_ci	},
1298c2ecf20Sopenharmony_ci	{
1308c2ecf20Sopenharmony_ci		ID_AHA_29320B,
1318c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1328c2ecf20Sopenharmony_ci		"Adaptec 29320B Ultra320 SCSI adapter",
1338c2ecf20Sopenharmony_ci		ahd_aic7902_setup
1348c2ecf20Sopenharmony_ci	},
1358c2ecf20Sopenharmony_ci	{
1368c2ecf20Sopenharmony_ci		ID_AHA_39320,
1378c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1388c2ecf20Sopenharmony_ci		"Adaptec 39320 Ultra320 SCSI adapter",
1398c2ecf20Sopenharmony_ci		ahd_aic7902_setup
1408c2ecf20Sopenharmony_ci	},
1418c2ecf20Sopenharmony_ci	{
1428c2ecf20Sopenharmony_ci		ID_AHA_39320_B,
1438c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1448c2ecf20Sopenharmony_ci		"Adaptec 39320 Ultra320 SCSI adapter",
1458c2ecf20Sopenharmony_ci		ahd_aic7902_setup
1468c2ecf20Sopenharmony_ci	},
1478c2ecf20Sopenharmony_ci	{
1488c2ecf20Sopenharmony_ci		ID_AHA_39320_B_DELL,
1498c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1508c2ecf20Sopenharmony_ci		"Adaptec (Dell OEM) 39320 Ultra320 SCSI adapter",
1518c2ecf20Sopenharmony_ci		ahd_aic7902_setup
1528c2ecf20Sopenharmony_ci	},
1538c2ecf20Sopenharmony_ci	{
1548c2ecf20Sopenharmony_ci		ID_AHA_39320A,
1558c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1568c2ecf20Sopenharmony_ci		"Adaptec 39320A Ultra320 SCSI adapter",
1578c2ecf20Sopenharmony_ci		ahd_aic7902_setup
1588c2ecf20Sopenharmony_ci	},
1598c2ecf20Sopenharmony_ci	{
1608c2ecf20Sopenharmony_ci		ID_AHA_39320D,
1618c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1628c2ecf20Sopenharmony_ci		"Adaptec 39320D Ultra320 SCSI adapter",
1638c2ecf20Sopenharmony_ci		ahd_aic7902_setup
1648c2ecf20Sopenharmony_ci	},
1658c2ecf20Sopenharmony_ci	{
1668c2ecf20Sopenharmony_ci		ID_AHA_39320D_HP,
1678c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1688c2ecf20Sopenharmony_ci		"Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",
1698c2ecf20Sopenharmony_ci		ahd_aic7902_setup
1708c2ecf20Sopenharmony_ci	},
1718c2ecf20Sopenharmony_ci	{
1728c2ecf20Sopenharmony_ci		ID_AHA_39320D_B,
1738c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1748c2ecf20Sopenharmony_ci		"Adaptec 39320D Ultra320 SCSI adapter",
1758c2ecf20Sopenharmony_ci		ahd_aic7902_setup
1768c2ecf20Sopenharmony_ci	},
1778c2ecf20Sopenharmony_ci	{
1788c2ecf20Sopenharmony_ci		ID_AHA_39320D_B_HP,
1798c2ecf20Sopenharmony_ci		ID_ALL_MASK,
1808c2ecf20Sopenharmony_ci		"Adaptec (HP OEM) 39320D Ultra320 SCSI adapter",
1818c2ecf20Sopenharmony_ci		ahd_aic7902_setup
1828c2ecf20Sopenharmony_ci	},
1838c2ecf20Sopenharmony_ci	/* Generic chip probes for devices we don't know 'exactly' */
1848c2ecf20Sopenharmony_ci	{
1858c2ecf20Sopenharmony_ci		ID_AIC7901 & ID_9005_GENERIC_MASK,
1868c2ecf20Sopenharmony_ci		ID_9005_GENERIC_MASK,
1878c2ecf20Sopenharmony_ci		"Adaptec AIC7901 Ultra320 SCSI adapter",
1888c2ecf20Sopenharmony_ci		ahd_aic7901_setup
1898c2ecf20Sopenharmony_ci	},
1908c2ecf20Sopenharmony_ci	{
1918c2ecf20Sopenharmony_ci		ID_AIC7901A & ID_DEV_VENDOR_MASK,
1928c2ecf20Sopenharmony_ci		ID_DEV_VENDOR_MASK,
1938c2ecf20Sopenharmony_ci		"Adaptec AIC7901A Ultra320 SCSI adapter",
1948c2ecf20Sopenharmony_ci		ahd_aic7901A_setup
1958c2ecf20Sopenharmony_ci	},
1968c2ecf20Sopenharmony_ci	{
1978c2ecf20Sopenharmony_ci		ID_AIC7902 & ID_9005_GENERIC_MASK,
1988c2ecf20Sopenharmony_ci		ID_9005_GENERIC_MASK,
1998c2ecf20Sopenharmony_ci		"Adaptec AIC7902 Ultra320 SCSI adapter",
2008c2ecf20Sopenharmony_ci		ahd_aic7902_setup
2018c2ecf20Sopenharmony_ci	}
2028c2ecf20Sopenharmony_ci};
2038c2ecf20Sopenharmony_ci
2048c2ecf20Sopenharmony_cistatic const u_int ahd_num_pci_devs = ARRAY_SIZE(ahd_pci_ident_table);
2058c2ecf20Sopenharmony_ci
2068c2ecf20Sopenharmony_ci#define	DEVCONFIG		0x40
2078c2ecf20Sopenharmony_ci#define		PCIXINITPAT	0x0000E000ul
2088c2ecf20Sopenharmony_ci#define			PCIXINIT_PCI33_66	0x0000E000ul
2098c2ecf20Sopenharmony_ci#define			PCIXINIT_PCIX50_66	0x0000C000ul
2108c2ecf20Sopenharmony_ci#define			PCIXINIT_PCIX66_100	0x0000A000ul
2118c2ecf20Sopenharmony_ci#define			PCIXINIT_PCIX100_133	0x00008000ul
2128c2ecf20Sopenharmony_ci#define	PCI_BUS_MODES_INDEX(devconfig)	\
2138c2ecf20Sopenharmony_ci	(((devconfig) & PCIXINITPAT) >> 13)
2148c2ecf20Sopenharmony_cistatic const char *pci_bus_modes[] =
2158c2ecf20Sopenharmony_ci{
2168c2ecf20Sopenharmony_ci	"PCI bus mode unknown",
2178c2ecf20Sopenharmony_ci	"PCI bus mode unknown",
2188c2ecf20Sopenharmony_ci	"PCI bus mode unknown",
2198c2ecf20Sopenharmony_ci	"PCI bus mode unknown",
2208c2ecf20Sopenharmony_ci	"PCI-X 101-133MHz",
2218c2ecf20Sopenharmony_ci	"PCI-X 67-100MHz",
2228c2ecf20Sopenharmony_ci	"PCI-X 50-66MHz",
2238c2ecf20Sopenharmony_ci	"PCI 33 or 66MHz"
2248c2ecf20Sopenharmony_ci};
2258c2ecf20Sopenharmony_ci
2268c2ecf20Sopenharmony_ci#define		TESTMODE	0x00000800ul
2278c2ecf20Sopenharmony_ci#define		IRDY_RST	0x00000200ul
2288c2ecf20Sopenharmony_ci#define		FRAME_RST	0x00000100ul
2298c2ecf20Sopenharmony_ci#define		PCI64BIT	0x00000080ul
2308c2ecf20Sopenharmony_ci#define		MRDCEN		0x00000040ul
2318c2ecf20Sopenharmony_ci#define		ENDIANSEL	0x00000020ul
2328c2ecf20Sopenharmony_ci#define		MIXQWENDIANEN	0x00000008ul
2338c2ecf20Sopenharmony_ci#define		DACEN		0x00000004ul
2348c2ecf20Sopenharmony_ci#define		STPWLEVEL	0x00000002ul
2358c2ecf20Sopenharmony_ci#define		QWENDIANSEL	0x00000001ul
2368c2ecf20Sopenharmony_ci
2378c2ecf20Sopenharmony_ci#define	DEVCONFIG1		0x44
2388c2ecf20Sopenharmony_ci#define		PREQDIS		0x01
2398c2ecf20Sopenharmony_ci
2408c2ecf20Sopenharmony_ci#define	CSIZE_LATTIME		0x0c
2418c2ecf20Sopenharmony_ci#define		CACHESIZE	0x000000fful
2428c2ecf20Sopenharmony_ci#define		LATTIME		0x0000ff00ul
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_cistatic int	ahd_check_extport(struct ahd_softc *ahd);
2458c2ecf20Sopenharmony_cistatic void	ahd_configure_termination(struct ahd_softc *ahd,
2468c2ecf20Sopenharmony_ci					  u_int adapter_control);
2478c2ecf20Sopenharmony_cistatic void	ahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat);
2488c2ecf20Sopenharmony_cistatic void	ahd_pci_intr(struct ahd_softc *ahd);
2498c2ecf20Sopenharmony_ci
2508c2ecf20Sopenharmony_ciconst struct ahd_pci_identity *
2518c2ecf20Sopenharmony_ciahd_find_pci_device(ahd_dev_softc_t pci)
2528c2ecf20Sopenharmony_ci{
2538c2ecf20Sopenharmony_ci	uint64_t  full_id;
2548c2ecf20Sopenharmony_ci	uint16_t  device;
2558c2ecf20Sopenharmony_ci	uint16_t  vendor;
2568c2ecf20Sopenharmony_ci	uint16_t  subdevice;
2578c2ecf20Sopenharmony_ci	uint16_t  subvendor;
2588c2ecf20Sopenharmony_ci	const struct ahd_pci_identity *entry;
2598c2ecf20Sopenharmony_ci	u_int	  i;
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_ci	vendor = ahd_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
2628c2ecf20Sopenharmony_ci	device = ahd_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
2638c2ecf20Sopenharmony_ci	subvendor = ahd_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
2648c2ecf20Sopenharmony_ci	subdevice = ahd_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
2658c2ecf20Sopenharmony_ci	full_id = ahd_compose_id(device,
2668c2ecf20Sopenharmony_ci				 vendor,
2678c2ecf20Sopenharmony_ci				 subdevice,
2688c2ecf20Sopenharmony_ci				 subvendor);
2698c2ecf20Sopenharmony_ci
2708c2ecf20Sopenharmony_ci	/*
2718c2ecf20Sopenharmony_ci	 * Controllers, mask out the IROC/HostRAID bit
2728c2ecf20Sopenharmony_ci	 */
2738c2ecf20Sopenharmony_ci
2748c2ecf20Sopenharmony_ci	full_id &= ID_ALL_IROC_MASK;
2758c2ecf20Sopenharmony_ci
2768c2ecf20Sopenharmony_ci	for (i = 0; i < ahd_num_pci_devs; i++) {
2778c2ecf20Sopenharmony_ci		entry = &ahd_pci_ident_table[i];
2788c2ecf20Sopenharmony_ci		if (entry->full_id == (full_id & entry->id_mask)) {
2798c2ecf20Sopenharmony_ci			/* Honor exclusion entries. */
2808c2ecf20Sopenharmony_ci			if (entry->name == NULL)
2818c2ecf20Sopenharmony_ci				return (NULL);
2828c2ecf20Sopenharmony_ci			return (entry);
2838c2ecf20Sopenharmony_ci		}
2848c2ecf20Sopenharmony_ci	}
2858c2ecf20Sopenharmony_ci	return (NULL);
2868c2ecf20Sopenharmony_ci}
2878c2ecf20Sopenharmony_ci
2888c2ecf20Sopenharmony_ciint
2898c2ecf20Sopenharmony_ciahd_pci_config(struct ahd_softc *ahd, const struct ahd_pci_identity *entry)
2908c2ecf20Sopenharmony_ci{
2918c2ecf20Sopenharmony_ci	u_int		 command;
2928c2ecf20Sopenharmony_ci	uint32_t	 devconfig;
2938c2ecf20Sopenharmony_ci	uint16_t	 subvendor;
2948c2ecf20Sopenharmony_ci	int		 error;
2958c2ecf20Sopenharmony_ci
2968c2ecf20Sopenharmony_ci	ahd->description = entry->name;
2978c2ecf20Sopenharmony_ci	/*
2988c2ecf20Sopenharmony_ci	 * Record if this is an HP board.
2998c2ecf20Sopenharmony_ci	 */
3008c2ecf20Sopenharmony_ci	subvendor = ahd_pci_read_config(ahd->dev_softc,
3018c2ecf20Sopenharmony_ci					PCIR_SUBVEND_0, /*bytes*/2);
3028c2ecf20Sopenharmony_ci	if (subvendor == SUBID_HP)
3038c2ecf20Sopenharmony_ci		ahd->flags |= AHD_HP_BOARD;
3048c2ecf20Sopenharmony_ci
3058c2ecf20Sopenharmony_ci	error = entry->setup(ahd);
3068c2ecf20Sopenharmony_ci	if (error != 0)
3078c2ecf20Sopenharmony_ci		return (error);
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci	devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
3108c2ecf20Sopenharmony_ci	if ((devconfig & PCIXINITPAT) == PCIXINIT_PCI33_66) {
3118c2ecf20Sopenharmony_ci		ahd->chip |= AHD_PCI;
3128c2ecf20Sopenharmony_ci		/* Disable PCIX workarounds when running in PCI mode. */
3138c2ecf20Sopenharmony_ci		ahd->bugs &= ~AHD_PCIX_BUG_MASK;
3148c2ecf20Sopenharmony_ci	} else {
3158c2ecf20Sopenharmony_ci		ahd->chip |= AHD_PCIX;
3168c2ecf20Sopenharmony_ci	}
3178c2ecf20Sopenharmony_ci	ahd->bus_description = pci_bus_modes[PCI_BUS_MODES_INDEX(devconfig)];
3188c2ecf20Sopenharmony_ci
3198c2ecf20Sopenharmony_ci	ahd_power_state_change(ahd, AHD_POWER_STATE_D0);
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	error = ahd_pci_map_registers(ahd);
3228c2ecf20Sopenharmony_ci	if (error != 0)
3238c2ecf20Sopenharmony_ci		return (error);
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci	/*
3268c2ecf20Sopenharmony_ci	 * If we need to support high memory, enable dual
3278c2ecf20Sopenharmony_ci	 * address cycles.  This bit must be set to enable
3288c2ecf20Sopenharmony_ci	 * high address bit generation even if we are on a
3298c2ecf20Sopenharmony_ci	 * 64bit bus (PCI64BIT set in devconfig).
3308c2ecf20Sopenharmony_ci	 */
3318c2ecf20Sopenharmony_ci	if ((ahd->flags & (AHD_39BIT_ADDRESSING|AHD_64BIT_ADDRESSING)) != 0) {
3328c2ecf20Sopenharmony_ci		if (bootverbose)
3338c2ecf20Sopenharmony_ci			printk("%s: Enabling 39Bit Addressing\n",
3348c2ecf20Sopenharmony_ci			       ahd_name(ahd));
3358c2ecf20Sopenharmony_ci		devconfig = ahd_pci_read_config(ahd->dev_softc,
3368c2ecf20Sopenharmony_ci						DEVCONFIG, /*bytes*/4);
3378c2ecf20Sopenharmony_ci		devconfig |= DACEN;
3388c2ecf20Sopenharmony_ci		ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,
3398c2ecf20Sopenharmony_ci				     devconfig, /*bytes*/4);
3408c2ecf20Sopenharmony_ci	}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	/* Ensure busmastering is enabled */
3438c2ecf20Sopenharmony_ci	command = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
3448c2ecf20Sopenharmony_ci	command |= PCIM_CMD_BUSMASTEREN;
3458c2ecf20Sopenharmony_ci	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, command, /*bytes*/2);
3468c2ecf20Sopenharmony_ci
3478c2ecf20Sopenharmony_ci	error = ahd_softc_init(ahd);
3488c2ecf20Sopenharmony_ci	if (error != 0)
3498c2ecf20Sopenharmony_ci		return (error);
3508c2ecf20Sopenharmony_ci
3518c2ecf20Sopenharmony_ci	ahd->bus_intr = ahd_pci_intr;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci	error = ahd_reset(ahd, /*reinit*/FALSE);
3548c2ecf20Sopenharmony_ci	if (error != 0)
3558c2ecf20Sopenharmony_ci		return (ENXIO);
3568c2ecf20Sopenharmony_ci
3578c2ecf20Sopenharmony_ci	ahd->pci_cachesize =
3588c2ecf20Sopenharmony_ci	    ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME,
3598c2ecf20Sopenharmony_ci				/*bytes*/1) & CACHESIZE;
3608c2ecf20Sopenharmony_ci	ahd->pci_cachesize *= 4;
3618c2ecf20Sopenharmony_ci
3628c2ecf20Sopenharmony_ci	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
3638c2ecf20Sopenharmony_ci	/* See if we have a SEEPROM and perform auto-term */
3648c2ecf20Sopenharmony_ci	error = ahd_check_extport(ahd);
3658c2ecf20Sopenharmony_ci	if (error != 0)
3668c2ecf20Sopenharmony_ci		return (error);
3678c2ecf20Sopenharmony_ci
3688c2ecf20Sopenharmony_ci	/* Core initialization */
3698c2ecf20Sopenharmony_ci	error = ahd_init(ahd);
3708c2ecf20Sopenharmony_ci	if (error != 0)
3718c2ecf20Sopenharmony_ci		return (error);
3728c2ecf20Sopenharmony_ci	ahd->init_level++;
3738c2ecf20Sopenharmony_ci
3748c2ecf20Sopenharmony_ci	/*
3758c2ecf20Sopenharmony_ci	 * Allow interrupts now that we are completely setup.
3768c2ecf20Sopenharmony_ci	 */
3778c2ecf20Sopenharmony_ci	return ahd_pci_map_int(ahd);
3788c2ecf20Sopenharmony_ci}
3798c2ecf20Sopenharmony_ci
3808c2ecf20Sopenharmony_ci#ifdef CONFIG_PM
3818c2ecf20Sopenharmony_civoid
3828c2ecf20Sopenharmony_ciahd_pci_suspend(struct ahd_softc *ahd)
3838c2ecf20Sopenharmony_ci{
3848c2ecf20Sopenharmony_ci	/*
3858c2ecf20Sopenharmony_ci	 * Save chip register configuration data for chip resets
3868c2ecf20Sopenharmony_ci	 * that occur during runtime and resume events.
3878c2ecf20Sopenharmony_ci	 */
3888c2ecf20Sopenharmony_ci	ahd->suspend_state.pci_state.devconfig =
3898c2ecf20Sopenharmony_ci	    ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
3908c2ecf20Sopenharmony_ci	ahd->suspend_state.pci_state.command =
3918c2ecf20Sopenharmony_ci	    ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/1);
3928c2ecf20Sopenharmony_ci	ahd->suspend_state.pci_state.csize_lattime =
3938c2ecf20Sopenharmony_ci	    ahd_pci_read_config(ahd->dev_softc, CSIZE_LATTIME, /*bytes*/1);
3948c2ecf20Sopenharmony_ci
3958c2ecf20Sopenharmony_ci}
3968c2ecf20Sopenharmony_ci
3978c2ecf20Sopenharmony_civoid
3988c2ecf20Sopenharmony_ciahd_pci_resume(struct ahd_softc *ahd)
3998c2ecf20Sopenharmony_ci{
4008c2ecf20Sopenharmony_ci	ahd_pci_write_config(ahd->dev_softc, DEVCONFIG,
4018c2ecf20Sopenharmony_ci			     ahd->suspend_state.pci_state.devconfig, /*bytes*/4);
4028c2ecf20Sopenharmony_ci	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
4038c2ecf20Sopenharmony_ci			     ahd->suspend_state.pci_state.command, /*bytes*/1);
4048c2ecf20Sopenharmony_ci	ahd_pci_write_config(ahd->dev_softc, CSIZE_LATTIME,
4058c2ecf20Sopenharmony_ci			     ahd->suspend_state.pci_state.csize_lattime, /*bytes*/1);
4068c2ecf20Sopenharmony_ci}
4078c2ecf20Sopenharmony_ci#endif
4088c2ecf20Sopenharmony_ci
4098c2ecf20Sopenharmony_ci/*
4108c2ecf20Sopenharmony_ci * Perform some simple tests that should catch situations where
4118c2ecf20Sopenharmony_ci * our registers are invalidly mapped.
4128c2ecf20Sopenharmony_ci */
4138c2ecf20Sopenharmony_ciint
4148c2ecf20Sopenharmony_ciahd_pci_test_register_access(struct ahd_softc *ahd)
4158c2ecf20Sopenharmony_ci{
4168c2ecf20Sopenharmony_ci	uint32_t cmd;
4178c2ecf20Sopenharmony_ci	u_int	 targpcistat;
4188c2ecf20Sopenharmony_ci	u_int	 pci_status1;
4198c2ecf20Sopenharmony_ci	int	 error;
4208c2ecf20Sopenharmony_ci	uint8_t	 hcntrl;
4218c2ecf20Sopenharmony_ci
4228c2ecf20Sopenharmony_ci	error = EIO;
4238c2ecf20Sopenharmony_ci
4248c2ecf20Sopenharmony_ci	/*
4258c2ecf20Sopenharmony_ci	 * Enable PCI error interrupt status, but suppress NMIs
4268c2ecf20Sopenharmony_ci	 * generated by SERR raised due to target aborts.
4278c2ecf20Sopenharmony_ci	 */
4288c2ecf20Sopenharmony_ci	cmd = ahd_pci_read_config(ahd->dev_softc, PCIR_COMMAND, /*bytes*/2);
4298c2ecf20Sopenharmony_ci	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND,
4308c2ecf20Sopenharmony_ci			     cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
4318c2ecf20Sopenharmony_ci
4328c2ecf20Sopenharmony_ci	/*
4338c2ecf20Sopenharmony_ci	 * First a simple test to see if any
4348c2ecf20Sopenharmony_ci	 * registers can be read.  Reading
4358c2ecf20Sopenharmony_ci	 * HCNTRL has no side effects and has
4368c2ecf20Sopenharmony_ci	 * at least one bit that is guaranteed to
4378c2ecf20Sopenharmony_ci	 * be zero so it is a good register to
4388c2ecf20Sopenharmony_ci	 * use for this test.
4398c2ecf20Sopenharmony_ci	 */
4408c2ecf20Sopenharmony_ci	hcntrl = ahd_inb(ahd, HCNTRL);
4418c2ecf20Sopenharmony_ci	if (hcntrl == 0xFF)
4428c2ecf20Sopenharmony_ci		goto fail;
4438c2ecf20Sopenharmony_ci
4448c2ecf20Sopenharmony_ci	/*
4458c2ecf20Sopenharmony_ci	 * Next create a situation where write combining
4468c2ecf20Sopenharmony_ci	 * or read prefetching could be initiated by the
4478c2ecf20Sopenharmony_ci	 * CPU or host bridge.  Our device does not support
4488c2ecf20Sopenharmony_ci	 * either, so look for data corruption and/or flaged
4498c2ecf20Sopenharmony_ci	 * PCI errors.  First pause without causing another
4508c2ecf20Sopenharmony_ci	 * chip reset.
4518c2ecf20Sopenharmony_ci	 */
4528c2ecf20Sopenharmony_ci	hcntrl &= ~CHIPRST;
4538c2ecf20Sopenharmony_ci	ahd_outb(ahd, HCNTRL, hcntrl|PAUSE);
4548c2ecf20Sopenharmony_ci	while (ahd_is_paused(ahd) == 0)
4558c2ecf20Sopenharmony_ci		;
4568c2ecf20Sopenharmony_ci
4578c2ecf20Sopenharmony_ci	/* Clear any PCI errors that occurred before our driver attached. */
4588c2ecf20Sopenharmony_ci	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
4598c2ecf20Sopenharmony_ci	targpcistat = ahd_inb(ahd, TARGPCISTAT);
4608c2ecf20Sopenharmony_ci	ahd_outb(ahd, TARGPCISTAT, targpcistat);
4618c2ecf20Sopenharmony_ci	pci_status1 = ahd_pci_read_config(ahd->dev_softc,
4628c2ecf20Sopenharmony_ci					  PCIR_STATUS + 1, /*bytes*/1);
4638c2ecf20Sopenharmony_ci	ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
4648c2ecf20Sopenharmony_ci			     pci_status1, /*bytes*/1);
4658c2ecf20Sopenharmony_ci	ahd_set_modes(ahd, AHD_MODE_SCSI, AHD_MODE_SCSI);
4668c2ecf20Sopenharmony_ci	ahd_outb(ahd, CLRINT, CLRPCIINT);
4678c2ecf20Sopenharmony_ci
4688c2ecf20Sopenharmony_ci	ahd_outb(ahd, SEQCTL0, PERRORDIS);
4698c2ecf20Sopenharmony_ci	ahd_outl(ahd, SRAM_BASE, 0x5aa555aa);
4708c2ecf20Sopenharmony_ci	if (ahd_inl(ahd, SRAM_BASE) != 0x5aa555aa)
4718c2ecf20Sopenharmony_ci		goto fail;
4728c2ecf20Sopenharmony_ci
4738c2ecf20Sopenharmony_ci	if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
4748c2ecf20Sopenharmony_ci		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
4758c2ecf20Sopenharmony_ci		targpcistat = ahd_inb(ahd, TARGPCISTAT);
4768c2ecf20Sopenharmony_ci		if ((targpcistat & STA) != 0)
4778c2ecf20Sopenharmony_ci			goto fail;
4788c2ecf20Sopenharmony_ci	}
4798c2ecf20Sopenharmony_ci
4808c2ecf20Sopenharmony_ci	error = 0;
4818c2ecf20Sopenharmony_ci
4828c2ecf20Sopenharmony_cifail:
4838c2ecf20Sopenharmony_ci	if ((ahd_inb(ahd, INTSTAT) & PCIINT) != 0) {
4848c2ecf20Sopenharmony_ci
4858c2ecf20Sopenharmony_ci		ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
4868c2ecf20Sopenharmony_ci		targpcistat = ahd_inb(ahd, TARGPCISTAT);
4878c2ecf20Sopenharmony_ci
4888c2ecf20Sopenharmony_ci		/* Silently clear any latched errors. */
4898c2ecf20Sopenharmony_ci		ahd_outb(ahd, TARGPCISTAT, targpcistat);
4908c2ecf20Sopenharmony_ci		pci_status1 = ahd_pci_read_config(ahd->dev_softc,
4918c2ecf20Sopenharmony_ci						  PCIR_STATUS + 1, /*bytes*/1);
4928c2ecf20Sopenharmony_ci		ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
4938c2ecf20Sopenharmony_ci				     pci_status1, /*bytes*/1);
4948c2ecf20Sopenharmony_ci		ahd_outb(ahd, CLRINT, CLRPCIINT);
4958c2ecf20Sopenharmony_ci	}
4968c2ecf20Sopenharmony_ci	ahd_outb(ahd, SEQCTL0, PERRORDIS|FAILDIS);
4978c2ecf20Sopenharmony_ci	ahd_pci_write_config(ahd->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
4988c2ecf20Sopenharmony_ci	return (error);
4998c2ecf20Sopenharmony_ci}
5008c2ecf20Sopenharmony_ci
5018c2ecf20Sopenharmony_ci/*
5028c2ecf20Sopenharmony_ci * Check the external port logic for a serial eeprom
5038c2ecf20Sopenharmony_ci * and termination/cable detection contrls.
5048c2ecf20Sopenharmony_ci */
5058c2ecf20Sopenharmony_cistatic int
5068c2ecf20Sopenharmony_ciahd_check_extport(struct ahd_softc *ahd)
5078c2ecf20Sopenharmony_ci{
5088c2ecf20Sopenharmony_ci	struct	vpd_config vpd;
5098c2ecf20Sopenharmony_ci	struct	seeprom_config *sc;
5108c2ecf20Sopenharmony_ci	u_int	adapter_control;
5118c2ecf20Sopenharmony_ci	int	have_seeprom;
5128c2ecf20Sopenharmony_ci	int	error;
5138c2ecf20Sopenharmony_ci
5148c2ecf20Sopenharmony_ci	sc = ahd->seep_config;
5158c2ecf20Sopenharmony_ci	have_seeprom = ahd_acquire_seeprom(ahd);
5168c2ecf20Sopenharmony_ci	if (have_seeprom) {
5178c2ecf20Sopenharmony_ci		u_int start_addr;
5188c2ecf20Sopenharmony_ci
5198c2ecf20Sopenharmony_ci		/*
5208c2ecf20Sopenharmony_ci		 * Fetch VPD for this function and parse it.
5218c2ecf20Sopenharmony_ci		 */
5228c2ecf20Sopenharmony_ci		if (bootverbose)
5238c2ecf20Sopenharmony_ci			printk("%s: Reading VPD from SEEPROM...",
5248c2ecf20Sopenharmony_ci			       ahd_name(ahd));
5258c2ecf20Sopenharmony_ci
5268c2ecf20Sopenharmony_ci		/* Address is always in units of 16bit words */
5278c2ecf20Sopenharmony_ci		start_addr = ((2 * sizeof(*sc))
5288c2ecf20Sopenharmony_ci			    + (sizeof(vpd) * (ahd->channel - 'A'))) / 2;
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci		error = ahd_read_seeprom(ahd, (uint16_t *)&vpd,
5318c2ecf20Sopenharmony_ci					 start_addr, sizeof(vpd)/2,
5328c2ecf20Sopenharmony_ci					 /*bytestream*/TRUE);
5338c2ecf20Sopenharmony_ci		if (error == 0)
5348c2ecf20Sopenharmony_ci			error = ahd_parse_vpddata(ahd, &vpd);
5358c2ecf20Sopenharmony_ci		if (bootverbose)
5368c2ecf20Sopenharmony_ci			printk("%s: VPD parsing %s\n",
5378c2ecf20Sopenharmony_ci			       ahd_name(ahd),
5388c2ecf20Sopenharmony_ci			       error == 0 ? "successful" : "failed");
5398c2ecf20Sopenharmony_ci
5408c2ecf20Sopenharmony_ci		if (bootverbose)
5418c2ecf20Sopenharmony_ci			printk("%s: Reading SEEPROM...", ahd_name(ahd));
5428c2ecf20Sopenharmony_ci
5438c2ecf20Sopenharmony_ci		/* Address is always in units of 16bit words */
5448c2ecf20Sopenharmony_ci		start_addr = (sizeof(*sc) / 2) * (ahd->channel - 'A');
5458c2ecf20Sopenharmony_ci
5468c2ecf20Sopenharmony_ci		error = ahd_read_seeprom(ahd, (uint16_t *)sc,
5478c2ecf20Sopenharmony_ci					 start_addr, sizeof(*sc)/2,
5488c2ecf20Sopenharmony_ci					 /*bytestream*/FALSE);
5498c2ecf20Sopenharmony_ci
5508c2ecf20Sopenharmony_ci		if (error != 0) {
5518c2ecf20Sopenharmony_ci			printk("Unable to read SEEPROM\n");
5528c2ecf20Sopenharmony_ci			have_seeprom = 0;
5538c2ecf20Sopenharmony_ci		} else {
5548c2ecf20Sopenharmony_ci			have_seeprom = ahd_verify_cksum(sc);
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci			if (bootverbose) {
5578c2ecf20Sopenharmony_ci				if (have_seeprom == 0)
5588c2ecf20Sopenharmony_ci					printk ("checksum error\n");
5598c2ecf20Sopenharmony_ci				else
5608c2ecf20Sopenharmony_ci					printk ("done.\n");
5618c2ecf20Sopenharmony_ci			}
5628c2ecf20Sopenharmony_ci		}
5638c2ecf20Sopenharmony_ci		ahd_release_seeprom(ahd);
5648c2ecf20Sopenharmony_ci	}
5658c2ecf20Sopenharmony_ci
5668c2ecf20Sopenharmony_ci	if (!have_seeprom) {
5678c2ecf20Sopenharmony_ci		u_int	  nvram_scb;
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci		/*
5708c2ecf20Sopenharmony_ci		 * Pull scratch ram settings and treat them as
5718c2ecf20Sopenharmony_ci		 * if they are the contents of an seeprom if
5728c2ecf20Sopenharmony_ci		 * the 'ADPT', 'BIOS', or 'ASPI' signature is found
5738c2ecf20Sopenharmony_ci		 * in SCB 0xFF.  We manually compose the data as 16bit
5748c2ecf20Sopenharmony_ci		 * values to avoid endian issues.
5758c2ecf20Sopenharmony_ci		 */
5768c2ecf20Sopenharmony_ci		ahd_set_scbptr(ahd, 0xFF);
5778c2ecf20Sopenharmony_ci		nvram_scb = ahd_inb_scbram(ahd, SCB_BASE + NVRAM_SCB_OFFSET);
5788c2ecf20Sopenharmony_ci		if (nvram_scb != 0xFF
5798c2ecf20Sopenharmony_ci		 && ((ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
5808c2ecf20Sopenharmony_ci		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'D'
5818c2ecf20Sopenharmony_ci		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
5828c2ecf20Sopenharmony_ci		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'T')
5838c2ecf20Sopenharmony_ci		  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'B'
5848c2ecf20Sopenharmony_ci		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'I'
5858c2ecf20Sopenharmony_ci		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'O'
5868c2ecf20Sopenharmony_ci		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'S')
5878c2ecf20Sopenharmony_ci		  || (ahd_inb_scbram(ahd, SCB_BASE + 0) == 'A'
5888c2ecf20Sopenharmony_ci		   && ahd_inb_scbram(ahd, SCB_BASE + 1) == 'S'
5898c2ecf20Sopenharmony_ci		   && ahd_inb_scbram(ahd, SCB_BASE + 2) == 'P'
5908c2ecf20Sopenharmony_ci		   && ahd_inb_scbram(ahd, SCB_BASE + 3) == 'I'))) {
5918c2ecf20Sopenharmony_ci			uint16_t *sc_data;
5928c2ecf20Sopenharmony_ci			int	  i;
5938c2ecf20Sopenharmony_ci
5948c2ecf20Sopenharmony_ci			ahd_set_scbptr(ahd, nvram_scb);
5958c2ecf20Sopenharmony_ci			sc_data = (uint16_t *)sc;
5968c2ecf20Sopenharmony_ci			for (i = 0; i < 64; i += 2)
5978c2ecf20Sopenharmony_ci				*sc_data++ = ahd_inw_scbram(ahd, SCB_BASE+i);
5988c2ecf20Sopenharmony_ci			have_seeprom = ahd_verify_cksum(sc);
5998c2ecf20Sopenharmony_ci			if (have_seeprom)
6008c2ecf20Sopenharmony_ci				ahd->flags |= AHD_SCB_CONFIG_USED;
6018c2ecf20Sopenharmony_ci		}
6028c2ecf20Sopenharmony_ci	}
6038c2ecf20Sopenharmony_ci
6048c2ecf20Sopenharmony_ci#ifdef AHD_DEBUG
6058c2ecf20Sopenharmony_ci	if (have_seeprom != 0
6068c2ecf20Sopenharmony_ci	 && (ahd_debug & AHD_DUMP_SEEPROM) != 0) {
6078c2ecf20Sopenharmony_ci		uint16_t *sc_data;
6088c2ecf20Sopenharmony_ci		int	  i;
6098c2ecf20Sopenharmony_ci
6108c2ecf20Sopenharmony_ci		printk("%s: Seeprom Contents:", ahd_name(ahd));
6118c2ecf20Sopenharmony_ci		sc_data = (uint16_t *)sc;
6128c2ecf20Sopenharmony_ci		for (i = 0; i < (sizeof(*sc)); i += 2)
6138c2ecf20Sopenharmony_ci			printk("\n\t0x%.4x", sc_data[i]);
6148c2ecf20Sopenharmony_ci		printk("\n");
6158c2ecf20Sopenharmony_ci	}
6168c2ecf20Sopenharmony_ci#endif
6178c2ecf20Sopenharmony_ci
6188c2ecf20Sopenharmony_ci	if (!have_seeprom) {
6198c2ecf20Sopenharmony_ci		if (bootverbose)
6208c2ecf20Sopenharmony_ci			printk("%s: No SEEPROM available.\n", ahd_name(ahd));
6218c2ecf20Sopenharmony_ci		ahd->flags |= AHD_USEDEFAULTS;
6228c2ecf20Sopenharmony_ci		error = ahd_default_config(ahd);
6238c2ecf20Sopenharmony_ci		adapter_control = CFAUTOTERM|CFSEAUTOTERM;
6248c2ecf20Sopenharmony_ci		kfree(ahd->seep_config);
6258c2ecf20Sopenharmony_ci		ahd->seep_config = NULL;
6268c2ecf20Sopenharmony_ci	} else {
6278c2ecf20Sopenharmony_ci		error = ahd_parse_cfgdata(ahd, sc);
6288c2ecf20Sopenharmony_ci		adapter_control = sc->adapter_control;
6298c2ecf20Sopenharmony_ci	}
6308c2ecf20Sopenharmony_ci	if (error != 0)
6318c2ecf20Sopenharmony_ci		return (error);
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	ahd_configure_termination(ahd, adapter_control);
6348c2ecf20Sopenharmony_ci
6358c2ecf20Sopenharmony_ci	return (0);
6368c2ecf20Sopenharmony_ci}
6378c2ecf20Sopenharmony_ci
6388c2ecf20Sopenharmony_cistatic void
6398c2ecf20Sopenharmony_ciahd_configure_termination(struct ahd_softc *ahd, u_int adapter_control)
6408c2ecf20Sopenharmony_ci{
6418c2ecf20Sopenharmony_ci	int	 error;
6428c2ecf20Sopenharmony_ci	u_int	 sxfrctl1;
6438c2ecf20Sopenharmony_ci	uint8_t	 termctl;
6448c2ecf20Sopenharmony_ci	uint32_t devconfig;
6458c2ecf20Sopenharmony_ci
6468c2ecf20Sopenharmony_ci	devconfig = ahd_pci_read_config(ahd->dev_softc, DEVCONFIG, /*bytes*/4);
6478c2ecf20Sopenharmony_ci	devconfig &= ~STPWLEVEL;
6488c2ecf20Sopenharmony_ci	if ((ahd->flags & AHD_STPWLEVEL_A) != 0)
6498c2ecf20Sopenharmony_ci		devconfig |= STPWLEVEL;
6508c2ecf20Sopenharmony_ci	if (bootverbose)
6518c2ecf20Sopenharmony_ci		printk("%s: STPWLEVEL is %s\n",
6528c2ecf20Sopenharmony_ci		       ahd_name(ahd), (devconfig & STPWLEVEL) ? "on" : "off");
6538c2ecf20Sopenharmony_ci	ahd_pci_write_config(ahd->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
6548c2ecf20Sopenharmony_ci
6558c2ecf20Sopenharmony_ci	/* Make sure current sensing is off. */
6568c2ecf20Sopenharmony_ci	if ((ahd->flags & AHD_CURRENT_SENSING) != 0) {
6578c2ecf20Sopenharmony_ci		(void)ahd_write_flexport(ahd, FLXADDR_ROMSTAT_CURSENSECTL, 0);
6588c2ecf20Sopenharmony_ci	}
6598c2ecf20Sopenharmony_ci
6608c2ecf20Sopenharmony_ci	/*
6618c2ecf20Sopenharmony_ci	 * Read to sense.  Write to set.
6628c2ecf20Sopenharmony_ci	 */
6638c2ecf20Sopenharmony_ci	error = ahd_read_flexport(ahd, FLXADDR_TERMCTL, &termctl);
6648c2ecf20Sopenharmony_ci	if ((adapter_control & CFAUTOTERM) == 0) {
6658c2ecf20Sopenharmony_ci		if (bootverbose)
6668c2ecf20Sopenharmony_ci			printk("%s: Manual Primary Termination\n",
6678c2ecf20Sopenharmony_ci			       ahd_name(ahd));
6688c2ecf20Sopenharmony_ci		termctl &= ~(FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH);
6698c2ecf20Sopenharmony_ci		if ((adapter_control & CFSTERM) != 0)
6708c2ecf20Sopenharmony_ci			termctl |= FLX_TERMCTL_ENPRILOW;
6718c2ecf20Sopenharmony_ci		if ((adapter_control & CFWSTERM) != 0)
6728c2ecf20Sopenharmony_ci			termctl |= FLX_TERMCTL_ENPRIHIGH;
6738c2ecf20Sopenharmony_ci	} else if (error != 0) {
6748c2ecf20Sopenharmony_ci		printk("%s: Primary Auto-Term Sensing failed! "
6758c2ecf20Sopenharmony_ci		       "Using Defaults.\n", ahd_name(ahd));
6768c2ecf20Sopenharmony_ci		termctl = FLX_TERMCTL_ENPRILOW|FLX_TERMCTL_ENPRIHIGH;
6778c2ecf20Sopenharmony_ci	}
6788c2ecf20Sopenharmony_ci
6798c2ecf20Sopenharmony_ci	if ((adapter_control & CFSEAUTOTERM) == 0) {
6808c2ecf20Sopenharmony_ci		if (bootverbose)
6818c2ecf20Sopenharmony_ci			printk("%s: Manual Secondary Termination\n",
6828c2ecf20Sopenharmony_ci			       ahd_name(ahd));
6838c2ecf20Sopenharmony_ci		termctl &= ~(FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH);
6848c2ecf20Sopenharmony_ci		if ((adapter_control & CFSELOWTERM) != 0)
6858c2ecf20Sopenharmony_ci			termctl |= FLX_TERMCTL_ENSECLOW;
6868c2ecf20Sopenharmony_ci		if ((adapter_control & CFSEHIGHTERM) != 0)
6878c2ecf20Sopenharmony_ci			termctl |= FLX_TERMCTL_ENSECHIGH;
6888c2ecf20Sopenharmony_ci	} else if (error != 0) {
6898c2ecf20Sopenharmony_ci		printk("%s: Secondary Auto-Term Sensing failed! "
6908c2ecf20Sopenharmony_ci		       "Using Defaults.\n", ahd_name(ahd));
6918c2ecf20Sopenharmony_ci		termctl |= FLX_TERMCTL_ENSECLOW|FLX_TERMCTL_ENSECHIGH;
6928c2ecf20Sopenharmony_ci	}
6938c2ecf20Sopenharmony_ci
6948c2ecf20Sopenharmony_ci	/*
6958c2ecf20Sopenharmony_ci	 * Now set the termination based on what we found.
6968c2ecf20Sopenharmony_ci	 */
6978c2ecf20Sopenharmony_ci	sxfrctl1 = ahd_inb(ahd, SXFRCTL1) & ~STPWEN;
6988c2ecf20Sopenharmony_ci	ahd->flags &= ~AHD_TERM_ENB_A;
6998c2ecf20Sopenharmony_ci	if ((termctl & FLX_TERMCTL_ENPRILOW) != 0) {
7008c2ecf20Sopenharmony_ci		ahd->flags |= AHD_TERM_ENB_A;
7018c2ecf20Sopenharmony_ci		sxfrctl1 |= STPWEN;
7028c2ecf20Sopenharmony_ci	}
7038c2ecf20Sopenharmony_ci	/* Must set the latch once in order to be effective. */
7048c2ecf20Sopenharmony_ci	ahd_outb(ahd, SXFRCTL1, sxfrctl1|STPWEN);
7058c2ecf20Sopenharmony_ci	ahd_outb(ahd, SXFRCTL1, sxfrctl1);
7068c2ecf20Sopenharmony_ci
7078c2ecf20Sopenharmony_ci	error = ahd_write_flexport(ahd, FLXADDR_TERMCTL, termctl);
7088c2ecf20Sopenharmony_ci	if (error != 0) {
7098c2ecf20Sopenharmony_ci		printk("%s: Unable to set termination settings!\n",
7108c2ecf20Sopenharmony_ci		       ahd_name(ahd));
7118c2ecf20Sopenharmony_ci	} else if (bootverbose) {
7128c2ecf20Sopenharmony_ci		printk("%s: Primary High byte termination %sabled\n",
7138c2ecf20Sopenharmony_ci		       ahd_name(ahd),
7148c2ecf20Sopenharmony_ci		       (termctl & FLX_TERMCTL_ENPRIHIGH) ? "En" : "Dis");
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci		printk("%s: Primary Low byte termination %sabled\n",
7178c2ecf20Sopenharmony_ci		       ahd_name(ahd),
7188c2ecf20Sopenharmony_ci		       (termctl & FLX_TERMCTL_ENPRILOW) ? "En" : "Dis");
7198c2ecf20Sopenharmony_ci
7208c2ecf20Sopenharmony_ci		printk("%s: Secondary High byte termination %sabled\n",
7218c2ecf20Sopenharmony_ci		       ahd_name(ahd),
7228c2ecf20Sopenharmony_ci		       (termctl & FLX_TERMCTL_ENSECHIGH) ? "En" : "Dis");
7238c2ecf20Sopenharmony_ci
7248c2ecf20Sopenharmony_ci		printk("%s: Secondary Low byte termination %sabled\n",
7258c2ecf20Sopenharmony_ci		       ahd_name(ahd),
7268c2ecf20Sopenharmony_ci		       (termctl & FLX_TERMCTL_ENSECLOW) ? "En" : "Dis");
7278c2ecf20Sopenharmony_ci	}
7288c2ecf20Sopenharmony_ci	return;
7298c2ecf20Sopenharmony_ci}
7308c2ecf20Sopenharmony_ci
7318c2ecf20Sopenharmony_ci#define	DPE	0x80
7328c2ecf20Sopenharmony_ci#define SSE	0x40
7338c2ecf20Sopenharmony_ci#define	RMA	0x20
7348c2ecf20Sopenharmony_ci#define	RTA	0x10
7358c2ecf20Sopenharmony_ci#define STA	0x08
7368c2ecf20Sopenharmony_ci#define DPR	0x01
7378c2ecf20Sopenharmony_ci
7388c2ecf20Sopenharmony_cistatic const char *split_status_source[] =
7398c2ecf20Sopenharmony_ci{
7408c2ecf20Sopenharmony_ci	"DFF0",
7418c2ecf20Sopenharmony_ci	"DFF1",
7428c2ecf20Sopenharmony_ci	"OVLY",
7438c2ecf20Sopenharmony_ci	"CMC",
7448c2ecf20Sopenharmony_ci};
7458c2ecf20Sopenharmony_ci
7468c2ecf20Sopenharmony_cistatic const char *pci_status_source[] =
7478c2ecf20Sopenharmony_ci{
7488c2ecf20Sopenharmony_ci	"DFF0",
7498c2ecf20Sopenharmony_ci	"DFF1",
7508c2ecf20Sopenharmony_ci	"SG",
7518c2ecf20Sopenharmony_ci	"CMC",
7528c2ecf20Sopenharmony_ci	"OVLY",
7538c2ecf20Sopenharmony_ci	"NONE",
7548c2ecf20Sopenharmony_ci	"MSI",
7558c2ecf20Sopenharmony_ci	"TARG"
7568c2ecf20Sopenharmony_ci};
7578c2ecf20Sopenharmony_ci
7588c2ecf20Sopenharmony_cistatic const char *split_status_strings[] =
7598c2ecf20Sopenharmony_ci{
7608c2ecf20Sopenharmony_ci	"%s: Received split response in %s.\n",
7618c2ecf20Sopenharmony_ci	"%s: Received split completion error message in %s\n",
7628c2ecf20Sopenharmony_ci	"%s: Receive overrun in %s\n",
7638c2ecf20Sopenharmony_ci	"%s: Count not complete in %s\n",
7648c2ecf20Sopenharmony_ci	"%s: Split completion data bucket in %s\n",
7658c2ecf20Sopenharmony_ci	"%s: Split completion address error in %s\n",
7668c2ecf20Sopenharmony_ci	"%s: Split completion byte count error in %s\n",
7678c2ecf20Sopenharmony_ci	"%s: Signaled Target-abort to early terminate a split in %s\n"
7688c2ecf20Sopenharmony_ci};
7698c2ecf20Sopenharmony_ci
7708c2ecf20Sopenharmony_cistatic const char *pci_status_strings[] =
7718c2ecf20Sopenharmony_ci{
7728c2ecf20Sopenharmony_ci	"%s: Data Parity Error has been reported via PERR# in %s\n",
7738c2ecf20Sopenharmony_ci	"%s: Target initial wait state error in %s\n",
7748c2ecf20Sopenharmony_ci	"%s: Split completion read data parity error in %s\n",
7758c2ecf20Sopenharmony_ci	"%s: Split completion address attribute parity error in %s\n",
7768c2ecf20Sopenharmony_ci	"%s: Received a Target Abort in %s\n",
7778c2ecf20Sopenharmony_ci	"%s: Received a Master Abort in %s\n",
7788c2ecf20Sopenharmony_ci	"%s: Signal System Error Detected in %s\n",
7798c2ecf20Sopenharmony_ci	"%s: Address or Write Phase Parity Error Detected in %s.\n"
7808c2ecf20Sopenharmony_ci};
7818c2ecf20Sopenharmony_ci
7828c2ecf20Sopenharmony_cistatic void
7838c2ecf20Sopenharmony_ciahd_pci_intr(struct ahd_softc *ahd)
7848c2ecf20Sopenharmony_ci{
7858c2ecf20Sopenharmony_ci	uint8_t		pci_status[8];
7868c2ecf20Sopenharmony_ci	ahd_mode_state	saved_modes;
7878c2ecf20Sopenharmony_ci	u_int		pci_status1;
7888c2ecf20Sopenharmony_ci	u_int		intstat;
7898c2ecf20Sopenharmony_ci	u_int		i;
7908c2ecf20Sopenharmony_ci	u_int		reg;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	intstat = ahd_inb(ahd, INTSTAT);
7938c2ecf20Sopenharmony_ci
7948c2ecf20Sopenharmony_ci	if ((intstat & SPLTINT) != 0)
7958c2ecf20Sopenharmony_ci		ahd_pci_split_intr(ahd, intstat);
7968c2ecf20Sopenharmony_ci
7978c2ecf20Sopenharmony_ci	if ((intstat & PCIINT) == 0)
7988c2ecf20Sopenharmony_ci		return;
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	printk("%s: PCI error Interrupt\n", ahd_name(ahd));
8018c2ecf20Sopenharmony_ci	saved_modes = ahd_save_modes(ahd);
8028c2ecf20Sopenharmony_ci	ahd_dump_card_state(ahd);
8038c2ecf20Sopenharmony_ci	ahd_set_modes(ahd, AHD_MODE_CFG, AHD_MODE_CFG);
8048c2ecf20Sopenharmony_ci	for (i = 0, reg = DF0PCISTAT; i < 8; i++, reg++) {
8058c2ecf20Sopenharmony_ci
8068c2ecf20Sopenharmony_ci		if (i == 5)
8078c2ecf20Sopenharmony_ci			continue;
8088c2ecf20Sopenharmony_ci		pci_status[i] = ahd_inb(ahd, reg);
8098c2ecf20Sopenharmony_ci		/* Clear latched errors.  So our interrupt deasserts. */
8108c2ecf20Sopenharmony_ci		ahd_outb(ahd, reg, pci_status[i]);
8118c2ecf20Sopenharmony_ci	}
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	for (i = 0; i < 8; i++) {
8148c2ecf20Sopenharmony_ci		u_int bit;
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci		if (i == 5)
8178c2ecf20Sopenharmony_ci			continue;
8188c2ecf20Sopenharmony_ci
8198c2ecf20Sopenharmony_ci		for (bit = 0; bit < 8; bit++) {
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci			if ((pci_status[i] & (0x1 << bit)) != 0) {
8228c2ecf20Sopenharmony_ci				const char *s;
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci				s = pci_status_strings[bit];
8258c2ecf20Sopenharmony_ci				if (i == 7/*TARG*/ && bit == 3)
8268c2ecf20Sopenharmony_ci					s = "%s: Signaled Target Abort\n";
8278c2ecf20Sopenharmony_ci				printk(s, ahd_name(ahd), pci_status_source[i]);
8288c2ecf20Sopenharmony_ci			}
8298c2ecf20Sopenharmony_ci		}
8308c2ecf20Sopenharmony_ci	}
8318c2ecf20Sopenharmony_ci	pci_status1 = ahd_pci_read_config(ahd->dev_softc,
8328c2ecf20Sopenharmony_ci					  PCIR_STATUS + 1, /*bytes*/1);
8338c2ecf20Sopenharmony_ci	ahd_pci_write_config(ahd->dev_softc, PCIR_STATUS + 1,
8348c2ecf20Sopenharmony_ci			     pci_status1, /*bytes*/1);
8358c2ecf20Sopenharmony_ci	ahd_restore_modes(ahd, saved_modes);
8368c2ecf20Sopenharmony_ci	ahd_outb(ahd, CLRINT, CLRPCIINT);
8378c2ecf20Sopenharmony_ci	ahd_unpause(ahd);
8388c2ecf20Sopenharmony_ci}
8398c2ecf20Sopenharmony_ci
8408c2ecf20Sopenharmony_cistatic void
8418c2ecf20Sopenharmony_ciahd_pci_split_intr(struct ahd_softc *ahd, u_int intstat)
8428c2ecf20Sopenharmony_ci{
8438c2ecf20Sopenharmony_ci	uint8_t		split_status[4];
8448c2ecf20Sopenharmony_ci	uint8_t		split_status1[4];
8458c2ecf20Sopenharmony_ci	uint8_t		sg_split_status[2];
8468c2ecf20Sopenharmony_ci	uint8_t		sg_split_status1[2];
8478c2ecf20Sopenharmony_ci	ahd_mode_state	saved_modes;
8488c2ecf20Sopenharmony_ci	u_int		i;
8498c2ecf20Sopenharmony_ci	uint16_t	pcix_status;
8508c2ecf20Sopenharmony_ci
8518c2ecf20Sopenharmony_ci	/*
8528c2ecf20Sopenharmony_ci	 * Check for splits in all modes.  Modes 0 and 1
8538c2ecf20Sopenharmony_ci	 * additionally have SG engine splits to look at.
8548c2ecf20Sopenharmony_ci	 */
8558c2ecf20Sopenharmony_ci	pcix_status = ahd_pci_read_config(ahd->dev_softc, PCIXR_STATUS,
8568c2ecf20Sopenharmony_ci					  /*bytes*/2);
8578c2ecf20Sopenharmony_ci	printk("%s: PCI Split Interrupt - PCI-X status = 0x%x\n",
8588c2ecf20Sopenharmony_ci	       ahd_name(ahd), pcix_status);
8598c2ecf20Sopenharmony_ci	saved_modes = ahd_save_modes(ahd);
8608c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
8618c2ecf20Sopenharmony_ci		ahd_set_modes(ahd, i, i);
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci		split_status[i] = ahd_inb(ahd, DCHSPLTSTAT0);
8648c2ecf20Sopenharmony_ci		split_status1[i] = ahd_inb(ahd, DCHSPLTSTAT1);
8658c2ecf20Sopenharmony_ci		/* Clear latched errors.  So our interrupt deasserts. */
8668c2ecf20Sopenharmony_ci		ahd_outb(ahd, DCHSPLTSTAT0, split_status[i]);
8678c2ecf20Sopenharmony_ci		ahd_outb(ahd, DCHSPLTSTAT1, split_status1[i]);
8688c2ecf20Sopenharmony_ci		if (i > 1)
8698c2ecf20Sopenharmony_ci			continue;
8708c2ecf20Sopenharmony_ci		sg_split_status[i] = ahd_inb(ahd, SGSPLTSTAT0);
8718c2ecf20Sopenharmony_ci		sg_split_status1[i] = ahd_inb(ahd, SGSPLTSTAT1);
8728c2ecf20Sopenharmony_ci		/* Clear latched errors.  So our interrupt deasserts. */
8738c2ecf20Sopenharmony_ci		ahd_outb(ahd, SGSPLTSTAT0, sg_split_status[i]);
8748c2ecf20Sopenharmony_ci		ahd_outb(ahd, SGSPLTSTAT1, sg_split_status1[i]);
8758c2ecf20Sopenharmony_ci	}
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	for (i = 0; i < 4; i++) {
8788c2ecf20Sopenharmony_ci		u_int bit;
8798c2ecf20Sopenharmony_ci
8808c2ecf20Sopenharmony_ci		for (bit = 0; bit < 8; bit++) {
8818c2ecf20Sopenharmony_ci
8828c2ecf20Sopenharmony_ci			if ((split_status[i] & (0x1 << bit)) != 0)
8838c2ecf20Sopenharmony_ci				printk(split_status_strings[bit], ahd_name(ahd),
8848c2ecf20Sopenharmony_ci				       split_status_source[i]);
8858c2ecf20Sopenharmony_ci
8868c2ecf20Sopenharmony_ci			if (i > 1)
8878c2ecf20Sopenharmony_ci				continue;
8888c2ecf20Sopenharmony_ci
8898c2ecf20Sopenharmony_ci			if ((sg_split_status[i] & (0x1 << bit)) != 0)
8908c2ecf20Sopenharmony_ci				printk(split_status_strings[bit], ahd_name(ahd), "SG");
8918c2ecf20Sopenharmony_ci		}
8928c2ecf20Sopenharmony_ci	}
8938c2ecf20Sopenharmony_ci	/*
8948c2ecf20Sopenharmony_ci	 * Clear PCI-X status bits.
8958c2ecf20Sopenharmony_ci	 */
8968c2ecf20Sopenharmony_ci	ahd_pci_write_config(ahd->dev_softc, PCIXR_STATUS,
8978c2ecf20Sopenharmony_ci			     pcix_status, /*bytes*/2);
8988c2ecf20Sopenharmony_ci	ahd_outb(ahd, CLRINT, CLRSPLTINT);
8998c2ecf20Sopenharmony_ci	ahd_restore_modes(ahd, saved_modes);
9008c2ecf20Sopenharmony_ci}
9018c2ecf20Sopenharmony_ci
9028c2ecf20Sopenharmony_cistatic int
9038c2ecf20Sopenharmony_ciahd_aic7901_setup(struct ahd_softc *ahd)
9048c2ecf20Sopenharmony_ci{
9058c2ecf20Sopenharmony_ci
9068c2ecf20Sopenharmony_ci	ahd->chip = AHD_AIC7901;
9078c2ecf20Sopenharmony_ci	ahd->features = AHD_AIC7901_FE;
9088c2ecf20Sopenharmony_ci	return (ahd_aic790X_setup(ahd));
9098c2ecf20Sopenharmony_ci}
9108c2ecf20Sopenharmony_ci
9118c2ecf20Sopenharmony_cistatic int
9128c2ecf20Sopenharmony_ciahd_aic7901A_setup(struct ahd_softc *ahd)
9138c2ecf20Sopenharmony_ci{
9148c2ecf20Sopenharmony_ci
9158c2ecf20Sopenharmony_ci	ahd->chip = AHD_AIC7901A;
9168c2ecf20Sopenharmony_ci	ahd->features = AHD_AIC7901A_FE;
9178c2ecf20Sopenharmony_ci	return (ahd_aic790X_setup(ahd));
9188c2ecf20Sopenharmony_ci}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_cistatic int
9218c2ecf20Sopenharmony_ciahd_aic7902_setup(struct ahd_softc *ahd)
9228c2ecf20Sopenharmony_ci{
9238c2ecf20Sopenharmony_ci	ahd->chip = AHD_AIC7902;
9248c2ecf20Sopenharmony_ci	ahd->features = AHD_AIC7902_FE;
9258c2ecf20Sopenharmony_ci	return (ahd_aic790X_setup(ahd));
9268c2ecf20Sopenharmony_ci}
9278c2ecf20Sopenharmony_ci
9288c2ecf20Sopenharmony_cistatic int
9298c2ecf20Sopenharmony_ciahd_aic790X_setup(struct ahd_softc *ahd)
9308c2ecf20Sopenharmony_ci{
9318c2ecf20Sopenharmony_ci	ahd_dev_softc_t pci;
9328c2ecf20Sopenharmony_ci	u_int rev;
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci	pci = ahd->dev_softc;
9358c2ecf20Sopenharmony_ci	rev = ahd_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
9368c2ecf20Sopenharmony_ci	if (rev < ID_AIC7902_PCI_REV_A4) {
9378c2ecf20Sopenharmony_ci		printk("%s: Unable to attach to unsupported chip revision %d\n",
9388c2ecf20Sopenharmony_ci		       ahd_name(ahd), rev);
9398c2ecf20Sopenharmony_ci		ahd_pci_write_config(pci, PCIR_COMMAND, 0, /*bytes*/2);
9408c2ecf20Sopenharmony_ci		return (ENXIO);
9418c2ecf20Sopenharmony_ci	}
9428c2ecf20Sopenharmony_ci	ahd->channel = ahd_get_pci_function(pci) + 'A';
9438c2ecf20Sopenharmony_ci	if (rev < ID_AIC7902_PCI_REV_B0) {
9448c2ecf20Sopenharmony_ci		/*
9458c2ecf20Sopenharmony_ci		 * Enable A series workarounds.
9468c2ecf20Sopenharmony_ci		 */
9478c2ecf20Sopenharmony_ci		ahd->bugs |= AHD_SENT_SCB_UPDATE_BUG|AHD_ABORT_LQI_BUG
9488c2ecf20Sopenharmony_ci			  |  AHD_PKT_BITBUCKET_BUG|AHD_LONG_SETIMO_BUG
9498c2ecf20Sopenharmony_ci			  |  AHD_NLQICRC_DELAYED_BUG|AHD_SCSIRST_BUG
9508c2ecf20Sopenharmony_ci			  |  AHD_LQO_ATNO_BUG|AHD_AUTOFLUSH_BUG
9518c2ecf20Sopenharmony_ci			  |  AHD_CLRLQO_AUTOCLR_BUG|AHD_PCIX_MMAPIO_BUG
9528c2ecf20Sopenharmony_ci			  |  AHD_PCIX_CHIPRST_BUG|AHD_PCIX_SCBRAM_RD_BUG
9538c2ecf20Sopenharmony_ci			  |  AHD_PKTIZED_STATUS_BUG|AHD_PKT_LUN_BUG
9548c2ecf20Sopenharmony_ci			  |  AHD_MDFF_WSCBPTR_BUG|AHD_REG_SLOW_SETTLE_BUG
9558c2ecf20Sopenharmony_ci			  |  AHD_SET_MODE_BUG|AHD_BUSFREEREV_BUG
9568c2ecf20Sopenharmony_ci			  |  AHD_NONPACKFIFO_BUG|AHD_PACED_NEGTABLE_BUG
9578c2ecf20Sopenharmony_ci			  |  AHD_FAINT_LED_BUG;
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci		/*
9608c2ecf20Sopenharmony_ci		 * IO Cell parameter setup.
9618c2ecf20Sopenharmony_ci		 */
9628c2ecf20Sopenharmony_ci		AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
9638c2ecf20Sopenharmony_ci
9648c2ecf20Sopenharmony_ci		if ((ahd->flags & AHD_HP_BOARD) == 0)
9658c2ecf20Sopenharmony_ci			AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVA);
9668c2ecf20Sopenharmony_ci	} else {
9678c2ecf20Sopenharmony_ci		/* This is revision B and newer. */
9688c2ecf20Sopenharmony_ci		extern uint32_t aic79xx_slowcrc;
9698c2ecf20Sopenharmony_ci		u_int devconfig1;
9708c2ecf20Sopenharmony_ci
9718c2ecf20Sopenharmony_ci		ahd->features |= AHD_RTI|AHD_NEW_IOCELL_OPTS
9728c2ecf20Sopenharmony_ci			      |  AHD_NEW_DFCNTRL_OPTS|AHD_FAST_CDB_DELIVERY
9738c2ecf20Sopenharmony_ci			      |  AHD_BUSFREEREV_BUG;
9748c2ecf20Sopenharmony_ci		ahd->bugs |= AHD_LQOOVERRUN_BUG|AHD_EARLY_REQ_BUG;
9758c2ecf20Sopenharmony_ci
9768c2ecf20Sopenharmony_ci		/* If the user requested that the SLOWCRC bit to be set. */
9778c2ecf20Sopenharmony_ci		if (aic79xx_slowcrc)
9788c2ecf20Sopenharmony_ci			ahd->features |= AHD_AIC79XXB_SLOWCRC;
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci		/*
9818c2ecf20Sopenharmony_ci		 * Some issues have been resolved in the 7901B.
9828c2ecf20Sopenharmony_ci		 */
9838c2ecf20Sopenharmony_ci		if ((ahd->features & AHD_MULTI_FUNC) != 0)
9848c2ecf20Sopenharmony_ci			ahd->bugs |= AHD_INTCOLLISION_BUG|AHD_ABORT_LQI_BUG;
9858c2ecf20Sopenharmony_ci
9868c2ecf20Sopenharmony_ci		/*
9878c2ecf20Sopenharmony_ci		 * IO Cell parameter setup.
9888c2ecf20Sopenharmony_ci		 */
9898c2ecf20Sopenharmony_ci		AHD_SET_PRECOMP(ahd, AHD_PRECOMP_CUTBACK_29);
9908c2ecf20Sopenharmony_ci		AHD_SET_SLEWRATE(ahd, AHD_SLEWRATE_DEF_REVB);
9918c2ecf20Sopenharmony_ci		AHD_SET_AMPLITUDE(ahd, AHD_AMPLITUDE_DEF);
9928c2ecf20Sopenharmony_ci
9938c2ecf20Sopenharmony_ci		/*
9948c2ecf20Sopenharmony_ci		 * Set the PREQDIS bit for H2B which disables some workaround
9958c2ecf20Sopenharmony_ci		 * that doesn't work on regular PCI busses.
9968c2ecf20Sopenharmony_ci		 * XXX - Find out exactly what this does from the hardware
9978c2ecf20Sopenharmony_ci		 * 	 folks!
9988c2ecf20Sopenharmony_ci		 */
9998c2ecf20Sopenharmony_ci		devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
10008c2ecf20Sopenharmony_ci		ahd_pci_write_config(pci, DEVCONFIG1,
10018c2ecf20Sopenharmony_ci				     devconfig1|PREQDIS, /*bytes*/1);
10028c2ecf20Sopenharmony_ci		devconfig1 = ahd_pci_read_config(pci, DEVCONFIG1, /*bytes*/1);
10038c2ecf20Sopenharmony_ci	}
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	return (0);
10068c2ecf20Sopenharmony_ci}
1007