1139749Simp/*-
265942Sgibbs * Product specific probe and attach routines for:
365942Sgibbs *      3940, 2940, aic7895, aic7890, aic7880,
465942Sgibbs *	aic7870, aic7860 and aic7850 SCSI controllers
565942Sgibbs *
695378Sgibbs * Copyright (c) 1994-2001 Justin T. Gibbs.
795378Sgibbs * Copyright (c) 2000-2001 Adaptec Inc.
865942Sgibbs * All rights reserved.
965942Sgibbs *
1065942Sgibbs * Redistribution and use in source and binary forms, with or without
1165942Sgibbs * modification, are permitted provided that the following conditions
1265942Sgibbs * are met:
1365942Sgibbs * 1. Redistributions of source code must retain the above copyright
1465942Sgibbs *    notice, this list of conditions, and the following disclaimer,
1595378Sgibbs *    without modification.
1695378Sgibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1795378Sgibbs *    substantially similar to the "NO WARRANTY" disclaimer below
1895378Sgibbs *    ("Disclaimer") and any redistribution must be conditioned upon
1995378Sgibbs *    including a substantially similar Disclaimer requirement for further
2095378Sgibbs *    binary redistribution.
2195378Sgibbs * 3. Neither the names of the above-listed copyright holders nor the names
2295378Sgibbs *    of any contributors may be used to endorse or promote products derived
2395378Sgibbs *    from this software without specific prior written permission.
2465942Sgibbs *
2565942Sgibbs * Alternatively, this software may be distributed under the terms of the
2695378Sgibbs * GNU General Public License ("GPL") version 2 as published by the Free
2795378Sgibbs * Software Foundation.
2865942Sgibbs *
2995378Sgibbs * NO WARRANTY
3095378Sgibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3195378Sgibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3295378Sgibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3395378Sgibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3495378Sgibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3565942Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3665942Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3795378Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3895378Sgibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3995378Sgibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4095378Sgibbs * POSSIBILITY OF SUCH DAMAGES.
4165942Sgibbs *
42123579Sgibbs * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#78 $
4365942Sgibbs */
4465942Sgibbs
4595378Sgibbs#ifdef __linux__
4695378Sgibbs#include "aic7xxx_osm.h"
4795378Sgibbs#include "aic7xxx_inline.h"
4895378Sgibbs#include "aic7xxx_93cx6.h"
4995378Sgibbs#else
50123579Sgibbs#include <sys/cdefs.h>
51123579Sgibbs__FBSDID("$FreeBSD$");
5295378Sgibbs#include <dev/aic7xxx/aic7xxx_osm.h>
5365942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h>
5465942Sgibbs#include <dev/aic7xxx/aic7xxx_93cx6.h>
5595378Sgibbs#endif
5665942Sgibbs
5765942Sgibbsstatic __inline uint64_t
5865942Sgibbsahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
5965942Sgibbs{
6065942Sgibbs	uint64_t id;
6165942Sgibbs
6265942Sgibbs	id = subvendor
6365942Sgibbs	   | (subdevice << 16)
6465942Sgibbs	   | ((uint64_t)vendor << 32)
6565942Sgibbs	   | ((uint64_t)device << 48);
6665942Sgibbs
6765942Sgibbs	return (id);
6865942Sgibbs}
6965942Sgibbs
7074094Sgibbs#define ID_ALL_MASK			0xFFFFFFFFFFFFFFFFull
7174094Sgibbs#define ID_DEV_VENDOR_MASK		0xFFFFFFFF00000000ull
7274094Sgibbs#define ID_9005_GENERIC_MASK		0xFFF0FFFF00000000ull
7374094Sgibbs#define ID_9005_SISL_MASK		0x000FFFFF00000000ull
7474094Sgibbs#define ID_9005_SISL_ID			0x0005900500000000ull
7574094Sgibbs#define ID_AIC7850			0x5078900400000000ull
76115338Sgibbs#define ID_AHA_2902_04_10_15_20C_30C	0x5078900478509004ull
7774094Sgibbs#define ID_AIC7855			0x5578900400000000ull
7874094Sgibbs#define ID_AIC7859			0x3860900400000000ull
7974094Sgibbs#define ID_AHA_2930CU			0x3860900438699004ull
8074094Sgibbs#define ID_AIC7860			0x6078900400000000ull
8174094Sgibbs#define ID_AIC7860C			0x6078900478609004ull
8274094Sgibbs#define ID_AHA_1480A			0x6075900400000000ull
8374094Sgibbs#define ID_AHA_2940AU_0			0x6178900400000000ull
8474094Sgibbs#define ID_AHA_2940AU_1			0x6178900478619004ull
8574094Sgibbs#define ID_AHA_2940AU_CN		0x2178900478219004ull
8674094Sgibbs#define ID_AHA_2930C_VAR		0x6038900438689004ull
8765942Sgibbs
8874094Sgibbs#define ID_AIC7870			0x7078900400000000ull
8974094Sgibbs#define ID_AHA_2940			0x7178900400000000ull
9074094Sgibbs#define ID_AHA_3940			0x7278900400000000ull
9174094Sgibbs#define ID_AHA_398X			0x7378900400000000ull
9274094Sgibbs#define ID_AHA_2944			0x7478900400000000ull
9374094Sgibbs#define ID_AHA_3944			0x7578900400000000ull
9474094Sgibbs#define ID_AHA_4944			0x7678900400000000ull
9565942Sgibbs
9674094Sgibbs#define ID_AIC7880			0x8078900400000000ull
9774094Sgibbs#define ID_AIC7880_B			0x8078900478809004ull
9874094Sgibbs#define ID_AHA_2940U			0x8178900400000000ull
9974094Sgibbs#define ID_AHA_3940U			0x8278900400000000ull
10074094Sgibbs#define ID_AHA_2944U			0x8478900400000000ull
10174094Sgibbs#define ID_AHA_3944U			0x8578900400000000ull
10274094Sgibbs#define ID_AHA_398XU			0x8378900400000000ull
10374094Sgibbs#define ID_AHA_4944U			0x8678900400000000ull
10474094Sgibbs#define ID_AHA_2940UB			0x8178900478819004ull
10574094Sgibbs#define ID_AHA_2930U			0x8878900478889004ull
10674094Sgibbs#define ID_AHA_2940U_PRO		0x8778900478879004ull
10774094Sgibbs#define ID_AHA_2940U_CN			0x0078900478009004ull
10865942Sgibbs
10974094Sgibbs#define ID_AIC7895			0x7895900478959004ull
11074094Sgibbs#define ID_AIC7895_ARO			0x7890900478939004ull
11174094Sgibbs#define ID_AIC7895_ARO_MASK		0xFFF0FFFFFFFFFFFFull
11274094Sgibbs#define ID_AHA_2940U_DUAL		0x7895900478919004ull
11374094Sgibbs#define ID_AHA_3940AU			0x7895900478929004ull
11474094Sgibbs#define ID_AHA_3944AU			0x7895900478949004ull
11565942Sgibbs
11674094Sgibbs#define ID_AIC7890			0x001F9005000F9005ull
11774094Sgibbs#define ID_AIC7890_ARO			0x00139005000F9005ull
11874094Sgibbs#define ID_AAA_131U2			0x0013900500039005ull
11974094Sgibbs#define ID_AHA_2930U2			0x0011900501819005ull
12074094Sgibbs#define ID_AHA_2940U2B			0x00109005A1009005ull
12174094Sgibbs#define ID_AHA_2940U2_OEM		0x0010900521809005ull
12274094Sgibbs#define ID_AHA_2940U2			0x00109005A1809005ull
12374094Sgibbs#define ID_AHA_2950U2B			0x00109005E1009005ull
12465942Sgibbs
12574094Sgibbs#define ID_AIC7892			0x008F9005FFFF9005ull
12674094Sgibbs#define ID_AIC7892_ARO			0x00839005FFFF9005ull
12774094Sgibbs#define ID_AHA_29160			0x00809005E2A09005ull
12874094Sgibbs#define ID_AHA_29160_CPQ		0x00809005E2A00E11ull
12974094Sgibbs#define ID_AHA_29160N			0x0080900562A09005ull
13074094Sgibbs#define ID_AHA_29160C			0x0080900562209005ull
13174094Sgibbs#define ID_AHA_29160B			0x00809005E2209005ull
13274094Sgibbs#define ID_AHA_19160B			0x0081900562A19005ull
133123579Sgibbs#define ID_AHA_2915_30LP		0x0082900502109005ull
13465942Sgibbs
13574094Sgibbs#define ID_AIC7896			0x005F9005FFFF9005ull
13674094Sgibbs#define ID_AIC7896_ARO			0x00539005FFFF9005ull
13774094Sgibbs#define ID_AHA_3950U2B_0		0x00509005FFFF9005ull
13874094Sgibbs#define ID_AHA_3950U2B_1		0x00509005F5009005ull
13974094Sgibbs#define ID_AHA_3950U2D_0		0x00519005FFFF9005ull
14074094Sgibbs#define ID_AHA_3950U2D_1		0x00519005B5009005ull
14165942Sgibbs
14274094Sgibbs#define ID_AIC7899			0x00CF9005FFFF9005ull
14374094Sgibbs#define ID_AIC7899_ARO			0x00C39005FFFF9005ull
14474094Sgibbs#define ID_AHA_3960D			0x00C09005F6209005ull
14574094Sgibbs#define ID_AHA_3960D_CPQ		0x00C09005F6200E11ull
14665942Sgibbs
14774094Sgibbs#define ID_AIC7810			0x1078900400000000ull
14874094Sgibbs#define ID_AIC7815			0x7815900400000000ull
14965942Sgibbs
15072325Sgibbs#define DEVID_9005_TYPE(id) ((id) & 0xF)
15172325Sgibbs#define		DEVID_9005_TYPE_HBA		0x0	/* Standard Card */
15272325Sgibbs#define		DEVID_9005_TYPE_AAA		0x3	/* RAID Card */
15395378Sgibbs#define		DEVID_9005_TYPE_SISL		0x5	/* Container ROMB */
15472325Sgibbs#define		DEVID_9005_TYPE_MB		0xF	/* On Motherboard */
15572325Sgibbs
15672325Sgibbs#define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
15772325Sgibbs#define		DEVID_9005_MAXRATE_U160		0x0
15872325Sgibbs#define		DEVID_9005_MAXRATE_ULTRA2	0x1
15972325Sgibbs#define		DEVID_9005_MAXRATE_ULTRA	0x2
16072325Sgibbs#define		DEVID_9005_MAXRATE_FAST		0x3
16172325Sgibbs
16272325Sgibbs#define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6)
16372325Sgibbs
16472325Sgibbs#define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8)
16572325Sgibbs#define		DEVID_9005_CLASS_SPI		0x0	/* Parallel SCSI */
16672325Sgibbs
16770693Sgibbs#define SUBID_9005_TYPE(id) ((id) & 0xF)
16870693Sgibbs#define		SUBID_9005_TYPE_MB		0xF	/* On Motherboard */
16970693Sgibbs#define		SUBID_9005_TYPE_CARD		0x0	/* Standard Card */
17070693Sgibbs#define		SUBID_9005_TYPE_LCCARD		0x1	/* Low Cost Card */
17170693Sgibbs#define		SUBID_9005_TYPE_RAID		0x3	/* Combined with Raid */
17270204Sgibbs
17372811Sgibbs#define SUBID_9005_TYPE_KNOWN(id)			\
17472811Sgibbs	  ((((id) & 0xF) == SUBID_9005_TYPE_MB)		\
17572811Sgibbs	|| (((id) & 0xF) == SUBID_9005_TYPE_CARD)	\
17672811Sgibbs	|| (((id) & 0xF) == SUBID_9005_TYPE_LCCARD)	\
17772811Sgibbs	|| (((id) & 0xF) == SUBID_9005_TYPE_RAID))
17872811Sgibbs
17970693Sgibbs#define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
18070693Sgibbs#define		SUBID_9005_MAXRATE_ULTRA2	0x0
18170693Sgibbs#define		SUBID_9005_MAXRATE_ULTRA	0x1
18270693Sgibbs#define		SUBID_9005_MAXRATE_U160		0x2
18370693Sgibbs#define		SUBID_9005_MAXRATE_RESERVED	0x3
18470693Sgibbs
18570693Sgibbs#define SUBID_9005_SEEPTYPE(id)						\
18670693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
18770693Sgibbs	 ? ((id) & 0xC0) >> 6						\
18870693Sgibbs	 : ((id) & 0x300) >> 8)
18970693Sgibbs#define		SUBID_9005_SEEPTYPE_NONE	0x0
19070693Sgibbs#define		SUBID_9005_SEEPTYPE_1K		0x1
19170693Sgibbs#define		SUBID_9005_SEEPTYPE_2K_4K	0x2
19270693Sgibbs#define		SUBID_9005_SEEPTYPE_RESERVED	0x3
19370693Sgibbs#define SUBID_9005_AUTOTERM(id)						\
19470693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
19570693Sgibbs	 ? (((id) & 0x400) >> 10) == 0					\
19670693Sgibbs	 : (((id) & 0x40) >> 6) == 0)
19770693Sgibbs
19870693Sgibbs#define SUBID_9005_NUMCHAN(id)						\
19970693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
20070693Sgibbs	 ? ((id) & 0x300) >> 8						\
20170693Sgibbs	 : ((id) & 0xC00) >> 10)
20270693Sgibbs
20370693Sgibbs#define SUBID_9005_LEGACYCONN(id)					\
20470693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
20570693Sgibbs	 ? 0								\
20670693Sgibbs	 : ((id) & 0x80) >> 7)
20770693Sgibbs
20870693Sgibbs#define SUBID_9005_MFUNCENB(id)						\
20970693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
21070693Sgibbs	 ? ((id) & 0x800) >> 11						\
21170693Sgibbs	 : ((id) & 0x1000) >> 12)
21270693Sgibbs/*
21370693Sgibbs * Informational only. Should use chip register to be
21495378Sgibbs * certain, but may be use in identification strings.
21570693Sgibbs */
21670693Sgibbs#define SUBID_9005_CARD_SCSIWIDTH_MASK	0x2000
21770693Sgibbs#define SUBID_9005_CARD_PCIWIDTH_MASK	0x4000
21870693Sgibbs#define SUBID_9005_CARD_SEDIFF_MASK	0x8000
21970693Sgibbs
22074094Sgibbsstatic ahc_device_setup_t ahc_aic785X_setup;
22165942Sgibbsstatic ahc_device_setup_t ahc_aic7860_setup;
22271390Sgibbsstatic ahc_device_setup_t ahc_apa1480_setup;
22365942Sgibbsstatic ahc_device_setup_t ahc_aic7870_setup;
22465942Sgibbsstatic ahc_device_setup_t ahc_aha394X_setup;
22565942Sgibbsstatic ahc_device_setup_t ahc_aha494X_setup;
22665942Sgibbsstatic ahc_device_setup_t ahc_aha398X_setup;
22765942Sgibbsstatic ahc_device_setup_t ahc_aic7880_setup;
22871390Sgibbsstatic ahc_device_setup_t ahc_aha2940Pro_setup;
22965942Sgibbsstatic ahc_device_setup_t ahc_aha394XU_setup;
23065942Sgibbsstatic ahc_device_setup_t ahc_aha398XU_setup;
23165942Sgibbsstatic ahc_device_setup_t ahc_aic7890_setup;
23265942Sgibbsstatic ahc_device_setup_t ahc_aic7892_setup;
23365942Sgibbsstatic ahc_device_setup_t ahc_aic7895_setup;
23465942Sgibbsstatic ahc_device_setup_t ahc_aic7896_setup;
23565942Sgibbsstatic ahc_device_setup_t ahc_aic7899_setup;
23671390Sgibbsstatic ahc_device_setup_t ahc_aha29160C_setup;
23765942Sgibbsstatic ahc_device_setup_t ahc_raid_setup;
23865942Sgibbsstatic ahc_device_setup_t ahc_aha394XX_setup;
23965942Sgibbsstatic ahc_device_setup_t ahc_aha494XX_setup;
24065942Sgibbsstatic ahc_device_setup_t ahc_aha398XX_setup;
24165942Sgibbs
24265942Sgibbsstruct ahc_pci_identity ahc_pci_ident_table [] =
24365942Sgibbs{
24465942Sgibbs	/* aic7850 based controllers */
24565942Sgibbs	{
246115338Sgibbs		ID_AHA_2902_04_10_15_20C_30C,
24765942Sgibbs		ID_ALL_MASK,
248115338Sgibbs		"Adaptec 2902/04/10/15/20C/30C SCSI adapter",
24974094Sgibbs		ahc_aic785X_setup
25065942Sgibbs	},
25165942Sgibbs	/* aic7860 based controllers */
25265942Sgibbs	{
25365942Sgibbs		ID_AHA_2930CU,
25465942Sgibbs		ID_ALL_MASK,
25565942Sgibbs		"Adaptec 2930CU SCSI adapter",
25665942Sgibbs		ahc_aic7860_setup
25765942Sgibbs	},
25865942Sgibbs	{
25965942Sgibbs		ID_AHA_1480A & ID_DEV_VENDOR_MASK,
26065942Sgibbs		ID_DEV_VENDOR_MASK,
26165942Sgibbs		"Adaptec 1480A Ultra SCSI adapter",
26271390Sgibbs		ahc_apa1480_setup
26365942Sgibbs	},
26465942Sgibbs	{
26565942Sgibbs		ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK,
26665942Sgibbs		ID_DEV_VENDOR_MASK,
26765942Sgibbs		"Adaptec 2940A Ultra SCSI adapter",
26865942Sgibbs		ahc_aic7860_setup
26965942Sgibbs	},
27065942Sgibbs	{
27165942Sgibbs		ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK,
27265942Sgibbs		ID_DEV_VENDOR_MASK,
27365942Sgibbs		"Adaptec 2940A/CN Ultra SCSI adapter",
27465942Sgibbs		ahc_aic7860_setup
27565942Sgibbs	},
27665942Sgibbs	{
27765942Sgibbs		ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK,
27865942Sgibbs		ID_DEV_VENDOR_MASK,
27976634Sgibbs		"Adaptec 2930C Ultra SCSI adapter (VAR)",
28065942Sgibbs		ahc_aic7860_setup
28165942Sgibbs	},
28265942Sgibbs	/* aic7870 based controllers */
28365942Sgibbs	{
28465942Sgibbs		ID_AHA_2940,
28565942Sgibbs		ID_ALL_MASK,
28665942Sgibbs		"Adaptec 2940 SCSI adapter",
28765942Sgibbs		ahc_aic7870_setup
28865942Sgibbs	},
28965942Sgibbs	{
29065942Sgibbs		ID_AHA_3940,
29165942Sgibbs		ID_ALL_MASK,
29265942Sgibbs		"Adaptec 3940 SCSI adapter",
29365942Sgibbs		ahc_aha394X_setup
29465942Sgibbs	},
29565942Sgibbs	{
29665942Sgibbs		ID_AHA_398X,
29765942Sgibbs		ID_ALL_MASK,
29865942Sgibbs		"Adaptec 398X SCSI RAID adapter",
29965942Sgibbs		ahc_aha398X_setup
30065942Sgibbs	},
30165942Sgibbs	{
30265942Sgibbs		ID_AHA_2944,
30365942Sgibbs		ID_ALL_MASK,
30465942Sgibbs		"Adaptec 2944 SCSI adapter",
30565942Sgibbs		ahc_aic7870_setup
30665942Sgibbs	},
30765942Sgibbs	{
30865942Sgibbs		ID_AHA_3944,
30965942Sgibbs		ID_ALL_MASK,
31065942Sgibbs		"Adaptec 3944 SCSI adapter",
31165942Sgibbs		ahc_aha394X_setup
31265942Sgibbs	},
31365942Sgibbs	{
31465942Sgibbs		ID_AHA_4944,
31565942Sgibbs		ID_ALL_MASK,
31665942Sgibbs		"Adaptec 4944 SCSI adapter",
31765942Sgibbs		ahc_aha494X_setup
31865942Sgibbs	},
31965942Sgibbs	/* aic7880 based controllers */
32065942Sgibbs	{
32165942Sgibbs		ID_AHA_2940U & ID_DEV_VENDOR_MASK,
32265942Sgibbs		ID_DEV_VENDOR_MASK,
32365942Sgibbs		"Adaptec 2940 Ultra SCSI adapter",
32465942Sgibbs		ahc_aic7880_setup
32565942Sgibbs	},
32665942Sgibbs	{
32765942Sgibbs		ID_AHA_3940U & ID_DEV_VENDOR_MASK,
32865942Sgibbs		ID_DEV_VENDOR_MASK,
32965942Sgibbs		"Adaptec 3940 Ultra SCSI adapter",
33065942Sgibbs		ahc_aha394XU_setup
33165942Sgibbs	},
33265942Sgibbs	{
33365942Sgibbs		ID_AHA_2944U & ID_DEV_VENDOR_MASK,
33465942Sgibbs		ID_DEV_VENDOR_MASK,
33565942Sgibbs		"Adaptec 2944 Ultra SCSI adapter",
33665942Sgibbs		ahc_aic7880_setup
33765942Sgibbs	},
33865942Sgibbs	{
33965942Sgibbs		ID_AHA_3944U & ID_DEV_VENDOR_MASK,
34065942Sgibbs		ID_DEV_VENDOR_MASK,
34165942Sgibbs		"Adaptec 3944 Ultra SCSI adapter",
34265942Sgibbs		ahc_aha394XU_setup
34365942Sgibbs	},
34465942Sgibbs	{
34565942Sgibbs		ID_AHA_398XU & ID_DEV_VENDOR_MASK,
34665942Sgibbs		ID_DEV_VENDOR_MASK,
34765942Sgibbs		"Adaptec 398X Ultra SCSI RAID adapter",
34865942Sgibbs		ahc_aha398XU_setup
34965942Sgibbs	},
35065942Sgibbs	{
35165942Sgibbs		/*
35265942Sgibbs		 * XXX Don't know the slot numbers
35365942Sgibbs		 * so we can't identify channels
35465942Sgibbs		 */
35565942Sgibbs		ID_AHA_4944U & ID_DEV_VENDOR_MASK,
35665942Sgibbs		ID_DEV_VENDOR_MASK,
35765942Sgibbs		"Adaptec 4944 Ultra SCSI adapter",
35865942Sgibbs		ahc_aic7880_setup
35965942Sgibbs	},
36065942Sgibbs	{
36165942Sgibbs		ID_AHA_2930U & ID_DEV_VENDOR_MASK,
36265942Sgibbs		ID_DEV_VENDOR_MASK,
36365942Sgibbs		"Adaptec 2930 Ultra SCSI adapter",
36465942Sgibbs		ahc_aic7880_setup
36565942Sgibbs	},
36665942Sgibbs	{
36765942Sgibbs		ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK,
36865942Sgibbs		ID_DEV_VENDOR_MASK,
36965942Sgibbs		"Adaptec 2940 Pro Ultra SCSI adapter",
37071390Sgibbs		ahc_aha2940Pro_setup
37165942Sgibbs	},
37265942Sgibbs	{
37365942Sgibbs		ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK,
37465942Sgibbs		ID_DEV_VENDOR_MASK,
37565942Sgibbs		"Adaptec 2940/CN Ultra SCSI adapter",
37665942Sgibbs		ahc_aic7880_setup
37765942Sgibbs	},
37872811Sgibbs	/* Ignore all SISL (AAC on MB) based controllers. */
37972811Sgibbs	{
38072811Sgibbs		ID_9005_SISL_ID,
38172811Sgibbs		ID_9005_SISL_MASK,
38272811Sgibbs		NULL,
38372811Sgibbs		NULL
38472811Sgibbs	},
38565942Sgibbs	/* aic7890 based controllers */
38665942Sgibbs	{
38765942Sgibbs		ID_AHA_2930U2,
38865942Sgibbs		ID_ALL_MASK,
38965942Sgibbs		"Adaptec 2930 Ultra2 SCSI adapter",
39065942Sgibbs		ahc_aic7890_setup
39165942Sgibbs	},
39265942Sgibbs	{
39365942Sgibbs		ID_AHA_2940U2B,
39465942Sgibbs		ID_ALL_MASK,
39565942Sgibbs		"Adaptec 2940B Ultra2 SCSI adapter",
39665942Sgibbs		ahc_aic7890_setup
39765942Sgibbs	},
39865942Sgibbs	{
39965942Sgibbs		ID_AHA_2940U2_OEM,
40065942Sgibbs		ID_ALL_MASK,
40165942Sgibbs		"Adaptec 2940 Ultra2 SCSI adapter (OEM)",
40265942Sgibbs		ahc_aic7890_setup
40365942Sgibbs	},
40465942Sgibbs	{
40565942Sgibbs		ID_AHA_2940U2,
40665942Sgibbs		ID_ALL_MASK,
40765942Sgibbs		"Adaptec 2940 Ultra2 SCSI adapter",
40865942Sgibbs		ahc_aic7890_setup
40965942Sgibbs	},
41065942Sgibbs	{
41165942Sgibbs		ID_AHA_2950U2B,
41265942Sgibbs		ID_ALL_MASK,
41365942Sgibbs		"Adaptec 2950 Ultra2 SCSI adapter",
41465942Sgibbs		ahc_aic7890_setup
41565942Sgibbs	},
41665942Sgibbs	{
41772811Sgibbs		ID_AIC7890_ARO,
41872811Sgibbs		ID_ALL_MASK,
41972811Sgibbs		"Adaptec aic7890/91 Ultra2 SCSI adapter (ARO)",
42072811Sgibbs		ahc_aic7890_setup
42172811Sgibbs	},
42272811Sgibbs	{
42365942Sgibbs		ID_AAA_131U2,
42465942Sgibbs		ID_ALL_MASK,
42565942Sgibbs		"Adaptec AAA-131 Ultra2 RAID adapter",
42665942Sgibbs		ahc_aic7890_setup
42765942Sgibbs	},
42865942Sgibbs	/* aic7892 based controllers */
42965942Sgibbs	{
43065942Sgibbs		ID_AHA_29160,
43165942Sgibbs		ID_ALL_MASK,
43265942Sgibbs		"Adaptec 29160 Ultra160 SCSI adapter",
43365942Sgibbs		ahc_aic7892_setup
43465942Sgibbs	},
43565942Sgibbs	{
43665942Sgibbs		ID_AHA_29160_CPQ,
43765942Sgibbs		ID_ALL_MASK,
43865942Sgibbs		"Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter",
43965942Sgibbs		ahc_aic7892_setup
44065942Sgibbs	},
44165942Sgibbs	{
44265942Sgibbs		ID_AHA_29160N,
44365942Sgibbs		ID_ALL_MASK,
44465942Sgibbs		"Adaptec 29160N Ultra160 SCSI adapter",
44565942Sgibbs		ahc_aic7892_setup
44665942Sgibbs	},
44765942Sgibbs	{
44870204Sgibbs		ID_AHA_29160C,
44970204Sgibbs		ID_ALL_MASK,
45070204Sgibbs		"Adaptec 29160C Ultra160 SCSI adapter",
45171390Sgibbs		ahc_aha29160C_setup
45270204Sgibbs	},
45370204Sgibbs	{
45465942Sgibbs		ID_AHA_29160B,
45565942Sgibbs		ID_ALL_MASK,
45665942Sgibbs		"Adaptec 29160B Ultra160 SCSI adapter",
45765942Sgibbs		ahc_aic7892_setup
45865942Sgibbs	},
45965942Sgibbs	{
46065942Sgibbs		ID_AHA_19160B,
46165942Sgibbs		ID_ALL_MASK,
46265942Sgibbs		"Adaptec 19160B Ultra160 SCSI adapter",
46365942Sgibbs		ahc_aic7892_setup
46465942Sgibbs	},
46572811Sgibbs	{
46672811Sgibbs		ID_AIC7892_ARO,
46772811Sgibbs		ID_ALL_MASK,
46876634Sgibbs		"Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
46972811Sgibbs		ahc_aic7892_setup
47072811Sgibbs	},
471123579Sgibbs	{
472123579Sgibbs		ID_AHA_2915_30LP,
473123579Sgibbs		ID_ALL_MASK,
474123579Sgibbs		"Adaptec 2915/30LP Ultra160 SCSI adapter",
475123579Sgibbs		ahc_aic7892_setup
476123579Sgibbs	},
47765942Sgibbs	/* aic7895 based controllers */
47865942Sgibbs	{
47965942Sgibbs		ID_AHA_2940U_DUAL,
48065942Sgibbs		ID_ALL_MASK,
48165942Sgibbs		"Adaptec 2940/DUAL Ultra SCSI adapter",
48265942Sgibbs		ahc_aic7895_setup
48365942Sgibbs	},
48465942Sgibbs	{
48565942Sgibbs		ID_AHA_3940AU,
48665942Sgibbs		ID_ALL_MASK,
48765942Sgibbs		"Adaptec 3940A Ultra SCSI adapter",
48865942Sgibbs		ahc_aic7895_setup
48965942Sgibbs	},
49065942Sgibbs	{
49165942Sgibbs		ID_AHA_3944AU,
49265942Sgibbs		ID_ALL_MASK,
49365942Sgibbs		"Adaptec 3944A Ultra SCSI adapter",
49465942Sgibbs		ahc_aic7895_setup
49565942Sgibbs	},
49672811Sgibbs	{
49772811Sgibbs		ID_AIC7895_ARO,
49872811Sgibbs		ID_AIC7895_ARO_MASK,
49972811Sgibbs		"Adaptec aic7895 Ultra SCSI adapter (ARO)",
50072811Sgibbs		ahc_aic7895_setup
50172811Sgibbs	},
50265942Sgibbs	/* aic7896/97 based controllers */
50365942Sgibbs	{
50465942Sgibbs		ID_AHA_3950U2B_0,
50565942Sgibbs		ID_ALL_MASK,
50665942Sgibbs		"Adaptec 3950B Ultra2 SCSI adapter",
50765942Sgibbs		ahc_aic7896_setup
50865942Sgibbs	},
50965942Sgibbs	{
51065942Sgibbs		ID_AHA_3950U2B_1,
51165942Sgibbs		ID_ALL_MASK,
51265942Sgibbs		"Adaptec 3950B Ultra2 SCSI adapter",
51365942Sgibbs		ahc_aic7896_setup
51465942Sgibbs	},
51565942Sgibbs	{
51665942Sgibbs		ID_AHA_3950U2D_0,
51765942Sgibbs		ID_ALL_MASK,
51865942Sgibbs		"Adaptec 3950D Ultra2 SCSI adapter",
51965942Sgibbs		ahc_aic7896_setup
52065942Sgibbs	},
52165942Sgibbs	{
52265942Sgibbs		ID_AHA_3950U2D_1,
52365942Sgibbs		ID_ALL_MASK,
52465942Sgibbs		"Adaptec 3950D Ultra2 SCSI adapter",
52565942Sgibbs		ahc_aic7896_setup
52665942Sgibbs	},
52772811Sgibbs	{
52872811Sgibbs		ID_AIC7896_ARO,
52972811Sgibbs		ID_ALL_MASK,
53072811Sgibbs		"Adaptec aic7896/97 Ultra2 SCSI adapter (ARO)",
53172811Sgibbs		ahc_aic7896_setup
53272811Sgibbs	},
53365942Sgibbs	/* aic7899 based controllers */
53465942Sgibbs	{
53565942Sgibbs		ID_AHA_3960D,
53665942Sgibbs		ID_ALL_MASK,
53765942Sgibbs		"Adaptec 3960D Ultra160 SCSI adapter",
53865942Sgibbs		ahc_aic7899_setup
53965942Sgibbs	},
54065942Sgibbs	{
54165942Sgibbs		ID_AHA_3960D_CPQ,
54265942Sgibbs		ID_ALL_MASK,
54365942Sgibbs		"Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter",
54465942Sgibbs		ahc_aic7899_setup
54565942Sgibbs	},
54672811Sgibbs	{
54772811Sgibbs		ID_AIC7899_ARO,
54872811Sgibbs		ID_ALL_MASK,
54972811Sgibbs		"Adaptec aic7899 Ultra160 SCSI adapter (ARO)",
55072811Sgibbs		ahc_aic7899_setup
55172811Sgibbs	},
55265942Sgibbs	/* Generic chip probes for devices we don't know 'exactly' */
55365942Sgibbs	{
55465942Sgibbs		ID_AIC7850 & ID_DEV_VENDOR_MASK,
55565942Sgibbs		ID_DEV_VENDOR_MASK,
55665942Sgibbs		"Adaptec aic7850 SCSI adapter",
55774094Sgibbs		ahc_aic785X_setup
55865942Sgibbs	},
55965942Sgibbs	{
56065942Sgibbs		ID_AIC7855 & ID_DEV_VENDOR_MASK,
56165942Sgibbs		ID_DEV_VENDOR_MASK,
56265942Sgibbs		"Adaptec aic7855 SCSI adapter",
56374094Sgibbs		ahc_aic785X_setup
56465942Sgibbs	},
56565942Sgibbs	{
56665942Sgibbs		ID_AIC7859 & ID_DEV_VENDOR_MASK,
56765942Sgibbs		ID_DEV_VENDOR_MASK,
56876634Sgibbs		"Adaptec aic7859 SCSI adapter",
56965942Sgibbs		ahc_aic7860_setup
57065942Sgibbs	},
57165942Sgibbs	{
57265942Sgibbs		ID_AIC7860 & ID_DEV_VENDOR_MASK,
57365942Sgibbs		ID_DEV_VENDOR_MASK,
57476634Sgibbs		"Adaptec aic7860 Ultra SCSI adapter",
57565942Sgibbs		ahc_aic7860_setup
57665942Sgibbs	},
57765942Sgibbs	{
57865942Sgibbs		ID_AIC7870 & ID_DEV_VENDOR_MASK,
57965942Sgibbs		ID_DEV_VENDOR_MASK,
58065942Sgibbs		"Adaptec aic7870 SCSI adapter",
58165942Sgibbs		ahc_aic7870_setup
58265942Sgibbs	},
58365942Sgibbs	{
58465942Sgibbs		ID_AIC7880 & ID_DEV_VENDOR_MASK,
58565942Sgibbs		ID_DEV_VENDOR_MASK,
58665942Sgibbs		"Adaptec aic7880 Ultra SCSI adapter",
58765942Sgibbs		ahc_aic7880_setup
58865942Sgibbs	},
58965942Sgibbs	{
59072325Sgibbs		ID_AIC7890 & ID_9005_GENERIC_MASK,
59172325Sgibbs		ID_9005_GENERIC_MASK,
59265942Sgibbs		"Adaptec aic7890/91 Ultra2 SCSI adapter",
59365942Sgibbs		ahc_aic7890_setup
59465942Sgibbs	},
59565942Sgibbs	{
59672325Sgibbs		ID_AIC7892 & ID_9005_GENERIC_MASK,
59772325Sgibbs		ID_9005_GENERIC_MASK,
59865942Sgibbs		"Adaptec aic7892 Ultra160 SCSI adapter",
59965942Sgibbs		ahc_aic7892_setup
60065942Sgibbs	},
60165942Sgibbs	{
60265942Sgibbs		ID_AIC7895 & ID_DEV_VENDOR_MASK,
60365942Sgibbs		ID_DEV_VENDOR_MASK,
60465942Sgibbs		"Adaptec aic7895 Ultra SCSI adapter",
60565942Sgibbs		ahc_aic7895_setup
60665942Sgibbs	},
60765942Sgibbs	{
60872325Sgibbs		ID_AIC7896 & ID_9005_GENERIC_MASK,
60972325Sgibbs		ID_9005_GENERIC_MASK,
61065942Sgibbs		"Adaptec aic7896/97 Ultra2 SCSI adapter",
61165942Sgibbs		ahc_aic7896_setup
61265942Sgibbs	},
61365942Sgibbs	{
61472325Sgibbs		ID_AIC7899 & ID_9005_GENERIC_MASK,
61572325Sgibbs		ID_9005_GENERIC_MASK,
61665942Sgibbs		"Adaptec aic7899 Ultra160 SCSI adapter",
61765942Sgibbs		ahc_aic7899_setup
61865942Sgibbs	},
61965942Sgibbs	{
62065942Sgibbs		ID_AIC7810 & ID_DEV_VENDOR_MASK,
62165942Sgibbs		ID_DEV_VENDOR_MASK,
62265942Sgibbs		"Adaptec aic7810 RAID memory controller",
62365942Sgibbs		ahc_raid_setup
62465942Sgibbs	},
62565942Sgibbs	{
62665942Sgibbs		ID_AIC7815 & ID_DEV_VENDOR_MASK,
62765942Sgibbs		ID_DEV_VENDOR_MASK,
62865942Sgibbs		"Adaptec aic7815 RAID memory controller",
62965942Sgibbs		ahc_raid_setup
63065942Sgibbs	}
63165942Sgibbs};
63265942Sgibbs
63370204Sgibbsconst u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table);
63465942Sgibbs
63565942Sgibbs#define AHC_394X_SLOT_CHANNEL_A	4
63665942Sgibbs#define AHC_394X_SLOT_CHANNEL_B	5
63765942Sgibbs
63865942Sgibbs#define AHC_398X_SLOT_CHANNEL_A	4
63965942Sgibbs#define AHC_398X_SLOT_CHANNEL_B	8
64065942Sgibbs#define AHC_398X_SLOT_CHANNEL_C	12
64165942Sgibbs
64265942Sgibbs#define AHC_494X_SLOT_CHANNEL_A	4
64365942Sgibbs#define AHC_494X_SLOT_CHANNEL_B	5
64465942Sgibbs#define AHC_494X_SLOT_CHANNEL_C	6
64565942Sgibbs#define AHC_494X_SLOT_CHANNEL_D	7
64665942Sgibbs
64765942Sgibbs#define	DEVCONFIG		0x40
648109590Sgibbs#define		PCIERRGENDIS	0x80000000ul
64965942Sgibbs#define		SCBSIZE32	0x00010000ul	/* aic789X only */
65074094Sgibbs#define		REXTVALID	0x00001000ul	/* ultra cards only */
65179874Sgibbs#define		MPORTMODE	0x00000400ul	/* aic7870+ only */
65279874Sgibbs#define		RAMPSM		0x00000200ul	/* aic7870+ only */
65365942Sgibbs#define		VOLSENSE	0x00000100ul
65479874Sgibbs#define		PCI64BIT	0x00000080ul	/* 64Bit PCI bus (Ultra2 Only)*/
65565942Sgibbs#define		SCBRAMSEL	0x00000080ul
65665942Sgibbs#define		MRDCEN		0x00000040ul
65765942Sgibbs#define		EXTSCBTIME	0x00000020ul	/* aic7870 only */
65865942Sgibbs#define		EXTSCBPEN	0x00000010ul	/* aic7870 only */
65965942Sgibbs#define		BERREN		0x00000008ul
66065942Sgibbs#define		DACEN		0x00000004ul
66165942Sgibbs#define		STPWLEVEL	0x00000002ul
66265942Sgibbs#define		DIFACTNEGEN	0x00000001ul	/* aic7870 only */
66365942Sgibbs
66465942Sgibbs#define	CSIZE_LATTIME		0x0c
66565942Sgibbs#define		CACHESIZE	0x0000003ful	/* only 5 bits */
66665942Sgibbs#define		LATTIME		0x0000ff00ul
66765942Sgibbs
668107419Sscottl/* PCI STATUS definitions */
669107419Sscottl#define	DPE	0x80
670107419Sscottl#define SSE	0x40
671107419Sscottl#define	RMA	0x20
672107419Sscottl#define	RTA	0x10
673107419Sscottl#define STA	0x08
674107419Sscottl#define DPR	0x01
675107419Sscottl
676253646Suqsstatic int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
677253646Suqs				     uint16_t subdevice, uint16_t subvendor);
67865942Sgibbsstatic int ahc_ext_scbram_present(struct ahc_softc *ahc);
67965942Sgibbsstatic void ahc_scbram_config(struct ahc_softc *ahc, int enable,
68065942Sgibbs				  int pcheck, int fast, int large);
68165942Sgibbsstatic void ahc_probe_ext_scbram(struct ahc_softc *ahc);
68265942Sgibbsstatic void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1);
683102676Sgibbsstatic void ahc_parse_pci_eeprom(struct ahc_softc *ahc,
684102676Sgibbs				 struct seeprom_config *sc);
68565942Sgibbsstatic void configure_termination(struct ahc_softc *ahc,
68665942Sgibbs				  struct seeprom_descriptor *sd,
68765942Sgibbs				  u_int adapter_control,
68865942Sgibbs	 			  u_int *sxfrctl1);
68965942Sgibbs
69065942Sgibbsstatic void ahc_new_term_detect(struct ahc_softc *ahc,
69165942Sgibbs				int *enableSEC_low,
69265942Sgibbs				int *enableSEC_high,
69365942Sgibbs				int *enablePRI_low,
69465942Sgibbs				int *enablePRI_high,
69565942Sgibbs				int *eeprom_present);
69665942Sgibbsstatic void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
69765942Sgibbs				 int *internal68_present,
69865942Sgibbs				 int *externalcable_present,
69965942Sgibbs				 int *eeprom_present);
70065942Sgibbsstatic void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
70165942Sgibbs				 int *externalcable_present,
70265942Sgibbs				 int *eeprom_present);
703114621Sgibbsstatic void    write_brdctl(struct ahc_softc *ahc, uint8_t value);
70465942Sgibbsstatic uint8_t read_brdctl(struct ahc_softc *ahc);
705114621Sgibbsstatic void ahc_pci_intr(struct ahc_softc *ahc);
706114621Sgibbsstatic int  ahc_pci_chip_init(struct ahc_softc *ahc);
707114621Sgibbsstatic int  ahc_pci_suspend(struct ahc_softc *ahc);
708114621Sgibbsstatic int  ahc_pci_resume(struct ahc_softc *ahc);
70965942Sgibbs
71095378Sgibbsstatic int
71195378Sgibbsahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
71295378Sgibbs			  uint16_t subdevice, uint16_t subvendor)
71395378Sgibbs{
71495378Sgibbs	int result;
71595378Sgibbs
71695378Sgibbs	/* Default to invalid. */
71795378Sgibbs	result = 0;
71895378Sgibbs	if (vendor == 0x9005
71995378Sgibbs	 && subvendor == 0x9005
72095378Sgibbs         && subdevice != device
72195378Sgibbs         && SUBID_9005_TYPE_KNOWN(subdevice) != 0) {
72295378Sgibbs
72395378Sgibbs		switch (SUBID_9005_TYPE(subdevice)) {
72495378Sgibbs		case SUBID_9005_TYPE_MB:
72595378Sgibbs			break;
72695378Sgibbs		case SUBID_9005_TYPE_CARD:
72795378Sgibbs		case SUBID_9005_TYPE_LCCARD:
72895378Sgibbs			/*
72995378Sgibbs			 * Currently only trust Adaptec cards to
73095378Sgibbs			 * get the sub device info correct.
73195378Sgibbs			 */
73295378Sgibbs			if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA)
73395378Sgibbs				result = 1;
73495378Sgibbs			break;
73595378Sgibbs		case SUBID_9005_TYPE_RAID:
73695378Sgibbs			break;
73795378Sgibbs		default:
73895378Sgibbs			break;
73995378Sgibbs		}
74095378Sgibbs	}
74195378Sgibbs	return (result);
74295378Sgibbs}
74395378Sgibbs
74465942Sgibbsstruct ahc_pci_identity *
745123579Sgibbsahc_find_pci_device(aic_dev_softc_t pci)
74665942Sgibbs{
74765942Sgibbs	uint64_t  full_id;
74865942Sgibbs	uint16_t  device;
74965942Sgibbs	uint16_t  vendor;
75065942Sgibbs	uint16_t  subdevice;
75165942Sgibbs	uint16_t  subvendor;
75265942Sgibbs	struct	  ahc_pci_identity *entry;
75365942Sgibbs	u_int	  i;
75465942Sgibbs
755123579Sgibbs	vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
756123579Sgibbs	device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
757123579Sgibbs	subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
758123579Sgibbs	subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
759114621Sgibbs	full_id = ahc_compose_id(device, vendor, subdevice, subvendor);
76065942Sgibbs
76179874Sgibbs	/*
76279874Sgibbs	 * If the second function is not hooked up, ignore it.
76379874Sgibbs	 * Unfortunately, not all MB vendors implement the
76479874Sgibbs	 * subdevice ID as per the Adaptec spec, so do our best
76579874Sgibbs	 * to sanity check it prior to accepting the subdevice
76679874Sgibbs	 * ID as valid.
76779874Sgibbs	 */
768123579Sgibbs	if (aic_get_pci_function(pci) > 0
769253646Suqs	 && ahc_9005_subdevinfo_valid(device, vendor, subdevice, subvendor)
77070693Sgibbs	 && SUBID_9005_MFUNCENB(subdevice) == 0)
77170204Sgibbs		return (NULL);
77270204Sgibbs
77365942Sgibbs	for (i = 0; i < ahc_num_pci_devs; i++) {
77465942Sgibbs		entry = &ahc_pci_ident_table[i];
77572811Sgibbs		if (entry->full_id == (full_id & entry->id_mask)) {
77672811Sgibbs			/* Honor exclusion entries. */
77772811Sgibbs			if (entry->name == NULL)
77872811Sgibbs				return (NULL);
77965942Sgibbs			return (entry);
78072811Sgibbs		}
78165942Sgibbs	}
78265942Sgibbs	return (NULL);
78365942Sgibbs}
78465942Sgibbs
78565942Sgibbsint
78665942Sgibbsahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
78765942Sgibbs{
788102676Sgibbs	u_int	 command;
789102676Sgibbs	u_int	 our_id;
790102676Sgibbs	u_int	 sxfrctl1;
791102676Sgibbs	u_int	 scsiseq;
792102676Sgibbs	u_int	 dscommand0;
793109590Sgibbs	uint32_t devconfig;
794102676Sgibbs	int	 error;
795102676Sgibbs	uint8_t	 sblkctl;
79665942Sgibbs
797102676Sgibbs	our_id = 0;
79879874Sgibbs	error = entry->setup(ahc);
79965942Sgibbs	if (error != 0)
80065942Sgibbs		return (error);
80179874Sgibbs	ahc->chip |= AHC_PCI;
80279874Sgibbs	ahc->description = entry->name;
80365942Sgibbs
804123579Sgibbs	aic_power_state_change(ahc, AIC_POWER_STATE_D0);
80595378Sgibbs
80665942Sgibbs	error = ahc_pci_map_registers(ahc);
80765942Sgibbs	if (error != 0)
80865942Sgibbs		return (error);
80965942Sgibbs
81095378Sgibbs	/*
81195378Sgibbs	 * Before we continue probing the card, ensure that
81295378Sgibbs	 * its interrupts are *disabled*.  We don't want
81395378Sgibbs	 * a misstep to hang the machine in an interrupt
81495378Sgibbs	 * storm.
81595378Sgibbs	 */
81695378Sgibbs	ahc_intr_enable(ahc, FALSE);
81770204Sgibbs
818123579Sgibbs	devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
819109590Sgibbs
82079874Sgibbs	/*
82179874Sgibbs	 * If we need to support high memory, enable dual
82279874Sgibbs	 * address cycles.  This bit must be set to enable
82379874Sgibbs	 * high address bit generation even if we are on a
82479874Sgibbs	 * 64bit bus (PCI64BIT set in devconfig).
82579874Sgibbs	 */
82679874Sgibbs	if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
82779874Sgibbs
82879874Sgibbs		if (bootverbose)
82979874Sgibbs			printf("%s: Enabling 39Bit Addressing\n",
83079874Sgibbs			       ahc_name(ahc));
83179874Sgibbs		devconfig |= DACEN;
83279874Sgibbs	}
83379874Sgibbs
834109590Sgibbs	/* Ensure that pci error generation, a test feature, is disabled. */
835109590Sgibbs	devconfig |= PCIERRGENDIS;
836109590Sgibbs
837123579Sgibbs	aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
838109590Sgibbs
83965942Sgibbs	/* Ensure busmastering is enabled */
840123579Sgibbs	command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
84165942Sgibbs	command |= PCIM_CMD_BUSMASTEREN;
842109590Sgibbs
843123579Sgibbs	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2);
84465942Sgibbs
84565942Sgibbs	/* On all PCI adapters, we allow SCB paging */
84679874Sgibbs	ahc->flags |= AHC_PAGESCBS;
84765942Sgibbs
84879874Sgibbs	error = ahc_softc_init(ahc);
84965942Sgibbs	if (error != 0)
85065942Sgibbs		return (error);
85165942Sgibbs
852114621Sgibbs	/*
853114621Sgibbs	 * Disable PCI parity error checking.  Users typically
854114621Sgibbs	 * do this to work around broken PCI chipsets that get
855114621Sgibbs	 * the parity timing wrong and thus generate lots of spurious
856114621Sgibbs	 * errors.  The chip only allows us to disable *all* parity
857114621Sgibbs	 * error reporting when doing this, so CIO bus, scb ram, and
858114621Sgibbs	 * scratch ram parity errors will be ignored too.
859114621Sgibbs	 */
860115332Sgibbs	if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0)
861115332Sgibbs		ahc->seqctl |= FAILDIS;
862114621Sgibbs
86374972Sgibbs	ahc->bus_intr = ahc_pci_intr;
864114621Sgibbs	ahc->bus_chip_init = ahc_pci_chip_init;
865114621Sgibbs	ahc->bus_suspend = ahc_pci_suspend;
866114621Sgibbs	ahc->bus_resume = ahc_pci_resume;
86774972Sgibbs
868299375Spfg	/* Remember how the card was setup in case there is no SEEPROM */
86970204Sgibbs	if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
87074094Sgibbs		ahc_pause(ahc);
87170204Sgibbs		if ((ahc->features & AHC_ULTRA2) != 0)
87270204Sgibbs			our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID;
87370204Sgibbs		else
87470204Sgibbs			our_id = ahc_inb(ahc, SCSIID) & OID;
87570204Sgibbs		sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN;
87670204Sgibbs		scsiseq = ahc_inb(ahc, SCSISEQ);
87770204Sgibbs	} else {
87870204Sgibbs		sxfrctl1 = STPWEN;
87970204Sgibbs		our_id = 7;
88070204Sgibbs		scsiseq = 0;
88170204Sgibbs	}
88265942Sgibbs
883115917Sgibbs	error = ahc_reset(ahc, /*reinit*/FALSE);
88465942Sgibbs	if (error != 0)
88565942Sgibbs		return (ENXIO);
88665942Sgibbs
88765942Sgibbs	if ((ahc->features & AHC_DT) != 0) {
88865942Sgibbs		u_int sfunct;
88965942Sgibbs
89065942Sgibbs		/* Perform ALT-Mode Setup */
89165942Sgibbs		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
89265942Sgibbs		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
89376634Sgibbs		ahc_outb(ahc, OPTIONMODE,
89476634Sgibbs			 OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS);
89565942Sgibbs		ahc_outb(ahc, SFUNCT, sfunct);
89665942Sgibbs
89765942Sgibbs		/* Normal mode setup */
89865942Sgibbs		ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN
89970204Sgibbs					  |TARGCRCENDEN);
90065942Sgibbs	}
90165942Sgibbs
90265942Sgibbs	dscommand0 = ahc_inb(ahc, DSCOMMAND0);
90366647Sgibbs	dscommand0 |= MPARCKEN|CACHETHEN;
90465942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
90565942Sgibbs
90665942Sgibbs		/*
90765942Sgibbs		 * DPARCKEN doesn't work correctly on
90865942Sgibbs		 * some MBs so don't use it.
90965942Sgibbs		 */
91065942Sgibbs		dscommand0 &= ~DPARCKEN;
91165942Sgibbs	}
91265942Sgibbs
91365942Sgibbs	/*
91465942Sgibbs	 * Handle chips that must have cache line
91565942Sgibbs	 * streaming (dis/en)abled.
91665942Sgibbs	 */
91765942Sgibbs	if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0)
91865942Sgibbs		dscommand0 |= CACHETHEN;
91965942Sgibbs
92065942Sgibbs	if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0)
92165942Sgibbs		dscommand0 &= ~CACHETHEN;
92265942Sgibbs
92365942Sgibbs	ahc_outb(ahc, DSCOMMAND0, dscommand0);
92465942Sgibbs
92565942Sgibbs	ahc->pci_cachesize =
926123579Sgibbs	    aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME,
92765942Sgibbs				/*bytes*/1) & CACHESIZE;
92865942Sgibbs	ahc->pci_cachesize *= 4;
92965942Sgibbs
93081170Sgibbs	if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0
93181170Sgibbs	 && ahc->pci_cachesize == 4) {
93281170Sgibbs
933123579Sgibbs		aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
93481170Sgibbs				     0, /*bytes*/1);
93581170Sgibbs		ahc->pci_cachesize = 0;
93681170Sgibbs	}
93781170Sgibbs
93876634Sgibbs	/*
939299375Spfg	 * We cannot perform ULTRA speeds without the presence
94076634Sgibbs	 * of the external precision resistor.
94176634Sgibbs	 */
94276634Sgibbs	if ((ahc->features & AHC_ULTRA) != 0) {
94376634Sgibbs		uint32_t devconfig;
94476634Sgibbs
945123579Sgibbs		devconfig = aic_pci_read_config(ahc->dev_softc,
94676634Sgibbs						DEVCONFIG, /*bytes*/4);
94776634Sgibbs		if ((devconfig & REXTVALID) == 0)
94876634Sgibbs			ahc->features &= ~AHC_ULTRA;
94976634Sgibbs	}
95076634Sgibbs
95165942Sgibbs	/* See if we have a SEEPROM and perform auto-term */
95265942Sgibbs	check_extport(ahc, &sxfrctl1);
95365942Sgibbs
95465942Sgibbs	/*
95565942Sgibbs	 * Take the LED out of diagnostic mode
95665942Sgibbs	 */
95765942Sgibbs	sblkctl = ahc_inb(ahc, SBLKCTL);
95865942Sgibbs	ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));
95965942Sgibbs
96065942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
96168087Sgibbs		ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX);
96265942Sgibbs	} else {
96365942Sgibbs		ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100);
96465942Sgibbs	}
96565942Sgibbs
96665942Sgibbs	if (ahc->flags & AHC_USEDEFAULTS) {
96765942Sgibbs		/*
96865942Sgibbs		 * PCI Adapter default setup
96965942Sgibbs		 * Should only be used if the adapter does not have
97065942Sgibbs		 * a SEEPROM.
97165942Sgibbs		 */
97265942Sgibbs		/* See if someone else set us up already */
973109590Sgibbs		if ((ahc->flags & AHC_NO_BIOS_INIT) == 0
974109590Sgibbs		 && scsiseq != 0) {
97565942Sgibbs			printf("%s: Using left over BIOS settings\n",
97665942Sgibbs				ahc_name(ahc));
97765942Sgibbs			ahc->flags &= ~AHC_USEDEFAULTS;
97872325Sgibbs			ahc->flags |= AHC_BIOS_ENABLED;
97965942Sgibbs		} else {
98065942Sgibbs			/*
98165942Sgibbs			 * Assume only one connector and always turn
98265942Sgibbs			 * on termination.
98365942Sgibbs			 */
98465942Sgibbs 			our_id = 0x07;
98565942Sgibbs			sxfrctl1 = STPWEN;
98665942Sgibbs		}
98765942Sgibbs		ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI);
98865942Sgibbs
98965942Sgibbs		ahc->our_id = our_id;
99065942Sgibbs	}
99165942Sgibbs
99265942Sgibbs	/*
99365942Sgibbs	 * Take a look to see if we have external SRAM.
99465942Sgibbs	 * We currently do not attempt to use SRAM that is
99565942Sgibbs	 * shared among multiple controllers.
99665942Sgibbs	 */
99765942Sgibbs	ahc_probe_ext_scbram(ahc);
99865942Sgibbs
99965942Sgibbs	/*
100065942Sgibbs	 * Record our termination setting for the
100165942Sgibbs	 * generic initialization routine.
100265942Sgibbs	 */
100365942Sgibbs	if ((sxfrctl1 & STPWEN) != 0)
100465942Sgibbs		ahc->flags |= AHC_TERM_ENB_A;
100565942Sgibbs
1006114621Sgibbs	/*
1007114621Sgibbs	 * Save chip register configuration data for chip resets
1008114621Sgibbs	 * that occur during runtime and resume events.
1009114621Sgibbs	 */
1010114621Sgibbs	ahc->bus_softc.pci_softc.devconfig =
1011123579Sgibbs	    aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
1012114621Sgibbs	ahc->bus_softc.pci_softc.command =
1013123579Sgibbs	    aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
1014114621Sgibbs	ahc->bus_softc.pci_softc.csize_lattime =
1015123579Sgibbs	    aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1);
1016114621Sgibbs	ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0);
1017114621Sgibbs	ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS);
1018114621Sgibbs	if ((ahc->features & AHC_DT) != 0) {
1019114621Sgibbs		u_int sfunct;
1020114621Sgibbs
1021114621Sgibbs		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
1022114621Sgibbs		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
1023114621Sgibbs		ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE);
1024114621Sgibbs		ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT);
1025114621Sgibbs		ahc_outb(ahc, SFUNCT, sfunct);
1026114621Sgibbs		ahc->bus_softc.pci_softc.crccontrol1 =
1027114621Sgibbs		    ahc_inb(ahc, CRCCONTROL1);
1028114621Sgibbs	}
1029114621Sgibbs	if ((ahc->features & AHC_MULTI_FUNC) != 0)
1030114621Sgibbs		ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR);
1031114621Sgibbs
1032114621Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
1033114621Sgibbs		ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH);
1034114621Sgibbs
103565942Sgibbs	/* Core initialization */
103665942Sgibbs	error = ahc_init(ahc);
103765942Sgibbs	if (error != 0)
103865942Sgibbs		return (error);
103965942Sgibbs
104065942Sgibbs	/*
104174972Sgibbs	 * Allow interrupts now that we are completely setup.
104274972Sgibbs	 */
104376634Sgibbs	error = ahc_pci_map_int(ahc);
104476634Sgibbs	if (error != 0)
104576634Sgibbs		return (error);
104676634Sgibbs
1047168807Sscottl	ahc_lock(ahc);
1048102676Sgibbs	/*
1049102676Sgibbs	 * Link this softc in with all other ahc instances.
1050102676Sgibbs	 */
1051102676Sgibbs	ahc_softc_insert(ahc);
1052168807Sscottl	ahc_unlock(ahc);
105365942Sgibbs	return (0);
105465942Sgibbs}
105565942Sgibbs
105665942Sgibbs/*
1057299375Spfg * Test for the presence of external sram in an
105865942Sgibbs * "unshared" configuration.
105965942Sgibbs */
106065942Sgibbsstatic int
106165942Sgibbsahc_ext_scbram_present(struct ahc_softc *ahc)
106265942Sgibbs{
106368087Sgibbs	u_int chip;
106465942Sgibbs	int ramps;
106565942Sgibbs	int single_user;
106665942Sgibbs	uint32_t devconfig;
106765942Sgibbs
106868087Sgibbs	chip = ahc->chip & AHC_CHIPID_MASK;
1069123579Sgibbs	devconfig = aic_pci_read_config(ahc->dev_softc,
107065942Sgibbs					DEVCONFIG, /*bytes*/4);
107165942Sgibbs	single_user = (devconfig & MPORTMODE) != 0;
107265942Sgibbs
107365942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
107465942Sgibbs		ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0;
107595378Sgibbs	else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C)
107695378Sgibbs		/*
107795378Sgibbs		 * External SCBRAM arbitration is flakey
107895378Sgibbs		 * on these chips.  Unfortunately this means
107995378Sgibbs		 * we don't use the extra SCB ram space on the
108095378Sgibbs		 * 3940AUW.
108195378Sgibbs		 */
108295378Sgibbs		ramps = 0;
108368087Sgibbs	else if (chip >= AHC_AIC7870)
108465942Sgibbs		ramps = (devconfig & RAMPSM) != 0;
108565942Sgibbs	else
108665942Sgibbs		ramps = 0;
108765942Sgibbs
108865942Sgibbs	if (ramps && single_user)
108965942Sgibbs		return (1);
109065942Sgibbs	return (0);
109165942Sgibbs}
109265942Sgibbs
109365942Sgibbs/*
109465942Sgibbs * Enable external scbram.
109565942Sgibbs */
109665942Sgibbsstatic void
109765942Sgibbsahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck,
109865942Sgibbs		  int fast, int large)
109965942Sgibbs{
110065942Sgibbs	uint32_t devconfig;
110165942Sgibbs
110265942Sgibbs	if (ahc->features & AHC_MULTI_FUNC) {
110365942Sgibbs		/*
110465942Sgibbs		 * Set the SCB Base addr (highest address bit)
110565942Sgibbs		 * depending on which channel we are.
110665942Sgibbs		 */
1107123579Sgibbs		ahc_outb(ahc, SCBBADDR, aic_get_pci_function(ahc->dev_softc));
110865942Sgibbs	}
110965942Sgibbs
1110102676Sgibbs	ahc->flags &= ~AHC_LSCBS_ENABLED;
1111102676Sgibbs	if (large)
1112102676Sgibbs		ahc->flags |= AHC_LSCBS_ENABLED;
1113123579Sgibbs	devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
111465942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
111565942Sgibbs		u_int dscommand0;
111665942Sgibbs
111765942Sgibbs		dscommand0 = ahc_inb(ahc, DSCOMMAND0);
111865942Sgibbs		if (enable)
111965942Sgibbs			dscommand0 &= ~INTSCBRAMSEL;
112065942Sgibbs		else
112165942Sgibbs			dscommand0 |= INTSCBRAMSEL;
112265942Sgibbs		if (large)
112365942Sgibbs			dscommand0 &= ~USCBSIZE32;
112465942Sgibbs		else
112565942Sgibbs			dscommand0 |= USCBSIZE32;
112665942Sgibbs		ahc_outb(ahc, DSCOMMAND0, dscommand0);
112765942Sgibbs	} else {
112865942Sgibbs		if (fast)
112965942Sgibbs			devconfig &= ~EXTSCBTIME;
113065942Sgibbs		else
113165942Sgibbs			devconfig |= EXTSCBTIME;
113265942Sgibbs		if (enable)
113365942Sgibbs			devconfig &= ~SCBRAMSEL;
113465942Sgibbs		else
113565942Sgibbs			devconfig |= SCBRAMSEL;
113665942Sgibbs		if (large)
113765942Sgibbs			devconfig &= ~SCBSIZE32;
113865942Sgibbs		else
113965942Sgibbs			devconfig |= SCBSIZE32;
114065942Sgibbs	}
114165942Sgibbs	if (pcheck)
114265942Sgibbs		devconfig |= EXTSCBPEN;
114365942Sgibbs	else
114465942Sgibbs		devconfig &= ~EXTSCBPEN;
114565942Sgibbs
1146123579Sgibbs	aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
114765942Sgibbs}
114865942Sgibbs
114965942Sgibbs/*
115065942Sgibbs * Take a look to see if we have external SRAM.
115165942Sgibbs * We currently do not attempt to use SRAM that is
115265942Sgibbs * shared among multiple controllers.
115365942Sgibbs */
115465942Sgibbsstatic void
115565942Sgibbsahc_probe_ext_scbram(struct ahc_softc *ahc)
115665942Sgibbs{
115765942Sgibbs	int num_scbs;
115865942Sgibbs	int test_num_scbs;
115965942Sgibbs	int enable;
116065942Sgibbs	int pcheck;
116165942Sgibbs	int fast;
116265942Sgibbs	int large;
116365942Sgibbs
116465942Sgibbs	enable = FALSE;
116565942Sgibbs	pcheck = FALSE;
116665942Sgibbs	fast = FALSE;
116765942Sgibbs	large = FALSE;
116865942Sgibbs	num_scbs = 0;
116965942Sgibbs
117065942Sgibbs	if (ahc_ext_scbram_present(ahc) == 0)
117165942Sgibbs		goto done;
117265942Sgibbs
117365942Sgibbs	/*
117465942Sgibbs	 * Probe for the best parameters to use.
117565942Sgibbs	 */
117665942Sgibbs	ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large);
117765942Sgibbs	num_scbs = ahc_probe_scbs(ahc);
117865942Sgibbs	if (num_scbs == 0) {
117965942Sgibbs		/* The SRAM wasn't really present. */
118065942Sgibbs		goto done;
118165942Sgibbs	}
118265942Sgibbs	enable = TRUE;
118365942Sgibbs
118465942Sgibbs	/*
118565942Sgibbs	 * Clear any outstanding parity error
118665942Sgibbs	 * and ensure that parity error reporting
118765942Sgibbs	 * is enabled.
118865942Sgibbs	 */
118965942Sgibbs	ahc_outb(ahc, SEQCTL, 0);
119065942Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
119165942Sgibbs	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
119265942Sgibbs
119365942Sgibbs	/* Now see if we can do parity */
119465942Sgibbs	ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large);
119565942Sgibbs	num_scbs = ahc_probe_scbs(ahc);
119665942Sgibbs	if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
119765942Sgibbs	 || (ahc_inb(ahc, ERROR) & MPARERR) == 0)
119865942Sgibbs		pcheck = TRUE;
119965942Sgibbs
120065942Sgibbs	/* Clear any resulting parity error */
120165942Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
120265942Sgibbs	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
120365942Sgibbs
120465942Sgibbs	/* Now see if we can do fast timing */
120565942Sgibbs	ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large);
120665942Sgibbs	test_num_scbs = ahc_probe_scbs(ahc);
120765942Sgibbs	if (test_num_scbs == num_scbs
120865942Sgibbs	 && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
120965942Sgibbs	  || (ahc_inb(ahc, ERROR) & MPARERR) == 0))
121065942Sgibbs		fast = TRUE;
121165942Sgibbs
121265942Sgibbs	/*
121365942Sgibbs	 * See if we can use large SCBs and still maintain
121465942Sgibbs	 * the same overall count of SCBs.
121565942Sgibbs	 */
121665942Sgibbs	if ((ahc->features & AHC_LARGE_SCBS) != 0) {
121765942Sgibbs		ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE);
121865942Sgibbs		test_num_scbs = ahc_probe_scbs(ahc);
121965942Sgibbs		if (test_num_scbs >= num_scbs) {
122065942Sgibbs			large = TRUE;
122165942Sgibbs			num_scbs = test_num_scbs;
122265942Sgibbs	 		if (num_scbs >= 64) {
122365942Sgibbs				/*
122465942Sgibbs				 * We have enough space to move the
122565942Sgibbs				 * "busy targets table" into SCB space
122665942Sgibbs				 * and make it qualify all the way to the
122765942Sgibbs				 * lun level.
122865942Sgibbs				 */
122965942Sgibbs				ahc->flags |= AHC_SCB_BTT;
123065942Sgibbs			}
123165942Sgibbs		}
123265942Sgibbs	}
123365942Sgibbsdone:
123465942Sgibbs	/*
123565942Sgibbs	 * Disable parity error reporting until we
123665942Sgibbs	 * can load instruction ram.
123765942Sgibbs	 */
123865942Sgibbs	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
123965942Sgibbs	/* Clear any latched parity error */
124065942Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
124165942Sgibbs	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
124265942Sgibbs	if (bootverbose && enable) {
124365942Sgibbs		printf("%s: External SRAM, %s access%s, %dbytes/SCB\n",
124465942Sgibbs		       ahc_name(ahc), fast ? "fast" : "slow",
124565942Sgibbs		       pcheck ? ", parity checking enabled" : "",
124665942Sgibbs		       large ? 64 : 32);
124765942Sgibbs	}
124865942Sgibbs	ahc_scbram_config(ahc, enable, pcheck, fast, large);
124965942Sgibbs}
125065942Sgibbs
125165942Sgibbs/*
1252107419Sscottl * Perform some simple tests that should catch situations where
1253107419Sscottl * our registers are invalidly mapped.
1254107419Sscottl */
1255107419Sscottlint
1256107419Sscottlahc_pci_test_register_access(struct ahc_softc *ahc)
1257107419Sscottl{
1258109590Sgibbs	int	 error;
1259109590Sgibbs	u_int	 status1;
1260109590Sgibbs	uint32_t cmd;
1261109590Sgibbs	uint8_t	 hcntrl;
1262107419Sscottl
1263107623Sscottl	error = EIO;
1264107623Sscottl
1265109590Sgibbs	/*
1266109590Sgibbs	 * Enable PCI error interrupt status, but suppress NMIs
1267109590Sgibbs	 * generated by SERR raised due to target aborts.
1268109590Sgibbs	 */
1269123579Sgibbs	cmd = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
1270123579Sgibbs	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
1271109590Sgibbs			     cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
1272107623Sscottl
1273107419Sscottl	/*
1274107419Sscottl	 * First a simple test to see if any
1275107419Sscottl	 * registers can be read.  Reading
1276107419Sscottl	 * HCNTRL has no side effects and has
1277107419Sscottl	 * at least one bit that is guaranteed to
1278107419Sscottl	 * be zero so it is a good register to
1279107419Sscottl	 * use for this test.
1280107419Sscottl	 */
1281109590Sgibbs	hcntrl = ahc_inb(ahc, HCNTRL);
1282123579Sgibbs
1283109590Sgibbs	if (hcntrl == 0xFF)
1284107623Sscottl		goto fail;
1285107419Sscottl
1286123579Sgibbs	if ((hcntrl & CHIPRST) != 0) {
1287123579Sgibbs		/*
1288123579Sgibbs		 * The chip has not been initialized since
1289123579Sgibbs		 * PCI/EISA/VLB bus reset.  Don't trust
1290123579Sgibbs		 * "left over BIOS data".
1291123579Sgibbs		 */
1292123579Sgibbs		ahc->flags |= AHC_NO_BIOS_INIT;
1293123579Sgibbs	}
1294123579Sgibbs
1295107419Sscottl	/*
1296107419Sscottl	 * Next create a situation where write combining
1297107419Sscottl	 * or read prefetching could be initiated by the
1298107419Sscottl	 * CPU or host bridge.  Our device does not support
1299107419Sscottl	 * either, so look for data corruption and/or flagged
1300120445Sscottl	 * PCI errors.  First pause without causing another
1301120445Sscottl	 * chip reset.
1302107419Sscottl	 */
1303120445Sscottl	hcntrl &= ~CHIPRST;
1304109590Sgibbs	ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
1305109590Sgibbs	while (ahc_is_paused(ahc) == 0)
1306109590Sgibbs		;
1307115919Sgibbs
1308115919Sgibbs	/* Clear any PCI errors that occurred before our driver attached. */
1309123579Sgibbs	status1 = aic_pci_read_config(ahc->dev_softc,
1310115919Sgibbs				      PCIR_STATUS + 1, /*bytes*/1);
1311123579Sgibbs	aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
1312115919Sgibbs			     status1, /*bytes*/1);
1313115919Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
1314115919Sgibbs
1315109590Sgibbs	ahc_outb(ahc, SEQCTL, PERRORDIS);
1316109590Sgibbs	ahc_outb(ahc, SCBPTR, 0);
1317109590Sgibbs	ahc_outl(ahc, SCB_BASE, 0x5aa555aa);
1318109590Sgibbs	if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa)
1319107623Sscottl		goto fail;
1320107419Sscottl
1321123579Sgibbs	status1 = aic_pci_read_config(ahc->dev_softc,
1322107419Sscottl				      PCIR_STATUS + 1, /*bytes*/1);
1323107623Sscottl	if ((status1 & STA) != 0)
1324107623Sscottl		goto fail;
1325107419Sscottl
1326107623Sscottl	error = 0;
1327107419Sscottl
1328107623Sscottlfail:
1329107623Sscottl	/* Silently clear any latched errors. */
1330123579Sgibbs	status1 = aic_pci_read_config(ahc->dev_softc,
1331107623Sscottl				      PCIR_STATUS + 1, /*bytes*/1);
1332123579Sgibbs	aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
1333107623Sscottl			     status1, /*bytes*/1);
1334107623Sscottl	ahc_outb(ahc, CLRINT, CLRPARERR);
1335109590Sgibbs	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
1336123579Sgibbs	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
1337107623Sscottl	return (error);
1338107419Sscottl}
1339107419Sscottl
1340107419Sscottl/*
134165942Sgibbs * Check the external port logic for a serial eeprom
134265942Sgibbs * and termination/cable detection contrls.
134365942Sgibbs */
134465942Sgibbsstatic void
134565942Sgibbscheck_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
134665942Sgibbs{
134765942Sgibbs	struct	seeprom_descriptor sd;
1348102676Sgibbs	struct	seeprom_config *sc;
134965942Sgibbs	int	have_seeprom;
135065942Sgibbs	int	have_autoterm;
135165942Sgibbs
135265942Sgibbs	sd.sd_ahc = ahc;
135365942Sgibbs	sd.sd_control_offset = SEECTL;
135465942Sgibbs	sd.sd_status_offset = SEECTL;
135565942Sgibbs	sd.sd_dataout_offset = SEECTL;
1356102676Sgibbs	sc = ahc->seep_config;
135765942Sgibbs
135865942Sgibbs	/*
135965942Sgibbs	 * For some multi-channel devices, the c46 is simply too
136065942Sgibbs	 * small to work.  For the other controller types, we can
136165942Sgibbs	 * get our information from either SEEPROM type.  Set the
136265942Sgibbs	 * type to start our probe with accordingly.
136365942Sgibbs	 */
136465942Sgibbs	if (ahc->flags & AHC_LARGE_SEEPROM)
136565942Sgibbs		sd.sd_chip = C56_66;
136665942Sgibbs	else
136765942Sgibbs		sd.sd_chip = C46;
136865942Sgibbs
136965942Sgibbs	sd.sd_MS = SEEMS;
137065942Sgibbs	sd.sd_RDY = SEERDY;
137165942Sgibbs	sd.sd_CS = SEECS;
137265942Sgibbs	sd.sd_CK = SEECK;
137365942Sgibbs	sd.sd_DO = SEEDO;
137465942Sgibbs	sd.sd_DI = SEEDI;
137565942Sgibbs
137695378Sgibbs	have_seeprom = ahc_acquire_seeprom(ahc, &sd);
137765942Sgibbs	if (have_seeprom) {
137865942Sgibbs
137965942Sgibbs		if (bootverbose)
138065942Sgibbs			printf("%s: Reading SEEPROM...", ahc_name(ahc));
138165942Sgibbs
138265942Sgibbs		for (;;) {
138365942Sgibbs			u_int start_addr;
138465942Sgibbs
138565942Sgibbs			start_addr = 32 * (ahc->channel - 'A');
138665942Sgibbs
1387102676Sgibbs			have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,
138895378Sgibbs							start_addr,
1389102676Sgibbs							sizeof(*sc)/2);
139065942Sgibbs
139165942Sgibbs			if (have_seeprom)
1392102676Sgibbs				have_seeprom = ahc_verify_cksum(sc);
139365942Sgibbs
139465942Sgibbs			if (have_seeprom != 0 || sd.sd_chip == C56_66) {
139565942Sgibbs				if (bootverbose) {
139665942Sgibbs					if (have_seeprom == 0)
139765942Sgibbs						printf ("checksum error\n");
139865942Sgibbs					else
139965942Sgibbs						printf ("done.\n");
140065942Sgibbs				}
140165942Sgibbs				break;
140265942Sgibbs			}
140365942Sgibbs			sd.sd_chip = C56_66;
140465942Sgibbs		}
140595378Sgibbs		ahc_release_seeprom(&sd);
1406123579Sgibbs
1407123579Sgibbs		/* Remember the SEEPROM type for later */
1408123579Sgibbs		if (sd.sd_chip == C56_66)
1409123579Sgibbs			ahc->flags |= AHC_LARGE_SEEPROM;
141065942Sgibbs	}
141165942Sgibbs
141265942Sgibbs	if (!have_seeprom) {
141365942Sgibbs		/*
141465942Sgibbs		 * Pull scratch ram settings and treat them as
141565942Sgibbs		 * if they are the contents of an seeprom if
141665942Sgibbs		 * the 'ADPT' signature is found in SCB2.
141774094Sgibbs		 * We manually compose the data as 16bit values
141874094Sgibbs		 * to avoid endian issues.
141965942Sgibbs		 */
142065942Sgibbs		ahc_outb(ahc, SCBPTR, 2);
142165942Sgibbs		if (ahc_inb(ahc, SCB_BASE) == 'A'
142265942Sgibbs		 && ahc_inb(ahc, SCB_BASE + 1) == 'D'
142365942Sgibbs		 && ahc_inb(ahc, SCB_BASE + 2) == 'P'
142465942Sgibbs		 && ahc_inb(ahc, SCB_BASE + 3) == 'T') {
142574094Sgibbs			uint16_t *sc_data;
142665942Sgibbs			int	  i;
142765942Sgibbs
1428102676Sgibbs			sc_data = (uint16_t *)sc;
1429102676Sgibbs			for (i = 0; i < 32; i++, sc_data++) {
1430102676Sgibbs				int	j;
143174094Sgibbs
143274094Sgibbs				j = i * 2;
1433102676Sgibbs				*sc_data = ahc_inb(ahc, SRAM_BASE + j)
1434102676Sgibbs					 | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
143574094Sgibbs			}
1436102676Sgibbs			have_seeprom = ahc_verify_cksum(sc);
1437102676Sgibbs			if (have_seeprom)
1438102676Sgibbs				ahc->flags |= AHC_SCB_CONFIG_USED;
143965942Sgibbs		}
144095378Sgibbs		/*
144195378Sgibbs		 * Clear any SCB parity errors in case this data and
144295378Sgibbs		 * its associated parity was not initialized by the BIOS
144395378Sgibbs		 */
144495378Sgibbs		ahc_outb(ahc, CLRINT, CLRPARERR);
144595378Sgibbs		ahc_outb(ahc, CLRINT, CLRBRKADRINT);
144665942Sgibbs	}
144765942Sgibbs
144865942Sgibbs	if (!have_seeprom) {
144965942Sgibbs		if (bootverbose)
145065942Sgibbs			printf("%s: No SEEPROM available.\n", ahc_name(ahc));
145165942Sgibbs		ahc->flags |= AHC_USEDEFAULTS;
1452102676Sgibbs		free(ahc->seep_config, M_DEVBUF);
1453102676Sgibbs		ahc->seep_config = NULL;
1454102676Sgibbs		sc = NULL;
145565942Sgibbs	} else {
1456102676Sgibbs		ahc_parse_pci_eeprom(ahc, sc);
145765942Sgibbs	}
145865942Sgibbs
145965942Sgibbs	/*
146065942Sgibbs	 * Cards that have the external logic necessary to talk to
146165942Sgibbs	 * a SEEPROM, are almost certain to have the remaining logic
146265942Sgibbs	 * necessary for auto-termination control.  This assumption
146365942Sgibbs	 * hasn't failed yet...
146465942Sgibbs	 */
146565942Sgibbs	have_autoterm = have_seeprom;
146665942Sgibbs
146765942Sgibbs	/*
146865942Sgibbs	 * Some low-cost chips have SEEPROM and auto-term control built
146965942Sgibbs	 * in, instead of using a GAL.  They can tell us directly
147065942Sgibbs	 * if the termination logic is enabled.
147165942Sgibbs	 */
147265942Sgibbs	if ((ahc->features & AHC_SPIOCAP) != 0) {
1473102676Sgibbs		if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0)
147465942Sgibbs			have_autoterm = FALSE;
147565942Sgibbs	}
147665942Sgibbs
147774094Sgibbs	if (have_autoterm) {
1478114621Sgibbs		ahc->flags |= AHC_HAS_TERM_LOGIC;
147995378Sgibbs		ahc_acquire_seeprom(ahc, &sd);
1480102676Sgibbs		configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1);
148195378Sgibbs		ahc_release_seeprom(&sd);
1482102676Sgibbs	} else if (have_seeprom) {
1483102676Sgibbs		*sxfrctl1 &= ~STPWEN;
1484102676Sgibbs		if ((sc->adapter_control & CFSTERM) != 0)
1485102676Sgibbs			*sxfrctl1 |= STPWEN;
1486102676Sgibbs		if (bootverbose)
1487102676Sgibbs			printf("%s: Low byte termination %sabled\n",
1488102676Sgibbs			       ahc_name(ahc),
1489102676Sgibbs			       (*sxfrctl1 & STPWEN) ? "en" : "dis");
149074094Sgibbs	}
149165942Sgibbs}
149265942Sgibbs
149365942Sgibbsstatic void
1494102676Sgibbsahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc)
1495102676Sgibbs{
1496102676Sgibbs	/*
1497102676Sgibbs	 * Put the data we've collected down into SRAM
1498102676Sgibbs	 * where ahc_init will find it.
1499102676Sgibbs	 */
1500102676Sgibbs	int	 i;
1501102676Sgibbs	int	 max_targ = sc->max_targets & CFMAXTARG;
1502102676Sgibbs	u_int	 scsi_conf;
1503102676Sgibbs	uint16_t discenable;
1504102676Sgibbs	uint16_t ultraenb;
1505102676Sgibbs
1506102676Sgibbs	discenable = 0;
1507102676Sgibbs	ultraenb = 0;
1508102676Sgibbs	if ((sc->adapter_control & CFULTRAEN) != 0) {
1509102676Sgibbs		/*
1510102676Sgibbs		 * Determine if this adapter has a "newstyle"
1511102676Sgibbs		 * SEEPROM format.
1512102676Sgibbs		 */
1513102676Sgibbs		for (i = 0; i < max_targ; i++) {
1514102676Sgibbs			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) {
1515102676Sgibbs				ahc->flags |= AHC_NEWEEPROM_FMT;
1516102676Sgibbs				break;
1517102676Sgibbs			}
1518102676Sgibbs		}
1519102676Sgibbs	}
1520102676Sgibbs
1521102676Sgibbs	for (i = 0; i < max_targ; i++) {
1522102676Sgibbs		u_int     scsirate;
1523102676Sgibbs		uint16_t target_mask;
1524102676Sgibbs
1525102676Sgibbs		target_mask = 0x01 << i;
1526102676Sgibbs		if (sc->device_flags[i] & CFDISC)
1527102676Sgibbs			discenable |= target_mask;
1528102676Sgibbs		if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) {
1529102676Sgibbs			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0)
1530102676Sgibbs				ultraenb |= target_mask;
1531102676Sgibbs		} else if ((sc->adapter_control & CFULTRAEN) != 0) {
1532102676Sgibbs			ultraenb |= target_mask;
1533102676Sgibbs		}
1534102676Sgibbs		if ((sc->device_flags[i] & CFXFER) == 0x04
1535102676Sgibbs		 && (ultraenb & target_mask) != 0) {
1536102676Sgibbs			/* Treat 10MHz as a non-ultra speed */
1537102676Sgibbs			sc->device_flags[i] &= ~CFXFER;
1538102676Sgibbs		 	ultraenb &= ~target_mask;
1539102676Sgibbs		}
1540102676Sgibbs		if ((ahc->features & AHC_ULTRA2) != 0) {
1541102676Sgibbs			u_int offset;
1542102676Sgibbs
1543102676Sgibbs			if (sc->device_flags[i] & CFSYNCH)
1544102676Sgibbs				offset = MAX_OFFSET_ULTRA2;
1545102676Sgibbs			else
1546102676Sgibbs				offset = 0;
1547102676Sgibbs			ahc_outb(ahc, TARG_OFFSET + i, offset);
1548102676Sgibbs
1549102676Sgibbs			/*
1550102676Sgibbs			 * The ultra enable bits contain the
1551102676Sgibbs			 * high bit of the ultra2 sync rate
1552102676Sgibbs			 * field.
1553102676Sgibbs			 */
1554102676Sgibbs			scsirate = (sc->device_flags[i] & CFXFER)
1555102676Sgibbs				 | ((ultraenb & target_mask) ? 0x8 : 0x0);
1556102676Sgibbs			if (sc->device_flags[i] & CFWIDEB)
1557102676Sgibbs				scsirate |= WIDEXFER;
1558102676Sgibbs		} else {
1559102676Sgibbs			scsirate = (sc->device_flags[i] & CFXFER) << 4;
1560102676Sgibbs			if (sc->device_flags[i] & CFSYNCH)
1561102676Sgibbs				scsirate |= SOFS;
1562102676Sgibbs			if (sc->device_flags[i] & CFWIDEB)
1563102676Sgibbs				scsirate |= WIDEXFER;
1564102676Sgibbs		}
1565102676Sgibbs		ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);
1566102676Sgibbs	}
1567102676Sgibbs	ahc->our_id = sc->brtime_id & CFSCSIID;
1568102676Sgibbs
1569102676Sgibbs	scsi_conf = (ahc->our_id & 0x7);
1570102676Sgibbs	if (sc->adapter_control & CFSPARITY)
1571102676Sgibbs		scsi_conf |= ENSPCHK;
1572102676Sgibbs	if (sc->adapter_control & CFRESETB)
1573102676Sgibbs		scsi_conf |= RESET_SCSI;
1574102676Sgibbs
1575102676Sgibbs	ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;
1576102676Sgibbs
1577102676Sgibbs	if (sc->bios_control & CFEXTEND)
1578102676Sgibbs		ahc->flags |= AHC_EXTENDED_TRANS_A;
1579102676Sgibbs
1580102676Sgibbs	if (sc->bios_control & CFBIOSEN)
1581102676Sgibbs		ahc->flags |= AHC_BIOS_ENABLED;
1582102676Sgibbs	if (ahc->features & AHC_ULTRA
1583102676Sgibbs	 && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {
1584102676Sgibbs		/* Should we enable Ultra mode? */
1585102676Sgibbs		if (!(sc->adapter_control & CFULTRAEN))
1586102676Sgibbs			/* Treat us as a non-ultra card */
1587102676Sgibbs			ultraenb = 0;
1588102676Sgibbs	}
1589102676Sgibbs
1590102676Sgibbs	if (sc->signature == CFSIGNATURE
1591102676Sgibbs	 || sc->signature == CFSIGNATURE2) {
1592102676Sgibbs		uint32_t devconfig;
1593102676Sgibbs
1594102676Sgibbs		/* Honor the STPWLEVEL settings */
1595123579Sgibbs		devconfig = aic_pci_read_config(ahc->dev_softc,
1596102676Sgibbs						DEVCONFIG, /*bytes*/4);
1597102676Sgibbs		devconfig &= ~STPWLEVEL;
1598102676Sgibbs		if ((sc->bios_control & CFSTPWLEVEL) != 0)
1599102676Sgibbs			devconfig |= STPWLEVEL;
1600123579Sgibbs		aic_pci_write_config(ahc->dev_softc, DEVCONFIG,
1601102676Sgibbs				     devconfig, /*bytes*/4);
1602102676Sgibbs	}
1603102676Sgibbs	/* Set SCSICONF info */
1604102676Sgibbs	ahc_outb(ahc, SCSICONF, scsi_conf);
1605102676Sgibbs	ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
1606102676Sgibbs	ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
1607102676Sgibbs	ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff);
1608102676Sgibbs	ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);
1609102676Sgibbs}
1610102676Sgibbs
1611102676Sgibbsstatic void
161265942Sgibbsconfigure_termination(struct ahc_softc *ahc,
161365942Sgibbs		      struct seeprom_descriptor *sd,
161465942Sgibbs		      u_int adapter_control,
161565942Sgibbs		      u_int *sxfrctl1)
161665942Sgibbs{
161765942Sgibbs	uint8_t brddat;
161865942Sgibbs
161965942Sgibbs	brddat = 0;
162065942Sgibbs
162165942Sgibbs	/*
162265942Sgibbs	 * Update the settings in sxfrctl1 to match the
162365942Sgibbs	 * termination settings
162465942Sgibbs	 */
162565942Sgibbs	*sxfrctl1 = 0;
162665942Sgibbs
162765942Sgibbs	/*
162865942Sgibbs	 * SEECS must be on for the GALS to latch
162965942Sgibbs	 * the data properly.  Be sure to leave MS
163065942Sgibbs	 * on or we will release the seeprom.
163165942Sgibbs	 */
163265942Sgibbs	SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS);
163365942Sgibbs	if ((adapter_control & CFAUTOTERM) != 0
163465942Sgibbs	 || (ahc->features & AHC_NEW_TERMCTL) != 0) {
163565942Sgibbs		int internal50_present;
163665942Sgibbs		int internal68_present;
163765942Sgibbs		int externalcable_present;
163865942Sgibbs		int eeprom_present;
163965942Sgibbs		int enableSEC_low;
164065942Sgibbs		int enableSEC_high;
164165942Sgibbs		int enablePRI_low;
164265942Sgibbs		int enablePRI_high;
164371390Sgibbs		int sum;
164465942Sgibbs
164565942Sgibbs		enableSEC_low = 0;
164665942Sgibbs		enableSEC_high = 0;
164765942Sgibbs		enablePRI_low = 0;
164865942Sgibbs		enablePRI_high = 0;
164965942Sgibbs		if ((ahc->features & AHC_NEW_TERMCTL) != 0) {
165065942Sgibbs			ahc_new_term_detect(ahc, &enableSEC_low,
1651102676Sgibbs					    &enableSEC_high,
1652102676Sgibbs					    &enablePRI_low,
1653102676Sgibbs					    &enablePRI_high,
1654102676Sgibbs					    &eeprom_present);
165565942Sgibbs			if ((adapter_control & CFSEAUTOTERM) == 0) {
165665942Sgibbs				if (bootverbose)
165765942Sgibbs					printf("%s: Manual SE Termination\n",
165865942Sgibbs					       ahc_name(ahc));
165965942Sgibbs				enableSEC_low = (adapter_control & CFSELOWTERM);
166065942Sgibbs				enableSEC_high =
166165942Sgibbs				    (adapter_control & CFSEHIGHTERM);
166265942Sgibbs			}
166365942Sgibbs			if ((adapter_control & CFAUTOTERM) == 0) {
166465942Sgibbs				if (bootverbose)
166565942Sgibbs					printf("%s: Manual LVD Termination\n",
166665942Sgibbs					       ahc_name(ahc));
166765942Sgibbs				enablePRI_low = (adapter_control & CFSTERM);
166865942Sgibbs				enablePRI_high = (adapter_control & CFWSTERM);
166965942Sgibbs			}
167065942Sgibbs			/* Make the table calculations below happy */
167165942Sgibbs			internal50_present = 0;
167265942Sgibbs			internal68_present = 1;
167365942Sgibbs			externalcable_present = 1;
167465942Sgibbs		} else if ((ahc->features & AHC_SPIOCAP) != 0) {
167565942Sgibbs			aic785X_cable_detect(ahc, &internal50_present,
167665942Sgibbs					     &externalcable_present,
167765942Sgibbs					     &eeprom_present);
1678102676Sgibbs			/* Can never support a wide connector. */
1679102676Sgibbs			internal68_present = 0;
168065942Sgibbs		} else {
168165942Sgibbs			aic787X_cable_detect(ahc, &internal50_present,
168265942Sgibbs					     &internal68_present,
168365942Sgibbs					     &externalcable_present,
168465942Sgibbs					     &eeprom_present);
168565942Sgibbs		}
168665942Sgibbs
168765942Sgibbs		if ((ahc->features & AHC_WIDE) == 0)
168865942Sgibbs			internal68_present = 0;
168965942Sgibbs
169071390Sgibbs		if (bootverbose
169171390Sgibbs		 && (ahc->features & AHC_ULTRA2) == 0) {
169271390Sgibbs			printf("%s: internal 50 cable %s present",
169371390Sgibbs			       ahc_name(ahc),
169471390Sgibbs			       internal50_present ? "is":"not");
169571390Sgibbs
169671390Sgibbs			if ((ahc->features & AHC_WIDE) != 0)
169771390Sgibbs				printf(", internal 68 cable %s present",
169865942Sgibbs				       internal68_present ? "is":"not");
169971390Sgibbs			printf("\n%s: external cable %s present\n",
170071390Sgibbs			       ahc_name(ahc),
170171390Sgibbs			       externalcable_present ? "is":"not");
170271390Sgibbs		}
170371390Sgibbs		if (bootverbose)
170465942Sgibbs			printf("%s: BIOS eeprom %s present\n",
170565942Sgibbs			       ahc_name(ahc), eeprom_present ? "is" : "not");
170665942Sgibbs
170765942Sgibbs		if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) {
170865942Sgibbs			/*
170965942Sgibbs			 * The 50 pin connector is a separate bus,
171065942Sgibbs			 * so force it to always be terminated.
171165942Sgibbs			 * In the future, perform current sensing
171265942Sgibbs			 * to determine if we are in the middle of
171365942Sgibbs			 * a properly terminated bus.
171465942Sgibbs			 */
171565942Sgibbs			internal50_present = 0;
171665942Sgibbs		}
171765942Sgibbs
171865942Sgibbs		/*
171965942Sgibbs		 * Now set the termination based on what
172065942Sgibbs		 * we found.
172165942Sgibbs		 * Flash Enable = BRDDAT7
172265942Sgibbs		 * Secondary High Term Enable = BRDDAT6
172365942Sgibbs		 * Secondary Low Term Enable = BRDDAT5 (7890)
172465942Sgibbs		 * Primary High Term Enable = BRDDAT4 (7890)
172565942Sgibbs		 */
172665942Sgibbs		if ((ahc->features & AHC_ULTRA2) == 0
172771390Sgibbs		 && (internal50_present != 0)
172871390Sgibbs		 && (internal68_present != 0)
172971390Sgibbs		 && (externalcable_present != 0)) {
173065942Sgibbs			printf("%s: Illegal cable configuration!!. "
173165942Sgibbs			       "Only two connectors on the "
173265942Sgibbs			       "adapter may be used at a "
173365942Sgibbs			       "time!\n", ahc_name(ahc));
173495378Sgibbs
173595378Sgibbs			/*
173695378Sgibbs			 * Pretend there are no cables in the hope
173795378Sgibbs			 * that having all of the termination on
173895378Sgibbs			 * gives us a more stable bus.
173995378Sgibbs			 */
174095378Sgibbs		 	internal50_present = 0;
174195378Sgibbs			internal68_present = 0;
174295378Sgibbs			externalcable_present = 0;
174365942Sgibbs		}
174465942Sgibbs
174565942Sgibbs		if ((ahc->features & AHC_WIDE) != 0
174665942Sgibbs		 && ((externalcable_present == 0)
174765942Sgibbs		  || (internal68_present == 0)
174865942Sgibbs		  || (enableSEC_high != 0))) {
174965942Sgibbs			brddat |= BRDDAT6;
175065942Sgibbs			if (bootverbose) {
175165942Sgibbs				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
175265942Sgibbs					printf("%s: 68 pin termination "
175365942Sgibbs					       "Enabled\n", ahc_name(ahc));
175465942Sgibbs				else
175565942Sgibbs					printf("%s: %sHigh byte termination "
175665942Sgibbs					       "Enabled\n", ahc_name(ahc),
175765942Sgibbs					       enableSEC_high ? "Secondary "
175865942Sgibbs							      : "");
175965942Sgibbs			}
176065942Sgibbs		}
176165942Sgibbs
176271390Sgibbs		sum = internal50_present + internal68_present
176371390Sgibbs		    + externalcable_present;
176471390Sgibbs		if (sum < 2 || (enableSEC_low != 0)) {
176565942Sgibbs			if ((ahc->features & AHC_ULTRA2) != 0)
176665942Sgibbs				brddat |= BRDDAT5;
176765942Sgibbs			else
176865942Sgibbs				*sxfrctl1 |= STPWEN;
176965942Sgibbs			if (bootverbose) {
177065942Sgibbs				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
177165942Sgibbs					printf("%s: 50 pin termination "
177265942Sgibbs					       "Enabled\n", ahc_name(ahc));
177365942Sgibbs				else
177465942Sgibbs					printf("%s: %sLow byte termination "
177565942Sgibbs					       "Enabled\n", ahc_name(ahc),
177665942Sgibbs					       enableSEC_low ? "Secondary "
177765942Sgibbs							     : "");
177865942Sgibbs			}
177965942Sgibbs		}
178065942Sgibbs
178165942Sgibbs		if (enablePRI_low != 0) {
178265942Sgibbs			*sxfrctl1 |= STPWEN;
178365942Sgibbs			if (bootverbose)
178465942Sgibbs				printf("%s: Primary Low Byte termination "
178565942Sgibbs				       "Enabled\n", ahc_name(ahc));
178665942Sgibbs		}
178765942Sgibbs
178865942Sgibbs		/*
178965942Sgibbs		 * Setup STPWEN before setting up the rest of
179065942Sgibbs		 * the termination per the tech note on the U160 cards.
179165942Sgibbs		 */
179265942Sgibbs		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
179365942Sgibbs
179465942Sgibbs		if (enablePRI_high != 0) {
179565942Sgibbs			brddat |= BRDDAT4;
179665942Sgibbs			if (bootverbose)
179765942Sgibbs				printf("%s: Primary High Byte "
179865942Sgibbs				       "termination Enabled\n",
179965942Sgibbs				       ahc_name(ahc));
180065942Sgibbs		}
180165942Sgibbs
180265942Sgibbs		write_brdctl(ahc, brddat);
180365942Sgibbs
180465942Sgibbs	} else {
180565942Sgibbs		if ((adapter_control & CFSTERM) != 0) {
180665942Sgibbs			*sxfrctl1 |= STPWEN;
180765942Sgibbs
180865942Sgibbs			if (bootverbose)
180965942Sgibbs				printf("%s: %sLow byte termination Enabled\n",
181065942Sgibbs				       ahc_name(ahc),
181165942Sgibbs				       (ahc->features & AHC_ULTRA2) ? "Primary "
181265942Sgibbs								    : "");
181365942Sgibbs		}
181465942Sgibbs
181571390Sgibbs		if ((adapter_control & CFWSTERM) != 0
181671390Sgibbs		 && (ahc->features & AHC_WIDE) != 0) {
181765942Sgibbs			brddat |= BRDDAT6;
181865942Sgibbs			if (bootverbose)
181965942Sgibbs				printf("%s: %sHigh byte termination Enabled\n",
182065942Sgibbs				       ahc_name(ahc),
182165942Sgibbs				       (ahc->features & AHC_ULTRA2)
182265942Sgibbs				     ? "Secondary " : "");
182365942Sgibbs		}
182465942Sgibbs
182565942Sgibbs		/*
182665942Sgibbs		 * Setup STPWEN before setting up the rest of
182765942Sgibbs		 * the termination per the tech note on the U160 cards.
182865942Sgibbs		 */
182965942Sgibbs		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
183065942Sgibbs
183171390Sgibbs		if ((ahc->features & AHC_WIDE) != 0)
183271390Sgibbs			write_brdctl(ahc, brddat);
183365942Sgibbs	}
183465942Sgibbs	SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */
183565942Sgibbs}
183665942Sgibbs
183765942Sgibbsstatic void
183865942Sgibbsahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low,
183965942Sgibbs		    int *enableSEC_high, int *enablePRI_low,
184065942Sgibbs		    int *enablePRI_high, int *eeprom_present)
184165942Sgibbs{
184265942Sgibbs	uint8_t brdctl;
184365942Sgibbs
184465942Sgibbs	/*
184565942Sgibbs	 * BRDDAT7 = Eeprom
184665942Sgibbs	 * BRDDAT6 = Enable Secondary High Byte termination
184765942Sgibbs	 * BRDDAT5 = Enable Secondary Low Byte termination
184865942Sgibbs	 * BRDDAT4 = Enable Primary high byte termination
184965942Sgibbs	 * BRDDAT3 = Enable Primary low byte termination
185065942Sgibbs	 */
185165942Sgibbs	brdctl = read_brdctl(ahc);
185265942Sgibbs	*eeprom_present = brdctl & BRDDAT7;
185365942Sgibbs	*enableSEC_high = (brdctl & BRDDAT6);
185465942Sgibbs	*enableSEC_low = (brdctl & BRDDAT5);
185565942Sgibbs	*enablePRI_high = (brdctl & BRDDAT4);
185665942Sgibbs	*enablePRI_low = (brdctl & BRDDAT3);
185765942Sgibbs}
185865942Sgibbs
185965942Sgibbsstatic void
186065942Sgibbsaic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
186165942Sgibbs		     int *internal68_present, int *externalcable_present,
186265942Sgibbs		     int *eeprom_present)
186365942Sgibbs{
186465942Sgibbs	uint8_t brdctl;
186565942Sgibbs
186665942Sgibbs	/*
186765942Sgibbs	 * First read the status of our cables.
186865942Sgibbs	 * Set the rom bank to 0 since the
186965942Sgibbs	 * bank setting serves as a multiplexor
187065942Sgibbs	 * for the cable detection logic.
187165942Sgibbs	 * BRDDAT5 controls the bank switch.
187265942Sgibbs	 */
187365942Sgibbs	write_brdctl(ahc, 0);
187465942Sgibbs
187565942Sgibbs	/*
187665942Sgibbs	 * Now read the state of the internal
187765942Sgibbs	 * connectors.  BRDDAT6 is INT50 and
187865942Sgibbs	 * BRDDAT7 is INT68.
187965942Sgibbs	 */
188065942Sgibbs	brdctl = read_brdctl(ahc);
188171390Sgibbs	*internal50_present = (brdctl & BRDDAT6) ? 0 : 1;
188271390Sgibbs	*internal68_present = (brdctl & BRDDAT7) ? 0 : 1;
188365942Sgibbs
188465942Sgibbs	/*
188565942Sgibbs	 * Set the rom bank to 1 and determine
188665942Sgibbs	 * the other signals.
188765942Sgibbs	 */
188865942Sgibbs	write_brdctl(ahc, BRDDAT5);
188965942Sgibbs
189065942Sgibbs	/*
189165942Sgibbs	 * Now read the state of the external
189265942Sgibbs	 * connectors.  BRDDAT6 is EXT68 and
189365942Sgibbs	 * BRDDAT7 is EPROMPS.
189465942Sgibbs	 */
189565942Sgibbs	brdctl = read_brdctl(ahc);
189671390Sgibbs	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
189771390Sgibbs	*eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;
189865942Sgibbs}
189965942Sgibbs
190065942Sgibbsstatic void
190165942Sgibbsaic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
190265942Sgibbs		     int *externalcable_present, int *eeprom_present)
190365942Sgibbs{
190465942Sgibbs	uint8_t brdctl;
1905102676Sgibbs	uint8_t spiocap;
190665942Sgibbs
1907102676Sgibbs	spiocap = ahc_inb(ahc, SPIOCAP);
1908102676Sgibbs	spiocap &= ~SOFTCMDEN;
1909102676Sgibbs	spiocap |= EXT_BRDCTL;
1910102676Sgibbs	ahc_outb(ahc, SPIOCAP, spiocap);
191165942Sgibbs	ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
1912114621Sgibbs	ahc_flush_device_writes(ahc);
1913123579Sgibbs	aic_delay(500);
191465942Sgibbs	ahc_outb(ahc, BRDCTL, 0);
1915114621Sgibbs	ahc_flush_device_writes(ahc);
1916123579Sgibbs	aic_delay(500);
191765942Sgibbs	brdctl = ahc_inb(ahc, BRDCTL);
191871390Sgibbs	*internal50_present = (brdctl & BRDDAT5) ? 0 : 1;
191971390Sgibbs	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
192071390Sgibbs	*eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
192165942Sgibbs}
192265942Sgibbs
192395378Sgibbsint
192495378Sgibbsahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
192565942Sgibbs{
192665942Sgibbs	int wait;
192765942Sgibbs
192865942Sgibbs	if ((ahc->features & AHC_SPIOCAP) != 0
192965942Sgibbs	 && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0)
193065942Sgibbs		return (0);
193165942Sgibbs
193265942Sgibbs	/*
193365942Sgibbs	 * Request access of the memory port.  When access is
193465942Sgibbs	 * granted, SEERDY will go high.  We use a 1 second
193565942Sgibbs	 * timeout which should be near 1 second more than
193665942Sgibbs	 * is needed.  Reason: after the chip reset, there
193765942Sgibbs	 * should be no contention.
193865942Sgibbs	 */
193965942Sgibbs	SEEPROM_OUTB(sd, sd->sd_MS);
194065942Sgibbs	wait = 1000;  /* 1 second timeout in msec */
194165942Sgibbs	while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
1942123579Sgibbs		aic_delay(1000);  /* delay 1 msec */
194365942Sgibbs	}
194465942Sgibbs	if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
194565942Sgibbs		SEEPROM_OUTB(sd, 0);
194665942Sgibbs		return (0);
194765942Sgibbs	}
194865942Sgibbs	return(1);
194965942Sgibbs}
195065942Sgibbs
195195378Sgibbsvoid
195295378Sgibbsahc_release_seeprom(struct seeprom_descriptor *sd)
195365942Sgibbs{
195465942Sgibbs	/* Release access to the memory port and the serial EEPROM. */
195565942Sgibbs	SEEPROM_OUTB(sd, 0);
195665942Sgibbs}
195765942Sgibbs
195865942Sgibbsstatic void
195965942Sgibbswrite_brdctl(struct ahc_softc *ahc, uint8_t value)
196065942Sgibbs{
196165942Sgibbs	uint8_t brdctl;
196265942Sgibbs
196365942Sgibbs	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
196465942Sgibbs		brdctl = BRDSTB;
196565942Sgibbs	 	if (ahc->channel == 'B')
196665942Sgibbs			brdctl |= BRDCS;
196765942Sgibbs	} else if ((ahc->features & AHC_ULTRA2) != 0) {
196865942Sgibbs		brdctl = 0;
196965942Sgibbs	} else {
197065942Sgibbs		brdctl = BRDSTB|BRDCS;
197165942Sgibbs	}
197265942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
197371390Sgibbs	ahc_flush_device_writes(ahc);
197465942Sgibbs	brdctl |= value;
197565942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
197671390Sgibbs	ahc_flush_device_writes(ahc);
197765942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
197865942Sgibbs		brdctl |= BRDSTB_ULTRA2;
197965942Sgibbs	else
198065942Sgibbs		brdctl &= ~BRDSTB;
198165942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
198271390Sgibbs	ahc_flush_device_writes(ahc);
198365942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
198465942Sgibbs		brdctl = 0;
198565942Sgibbs	else
198665942Sgibbs		brdctl &= ~BRDCS;
198765942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
198865942Sgibbs}
198965942Sgibbs
199065942Sgibbsstatic uint8_t
1991115328Sgibbsread_brdctl(struct ahc_softc *ahc)
199265942Sgibbs{
199365942Sgibbs	uint8_t brdctl;
199465942Sgibbs	uint8_t value;
199565942Sgibbs
199665942Sgibbs	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
199765942Sgibbs		brdctl = BRDRW;
199865942Sgibbs	 	if (ahc->channel == 'B')
199965942Sgibbs			brdctl |= BRDCS;
200065942Sgibbs	} else if ((ahc->features & AHC_ULTRA2) != 0) {
200165942Sgibbs		brdctl = BRDRW_ULTRA2;
200265942Sgibbs	} else {
200365942Sgibbs		brdctl = BRDRW|BRDCS;
200465942Sgibbs	}
200565942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
200671390Sgibbs	ahc_flush_device_writes(ahc);
200765942Sgibbs	value = ahc_inb(ahc, BRDCTL);
200865942Sgibbs	ahc_outb(ahc, BRDCTL, 0);
200965942Sgibbs	return (value);
201065942Sgibbs}
201165942Sgibbs
2012114621Sgibbsstatic void
201365942Sgibbsahc_pci_intr(struct ahc_softc *ahc)
201465942Sgibbs{
201566269Sgibbs	u_int error;
201666269Sgibbs	u_int status1;
201765942Sgibbs
201866269Sgibbs	error = ahc_inb(ahc, ERROR);
201966269Sgibbs	if ((error & PCIERRSTAT) == 0)
202066269Sgibbs		return;
202166269Sgibbs
2022123579Sgibbs	status1 = aic_pci_read_config(ahc->dev_softc,
202365942Sgibbs				      PCIR_STATUS + 1, /*bytes*/1);
202465942Sgibbs
2025150453Sgibbs	if ((status1 & ~DPE) != 0
2026150453Sgibbs	 || (ahc->flags & AHC_DISABLE_PCI_PERR) == 0) {
2027150453Sgibbs		printf("%s: PCI error Interrupt at seqaddr = 0x%x\n",
2028150453Sgibbs		       ahc_name(ahc),
2029150453Sgibbs		       ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
2030150453Sgibbs	}
203166269Sgibbs
2032150453Sgibbs	if (status1 & DPE
2033150453Sgibbs	 && (ahc->flags & AHC_DISABLE_PCI_PERR) == 0) {
2034114621Sgibbs		ahc->pci_target_perr_count++;
203565942Sgibbs		printf("%s: Data Parity Error Detected during address "
203665942Sgibbs		       "or write data phase\n", ahc_name(ahc));
203765942Sgibbs	}
203865942Sgibbs	if (status1 & SSE) {
203966647Sgibbs		printf("%s: Signal System Error Detected\n", ahc_name(ahc));
204065942Sgibbs	}
204165942Sgibbs	if (status1 & RMA) {
204266647Sgibbs		printf("%s: Received a Master Abort\n", ahc_name(ahc));
204365942Sgibbs	}
204465942Sgibbs	if (status1 & RTA) {
204565942Sgibbs		printf("%s: Received a Target Abort\n", ahc_name(ahc));
204665942Sgibbs	}
204765942Sgibbs	if (status1 & STA) {
204865942Sgibbs		printf("%s: Signaled a Target Abort\n", ahc_name(ahc));
204965942Sgibbs	}
205065942Sgibbs	if (status1 & DPR) {
205165942Sgibbs		printf("%s: Data Parity Error has been reported via PERR#\n",
205265942Sgibbs		       ahc_name(ahc));
205365942Sgibbs	}
205479874Sgibbs
205579874Sgibbs	/* Clear latched errors. */
2056123579Sgibbs	aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
205779874Sgibbs			     status1, /*bytes*/1);
205879874Sgibbs
205965942Sgibbs	if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) {
206065942Sgibbs		printf("%s: Latched PCIERR interrupt with "
206165942Sgibbs		       "no status bits set\n", ahc_name(ahc));
206279874Sgibbs	} else {
206365942Sgibbs		ahc_outb(ahc, CLRINT, CLRPARERR);
206465942Sgibbs	}
206566269Sgibbs
2066150453Sgibbs	if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH
2067150453Sgibbs	 && (ahc->flags & AHC_DISABLE_PCI_PERR) == 0) {
2068114621Sgibbs		printf(
2069114621Sgibbs"%s: WARNING WARNING WARNING WARNING\n"
2070114621Sgibbs"%s: Too many PCI parity errors observed as a target.\n"
2071150453Sgibbs"%s: Some device on this PCI bus is generating bad parity.\n"
2072150453Sgibbs"%s: This is an error *observed by*, not *generated by*, %s.\n"
2073114621Sgibbs"%s: PCI parity error checking has been disabled.\n"
2074114621Sgibbs"%s: WARNING WARNING WARNING WARNING\n",
2075114621Sgibbs		       ahc_name(ahc), ahc_name(ahc), ahc_name(ahc),
2076150453Sgibbs		       ahc_name(ahc), ahc_name(ahc), ahc_name(ahc),
2077150453Sgibbs		       ahc_name(ahc));
2078115332Sgibbs		ahc->seqctl |= FAILDIS;
2079150453Sgibbs		ahc->flags |= AHC_DISABLE_PCI_PERR;
2080115332Sgibbs		ahc_outb(ahc, SEQCTL, ahc->seqctl);
2081114621Sgibbs	}
208274094Sgibbs	ahc_unpause(ahc);
208365942Sgibbs}
208465942Sgibbs
208565942Sgibbsstatic int
2086114621Sgibbsahc_pci_chip_init(struct ahc_softc *ahc)
2087114621Sgibbs{
2088114621Sgibbs	ahc_outb(ahc, DSCOMMAND0, ahc->bus_softc.pci_softc.dscommand0);
2089114621Sgibbs	ahc_outb(ahc, DSPCISTATUS, ahc->bus_softc.pci_softc.dspcistatus);
2090114621Sgibbs	if ((ahc->features & AHC_DT) != 0) {
2091114621Sgibbs		u_int sfunct;
2092114621Sgibbs
2093114621Sgibbs		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
2094114621Sgibbs		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
2095114621Sgibbs		ahc_outb(ahc, OPTIONMODE, ahc->bus_softc.pci_softc.optionmode);
2096114621Sgibbs		ahc_outw(ahc, TARGCRCCNT, ahc->bus_softc.pci_softc.targcrccnt);
2097114621Sgibbs		ahc_outb(ahc, SFUNCT, sfunct);
2098114621Sgibbs		ahc_outb(ahc, CRCCONTROL1,
2099114621Sgibbs			 ahc->bus_softc.pci_softc.crccontrol1);
2100114621Sgibbs	}
2101114621Sgibbs	if ((ahc->features & AHC_MULTI_FUNC) != 0)
2102114621Sgibbs		ahc_outb(ahc, SCBBADDR, ahc->bus_softc.pci_softc.scbbaddr);
2103114621Sgibbs
2104114621Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
2105114621Sgibbs		ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh);
2106114621Sgibbs
2107114621Sgibbs	return (ahc_chip_init(ahc));
2108114621Sgibbs}
2109114621Sgibbs
2110114621Sgibbsstatic int
2111114621Sgibbsahc_pci_suspend(struct ahc_softc *ahc)
2112114621Sgibbs{
2113114621Sgibbs	return (ahc_suspend(ahc));
2114114621Sgibbs}
2115114621Sgibbs
2116114621Sgibbsstatic int
2117114621Sgibbsahc_pci_resume(struct ahc_softc *ahc)
2118114621Sgibbs{
2119114621Sgibbs
2120123579Sgibbs	aic_power_state_change(ahc, AIC_POWER_STATE_D0);
2121114621Sgibbs
2122114621Sgibbs	/*
2123114621Sgibbs	 * We assume that the OS has restored our register
2124114621Sgibbs	 * mappings, etc.  Just update the config space registers
2125114621Sgibbs	 * that the OS doesn't know about and rely on our chip
2126114621Sgibbs	 * reset handler to handle the rest.
2127114621Sgibbs	 */
2128134157Sgibbs	aic_pci_write_config(ahc->dev_softc, DEVCONFIG,
2129134157Sgibbs			     ahc->bus_softc.pci_softc.devconfig, /*bytes*/4);
2130134157Sgibbs	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
2131134157Sgibbs			     ahc->bus_softc.pci_softc.command, /*bytes*/1);
2132134157Sgibbs	aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
2133134157Sgibbs			     ahc->bus_softc.pci_softc.csize_lattime,
2134134157Sgibbs			     /*bytes*/1);
2135114621Sgibbs	if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
2136114621Sgibbs		struct	seeprom_descriptor sd;
2137114621Sgibbs		u_int	sxfrctl1;
2138114621Sgibbs
2139114621Sgibbs		sd.sd_ahc = ahc;
2140114621Sgibbs		sd.sd_control_offset = SEECTL;
2141114621Sgibbs		sd.sd_status_offset = SEECTL;
2142114621Sgibbs		sd.sd_dataout_offset = SEECTL;
2143114621Sgibbs
2144114621Sgibbs		ahc_acquire_seeprom(ahc, &sd);
2145114621Sgibbs		configure_termination(ahc, &sd,
2146114621Sgibbs				      ahc->seep_config->adapter_control,
2147114621Sgibbs				      &sxfrctl1);
2148114621Sgibbs		ahc_release_seeprom(&sd);
2149114621Sgibbs	}
2150114621Sgibbs	return (ahc_resume(ahc));
2151114621Sgibbs}
2152114621Sgibbs
2153114621Sgibbsstatic int
215479874Sgibbsahc_aic785X_setup(struct ahc_softc *ahc)
215565942Sgibbs{
2156123579Sgibbs	aic_dev_softc_t pci;
215774094Sgibbs	uint8_t rev;
215874094Sgibbs
215979874Sgibbs	pci = ahc->dev_softc;
216079874Sgibbs	ahc->channel = 'A';
216179874Sgibbs	ahc->chip = AHC_AIC7850;
216279874Sgibbs	ahc->features = AHC_AIC7850_FE;
216379874Sgibbs	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2164123579Sgibbs	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
216574094Sgibbs	if (rev >= 1)
216679874Sgibbs		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
2167114621Sgibbs	ahc->instruction_ram_size = 512;
216865942Sgibbs	return (0);
216965942Sgibbs}
217065942Sgibbs
217165942Sgibbsstatic int
217279874Sgibbsahc_aic7860_setup(struct ahc_softc *ahc)
217365942Sgibbs{
2174123579Sgibbs	aic_dev_softc_t pci;
217565942Sgibbs	uint8_t rev;
217665942Sgibbs
217779874Sgibbs	pci = ahc->dev_softc;
217879874Sgibbs	ahc->channel = 'A';
217979874Sgibbs	ahc->chip = AHC_AIC7860;
218079874Sgibbs	ahc->features = AHC_AIC7860_FE;
218179874Sgibbs	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2182123579Sgibbs	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
218365942Sgibbs	if (rev >= 1)
218479874Sgibbs		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
2185114621Sgibbs	ahc->instruction_ram_size = 512;
218665942Sgibbs	return (0);
218765942Sgibbs}
218865942Sgibbs
218965942Sgibbsstatic int
219079874Sgibbsahc_apa1480_setup(struct ahc_softc *ahc)
219171390Sgibbs{
219271390Sgibbs	int error;
219371390Sgibbs
219479874Sgibbs	error = ahc_aic7860_setup(ahc);
219571390Sgibbs	if (error != 0)
219671390Sgibbs		return (error);
219779874Sgibbs	ahc->features |= AHC_REMOVABLE;
219871390Sgibbs	return (0);
219971390Sgibbs}
220071390Sgibbs
220171390Sgibbsstatic int
220279874Sgibbsahc_aic7870_setup(struct ahc_softc *ahc)
220365942Sgibbs{
220479874Sgibbs
220579874Sgibbs	ahc->channel = 'A';
220679874Sgibbs	ahc->chip = AHC_AIC7870;
220779874Sgibbs	ahc->features = AHC_AIC7870_FE;
220879874Sgibbs	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2209114621Sgibbs	ahc->instruction_ram_size = 512;
221065942Sgibbs	return (0);
221165942Sgibbs}
221265942Sgibbs
221365942Sgibbsstatic int
221479874Sgibbsahc_aha394X_setup(struct ahc_softc *ahc)
221565942Sgibbs{
221665942Sgibbs	int error;
221765942Sgibbs
221879874Sgibbs	error = ahc_aic7870_setup(ahc);
221965942Sgibbs	if (error == 0)
222079874Sgibbs		error = ahc_aha394XX_setup(ahc);
222165942Sgibbs	return (error);
222265942Sgibbs}
222365942Sgibbs
222465942Sgibbsstatic int
222579874Sgibbsahc_aha398X_setup(struct ahc_softc *ahc)
222665942Sgibbs{
222765942Sgibbs	int error;
222865942Sgibbs
222979874Sgibbs	error = ahc_aic7870_setup(ahc);
223065942Sgibbs	if (error == 0)
223179874Sgibbs		error = ahc_aha398XX_setup(ahc);
223265942Sgibbs	return (error);
223365942Sgibbs}
223465942Sgibbs
223565942Sgibbsstatic int
223679874Sgibbsahc_aha494X_setup(struct ahc_softc *ahc)
223765942Sgibbs{
223865942Sgibbs	int error;
223965942Sgibbs
224079874Sgibbs	error = ahc_aic7870_setup(ahc);
224165942Sgibbs	if (error == 0)
224279874Sgibbs		error = ahc_aha494XX_setup(ahc);
224365942Sgibbs	return (error);
224465942Sgibbs}
224565942Sgibbs
224665942Sgibbsstatic int
224779874Sgibbsahc_aic7880_setup(struct ahc_softc *ahc)
224865942Sgibbs{
2249123579Sgibbs	aic_dev_softc_t pci;
225065942Sgibbs	uint8_t rev;
225165942Sgibbs
225279874Sgibbs	pci = ahc->dev_softc;
225379874Sgibbs	ahc->channel = 'A';
225479874Sgibbs	ahc->chip = AHC_AIC7880;
225579874Sgibbs	ahc->features = AHC_AIC7880_FE;
225679874Sgibbs	ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
2257123579Sgibbs	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
225865942Sgibbs	if (rev >= 1) {
225979874Sgibbs		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
226065942Sgibbs	} else {
226179874Sgibbs		ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
226265942Sgibbs	}
2263114621Sgibbs	ahc->instruction_ram_size = 512;
226465942Sgibbs	return (0);
226565942Sgibbs}
226665942Sgibbs
226765942Sgibbsstatic int
226879874Sgibbsahc_aha2940Pro_setup(struct ahc_softc *ahc)
226965942Sgibbs{
227065942Sgibbs
227179874Sgibbs	ahc->flags |= AHC_INT50_SPEEDFLEX;
2272102676Sgibbs	return (ahc_aic7880_setup(ahc));
227365942Sgibbs}
227465942Sgibbs
227565942Sgibbsstatic int
227679874Sgibbsahc_aha394XU_setup(struct ahc_softc *ahc)
227765942Sgibbs{
227865942Sgibbs	int error;
227965942Sgibbs
228079874Sgibbs	error = ahc_aic7880_setup(ahc);
228165942Sgibbs	if (error == 0)
228279874Sgibbs		error = ahc_aha394XX_setup(ahc);
228365942Sgibbs	return (error);
228465942Sgibbs}
228565942Sgibbs
228665942Sgibbsstatic int
228779874Sgibbsahc_aha398XU_setup(struct ahc_softc *ahc)
228865942Sgibbs{
228965942Sgibbs	int error;
229065942Sgibbs
229179874Sgibbs	error = ahc_aic7880_setup(ahc);
229265942Sgibbs	if (error == 0)
229379874Sgibbs		error = ahc_aha398XX_setup(ahc);
229465942Sgibbs	return (error);
229565942Sgibbs}
229665942Sgibbs
229765942Sgibbsstatic int
229879874Sgibbsahc_aic7890_setup(struct ahc_softc *ahc)
229965942Sgibbs{
2300123579Sgibbs	aic_dev_softc_t pci;
230165942Sgibbs	uint8_t rev;
230265942Sgibbs
230379874Sgibbs	pci = ahc->dev_softc;
230479874Sgibbs	ahc->channel = 'A';
230579874Sgibbs	ahc->chip = AHC_AIC7890;
230679874Sgibbs	ahc->features = AHC_AIC7890_FE;
230779874Sgibbs	ahc->flags |= AHC_NEWEEPROM_FMT;
2308123579Sgibbs	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
230965942Sgibbs	if (rev == 0)
231079874Sgibbs		ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG;
2311114621Sgibbs	ahc->instruction_ram_size = 768;
231265942Sgibbs	return (0);
231365942Sgibbs}
231465942Sgibbs
231565942Sgibbsstatic int
231679874Sgibbsahc_aic7892_setup(struct ahc_softc *ahc)
231765942Sgibbs{
231879874Sgibbs
231979874Sgibbs	ahc->channel = 'A';
232079874Sgibbs	ahc->chip = AHC_AIC7892;
232179874Sgibbs	ahc->features = AHC_AIC7892_FE;
232279874Sgibbs	ahc->flags |= AHC_NEWEEPROM_FMT;
232379874Sgibbs	ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
2324114621Sgibbs	ahc->instruction_ram_size = 1024;
232565942Sgibbs	return (0);
232665942Sgibbs}
232765942Sgibbs
232865942Sgibbsstatic int
232979874Sgibbsahc_aic7895_setup(struct ahc_softc *ahc)
233065942Sgibbs{
2331123579Sgibbs	aic_dev_softc_t pci;
233265942Sgibbs	uint8_t rev;
233365942Sgibbs
233479874Sgibbs	pci = ahc->dev_softc;
2335123579Sgibbs	ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A';
233665942Sgibbs	/*
233765942Sgibbs	 * The 'C' revision of the aic7895 has a few additional features.
233865942Sgibbs	 */
2339123579Sgibbs	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
234065942Sgibbs	if (rev >= 4) {
234179874Sgibbs		ahc->chip = AHC_AIC7895C;
234279874Sgibbs		ahc->features = AHC_AIC7895C_FE;
234365942Sgibbs	} else  {
234465942Sgibbs		u_int command;
234565942Sgibbs
234679874Sgibbs		ahc->chip = AHC_AIC7895;
234779874Sgibbs		ahc->features = AHC_AIC7895_FE;
234865942Sgibbs
234965942Sgibbs		/*
235065942Sgibbs		 * The BIOS disables the use of MWI transactions
235165942Sgibbs		 * since it does not have the MWI bug work around
235265942Sgibbs		 * we have.  Disabling MWI reduces performance, so
235365942Sgibbs		 * turn it on again.
235465942Sgibbs		 */
2355123579Sgibbs		command = aic_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1);
235665942Sgibbs		command |= PCIM_CMD_MWRICEN;
2357123579Sgibbs		aic_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1);
235879874Sgibbs		ahc->bugs |= AHC_PCI_MWI_BUG;
235965942Sgibbs	}
236065942Sgibbs	/*
236165942Sgibbs	 * XXX Does CACHETHEN really not work???  What about PCI retry?
236265942Sgibbs	 * on C level chips.  Need to test, but for now, play it safe.
236365942Sgibbs	 */
236479874Sgibbs	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG
236579874Sgibbs		  |  AHC_CACHETHEN_BUG;
236665942Sgibbs
236765942Sgibbs#if 0
236865942Sgibbs	uint32_t devconfig;
236965942Sgibbs
237065942Sgibbs	/*
237165942Sgibbs	 * Cachesize must also be zero due to stray DAC
237265942Sgibbs	 * problem when sitting behind some bridges.
237365942Sgibbs	 */
2374123579Sgibbs	aic_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1);
2375123579Sgibbs	devconfig = aic_pci_read_config(pci, DEVCONFIG, /*bytes*/1);
237665942Sgibbs	devconfig |= MRDCEN;
2377123579Sgibbs	aic_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1);
237865942Sgibbs#endif
237979874Sgibbs	ahc->flags |= AHC_NEWEEPROM_FMT;
2380114621Sgibbs	ahc->instruction_ram_size = 512;
238165942Sgibbs	return (0);
238265942Sgibbs}
238365942Sgibbs
238465942Sgibbsstatic int
238579874Sgibbsahc_aic7896_setup(struct ahc_softc *ahc)
238665942Sgibbs{
2387123579Sgibbs	aic_dev_softc_t pci;
238879874Sgibbs
238979874Sgibbs	pci = ahc->dev_softc;
2390123579Sgibbs	ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A';
239179874Sgibbs	ahc->chip = AHC_AIC7896;
239279874Sgibbs	ahc->features = AHC_AIC7896_FE;
239379874Sgibbs	ahc->flags |= AHC_NEWEEPROM_FMT;
239479874Sgibbs	ahc->bugs |= AHC_CACHETHEN_DIS_BUG;
2395114621Sgibbs	ahc->instruction_ram_size = 768;
239665942Sgibbs	return (0);
239765942Sgibbs}
239865942Sgibbs
239965942Sgibbsstatic int
240079874Sgibbsahc_aic7899_setup(struct ahc_softc *ahc)
240165942Sgibbs{
2402123579Sgibbs	aic_dev_softc_t pci;
240379874Sgibbs
240479874Sgibbs	pci = ahc->dev_softc;
2405123579Sgibbs	ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A';
240679874Sgibbs	ahc->chip = AHC_AIC7899;
240779874Sgibbs	ahc->features = AHC_AIC7899_FE;
240879874Sgibbs	ahc->flags |= AHC_NEWEEPROM_FMT;
240979874Sgibbs	ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
2410114621Sgibbs	ahc->instruction_ram_size = 1024;
241165942Sgibbs	return (0);
241265942Sgibbs}
241365942Sgibbs
241465942Sgibbsstatic int
241579874Sgibbsahc_aha29160C_setup(struct ahc_softc *ahc)
241671390Sgibbs{
241771390Sgibbs	int error;
241871390Sgibbs
241979874Sgibbs	error = ahc_aic7899_setup(ahc);
242071390Sgibbs	if (error != 0)
242171390Sgibbs		return (error);
242279874Sgibbs	ahc->features |= AHC_REMOVABLE;
242371390Sgibbs	return (0);
242471390Sgibbs}
242571390Sgibbs
242671390Sgibbsstatic int
242779874Sgibbsahc_raid_setup(struct ahc_softc *ahc)
242865942Sgibbs{
242965942Sgibbs	printf("RAID functionality unsupported\n");
243065942Sgibbs	return (ENXIO);
243165942Sgibbs}
243265942Sgibbs
243365942Sgibbsstatic int
243479874Sgibbsahc_aha394XX_setup(struct ahc_softc *ahc)
243565942Sgibbs{
2436123579Sgibbs	aic_dev_softc_t pci;
243779874Sgibbs
243879874Sgibbs	pci = ahc->dev_softc;
2439123579Sgibbs	switch (aic_get_pci_slot(pci)) {
244065942Sgibbs	case AHC_394X_SLOT_CHANNEL_A:
244179874Sgibbs		ahc->channel = 'A';
244265942Sgibbs		break;
244365942Sgibbs	case AHC_394X_SLOT_CHANNEL_B:
244479874Sgibbs		ahc->channel = 'B';
244565942Sgibbs		break;
244665942Sgibbs	default:
244765942Sgibbs		printf("adapter at unexpected slot %d\n"
244865942Sgibbs		       "unable to map to a channel\n",
2449123579Sgibbs		       aic_get_pci_slot(pci));
245079874Sgibbs		ahc->channel = 'A';
245165942Sgibbs	}
245265942Sgibbs	return (0);
245365942Sgibbs}
245465942Sgibbs
245565942Sgibbsstatic int
245679874Sgibbsahc_aha398XX_setup(struct ahc_softc *ahc)
245765942Sgibbs{
2458123579Sgibbs	aic_dev_softc_t pci;
245979874Sgibbs
246079874Sgibbs	pci = ahc->dev_softc;
2461123579Sgibbs	switch (aic_get_pci_slot(pci)) {
246265942Sgibbs	case AHC_398X_SLOT_CHANNEL_A:
246379874Sgibbs		ahc->channel = 'A';
246465942Sgibbs		break;
246565942Sgibbs	case AHC_398X_SLOT_CHANNEL_B:
246679874Sgibbs		ahc->channel = 'B';
246765942Sgibbs		break;
246865942Sgibbs	case AHC_398X_SLOT_CHANNEL_C:
246979874Sgibbs		ahc->channel = 'C';
247065942Sgibbs		break;
247165942Sgibbs	default:
247265942Sgibbs		printf("adapter at unexpected slot %d\n"
247365942Sgibbs		       "unable to map to a channel\n",
2474123579Sgibbs		       aic_get_pci_slot(pci));
247579874Sgibbs		ahc->channel = 'A';
247665942Sgibbs		break;
247765942Sgibbs	}
247879874Sgibbs	ahc->flags |= AHC_LARGE_SEEPROM;
247965942Sgibbs	return (0);
248065942Sgibbs}
248165942Sgibbs
248265942Sgibbsstatic int
248379874Sgibbsahc_aha494XX_setup(struct ahc_softc *ahc)
248465942Sgibbs{
2485123579Sgibbs	aic_dev_softc_t pci;
248679874Sgibbs
248779874Sgibbs	pci = ahc->dev_softc;
2488123579Sgibbs	switch (aic_get_pci_slot(pci)) {
248965942Sgibbs	case AHC_494X_SLOT_CHANNEL_A:
249079874Sgibbs		ahc->channel = 'A';
249165942Sgibbs		break;
249265942Sgibbs	case AHC_494X_SLOT_CHANNEL_B:
249379874Sgibbs		ahc->channel = 'B';
249465942Sgibbs		break;
249565942Sgibbs	case AHC_494X_SLOT_CHANNEL_C:
249679874Sgibbs		ahc->channel = 'C';
249765942Sgibbs		break;
249865942Sgibbs	case AHC_494X_SLOT_CHANNEL_D:
249979874Sgibbs		ahc->channel = 'D';
250065942Sgibbs		break;
250165942Sgibbs	default:
250265942Sgibbs		printf("adapter at unexpected slot %d\n"
250365942Sgibbs		       "unable to map to a channel\n",
2504123579Sgibbs		       aic_get_pci_slot(pci));
250579874Sgibbs		ahc->channel = 'A';
250665942Sgibbs	}
250779874Sgibbs	ahc->flags |= AHC_LARGE_SEEPROM;
250865942Sgibbs	return (0);
250965942Sgibbs}
2510