xref: /freebsd/sys/dev/aic7xxx/aic7xxx_pci.c (revision 65971073d935e8314bff8bca26d1445e9e336fce)
1098ca2bdSWarner Losh /*-
2717d4247SJustin T. Gibbs  * Product specific probe and attach routines for:
3717d4247SJustin T. Gibbs  *      3940, 2940, aic7895, aic7890, aic7880,
4717d4247SJustin T. Gibbs  *	aic7870, aic7860 and aic7850 SCSI controllers
5717d4247SJustin T. Gibbs  *
6*718cf2ccSPedro F. Giffuni  * SPDX-License-Identifier: BSD-3-Clause
7*718cf2ccSPedro F. Giffuni  *
88f214efcSJustin T. Gibbs  * Copyright (c) 1994-2001 Justin T. Gibbs.
98f214efcSJustin T. Gibbs  * Copyright (c) 2000-2001 Adaptec Inc.
10717d4247SJustin T. Gibbs  * All rights reserved.
11717d4247SJustin T. Gibbs  *
12717d4247SJustin T. Gibbs  * Redistribution and use in source and binary forms, with or without
13717d4247SJustin T. Gibbs  * modification, are permitted provided that the following conditions
14717d4247SJustin T. Gibbs  * are met:
15717d4247SJustin T. Gibbs  * 1. Redistributions of source code must retain the above copyright
16717d4247SJustin T. Gibbs  *    notice, this list of conditions, and the following disclaimer,
178f214efcSJustin T. Gibbs  *    without modification.
188f214efcSJustin T. Gibbs  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
198f214efcSJustin T. Gibbs  *    substantially similar to the "NO WARRANTY" disclaimer below
208f214efcSJustin T. Gibbs  *    ("Disclaimer") and any redistribution must be conditioned upon
218f214efcSJustin T. Gibbs  *    including a substantially similar Disclaimer requirement for further
228f214efcSJustin T. Gibbs  *    binary redistribution.
238f214efcSJustin T. Gibbs  * 3. Neither the names of the above-listed copyright holders nor the names
248f214efcSJustin T. Gibbs  *    of any contributors may be used to endorse or promote products derived
258f214efcSJustin T. Gibbs  *    from this software without specific prior written permission.
26717d4247SJustin T. Gibbs  *
27717d4247SJustin T. Gibbs  * Alternatively, this software may be distributed under the terms of the
288f214efcSJustin T. Gibbs  * GNU General Public License ("GPL") version 2 as published by the Free
298f214efcSJustin T. Gibbs  * Software Foundation.
30717d4247SJustin T. Gibbs  *
318f214efcSJustin T. Gibbs  * NO WARRANTY
328f214efcSJustin T. Gibbs  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
338f214efcSJustin T. Gibbs  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
348f214efcSJustin T. Gibbs  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
358f214efcSJustin T. Gibbs  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
368f214efcSJustin T. Gibbs  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37717d4247SJustin T. Gibbs  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38717d4247SJustin T. Gibbs  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
398f214efcSJustin T. Gibbs  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
408f214efcSJustin T. Gibbs  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
418f214efcSJustin T. Gibbs  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
428f214efcSJustin T. Gibbs  * POSSIBILITY OF SUCH DAMAGES.
43717d4247SJustin T. Gibbs  *
44b3b25f2cSJustin T. Gibbs  * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#78 $
45717d4247SJustin T. Gibbs  */
46717d4247SJustin T. Gibbs 
478f214efcSJustin T. Gibbs #include <dev/aic7xxx/aic7xxx_osm.h>
48717d4247SJustin T. Gibbs #include <dev/aic7xxx/aic7xxx_inline.h>
49717d4247SJustin T. Gibbs #include <dev/aic7xxx/aic7xxx_93cx6.h>
50717d4247SJustin T. Gibbs 
51717d4247SJustin T. Gibbs static __inline uint64_t
52717d4247SJustin T. Gibbs ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
53717d4247SJustin T. Gibbs {
54717d4247SJustin T. Gibbs 	uint64_t id;
55717d4247SJustin T. Gibbs 
56717d4247SJustin T. Gibbs 	id = subvendor
57717d4247SJustin T. Gibbs 	   | (subdevice << 16)
58717d4247SJustin T. Gibbs 	   | ((uint64_t)vendor << 32)
59717d4247SJustin T. Gibbs 	   | ((uint64_t)device << 48);
60717d4247SJustin T. Gibbs 
61717d4247SJustin T. Gibbs 	return (id);
62717d4247SJustin T. Gibbs }
63717d4247SJustin T. Gibbs 
64717d4247SJustin T. Gibbs #define ID_ALL_MASK			0xFFFFFFFFFFFFFFFFull
65717d4247SJustin T. Gibbs #define ID_DEV_VENDOR_MASK		0xFFFFFFFF00000000ull
66bfadd24dSJustin T. Gibbs #define ID_9005_GENERIC_MASK		0xFFF0FFFF00000000ull
671478c711SJustin T. Gibbs #define ID_9005_SISL_MASK		0x000FFFFF00000000ull
681478c711SJustin T. Gibbs #define ID_9005_SISL_ID			0x0005900500000000ull
69717d4247SJustin T. Gibbs #define ID_AIC7850			0x5078900400000000ull
70177799b5SJustin T. Gibbs #define ID_AHA_2902_04_10_15_20C_30C	0x5078900478509004ull
71717d4247SJustin T. Gibbs #define ID_AIC7855			0x5578900400000000ull
72717d4247SJustin T. Gibbs #define ID_AIC7859			0x3860900400000000ull
73717d4247SJustin T. Gibbs #define ID_AHA_2930CU			0x3860900438699004ull
74717d4247SJustin T. Gibbs #define ID_AIC7860			0x6078900400000000ull
75717d4247SJustin T. Gibbs #define ID_AIC7860C			0x6078900478609004ull
76717d4247SJustin T. Gibbs #define ID_AHA_1480A			0x6075900400000000ull
77717d4247SJustin T. Gibbs #define ID_AHA_2940AU_0			0x6178900400000000ull
78717d4247SJustin T. Gibbs #define ID_AHA_2940AU_1			0x6178900478619004ull
79717d4247SJustin T. Gibbs #define ID_AHA_2940AU_CN		0x2178900478219004ull
80717d4247SJustin T. Gibbs #define ID_AHA_2930C_VAR		0x6038900438689004ull
81717d4247SJustin T. Gibbs 
82717d4247SJustin T. Gibbs #define ID_AIC7870			0x7078900400000000ull
83717d4247SJustin T. Gibbs #define ID_AHA_2940			0x7178900400000000ull
84717d4247SJustin T. Gibbs #define ID_AHA_3940			0x7278900400000000ull
85717d4247SJustin T. Gibbs #define ID_AHA_398X			0x7378900400000000ull
86717d4247SJustin T. Gibbs #define ID_AHA_2944			0x7478900400000000ull
87717d4247SJustin T. Gibbs #define ID_AHA_3944			0x7578900400000000ull
88717d4247SJustin T. Gibbs #define ID_AHA_4944			0x7678900400000000ull
89717d4247SJustin T. Gibbs 
90717d4247SJustin T. Gibbs #define ID_AIC7880			0x8078900400000000ull
91717d4247SJustin T. Gibbs #define ID_AIC7880_B			0x8078900478809004ull
92717d4247SJustin T. Gibbs #define ID_AHA_2940U			0x8178900400000000ull
93717d4247SJustin T. Gibbs #define ID_AHA_3940U			0x8278900400000000ull
94717d4247SJustin T. Gibbs #define ID_AHA_2944U			0x8478900400000000ull
95717d4247SJustin T. Gibbs #define ID_AHA_3944U			0x8578900400000000ull
96717d4247SJustin T. Gibbs #define ID_AHA_398XU			0x8378900400000000ull
97717d4247SJustin T. Gibbs #define ID_AHA_4944U			0x8678900400000000ull
98717d4247SJustin T. Gibbs #define ID_AHA_2940UB			0x8178900478819004ull
99717d4247SJustin T. Gibbs #define ID_AHA_2930U			0x8878900478889004ull
100717d4247SJustin T. Gibbs #define ID_AHA_2940U_PRO		0x8778900478879004ull
101717d4247SJustin T. Gibbs #define ID_AHA_2940U_CN			0x0078900478009004ull
102717d4247SJustin T. Gibbs 
103717d4247SJustin T. Gibbs #define ID_AIC7895			0x7895900478959004ull
1041478c711SJustin T. Gibbs #define ID_AIC7895_ARO			0x7890900478939004ull
1051478c711SJustin T. Gibbs #define ID_AIC7895_ARO_MASK		0xFFF0FFFFFFFFFFFFull
106717d4247SJustin T. Gibbs #define ID_AHA_2940U_DUAL		0x7895900478919004ull
107717d4247SJustin T. Gibbs #define ID_AHA_3940AU			0x7895900478929004ull
108717d4247SJustin T. Gibbs #define ID_AHA_3944AU			0x7895900478949004ull
109717d4247SJustin T. Gibbs 
110717d4247SJustin T. Gibbs #define ID_AIC7890			0x001F9005000F9005ull
1111478c711SJustin T. Gibbs #define ID_AIC7890_ARO			0x00139005000F9005ull
112717d4247SJustin T. Gibbs #define ID_AAA_131U2			0x0013900500039005ull
113717d4247SJustin T. Gibbs #define ID_AHA_2930U2			0x0011900501819005ull
114717d4247SJustin T. Gibbs #define ID_AHA_2940U2B			0x00109005A1009005ull
115717d4247SJustin T. Gibbs #define ID_AHA_2940U2_OEM		0x0010900521809005ull
116717d4247SJustin T. Gibbs #define ID_AHA_2940U2			0x00109005A1809005ull
117717d4247SJustin T. Gibbs #define ID_AHA_2950U2B			0x00109005E1009005ull
118717d4247SJustin T. Gibbs 
119717d4247SJustin T. Gibbs #define ID_AIC7892			0x008F9005FFFF9005ull
1201478c711SJustin T. Gibbs #define ID_AIC7892_ARO			0x00839005FFFF9005ull
121717d4247SJustin T. Gibbs #define ID_AHA_29160			0x00809005E2A09005ull
122717d4247SJustin T. Gibbs #define ID_AHA_29160_CPQ		0x00809005E2A00E11ull
123717d4247SJustin T. Gibbs #define ID_AHA_29160N			0x0080900562A09005ull
12456a7c4a8SJustin T. Gibbs #define ID_AHA_29160C			0x0080900562209005ull
125717d4247SJustin T. Gibbs #define ID_AHA_29160B			0x00809005E2209005ull
126717d4247SJustin T. Gibbs #define ID_AHA_19160B			0x0081900562A19005ull
127b3b25f2cSJustin T. Gibbs #define ID_AHA_2915_30LP		0x0082900502109005ull
128717d4247SJustin T. Gibbs 
129717d4247SJustin T. Gibbs #define ID_AIC7896			0x005F9005FFFF9005ull
1301478c711SJustin T. Gibbs #define ID_AIC7896_ARO			0x00539005FFFF9005ull
131717d4247SJustin T. Gibbs #define ID_AHA_3950U2B_0		0x00509005FFFF9005ull
132717d4247SJustin T. Gibbs #define ID_AHA_3950U2B_1		0x00509005F5009005ull
133717d4247SJustin T. Gibbs #define ID_AHA_3950U2D_0		0x00519005FFFF9005ull
134717d4247SJustin T. Gibbs #define ID_AHA_3950U2D_1		0x00519005B5009005ull
135717d4247SJustin T. Gibbs 
136717d4247SJustin T. Gibbs #define ID_AIC7899			0x00CF9005FFFF9005ull
1371478c711SJustin T. Gibbs #define ID_AIC7899_ARO			0x00C39005FFFF9005ull
1386fb77fefSJustin T. Gibbs #define ID_AHA_3960D			0x00C09005F6209005ull
139717d4247SJustin T. Gibbs #define ID_AHA_3960D_CPQ		0x00C09005F6200E11ull
140717d4247SJustin T. Gibbs 
141717d4247SJustin T. Gibbs #define ID_AIC7810			0x1078900400000000ull
142717d4247SJustin T. Gibbs #define ID_AIC7815			0x7815900400000000ull
143717d4247SJustin T. Gibbs 
144bfadd24dSJustin T. Gibbs #define DEVID_9005_TYPE(id) ((id) & 0xF)
145bfadd24dSJustin T. Gibbs #define		DEVID_9005_TYPE_HBA		0x0	/* Standard Card */
146bfadd24dSJustin T. Gibbs #define		DEVID_9005_TYPE_AAA		0x3	/* RAID Card */
1478f214efcSJustin T. Gibbs #define		DEVID_9005_TYPE_SISL		0x5	/* Container ROMB */
148bfadd24dSJustin T. Gibbs #define		DEVID_9005_TYPE_MB		0xF	/* On Motherboard */
149bfadd24dSJustin T. Gibbs 
150bfadd24dSJustin T. Gibbs #define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
151bfadd24dSJustin T. Gibbs #define		DEVID_9005_MAXRATE_U160		0x0
152bfadd24dSJustin T. Gibbs #define		DEVID_9005_MAXRATE_ULTRA2	0x1
153bfadd24dSJustin T. Gibbs #define		DEVID_9005_MAXRATE_ULTRA	0x2
154bfadd24dSJustin T. Gibbs #define		DEVID_9005_MAXRATE_FAST		0x3
155bfadd24dSJustin T. Gibbs 
156bfadd24dSJustin T. Gibbs #define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6)
157bfadd24dSJustin T. Gibbs 
158bfadd24dSJustin T. Gibbs #define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8)
159bfadd24dSJustin T. Gibbs #define		DEVID_9005_CLASS_SPI		0x0	/* Parallel SCSI */
160bfadd24dSJustin T. Gibbs 
161f8838555SJustin T. Gibbs #define SUBID_9005_TYPE(id) ((id) & 0xF)
162f8838555SJustin T. Gibbs #define		SUBID_9005_TYPE_MB		0xF	/* On Motherboard */
163f8838555SJustin T. Gibbs #define		SUBID_9005_TYPE_CARD		0x0	/* Standard Card */
164f8838555SJustin T. Gibbs #define		SUBID_9005_TYPE_LCCARD		0x1	/* Low Cost Card */
165f8838555SJustin T. Gibbs #define		SUBID_9005_TYPE_RAID		0x3	/* Combined with Raid */
166f8838555SJustin T. Gibbs 
1671478c711SJustin T. Gibbs #define SUBID_9005_TYPE_KNOWN(id)			\
1681478c711SJustin T. Gibbs 	  ((((id) & 0xF) == SUBID_9005_TYPE_MB)		\
1691478c711SJustin T. Gibbs 	|| (((id) & 0xF) == SUBID_9005_TYPE_CARD)	\
1701478c711SJustin T. Gibbs 	|| (((id) & 0xF) == SUBID_9005_TYPE_LCCARD)	\
1711478c711SJustin T. Gibbs 	|| (((id) & 0xF) == SUBID_9005_TYPE_RAID))
1721478c711SJustin T. Gibbs 
173f8838555SJustin T. Gibbs #define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
174f8838555SJustin T. Gibbs #define		SUBID_9005_MAXRATE_ULTRA2	0x0
175f8838555SJustin T. Gibbs #define		SUBID_9005_MAXRATE_ULTRA	0x1
176f8838555SJustin T. Gibbs #define		SUBID_9005_MAXRATE_U160		0x2
177f8838555SJustin T. Gibbs #define		SUBID_9005_MAXRATE_RESERVED	0x3
178f8838555SJustin T. Gibbs 
179f8838555SJustin T. Gibbs #define SUBID_9005_SEEPTYPE(id)						\
180f8838555SJustin T. Gibbs 	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
181f8838555SJustin T. Gibbs 	 ? ((id) & 0xC0) >> 6						\
182f8838555SJustin T. Gibbs 	 : ((id) & 0x300) >> 8)
183f8838555SJustin T. Gibbs #define		SUBID_9005_SEEPTYPE_NONE	0x0
184f8838555SJustin T. Gibbs #define		SUBID_9005_SEEPTYPE_1K		0x1
185f8838555SJustin T. Gibbs #define		SUBID_9005_SEEPTYPE_2K_4K	0x2
186f8838555SJustin T. Gibbs #define		SUBID_9005_SEEPTYPE_RESERVED	0x3
187f8838555SJustin T. Gibbs #define SUBID_9005_AUTOTERM(id)						\
188f8838555SJustin T. Gibbs 	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
189f8838555SJustin T. Gibbs 	 ? (((id) & 0x400) >> 10) == 0					\
190f8838555SJustin T. Gibbs 	 : (((id) & 0x40) >> 6) == 0)
191f8838555SJustin T. Gibbs 
192f8838555SJustin T. Gibbs #define SUBID_9005_NUMCHAN(id)						\
193f8838555SJustin T. Gibbs 	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
194f8838555SJustin T. Gibbs 	 ? ((id) & 0x300) >> 8						\
195f8838555SJustin T. Gibbs 	 : ((id) & 0xC00) >> 10)
196f8838555SJustin T. Gibbs 
197f8838555SJustin T. Gibbs #define SUBID_9005_LEGACYCONN(id)					\
198f8838555SJustin T. Gibbs 	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
199f8838555SJustin T. Gibbs 	 ? 0								\
200f8838555SJustin T. Gibbs 	 : ((id) & 0x80) >> 7)
201f8838555SJustin T. Gibbs 
202f8838555SJustin T. Gibbs #define SUBID_9005_MFUNCENB(id)						\
203f8838555SJustin T. Gibbs 	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
204f8838555SJustin T. Gibbs 	 ? ((id) & 0x800) >> 11						\
205f8838555SJustin T. Gibbs 	 : ((id) & 0x1000) >> 12)
206f8838555SJustin T. Gibbs /*
207f8838555SJustin T. Gibbs  * Informational only. Should use chip register to be
2088f214efcSJustin T. Gibbs  * certain, but may be use in identification strings.
209f8838555SJustin T. Gibbs  */
210f8838555SJustin T. Gibbs #define SUBID_9005_CARD_SCSIWIDTH_MASK	0x2000
211f8838555SJustin T. Gibbs #define SUBID_9005_CARD_PCIWIDTH_MASK	0x4000
212f8838555SJustin T. Gibbs #define SUBID_9005_CARD_SEDIFF_MASK	0x8000
21356a7c4a8SJustin T. Gibbs 
2146fb77fefSJustin T. Gibbs static ahc_device_setup_t ahc_aic785X_setup;
215717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7860_setup;
216a5847d5cSJustin T. Gibbs static ahc_device_setup_t ahc_apa1480_setup;
217717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7870_setup;
218717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha394X_setup;
219717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha494X_setup;
220717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha398X_setup;
221717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7880_setup;
222a5847d5cSJustin T. Gibbs static ahc_device_setup_t ahc_aha2940Pro_setup;
223717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha394XU_setup;
224717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha398XU_setup;
225717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7890_setup;
226717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7892_setup;
227717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7895_setup;
228717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7896_setup;
229717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aic7899_setup;
230a5847d5cSJustin T. Gibbs static ahc_device_setup_t ahc_aha29160C_setup;
231717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_raid_setup;
232717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha394XX_setup;
233717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha494XX_setup;
234717d4247SJustin T. Gibbs static ahc_device_setup_t ahc_aha398XX_setup;
235717d4247SJustin T. Gibbs 
236717d4247SJustin T. Gibbs struct ahc_pci_identity ahc_pci_ident_table [] =
237717d4247SJustin T. Gibbs {
238717d4247SJustin T. Gibbs 	/* aic7850 based controllers */
239717d4247SJustin T. Gibbs 	{
240177799b5SJustin T. Gibbs 		ID_AHA_2902_04_10_15_20C_30C,
241717d4247SJustin T. Gibbs 		ID_ALL_MASK,
242177799b5SJustin T. Gibbs 		"Adaptec 2902/04/10/15/20C/30C SCSI adapter",
2436fb77fefSJustin T. Gibbs 		ahc_aic785X_setup
244717d4247SJustin T. Gibbs 	},
245717d4247SJustin T. Gibbs 	/* aic7860 based controllers */
246717d4247SJustin T. Gibbs 	{
247717d4247SJustin T. Gibbs 		ID_AHA_2930CU,
248717d4247SJustin T. Gibbs 		ID_ALL_MASK,
249717d4247SJustin T. Gibbs 		"Adaptec 2930CU SCSI adapter",
250717d4247SJustin T. Gibbs 		ahc_aic7860_setup
251717d4247SJustin T. Gibbs 	},
252717d4247SJustin T. Gibbs 	{
253717d4247SJustin T. Gibbs 		ID_AHA_1480A & ID_DEV_VENDOR_MASK,
254717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
255717d4247SJustin T. Gibbs 		"Adaptec 1480A Ultra SCSI adapter",
256a5847d5cSJustin T. Gibbs 		ahc_apa1480_setup
257717d4247SJustin T. Gibbs 	},
258717d4247SJustin T. Gibbs 	{
259717d4247SJustin T. Gibbs 		ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK,
260717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
261717d4247SJustin T. Gibbs 		"Adaptec 2940A Ultra SCSI adapter",
262717d4247SJustin T. Gibbs 		ahc_aic7860_setup
263717d4247SJustin T. Gibbs 	},
264717d4247SJustin T. Gibbs 	{
265717d4247SJustin T. Gibbs 		ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK,
266717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
267717d4247SJustin T. Gibbs 		"Adaptec 2940A/CN Ultra SCSI adapter",
268717d4247SJustin T. Gibbs 		ahc_aic7860_setup
269717d4247SJustin T. Gibbs 	},
270717d4247SJustin T. Gibbs 	{
271717d4247SJustin T. Gibbs 		ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK,
272717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
27358fb7d8eSJustin T. Gibbs 		"Adaptec 2930C Ultra SCSI adapter (VAR)",
274717d4247SJustin T. Gibbs 		ahc_aic7860_setup
275717d4247SJustin T. Gibbs 	},
276717d4247SJustin T. Gibbs 	/* aic7870 based controllers */
277717d4247SJustin T. Gibbs 	{
278717d4247SJustin T. Gibbs 		ID_AHA_2940,
279717d4247SJustin T. Gibbs 		ID_ALL_MASK,
280717d4247SJustin T. Gibbs 		"Adaptec 2940 SCSI adapter",
281717d4247SJustin T. Gibbs 		ahc_aic7870_setup
282717d4247SJustin T. Gibbs 	},
283717d4247SJustin T. Gibbs 	{
284717d4247SJustin T. Gibbs 		ID_AHA_3940,
285717d4247SJustin T. Gibbs 		ID_ALL_MASK,
286717d4247SJustin T. Gibbs 		"Adaptec 3940 SCSI adapter",
287717d4247SJustin T. Gibbs 		ahc_aha394X_setup
288717d4247SJustin T. Gibbs 	},
289717d4247SJustin T. Gibbs 	{
290717d4247SJustin T. Gibbs 		ID_AHA_398X,
291717d4247SJustin T. Gibbs 		ID_ALL_MASK,
292717d4247SJustin T. Gibbs 		"Adaptec 398X SCSI RAID adapter",
293717d4247SJustin T. Gibbs 		ahc_aha398X_setup
294717d4247SJustin T. Gibbs 	},
295717d4247SJustin T. Gibbs 	{
296717d4247SJustin T. Gibbs 		ID_AHA_2944,
297717d4247SJustin T. Gibbs 		ID_ALL_MASK,
298717d4247SJustin T. Gibbs 		"Adaptec 2944 SCSI adapter",
299717d4247SJustin T. Gibbs 		ahc_aic7870_setup
300717d4247SJustin T. Gibbs 	},
301717d4247SJustin T. Gibbs 	{
302717d4247SJustin T. Gibbs 		ID_AHA_3944,
303717d4247SJustin T. Gibbs 		ID_ALL_MASK,
304717d4247SJustin T. Gibbs 		"Adaptec 3944 SCSI adapter",
305717d4247SJustin T. Gibbs 		ahc_aha394X_setup
306717d4247SJustin T. Gibbs 	},
307717d4247SJustin T. Gibbs 	{
308717d4247SJustin T. Gibbs 		ID_AHA_4944,
309717d4247SJustin T. Gibbs 		ID_ALL_MASK,
310717d4247SJustin T. Gibbs 		"Adaptec 4944 SCSI adapter",
311717d4247SJustin T. Gibbs 		ahc_aha494X_setup
312717d4247SJustin T. Gibbs 	},
313717d4247SJustin T. Gibbs 	/* aic7880 based controllers */
314717d4247SJustin T. Gibbs 	{
315717d4247SJustin T. Gibbs 		ID_AHA_2940U & ID_DEV_VENDOR_MASK,
316717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
317717d4247SJustin T. Gibbs 		"Adaptec 2940 Ultra SCSI adapter",
318717d4247SJustin T. Gibbs 		ahc_aic7880_setup
319717d4247SJustin T. Gibbs 	},
320717d4247SJustin T. Gibbs 	{
321717d4247SJustin T. Gibbs 		ID_AHA_3940U & ID_DEV_VENDOR_MASK,
322717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
323717d4247SJustin T. Gibbs 		"Adaptec 3940 Ultra SCSI adapter",
324717d4247SJustin T. Gibbs 		ahc_aha394XU_setup
325717d4247SJustin T. Gibbs 	},
326717d4247SJustin T. Gibbs 	{
327717d4247SJustin T. Gibbs 		ID_AHA_2944U & ID_DEV_VENDOR_MASK,
328717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
329717d4247SJustin T. Gibbs 		"Adaptec 2944 Ultra SCSI adapter",
330717d4247SJustin T. Gibbs 		ahc_aic7880_setup
331717d4247SJustin T. Gibbs 	},
332717d4247SJustin T. Gibbs 	{
333717d4247SJustin T. Gibbs 		ID_AHA_3944U & ID_DEV_VENDOR_MASK,
334717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
335717d4247SJustin T. Gibbs 		"Adaptec 3944 Ultra SCSI adapter",
336717d4247SJustin T. Gibbs 		ahc_aha394XU_setup
337717d4247SJustin T. Gibbs 	},
338717d4247SJustin T. Gibbs 	{
339717d4247SJustin T. Gibbs 		ID_AHA_398XU & ID_DEV_VENDOR_MASK,
340717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
341717d4247SJustin T. Gibbs 		"Adaptec 398X Ultra SCSI RAID adapter",
342717d4247SJustin T. Gibbs 		ahc_aha398XU_setup
343717d4247SJustin T. Gibbs 	},
344717d4247SJustin T. Gibbs 	{
345717d4247SJustin T. Gibbs 		/*
346717d4247SJustin T. Gibbs 		 * XXX Don't know the slot numbers
347717d4247SJustin T. Gibbs 		 * so we can't identify channels
348717d4247SJustin T. Gibbs 		 */
349717d4247SJustin T. Gibbs 		ID_AHA_4944U & ID_DEV_VENDOR_MASK,
350717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
351717d4247SJustin T. Gibbs 		"Adaptec 4944 Ultra SCSI adapter",
352717d4247SJustin T. Gibbs 		ahc_aic7880_setup
353717d4247SJustin T. Gibbs 	},
354717d4247SJustin T. Gibbs 	{
355717d4247SJustin T. Gibbs 		ID_AHA_2930U & ID_DEV_VENDOR_MASK,
356717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
357717d4247SJustin T. Gibbs 		"Adaptec 2930 Ultra SCSI adapter",
358717d4247SJustin T. Gibbs 		ahc_aic7880_setup
359717d4247SJustin T. Gibbs 	},
360717d4247SJustin T. Gibbs 	{
361717d4247SJustin T. Gibbs 		ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK,
362717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
363717d4247SJustin T. Gibbs 		"Adaptec 2940 Pro Ultra SCSI adapter",
364a5847d5cSJustin T. Gibbs 		ahc_aha2940Pro_setup
365717d4247SJustin T. Gibbs 	},
366717d4247SJustin T. Gibbs 	{
367717d4247SJustin T. Gibbs 		ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK,
368717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
369717d4247SJustin T. Gibbs 		"Adaptec 2940/CN Ultra SCSI adapter",
370717d4247SJustin T. Gibbs 		ahc_aic7880_setup
371717d4247SJustin T. Gibbs 	},
3721478c711SJustin T. Gibbs 	/* Ignore all SISL (AAC on MB) based controllers. */
3731478c711SJustin T. Gibbs 	{
3741478c711SJustin T. Gibbs 		ID_9005_SISL_ID,
3751478c711SJustin T. Gibbs 		ID_9005_SISL_MASK,
3761478c711SJustin T. Gibbs 		NULL,
3771478c711SJustin T. Gibbs 		NULL
3781478c711SJustin T. Gibbs 	},
379717d4247SJustin T. Gibbs 	/* aic7890 based controllers */
380717d4247SJustin T. Gibbs 	{
381717d4247SJustin T. Gibbs 		ID_AHA_2930U2,
382717d4247SJustin T. Gibbs 		ID_ALL_MASK,
383717d4247SJustin T. Gibbs 		"Adaptec 2930 Ultra2 SCSI adapter",
384717d4247SJustin T. Gibbs 		ahc_aic7890_setup
385717d4247SJustin T. Gibbs 	},
386717d4247SJustin T. Gibbs 	{
387717d4247SJustin T. Gibbs 		ID_AHA_2940U2B,
388717d4247SJustin T. Gibbs 		ID_ALL_MASK,
389717d4247SJustin T. Gibbs 		"Adaptec 2940B Ultra2 SCSI adapter",
390717d4247SJustin T. Gibbs 		ahc_aic7890_setup
391717d4247SJustin T. Gibbs 	},
392717d4247SJustin T. Gibbs 	{
393717d4247SJustin T. Gibbs 		ID_AHA_2940U2_OEM,
394717d4247SJustin T. Gibbs 		ID_ALL_MASK,
395717d4247SJustin T. Gibbs 		"Adaptec 2940 Ultra2 SCSI adapter (OEM)",
396717d4247SJustin T. Gibbs 		ahc_aic7890_setup
397717d4247SJustin T. Gibbs 	},
398717d4247SJustin T. Gibbs 	{
399717d4247SJustin T. Gibbs 		ID_AHA_2940U2,
400717d4247SJustin T. Gibbs 		ID_ALL_MASK,
401717d4247SJustin T. Gibbs 		"Adaptec 2940 Ultra2 SCSI adapter",
402717d4247SJustin T. Gibbs 		ahc_aic7890_setup
403717d4247SJustin T. Gibbs 	},
404717d4247SJustin T. Gibbs 	{
405717d4247SJustin T. Gibbs 		ID_AHA_2950U2B,
406717d4247SJustin T. Gibbs 		ID_ALL_MASK,
407717d4247SJustin T. Gibbs 		"Adaptec 2950 Ultra2 SCSI adapter",
408717d4247SJustin T. Gibbs 		ahc_aic7890_setup
409717d4247SJustin T. Gibbs 	},
410717d4247SJustin T. Gibbs 	{
4111478c711SJustin T. Gibbs 		ID_AIC7890_ARO,
4121478c711SJustin T. Gibbs 		ID_ALL_MASK,
4131478c711SJustin T. Gibbs 		"Adaptec aic7890/91 Ultra2 SCSI adapter (ARO)",
4141478c711SJustin T. Gibbs 		ahc_aic7890_setup
4151478c711SJustin T. Gibbs 	},
4161478c711SJustin T. Gibbs 	{
417717d4247SJustin T. Gibbs 		ID_AAA_131U2,
418717d4247SJustin T. Gibbs 		ID_ALL_MASK,
419717d4247SJustin T. Gibbs 		"Adaptec AAA-131 Ultra2 RAID adapter",
420717d4247SJustin T. Gibbs 		ahc_aic7890_setup
421717d4247SJustin T. Gibbs 	},
422717d4247SJustin T. Gibbs 	/* aic7892 based controllers */
423717d4247SJustin T. Gibbs 	{
424717d4247SJustin T. Gibbs 		ID_AHA_29160,
425717d4247SJustin T. Gibbs 		ID_ALL_MASK,
426717d4247SJustin T. Gibbs 		"Adaptec 29160 Ultra160 SCSI adapter",
427717d4247SJustin T. Gibbs 		ahc_aic7892_setup
428717d4247SJustin T. Gibbs 	},
429717d4247SJustin T. Gibbs 	{
430717d4247SJustin T. Gibbs 		ID_AHA_29160_CPQ,
431717d4247SJustin T. Gibbs 		ID_ALL_MASK,
432717d4247SJustin T. Gibbs 		"Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter",
433717d4247SJustin T. Gibbs 		ahc_aic7892_setup
434717d4247SJustin T. Gibbs 	},
435717d4247SJustin T. Gibbs 	{
436717d4247SJustin T. Gibbs 		ID_AHA_29160N,
437717d4247SJustin T. Gibbs 		ID_ALL_MASK,
438717d4247SJustin T. Gibbs 		"Adaptec 29160N Ultra160 SCSI adapter",
439717d4247SJustin T. Gibbs 		ahc_aic7892_setup
440717d4247SJustin T. Gibbs 	},
441717d4247SJustin T. Gibbs 	{
44256a7c4a8SJustin T. Gibbs 		ID_AHA_29160C,
44356a7c4a8SJustin T. Gibbs 		ID_ALL_MASK,
44456a7c4a8SJustin T. Gibbs 		"Adaptec 29160C Ultra160 SCSI adapter",
445a5847d5cSJustin T. Gibbs 		ahc_aha29160C_setup
44656a7c4a8SJustin T. Gibbs 	},
44756a7c4a8SJustin T. Gibbs 	{
448717d4247SJustin T. Gibbs 		ID_AHA_29160B,
449717d4247SJustin T. Gibbs 		ID_ALL_MASK,
450717d4247SJustin T. Gibbs 		"Adaptec 29160B Ultra160 SCSI adapter",
451717d4247SJustin T. Gibbs 		ahc_aic7892_setup
452717d4247SJustin T. Gibbs 	},
453717d4247SJustin T. Gibbs 	{
454717d4247SJustin T. Gibbs 		ID_AHA_19160B,
455717d4247SJustin T. Gibbs 		ID_ALL_MASK,
456717d4247SJustin T. Gibbs 		"Adaptec 19160B Ultra160 SCSI adapter",
457717d4247SJustin T. Gibbs 		ahc_aic7892_setup
458717d4247SJustin T. Gibbs 	},
4591478c711SJustin T. Gibbs 	{
4601478c711SJustin T. Gibbs 		ID_AIC7892_ARO,
4611478c711SJustin T. Gibbs 		ID_ALL_MASK,
46258fb7d8eSJustin T. Gibbs 		"Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
4631478c711SJustin T. Gibbs 		ahc_aic7892_setup
4641478c711SJustin T. Gibbs 	},
465b3b25f2cSJustin T. Gibbs 	{
466b3b25f2cSJustin T. Gibbs 		ID_AHA_2915_30LP,
467b3b25f2cSJustin T. Gibbs 		ID_ALL_MASK,
468b3b25f2cSJustin T. Gibbs 		"Adaptec 2915/30LP Ultra160 SCSI adapter",
469b3b25f2cSJustin T. Gibbs 		ahc_aic7892_setup
470b3b25f2cSJustin T. Gibbs 	},
471717d4247SJustin T. Gibbs 	/* aic7895 based controllers */
472717d4247SJustin T. Gibbs 	{
473717d4247SJustin T. Gibbs 		ID_AHA_2940U_DUAL,
474717d4247SJustin T. Gibbs 		ID_ALL_MASK,
475717d4247SJustin T. Gibbs 		"Adaptec 2940/DUAL Ultra SCSI adapter",
476717d4247SJustin T. Gibbs 		ahc_aic7895_setup
477717d4247SJustin T. Gibbs 	},
478717d4247SJustin T. Gibbs 	{
479717d4247SJustin T. Gibbs 		ID_AHA_3940AU,
480717d4247SJustin T. Gibbs 		ID_ALL_MASK,
481717d4247SJustin T. Gibbs 		"Adaptec 3940A Ultra SCSI adapter",
482717d4247SJustin T. Gibbs 		ahc_aic7895_setup
483717d4247SJustin T. Gibbs 	},
484717d4247SJustin T. Gibbs 	{
485717d4247SJustin T. Gibbs 		ID_AHA_3944AU,
486717d4247SJustin T. Gibbs 		ID_ALL_MASK,
487717d4247SJustin T. Gibbs 		"Adaptec 3944A Ultra SCSI adapter",
488717d4247SJustin T. Gibbs 		ahc_aic7895_setup
489717d4247SJustin T. Gibbs 	},
4901478c711SJustin T. Gibbs 	{
4911478c711SJustin T. Gibbs 		ID_AIC7895_ARO,
4921478c711SJustin T. Gibbs 		ID_AIC7895_ARO_MASK,
4931478c711SJustin T. Gibbs 		"Adaptec aic7895 Ultra SCSI adapter (ARO)",
4941478c711SJustin T. Gibbs 		ahc_aic7895_setup
4951478c711SJustin T. Gibbs 	},
496717d4247SJustin T. Gibbs 	/* aic7896/97 based controllers */
497717d4247SJustin T. Gibbs 	{
498717d4247SJustin T. Gibbs 		ID_AHA_3950U2B_0,
499717d4247SJustin T. Gibbs 		ID_ALL_MASK,
500717d4247SJustin T. Gibbs 		"Adaptec 3950B Ultra2 SCSI adapter",
501717d4247SJustin T. Gibbs 		ahc_aic7896_setup
502717d4247SJustin T. Gibbs 	},
503717d4247SJustin T. Gibbs 	{
504717d4247SJustin T. Gibbs 		ID_AHA_3950U2B_1,
505717d4247SJustin T. Gibbs 		ID_ALL_MASK,
506717d4247SJustin T. Gibbs 		"Adaptec 3950B Ultra2 SCSI adapter",
507717d4247SJustin T. Gibbs 		ahc_aic7896_setup
508717d4247SJustin T. Gibbs 	},
509717d4247SJustin T. Gibbs 	{
510717d4247SJustin T. Gibbs 		ID_AHA_3950U2D_0,
511717d4247SJustin T. Gibbs 		ID_ALL_MASK,
512717d4247SJustin T. Gibbs 		"Adaptec 3950D Ultra2 SCSI adapter",
513717d4247SJustin T. Gibbs 		ahc_aic7896_setup
514717d4247SJustin T. Gibbs 	},
515717d4247SJustin T. Gibbs 	{
516717d4247SJustin T. Gibbs 		ID_AHA_3950U2D_1,
517717d4247SJustin T. Gibbs 		ID_ALL_MASK,
518717d4247SJustin T. Gibbs 		"Adaptec 3950D Ultra2 SCSI adapter",
519717d4247SJustin T. Gibbs 		ahc_aic7896_setup
520717d4247SJustin T. Gibbs 	},
5211478c711SJustin T. Gibbs 	{
5221478c711SJustin T. Gibbs 		ID_AIC7896_ARO,
5231478c711SJustin T. Gibbs 		ID_ALL_MASK,
5241478c711SJustin T. Gibbs 		"Adaptec aic7896/97 Ultra2 SCSI adapter (ARO)",
5251478c711SJustin T. Gibbs 		ahc_aic7896_setup
5261478c711SJustin T. Gibbs 	},
527717d4247SJustin T. Gibbs 	/* aic7899 based controllers */
528717d4247SJustin T. Gibbs 	{
529717d4247SJustin T. Gibbs 		ID_AHA_3960D,
530717d4247SJustin T. Gibbs 		ID_ALL_MASK,
531717d4247SJustin T. Gibbs 		"Adaptec 3960D Ultra160 SCSI adapter",
532717d4247SJustin T. Gibbs 		ahc_aic7899_setup
533717d4247SJustin T. Gibbs 	},
534717d4247SJustin T. Gibbs 	{
535717d4247SJustin T. Gibbs 		ID_AHA_3960D_CPQ,
536717d4247SJustin T. Gibbs 		ID_ALL_MASK,
537717d4247SJustin T. Gibbs 		"Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter",
538717d4247SJustin T. Gibbs 		ahc_aic7899_setup
539717d4247SJustin T. Gibbs 	},
5401478c711SJustin T. Gibbs 	{
5411478c711SJustin T. Gibbs 		ID_AIC7899_ARO,
5421478c711SJustin T. Gibbs 		ID_ALL_MASK,
5431478c711SJustin T. Gibbs 		"Adaptec aic7899 Ultra160 SCSI adapter (ARO)",
5441478c711SJustin T. Gibbs 		ahc_aic7899_setup
5451478c711SJustin T. Gibbs 	},
546717d4247SJustin T. Gibbs 	/* Generic chip probes for devices we don't know 'exactly' */
547717d4247SJustin T. Gibbs 	{
548717d4247SJustin T. Gibbs 		ID_AIC7850 & ID_DEV_VENDOR_MASK,
549717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
550717d4247SJustin T. Gibbs 		"Adaptec aic7850 SCSI adapter",
5516fb77fefSJustin T. Gibbs 		ahc_aic785X_setup
552717d4247SJustin T. Gibbs 	},
553717d4247SJustin T. Gibbs 	{
554717d4247SJustin T. Gibbs 		ID_AIC7855 & ID_DEV_VENDOR_MASK,
555717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
556717d4247SJustin T. Gibbs 		"Adaptec aic7855 SCSI adapter",
5576fb77fefSJustin T. Gibbs 		ahc_aic785X_setup
558717d4247SJustin T. Gibbs 	},
559717d4247SJustin T. Gibbs 	{
560717d4247SJustin T. Gibbs 		ID_AIC7859 & ID_DEV_VENDOR_MASK,
561717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
56258fb7d8eSJustin T. Gibbs 		"Adaptec aic7859 SCSI adapter",
563717d4247SJustin T. Gibbs 		ahc_aic7860_setup
564717d4247SJustin T. Gibbs 	},
565717d4247SJustin T. Gibbs 	{
566717d4247SJustin T. Gibbs 		ID_AIC7860 & ID_DEV_VENDOR_MASK,
567717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
56858fb7d8eSJustin T. Gibbs 		"Adaptec aic7860 Ultra SCSI adapter",
569717d4247SJustin T. Gibbs 		ahc_aic7860_setup
570717d4247SJustin T. Gibbs 	},
571717d4247SJustin T. Gibbs 	{
572717d4247SJustin T. Gibbs 		ID_AIC7870 & ID_DEV_VENDOR_MASK,
573717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
574717d4247SJustin T. Gibbs 		"Adaptec aic7870 SCSI adapter",
575717d4247SJustin T. Gibbs 		ahc_aic7870_setup
576717d4247SJustin T. Gibbs 	},
577717d4247SJustin T. Gibbs 	{
578717d4247SJustin T. Gibbs 		ID_AIC7880 & ID_DEV_VENDOR_MASK,
579717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
580717d4247SJustin T. Gibbs 		"Adaptec aic7880 Ultra SCSI adapter",
581717d4247SJustin T. Gibbs 		ahc_aic7880_setup
582717d4247SJustin T. Gibbs 	},
583717d4247SJustin T. Gibbs 	{
584bfadd24dSJustin T. Gibbs 		ID_AIC7890 & ID_9005_GENERIC_MASK,
585bfadd24dSJustin T. Gibbs 		ID_9005_GENERIC_MASK,
586717d4247SJustin T. Gibbs 		"Adaptec aic7890/91 Ultra2 SCSI adapter",
587717d4247SJustin T. Gibbs 		ahc_aic7890_setup
588717d4247SJustin T. Gibbs 	},
589717d4247SJustin T. Gibbs 	{
590bfadd24dSJustin T. Gibbs 		ID_AIC7892 & ID_9005_GENERIC_MASK,
591bfadd24dSJustin T. Gibbs 		ID_9005_GENERIC_MASK,
592717d4247SJustin T. Gibbs 		"Adaptec aic7892 Ultra160 SCSI adapter",
593717d4247SJustin T. Gibbs 		ahc_aic7892_setup
594717d4247SJustin T. Gibbs 	},
595717d4247SJustin T. Gibbs 	{
596717d4247SJustin T. Gibbs 		ID_AIC7895 & ID_DEV_VENDOR_MASK,
597717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
598717d4247SJustin T. Gibbs 		"Adaptec aic7895 Ultra SCSI adapter",
599717d4247SJustin T. Gibbs 		ahc_aic7895_setup
600717d4247SJustin T. Gibbs 	},
601717d4247SJustin T. Gibbs 	{
602bfadd24dSJustin T. Gibbs 		ID_AIC7896 & ID_9005_GENERIC_MASK,
603bfadd24dSJustin T. Gibbs 		ID_9005_GENERIC_MASK,
604717d4247SJustin T. Gibbs 		"Adaptec aic7896/97 Ultra2 SCSI adapter",
605717d4247SJustin T. Gibbs 		ahc_aic7896_setup
606717d4247SJustin T. Gibbs 	},
607717d4247SJustin T. Gibbs 	{
608bfadd24dSJustin T. Gibbs 		ID_AIC7899 & ID_9005_GENERIC_MASK,
609bfadd24dSJustin T. Gibbs 		ID_9005_GENERIC_MASK,
610717d4247SJustin T. Gibbs 		"Adaptec aic7899 Ultra160 SCSI adapter",
611717d4247SJustin T. Gibbs 		ahc_aic7899_setup
612717d4247SJustin T. Gibbs 	},
613717d4247SJustin T. Gibbs 	{
614717d4247SJustin T. Gibbs 		ID_AIC7810 & ID_DEV_VENDOR_MASK,
615717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
616717d4247SJustin T. Gibbs 		"Adaptec aic7810 RAID memory controller",
617717d4247SJustin T. Gibbs 		ahc_raid_setup
618717d4247SJustin T. Gibbs 	},
619717d4247SJustin T. Gibbs 	{
620717d4247SJustin T. Gibbs 		ID_AIC7815 & ID_DEV_VENDOR_MASK,
621717d4247SJustin T. Gibbs 		ID_DEV_VENDOR_MASK,
622717d4247SJustin T. Gibbs 		"Adaptec aic7815 RAID memory controller",
623717d4247SJustin T. Gibbs 		ahc_raid_setup
624717d4247SJustin T. Gibbs 	}
625717d4247SJustin T. Gibbs };
626717d4247SJustin T. Gibbs 
62756a7c4a8SJustin T. Gibbs const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table);
628717d4247SJustin T. Gibbs 
629717d4247SJustin T. Gibbs #define AHC_394X_SLOT_CHANNEL_A	4
630717d4247SJustin T. Gibbs #define AHC_394X_SLOT_CHANNEL_B	5
631717d4247SJustin T. Gibbs 
632717d4247SJustin T. Gibbs #define AHC_398X_SLOT_CHANNEL_A	4
633717d4247SJustin T. Gibbs #define AHC_398X_SLOT_CHANNEL_B	8
634717d4247SJustin T. Gibbs #define AHC_398X_SLOT_CHANNEL_C	12
635717d4247SJustin T. Gibbs 
636717d4247SJustin T. Gibbs #define AHC_494X_SLOT_CHANNEL_A	4
637717d4247SJustin T. Gibbs #define AHC_494X_SLOT_CHANNEL_B	5
638717d4247SJustin T. Gibbs #define AHC_494X_SLOT_CHANNEL_C	6
639717d4247SJustin T. Gibbs #define AHC_494X_SLOT_CHANNEL_D	7
640717d4247SJustin T. Gibbs 
641717d4247SJustin T. Gibbs #define	DEVCONFIG		0x40
64270b41139SJustin T. Gibbs #define		PCIERRGENDIS	0x80000000ul
643717d4247SJustin T. Gibbs #define		SCBSIZE32	0x00010000ul	/* aic789X only */
6446fb77fefSJustin T. Gibbs #define		REXTVALID	0x00001000ul	/* ultra cards only */
645cd036e89SJustin T. Gibbs #define		MPORTMODE	0x00000400ul	/* aic7870+ only */
646cd036e89SJustin T. Gibbs #define		RAMPSM		0x00000200ul	/* aic7870+ only */
647717d4247SJustin T. Gibbs #define		VOLSENSE	0x00000100ul
648cd036e89SJustin T. Gibbs #define		PCI64BIT	0x00000080ul	/* 64Bit PCI bus (Ultra2 Only)*/
649717d4247SJustin T. Gibbs #define		SCBRAMSEL	0x00000080ul
650717d4247SJustin T. Gibbs #define		MRDCEN		0x00000040ul
651717d4247SJustin T. Gibbs #define		EXTSCBTIME	0x00000020ul	/* aic7870 only */
652717d4247SJustin T. Gibbs #define		EXTSCBPEN	0x00000010ul	/* aic7870 only */
653717d4247SJustin T. Gibbs #define		BERREN		0x00000008ul
654717d4247SJustin T. Gibbs #define		DACEN		0x00000004ul
655717d4247SJustin T. Gibbs #define		STPWLEVEL	0x00000002ul
656717d4247SJustin T. Gibbs #define		DIFACTNEGEN	0x00000001ul	/* aic7870 only */
657717d4247SJustin T. Gibbs 
658717d4247SJustin T. Gibbs #define	CSIZE_LATTIME		0x0c
659717d4247SJustin T. Gibbs #define		CACHESIZE	0x0000003ful	/* only 5 bits */
660717d4247SJustin T. Gibbs #define		LATTIME		0x0000ff00ul
661717d4247SJustin T. Gibbs 
662dc67dad8SScott Long /* PCI STATUS definitions */
663dc67dad8SScott Long #define	DPE	0x80
664dc67dad8SScott Long #define SSE	0x40
665dc67dad8SScott Long #define	RMA	0x20
666dc67dad8SScott Long #define	RTA	0x10
667dc67dad8SScott Long #define STA	0x08
668dc67dad8SScott Long #define DPR	0x01
669dc67dad8SScott Long 
670b4d0045dSUlrich Spörlein static int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
671b4d0045dSUlrich Spörlein 				     uint16_t subdevice, uint16_t subvendor);
672717d4247SJustin T. Gibbs static int ahc_ext_scbram_present(struct ahc_softc *ahc);
673717d4247SJustin T. Gibbs static void ahc_scbram_config(struct ahc_softc *ahc, int enable,
674717d4247SJustin T. Gibbs 				  int pcheck, int fast, int large);
675717d4247SJustin T. Gibbs static void ahc_probe_ext_scbram(struct ahc_softc *ahc);
676717d4247SJustin T. Gibbs static void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1);
677274c4127SJustin T. Gibbs static void ahc_parse_pci_eeprom(struct ahc_softc *ahc,
678274c4127SJustin T. Gibbs 				 struct seeprom_config *sc);
679717d4247SJustin T. Gibbs static void configure_termination(struct ahc_softc *ahc,
680717d4247SJustin T. Gibbs 				  struct seeprom_descriptor *sd,
681717d4247SJustin T. Gibbs 				  u_int adapter_control,
682717d4247SJustin T. Gibbs 	 			  u_int *sxfrctl1);
683717d4247SJustin T. Gibbs 
684717d4247SJustin T. Gibbs static void ahc_new_term_detect(struct ahc_softc *ahc,
685717d4247SJustin T. Gibbs 				int *enableSEC_low,
686717d4247SJustin T. Gibbs 				int *enableSEC_high,
687717d4247SJustin T. Gibbs 				int *enablePRI_low,
688717d4247SJustin T. Gibbs 				int *enablePRI_high,
689717d4247SJustin T. Gibbs 				int *eeprom_present);
690717d4247SJustin T. Gibbs static void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
691717d4247SJustin T. Gibbs 				 int *internal68_present,
692717d4247SJustin T. Gibbs 				 int *externalcable_present,
693717d4247SJustin T. Gibbs 				 int *eeprom_present);
694717d4247SJustin T. Gibbs static void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
695717d4247SJustin T. Gibbs 				 int *externalcable_present,
696717d4247SJustin T. Gibbs 				 int *eeprom_present);
697717d4247SJustin T. Gibbs static void    write_brdctl(struct ahc_softc *ahc, uint8_t value);
698717d4247SJustin T. Gibbs static uint8_t read_brdctl(struct ahc_softc *ahc);
6999bf327a7SJustin T. Gibbs static void ahc_pci_intr(struct ahc_softc *ahc);
7009bf327a7SJustin T. Gibbs static int  ahc_pci_chip_init(struct ahc_softc *ahc);
7019bf327a7SJustin T. Gibbs static int  ahc_pci_suspend(struct ahc_softc *ahc);
7029bf327a7SJustin T. Gibbs static int  ahc_pci_resume(struct ahc_softc *ahc);
703717d4247SJustin T. Gibbs 
7048f214efcSJustin T. Gibbs static int
7058f214efcSJustin T. Gibbs ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
7068f214efcSJustin T. Gibbs 			  uint16_t subdevice, uint16_t subvendor)
7078f214efcSJustin T. Gibbs {
7088f214efcSJustin T. Gibbs 	int result;
7098f214efcSJustin T. Gibbs 
7108f214efcSJustin T. Gibbs 	/* Default to invalid. */
7118f214efcSJustin T. Gibbs 	result = 0;
7128f214efcSJustin T. Gibbs 	if (vendor == 0x9005
7138f214efcSJustin T. Gibbs 	 && subvendor == 0x9005
7148f214efcSJustin T. Gibbs          && subdevice != device
7158f214efcSJustin T. Gibbs          && SUBID_9005_TYPE_KNOWN(subdevice) != 0) {
7168f214efcSJustin T. Gibbs 		switch (SUBID_9005_TYPE(subdevice)) {
7178f214efcSJustin T. Gibbs 		case SUBID_9005_TYPE_MB:
7188f214efcSJustin T. Gibbs 			break;
7198f214efcSJustin T. Gibbs 		case SUBID_9005_TYPE_CARD:
7208f214efcSJustin T. Gibbs 		case SUBID_9005_TYPE_LCCARD:
7218f214efcSJustin T. Gibbs 			/*
7228f214efcSJustin T. Gibbs 			 * Currently only trust Adaptec cards to
7238f214efcSJustin T. Gibbs 			 * get the sub device info correct.
7248f214efcSJustin T. Gibbs 			 */
7258f214efcSJustin T. Gibbs 			if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA)
7268f214efcSJustin T. Gibbs 				result = 1;
7278f214efcSJustin T. Gibbs 			break;
7288f214efcSJustin T. Gibbs 		case SUBID_9005_TYPE_RAID:
7298f214efcSJustin T. Gibbs 			break;
7308f214efcSJustin T. Gibbs 		default:
7318f214efcSJustin T. Gibbs 			break;
7328f214efcSJustin T. Gibbs 		}
7338f214efcSJustin T. Gibbs 	}
7348f214efcSJustin T. Gibbs 	return (result);
7358f214efcSJustin T. Gibbs }
7368f214efcSJustin T. Gibbs 
737717d4247SJustin T. Gibbs struct ahc_pci_identity *
738b3b25f2cSJustin T. Gibbs ahc_find_pci_device(aic_dev_softc_t pci)
739717d4247SJustin T. Gibbs {
740717d4247SJustin T. Gibbs 	uint64_t  full_id;
741717d4247SJustin T. Gibbs 	uint16_t  device;
742717d4247SJustin T. Gibbs 	uint16_t  vendor;
743717d4247SJustin T. Gibbs 	uint16_t  subdevice;
744717d4247SJustin T. Gibbs 	uint16_t  subvendor;
745717d4247SJustin T. Gibbs 	struct	  ahc_pci_identity *entry;
746717d4247SJustin T. Gibbs 	u_int	  i;
747717d4247SJustin T. Gibbs 
748b3b25f2cSJustin T. Gibbs 	vendor = aic_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
749b3b25f2cSJustin T. Gibbs 	device = aic_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
750b3b25f2cSJustin T. Gibbs 	subvendor = aic_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
751b3b25f2cSJustin T. Gibbs 	subdevice = aic_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
7529bf327a7SJustin T. Gibbs 	full_id = ahc_compose_id(device, vendor, subdevice, subvendor);
753717d4247SJustin T. Gibbs 
754cd036e89SJustin T. Gibbs 	/*
755cd036e89SJustin T. Gibbs 	 * If the second function is not hooked up, ignore it.
756cd036e89SJustin T. Gibbs 	 * Unfortunately, not all MB vendors implement the
757cd036e89SJustin T. Gibbs 	 * subdevice ID as per the Adaptec spec, so do our best
758cd036e89SJustin T. Gibbs 	 * to sanity check it prior to accepting the subdevice
759cd036e89SJustin T. Gibbs 	 * ID as valid.
760cd036e89SJustin T. Gibbs 	 */
761b3b25f2cSJustin T. Gibbs 	if (aic_get_pci_function(pci) > 0
762b4d0045dSUlrich Spörlein 	 && ahc_9005_subdevinfo_valid(device, vendor, subdevice, subvendor)
763f8838555SJustin T. Gibbs 	 && SUBID_9005_MFUNCENB(subdevice) == 0)
76456a7c4a8SJustin T. Gibbs 		return (NULL);
76556a7c4a8SJustin T. Gibbs 
766717d4247SJustin T. Gibbs 	for (i = 0; i < ahc_num_pci_devs; i++) {
767717d4247SJustin T. Gibbs 		entry = &ahc_pci_ident_table[i];
7681478c711SJustin T. Gibbs 		if (entry->full_id == (full_id & entry->id_mask)) {
7691478c711SJustin T. Gibbs 			/* Honor exclusion entries. */
7701478c711SJustin T. Gibbs 			if (entry->name == NULL)
7711478c711SJustin T. Gibbs 				return (NULL);
772717d4247SJustin T. Gibbs 			return (entry);
773717d4247SJustin T. Gibbs 		}
7741478c711SJustin T. Gibbs 	}
775717d4247SJustin T. Gibbs 	return (NULL);
776717d4247SJustin T. Gibbs }
777717d4247SJustin T. Gibbs 
778717d4247SJustin T. Gibbs int
779717d4247SJustin T. Gibbs ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
780717d4247SJustin T. Gibbs {
781717d4247SJustin T. Gibbs 	u_int	 command;
782274c4127SJustin T. Gibbs 	u_int	 our_id;
783717d4247SJustin T. Gibbs 	u_int	 sxfrctl1;
784717d4247SJustin T. Gibbs 	u_int	 scsiseq;
785717d4247SJustin T. Gibbs 	u_int	 dscommand0;
78670b41139SJustin T. Gibbs 	uint32_t devconfig;
787717d4247SJustin T. Gibbs 	int	 error;
788717d4247SJustin T. Gibbs 	uint8_t	 sblkctl;
789717d4247SJustin T. Gibbs 
790274c4127SJustin T. Gibbs 	our_id = 0;
791cd036e89SJustin T. Gibbs 	error = entry->setup(ahc);
792717d4247SJustin T. Gibbs 	if (error != 0)
793717d4247SJustin T. Gibbs 		return (error);
794cd036e89SJustin T. Gibbs 	ahc->chip |= AHC_PCI;
795cd036e89SJustin T. Gibbs 	ahc->description = entry->name;
796717d4247SJustin T. Gibbs 
797b3b25f2cSJustin T. Gibbs 	aic_power_state_change(ahc, AIC_POWER_STATE_D0);
7988f214efcSJustin T. Gibbs 
799717d4247SJustin T. Gibbs 	error = ahc_pci_map_registers(ahc);
800717d4247SJustin T. Gibbs 	if (error != 0)
801717d4247SJustin T. Gibbs 		return (error);
802717d4247SJustin T. Gibbs 
8038f214efcSJustin T. Gibbs 	/*
8048f214efcSJustin T. Gibbs 	 * Before we continue probing the card, ensure that
8058f214efcSJustin T. Gibbs 	 * its interrupts are *disabled*.  We don't want
8068f214efcSJustin T. Gibbs 	 * a misstep to hang the machine in an interrupt
8078f214efcSJustin T. Gibbs 	 * storm.
8088f214efcSJustin T. Gibbs 	 */
8098f214efcSJustin T. Gibbs 	ahc_intr_enable(ahc, FALSE);
81056a7c4a8SJustin T. Gibbs 
811b3b25f2cSJustin T. Gibbs 	devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
81270b41139SJustin T. Gibbs 
813cd036e89SJustin T. Gibbs 	/*
814cd036e89SJustin T. Gibbs 	 * If we need to support high memory, enable dual
815cd036e89SJustin T. Gibbs 	 * address cycles.  This bit must be set to enable
816cd036e89SJustin T. Gibbs 	 * high address bit generation even if we are on a
817cd036e89SJustin T. Gibbs 	 * 64bit bus (PCI64BIT set in devconfig).
818cd036e89SJustin T. Gibbs 	 */
819cd036e89SJustin T. Gibbs 	if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
820cd036e89SJustin T. Gibbs 		if (bootverbose)
821cd036e89SJustin T. Gibbs 			printf("%s: Enabling 39Bit Addressing\n",
822cd036e89SJustin T. Gibbs 			       ahc_name(ahc));
823cd036e89SJustin T. Gibbs 		devconfig |= DACEN;
824cd036e89SJustin T. Gibbs 	}
825cd036e89SJustin T. Gibbs 
82670b41139SJustin T. Gibbs 	/* Ensure that pci error generation, a test feature, is disabled. */
82770b41139SJustin T. Gibbs 	devconfig |= PCIERRGENDIS;
82870b41139SJustin T. Gibbs 
829b3b25f2cSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
83070b41139SJustin T. Gibbs 
831717d4247SJustin T. Gibbs 	/* Ensure busmastering is enabled */
832b3b25f2cSJustin T. Gibbs 	command = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
833717d4247SJustin T. Gibbs 	command |= PCIM_CMD_BUSMASTEREN;
83470b41139SJustin T. Gibbs 
835b3b25f2cSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2);
836717d4247SJustin T. Gibbs 
837717d4247SJustin T. Gibbs 	/* On all PCI adapters, we allow SCB paging */
838cd036e89SJustin T. Gibbs 	ahc->flags |= AHC_PAGESCBS;
839717d4247SJustin T. Gibbs 
840cd036e89SJustin T. Gibbs 	error = ahc_softc_init(ahc);
841717d4247SJustin T. Gibbs 	if (error != 0)
842717d4247SJustin T. Gibbs 		return (error);
843717d4247SJustin T. Gibbs 
8449bf327a7SJustin T. Gibbs 	/*
8459bf327a7SJustin T. Gibbs 	 * Disable PCI parity error checking.  Users typically
8469bf327a7SJustin T. Gibbs 	 * do this to work around broken PCI chipsets that get
8479bf327a7SJustin T. Gibbs 	 * the parity timing wrong and thus generate lots of spurious
8489bf327a7SJustin T. Gibbs 	 * errors.  The chip only allows us to disable *all* parity
8499bf327a7SJustin T. Gibbs 	 * error reporting when doing this, so CIO bus, scb ram, and
8509bf327a7SJustin T. Gibbs 	 * scratch ram parity errors will be ignored too.
8519bf327a7SJustin T. Gibbs 	 */
852e4e6e6d6SJustin T. Gibbs 	if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0)
853e4e6e6d6SJustin T. Gibbs 		ahc->seqctl |= FAILDIS;
8549bf327a7SJustin T. Gibbs 
855b95de6daSJustin T. Gibbs 	ahc->bus_intr = ahc_pci_intr;
8569bf327a7SJustin T. Gibbs 	ahc->bus_chip_init = ahc_pci_chip_init;
8579bf327a7SJustin T. Gibbs 	ahc->bus_suspend = ahc_pci_suspend;
8589bf327a7SJustin T. Gibbs 	ahc->bus_resume = ahc_pci_resume;
859b95de6daSJustin T. Gibbs 
860594c945aSPedro F. Giffuni 	/* Remember how the card was setup in case there is no SEEPROM */
86156a7c4a8SJustin T. Gibbs 	if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
8626fb77fefSJustin T. Gibbs 		ahc_pause(ahc);
863717d4247SJustin T. Gibbs 		if ((ahc->features & AHC_ULTRA2) != 0)
864717d4247SJustin T. Gibbs 			our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID;
865717d4247SJustin T. Gibbs 		else
866717d4247SJustin T. Gibbs 			our_id = ahc_inb(ahc, SCSIID) & OID;
867717d4247SJustin T. Gibbs 		sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN;
868717d4247SJustin T. Gibbs 		scsiseq = ahc_inb(ahc, SCSISEQ);
86956a7c4a8SJustin T. Gibbs 	} else {
87056a7c4a8SJustin T. Gibbs 		sxfrctl1 = STPWEN;
87156a7c4a8SJustin T. Gibbs 		our_id = 7;
87256a7c4a8SJustin T. Gibbs 		scsiseq = 0;
87356a7c4a8SJustin T. Gibbs 	}
874717d4247SJustin T. Gibbs 
8751d528d67SJustin T. Gibbs 	error = ahc_reset(ahc, /*reinit*/FALSE);
876717d4247SJustin T. Gibbs 	if (error != 0)
877717d4247SJustin T. Gibbs 		return (ENXIO);
878717d4247SJustin T. Gibbs 
879717d4247SJustin T. Gibbs 	if ((ahc->features & AHC_DT) != 0) {
880717d4247SJustin T. Gibbs 		u_int sfunct;
881717d4247SJustin T. Gibbs 
882717d4247SJustin T. Gibbs 		/* Perform ALT-Mode Setup */
883717d4247SJustin T. Gibbs 		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
884717d4247SJustin T. Gibbs 		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
88558fb7d8eSJustin T. Gibbs 		ahc_outb(ahc, OPTIONMODE,
88658fb7d8eSJustin T. Gibbs 			 OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS);
887717d4247SJustin T. Gibbs 		ahc_outb(ahc, SFUNCT, sfunct);
888717d4247SJustin T. Gibbs 
889717d4247SJustin T. Gibbs 		/* Normal mode setup */
890717d4247SJustin T. Gibbs 		ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN
89156a7c4a8SJustin T. Gibbs 					  |TARGCRCENDEN);
892717d4247SJustin T. Gibbs 	}
893717d4247SJustin T. Gibbs 
894717d4247SJustin T. Gibbs 	dscommand0 = ahc_inb(ahc, DSCOMMAND0);
895a49630acSJustin T. Gibbs 	dscommand0 |= MPARCKEN|CACHETHEN;
896717d4247SJustin T. Gibbs 	if ((ahc->features & AHC_ULTRA2) != 0) {
897717d4247SJustin T. Gibbs 		/*
898717d4247SJustin T. Gibbs 		 * DPARCKEN doesn't work correctly on
899717d4247SJustin T. Gibbs 		 * some MBs so don't use it.
900717d4247SJustin T. Gibbs 		 */
901717d4247SJustin T. Gibbs 		dscommand0 &= ~DPARCKEN;
902717d4247SJustin T. Gibbs 	}
903717d4247SJustin T. Gibbs 
904717d4247SJustin T. Gibbs 	/*
905717d4247SJustin T. Gibbs 	 * Handle chips that must have cache line
906717d4247SJustin T. Gibbs 	 * streaming (dis/en)abled.
907717d4247SJustin T. Gibbs 	 */
908717d4247SJustin T. Gibbs 	if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0)
909717d4247SJustin T. Gibbs 		dscommand0 |= CACHETHEN;
910717d4247SJustin T. Gibbs 
911717d4247SJustin T. Gibbs 	if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0)
912717d4247SJustin T. Gibbs 		dscommand0 &= ~CACHETHEN;
913717d4247SJustin T. Gibbs 
914717d4247SJustin T. Gibbs 	ahc_outb(ahc, DSCOMMAND0, dscommand0);
915717d4247SJustin T. Gibbs 
916717d4247SJustin T. Gibbs 	ahc->pci_cachesize =
917b3b25f2cSJustin T. Gibbs 	    aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME,
918717d4247SJustin T. Gibbs 				/*bytes*/1) & CACHESIZE;
919717d4247SJustin T. Gibbs 	ahc->pci_cachesize *= 4;
920717d4247SJustin T. Gibbs 
9219f152ec7SJustin T. Gibbs 	if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0
9229f152ec7SJustin T. Gibbs 	 && ahc->pci_cachesize == 4) {
923b3b25f2cSJustin T. Gibbs 		aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
9249f152ec7SJustin T. Gibbs 				     0, /*bytes*/1);
9259f152ec7SJustin T. Gibbs 		ahc->pci_cachesize = 0;
9269f152ec7SJustin T. Gibbs 	}
9279f152ec7SJustin T. Gibbs 
92858fb7d8eSJustin T. Gibbs 	/*
929594c945aSPedro F. Giffuni 	 * We cannot perform ULTRA speeds without the presence
93058fb7d8eSJustin T. Gibbs 	 * of the external precision resistor.
93158fb7d8eSJustin T. Gibbs 	 */
93258fb7d8eSJustin T. Gibbs 	if ((ahc->features & AHC_ULTRA) != 0) {
93358fb7d8eSJustin T. Gibbs 		uint32_t devconfig;
93458fb7d8eSJustin T. Gibbs 
935b3b25f2cSJustin T. Gibbs 		devconfig = aic_pci_read_config(ahc->dev_softc,
93658fb7d8eSJustin T. Gibbs 						DEVCONFIG, /*bytes*/4);
93758fb7d8eSJustin T. Gibbs 		if ((devconfig & REXTVALID) == 0)
93858fb7d8eSJustin T. Gibbs 			ahc->features &= ~AHC_ULTRA;
93958fb7d8eSJustin T. Gibbs 	}
94058fb7d8eSJustin T. Gibbs 
941717d4247SJustin T. Gibbs 	/* See if we have a SEEPROM and perform auto-term */
942717d4247SJustin T. Gibbs 	check_extport(ahc, &sxfrctl1);
943717d4247SJustin T. Gibbs 
944717d4247SJustin T. Gibbs 	/*
945717d4247SJustin T. Gibbs 	 * Take the LED out of diagnostic mode
946717d4247SJustin T. Gibbs 	 */
947717d4247SJustin T. Gibbs 	sblkctl = ahc_inb(ahc, SBLKCTL);
948717d4247SJustin T. Gibbs 	ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));
949717d4247SJustin T. Gibbs 
950717d4247SJustin T. Gibbs 	if ((ahc->features & AHC_ULTRA2) != 0) {
951dd1290f0SJustin T. Gibbs 		ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX);
952717d4247SJustin T. Gibbs 	} else {
953717d4247SJustin T. Gibbs 		ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100);
954717d4247SJustin T. Gibbs 	}
955717d4247SJustin T. Gibbs 
956717d4247SJustin T. Gibbs 	if (ahc->flags & AHC_USEDEFAULTS) {
957717d4247SJustin T. Gibbs 		/*
958717d4247SJustin T. Gibbs 		 * PCI Adapter default setup
959717d4247SJustin T. Gibbs 		 * Should only be used if the adapter does not have
960717d4247SJustin T. Gibbs 		 * a SEEPROM.
961717d4247SJustin T. Gibbs 		 */
962717d4247SJustin T. Gibbs 		/* See if someone else set us up already */
96370b41139SJustin T. Gibbs 		if ((ahc->flags & AHC_NO_BIOS_INIT) == 0
96470b41139SJustin T. Gibbs 		 && scsiseq != 0) {
965717d4247SJustin T. Gibbs 			printf("%s: Using left over BIOS settings\n",
966717d4247SJustin T. Gibbs 				ahc_name(ahc));
967717d4247SJustin T. Gibbs 			ahc->flags &= ~AHC_USEDEFAULTS;
968bfadd24dSJustin T. Gibbs 			ahc->flags |= AHC_BIOS_ENABLED;
969717d4247SJustin T. Gibbs 		} else {
970717d4247SJustin T. Gibbs 			/*
971717d4247SJustin T. Gibbs 			 * Assume only one connector and always turn
972717d4247SJustin T. Gibbs 			 * on termination.
973717d4247SJustin T. Gibbs 			 */
974717d4247SJustin T. Gibbs  			our_id = 0x07;
975717d4247SJustin T. Gibbs 			sxfrctl1 = STPWEN;
976717d4247SJustin T. Gibbs 		}
977717d4247SJustin T. Gibbs 		ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI);
978717d4247SJustin T. Gibbs 
979717d4247SJustin T. Gibbs 		ahc->our_id = our_id;
980717d4247SJustin T. Gibbs 	}
981717d4247SJustin T. Gibbs 
982717d4247SJustin T. Gibbs 	/*
983717d4247SJustin T. Gibbs 	 * Take a look to see if we have external SRAM.
984717d4247SJustin T. Gibbs 	 * We currently do not attempt to use SRAM that is
985717d4247SJustin T. Gibbs 	 * shared among multiple controllers.
986717d4247SJustin T. Gibbs 	 */
987717d4247SJustin T. Gibbs 	ahc_probe_ext_scbram(ahc);
988717d4247SJustin T. Gibbs 
989717d4247SJustin T. Gibbs 	/*
990717d4247SJustin T. Gibbs 	 * Record our termination setting for the
991717d4247SJustin T. Gibbs 	 * generic initialization routine.
992717d4247SJustin T. Gibbs 	 */
993717d4247SJustin T. Gibbs 	if ((sxfrctl1 & STPWEN) != 0)
994717d4247SJustin T. Gibbs 		ahc->flags |= AHC_TERM_ENB_A;
995717d4247SJustin T. Gibbs 
9969bf327a7SJustin T. Gibbs 	/*
9979bf327a7SJustin T. Gibbs 	 * Save chip register configuration data for chip resets
9989bf327a7SJustin T. Gibbs 	 * that occur during runtime and resume events.
9999bf327a7SJustin T. Gibbs 	 */
10009bf327a7SJustin T. Gibbs 	ahc->bus_softc.pci_softc.devconfig =
1001b3b25f2cSJustin T. Gibbs 	    aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
10029bf327a7SJustin T. Gibbs 	ahc->bus_softc.pci_softc.command =
1003b3b25f2cSJustin T. Gibbs 	    aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
10049bf327a7SJustin T. Gibbs 	ahc->bus_softc.pci_softc.csize_lattime =
1005b3b25f2cSJustin T. Gibbs 	    aic_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1);
10069bf327a7SJustin T. Gibbs 	ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0);
10079bf327a7SJustin T. Gibbs 	ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS);
10089bf327a7SJustin T. Gibbs 	if ((ahc->features & AHC_DT) != 0) {
10099bf327a7SJustin T. Gibbs 		u_int sfunct;
10109bf327a7SJustin T. Gibbs 
10119bf327a7SJustin T. Gibbs 		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
10129bf327a7SJustin T. Gibbs 		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
10139bf327a7SJustin T. Gibbs 		ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE);
10149bf327a7SJustin T. Gibbs 		ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT);
10159bf327a7SJustin T. Gibbs 		ahc_outb(ahc, SFUNCT, sfunct);
10169bf327a7SJustin T. Gibbs 		ahc->bus_softc.pci_softc.crccontrol1 =
10179bf327a7SJustin T. Gibbs 		    ahc_inb(ahc, CRCCONTROL1);
10189bf327a7SJustin T. Gibbs 	}
10199bf327a7SJustin T. Gibbs 	if ((ahc->features & AHC_MULTI_FUNC) != 0)
10209bf327a7SJustin T. Gibbs 		ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR);
10219bf327a7SJustin T. Gibbs 
10229bf327a7SJustin T. Gibbs 	if ((ahc->features & AHC_ULTRA2) != 0)
10239bf327a7SJustin T. Gibbs 		ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH);
10249bf327a7SJustin T. Gibbs 
1025717d4247SJustin T. Gibbs 	/* Core initialization */
1026717d4247SJustin T. Gibbs 	error = ahc_init(ahc);
1027717d4247SJustin T. Gibbs 	if (error != 0)
1028717d4247SJustin T. Gibbs 		return (error);
1029717d4247SJustin T. Gibbs 
1030717d4247SJustin T. Gibbs 	/*
1031b95de6daSJustin T. Gibbs 	 * Allow interrupts now that we are completely setup.
1032b95de6daSJustin T. Gibbs 	 */
103358fb7d8eSJustin T. Gibbs 	error = ahc_pci_map_int(ahc);
103458fb7d8eSJustin T. Gibbs 	if (error != 0)
103558fb7d8eSJustin T. Gibbs 		return (error);
103658fb7d8eSJustin T. Gibbs 
1037032b0a17SScott Long 	ahc_lock(ahc);
1038274c4127SJustin T. Gibbs 	/*
1039274c4127SJustin T. Gibbs 	 * Link this softc in with all other ahc instances.
1040274c4127SJustin T. Gibbs 	 */
1041274c4127SJustin T. Gibbs 	ahc_softc_insert(ahc);
1042032b0a17SScott Long 	ahc_unlock(ahc);
1043717d4247SJustin T. Gibbs 	return (0);
1044717d4247SJustin T. Gibbs }
1045717d4247SJustin T. Gibbs 
1046717d4247SJustin T. Gibbs /*
1047594c945aSPedro F. Giffuni  * Test for the presence of external sram in an
1048717d4247SJustin T. Gibbs  * "unshared" configuration.
1049717d4247SJustin T. Gibbs  */
1050717d4247SJustin T. Gibbs static int
1051717d4247SJustin T. Gibbs ahc_ext_scbram_present(struct ahc_softc *ahc)
1052717d4247SJustin T. Gibbs {
1053dd1290f0SJustin T. Gibbs 	u_int chip;
1054717d4247SJustin T. Gibbs 	int ramps;
1055717d4247SJustin T. Gibbs 	int single_user;
1056717d4247SJustin T. Gibbs 	uint32_t devconfig;
1057717d4247SJustin T. Gibbs 
1058dd1290f0SJustin T. Gibbs 	chip = ahc->chip & AHC_CHIPID_MASK;
1059b3b25f2cSJustin T. Gibbs 	devconfig = aic_pci_read_config(ahc->dev_softc,
1060717d4247SJustin T. Gibbs 					DEVCONFIG, /*bytes*/4);
1061717d4247SJustin T. Gibbs 	single_user = (devconfig & MPORTMODE) != 0;
1062717d4247SJustin T. Gibbs 
1063717d4247SJustin T. Gibbs 	if ((ahc->features & AHC_ULTRA2) != 0)
1064717d4247SJustin T. Gibbs 		ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0;
10658f214efcSJustin T. Gibbs 	else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C)
10668f214efcSJustin T. Gibbs 		/*
10678f214efcSJustin T. Gibbs 		 * External SCBRAM arbitration is flakey
10688f214efcSJustin T. Gibbs 		 * on these chips.  Unfortunately this means
10698f214efcSJustin T. Gibbs 		 * we don't use the extra SCB ram space on the
10708f214efcSJustin T. Gibbs 		 * 3940AUW.
10718f214efcSJustin T. Gibbs 		 */
10728f214efcSJustin T. Gibbs 		ramps = 0;
1073dd1290f0SJustin T. Gibbs 	else if (chip >= AHC_AIC7870)
1074717d4247SJustin T. Gibbs 		ramps = (devconfig & RAMPSM) != 0;
1075717d4247SJustin T. Gibbs 	else
1076717d4247SJustin T. Gibbs 		ramps = 0;
1077717d4247SJustin T. Gibbs 
1078717d4247SJustin T. Gibbs 	if (ramps && single_user)
1079717d4247SJustin T. Gibbs 		return (1);
1080717d4247SJustin T. Gibbs 	return (0);
1081717d4247SJustin T. Gibbs }
1082717d4247SJustin T. Gibbs 
1083717d4247SJustin T. Gibbs /*
1084717d4247SJustin T. Gibbs  * Enable external scbram.
1085717d4247SJustin T. Gibbs  */
1086717d4247SJustin T. Gibbs static void
1087717d4247SJustin T. Gibbs ahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck,
1088717d4247SJustin T. Gibbs 		  int fast, int large)
1089717d4247SJustin T. Gibbs {
1090717d4247SJustin T. Gibbs 	uint32_t devconfig;
1091717d4247SJustin T. Gibbs 
1092717d4247SJustin T. Gibbs 	if (ahc->features & AHC_MULTI_FUNC) {
1093717d4247SJustin T. Gibbs 		/*
1094717d4247SJustin T. Gibbs 		 * Set the SCB Base addr (highest address bit)
1095717d4247SJustin T. Gibbs 		 * depending on which channel we are.
1096717d4247SJustin T. Gibbs 		 */
1097b3b25f2cSJustin T. Gibbs 		ahc_outb(ahc, SCBBADDR, aic_get_pci_function(ahc->dev_softc));
1098717d4247SJustin T. Gibbs 	}
1099717d4247SJustin T. Gibbs 
1100274c4127SJustin T. Gibbs 	ahc->flags &= ~AHC_LSCBS_ENABLED;
1101274c4127SJustin T. Gibbs 	if (large)
1102274c4127SJustin T. Gibbs 		ahc->flags |= AHC_LSCBS_ENABLED;
1103b3b25f2cSJustin T. Gibbs 	devconfig = aic_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
1104717d4247SJustin T. Gibbs 	if ((ahc->features & AHC_ULTRA2) != 0) {
1105717d4247SJustin T. Gibbs 		u_int dscommand0;
1106717d4247SJustin T. Gibbs 
1107717d4247SJustin T. Gibbs 		dscommand0 = ahc_inb(ahc, DSCOMMAND0);
1108717d4247SJustin T. Gibbs 		if (enable)
1109717d4247SJustin T. Gibbs 			dscommand0 &= ~INTSCBRAMSEL;
1110717d4247SJustin T. Gibbs 		else
1111717d4247SJustin T. Gibbs 			dscommand0 |= INTSCBRAMSEL;
1112717d4247SJustin T. Gibbs 		if (large)
1113717d4247SJustin T. Gibbs 			dscommand0 &= ~USCBSIZE32;
1114717d4247SJustin T. Gibbs 		else
1115717d4247SJustin T. Gibbs 			dscommand0 |= USCBSIZE32;
1116717d4247SJustin T. Gibbs 		ahc_outb(ahc, DSCOMMAND0, dscommand0);
1117717d4247SJustin T. Gibbs 	} else {
1118717d4247SJustin T. Gibbs 		if (fast)
1119717d4247SJustin T. Gibbs 			devconfig &= ~EXTSCBTIME;
1120717d4247SJustin T. Gibbs 		else
1121717d4247SJustin T. Gibbs 			devconfig |= EXTSCBTIME;
1122717d4247SJustin T. Gibbs 		if (enable)
1123717d4247SJustin T. Gibbs 			devconfig &= ~SCBRAMSEL;
1124717d4247SJustin T. Gibbs 		else
1125717d4247SJustin T. Gibbs 			devconfig |= SCBRAMSEL;
1126717d4247SJustin T. Gibbs 		if (large)
1127717d4247SJustin T. Gibbs 			devconfig &= ~SCBSIZE32;
1128717d4247SJustin T. Gibbs 		else
1129717d4247SJustin T. Gibbs 			devconfig |= SCBSIZE32;
1130717d4247SJustin T. Gibbs 	}
1131717d4247SJustin T. Gibbs 	if (pcheck)
1132717d4247SJustin T. Gibbs 		devconfig |= EXTSCBPEN;
1133717d4247SJustin T. Gibbs 	else
1134717d4247SJustin T. Gibbs 		devconfig &= ~EXTSCBPEN;
1135717d4247SJustin T. Gibbs 
1136b3b25f2cSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
1137717d4247SJustin T. Gibbs }
1138717d4247SJustin T. Gibbs 
1139717d4247SJustin T. Gibbs /*
1140717d4247SJustin T. Gibbs  * Take a look to see if we have external SRAM.
1141717d4247SJustin T. Gibbs  * We currently do not attempt to use SRAM that is
1142717d4247SJustin T. Gibbs  * shared among multiple controllers.
1143717d4247SJustin T. Gibbs  */
1144717d4247SJustin T. Gibbs static void
1145717d4247SJustin T. Gibbs ahc_probe_ext_scbram(struct ahc_softc *ahc)
1146717d4247SJustin T. Gibbs {
1147717d4247SJustin T. Gibbs 	int num_scbs;
1148717d4247SJustin T. Gibbs 	int test_num_scbs;
1149717d4247SJustin T. Gibbs 	int enable;
1150717d4247SJustin T. Gibbs 	int pcheck;
1151717d4247SJustin T. Gibbs 	int fast;
1152717d4247SJustin T. Gibbs 	int large;
1153717d4247SJustin T. Gibbs 
1154717d4247SJustin T. Gibbs 	enable = FALSE;
1155717d4247SJustin T. Gibbs 	pcheck = FALSE;
1156717d4247SJustin T. Gibbs 	fast = FALSE;
1157717d4247SJustin T. Gibbs 	large = FALSE;
1158717d4247SJustin T. Gibbs 	num_scbs = 0;
1159717d4247SJustin T. Gibbs 
1160717d4247SJustin T. Gibbs 	if (ahc_ext_scbram_present(ahc) == 0)
1161717d4247SJustin T. Gibbs 		goto done;
1162717d4247SJustin T. Gibbs 
1163717d4247SJustin T. Gibbs 	/*
1164717d4247SJustin T. Gibbs 	 * Probe for the best parameters to use.
1165717d4247SJustin T. Gibbs 	 */
1166717d4247SJustin T. Gibbs 	ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large);
1167717d4247SJustin T. Gibbs 	num_scbs = ahc_probe_scbs(ahc);
1168717d4247SJustin T. Gibbs 	if (num_scbs == 0) {
1169717d4247SJustin T. Gibbs 		/* The SRAM wasn't really present. */
1170717d4247SJustin T. Gibbs 		goto done;
1171717d4247SJustin T. Gibbs 	}
1172717d4247SJustin T. Gibbs 	enable = TRUE;
1173717d4247SJustin T. Gibbs 
1174717d4247SJustin T. Gibbs 	/*
1175717d4247SJustin T. Gibbs 	 * Clear any outstanding parity error
1176717d4247SJustin T. Gibbs 	 * and ensure that parity error reporting
1177717d4247SJustin T. Gibbs 	 * is enabled.
1178717d4247SJustin T. Gibbs 	 */
1179717d4247SJustin T. Gibbs 	ahc_outb(ahc, SEQCTL, 0);
1180717d4247SJustin T. Gibbs 	ahc_outb(ahc, CLRINT, CLRPARERR);
1181717d4247SJustin T. Gibbs 	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
1182717d4247SJustin T. Gibbs 
1183717d4247SJustin T. Gibbs 	/* Now see if we can do parity */
1184717d4247SJustin T. Gibbs 	ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large);
1185717d4247SJustin T. Gibbs 	num_scbs = ahc_probe_scbs(ahc);
1186717d4247SJustin T. Gibbs 	if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
1187717d4247SJustin T. Gibbs 	 || (ahc_inb(ahc, ERROR) & MPARERR) == 0)
1188717d4247SJustin T. Gibbs 		pcheck = TRUE;
1189717d4247SJustin T. Gibbs 
1190717d4247SJustin T. Gibbs 	/* Clear any resulting parity error */
1191717d4247SJustin T. Gibbs 	ahc_outb(ahc, CLRINT, CLRPARERR);
1192717d4247SJustin T. Gibbs 	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
1193717d4247SJustin T. Gibbs 
1194717d4247SJustin T. Gibbs 	/* Now see if we can do fast timing */
1195717d4247SJustin T. Gibbs 	ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large);
1196717d4247SJustin T. Gibbs 	test_num_scbs = ahc_probe_scbs(ahc);
1197717d4247SJustin T. Gibbs 	if (test_num_scbs == num_scbs
1198717d4247SJustin T. Gibbs 	 && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
1199717d4247SJustin T. Gibbs 	  || (ahc_inb(ahc, ERROR) & MPARERR) == 0))
1200717d4247SJustin T. Gibbs 		fast = TRUE;
1201717d4247SJustin T. Gibbs 
1202717d4247SJustin T. Gibbs 	/*
1203717d4247SJustin T. Gibbs 	 * See if we can use large SCBs and still maintain
1204717d4247SJustin T. Gibbs 	 * the same overall count of SCBs.
1205717d4247SJustin T. Gibbs 	 */
1206717d4247SJustin T. Gibbs 	if ((ahc->features & AHC_LARGE_SCBS) != 0) {
1207717d4247SJustin T. Gibbs 		ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE);
1208717d4247SJustin T. Gibbs 		test_num_scbs = ahc_probe_scbs(ahc);
1209717d4247SJustin T. Gibbs 		if (test_num_scbs >= num_scbs) {
1210717d4247SJustin T. Gibbs 			large = TRUE;
1211717d4247SJustin T. Gibbs 			num_scbs = test_num_scbs;
1212717d4247SJustin T. Gibbs 	 		if (num_scbs >= 64) {
1213717d4247SJustin T. Gibbs 				/*
1214717d4247SJustin T. Gibbs 				 * We have enough space to move the
1215717d4247SJustin T. Gibbs 				 * "busy targets table" into SCB space
1216717d4247SJustin T. Gibbs 				 * and make it qualify all the way to the
1217717d4247SJustin T. Gibbs 				 * lun level.
1218717d4247SJustin T. Gibbs 				 */
1219717d4247SJustin T. Gibbs 				ahc->flags |= AHC_SCB_BTT;
1220717d4247SJustin T. Gibbs 			}
1221717d4247SJustin T. Gibbs 		}
1222717d4247SJustin T. Gibbs 	}
1223717d4247SJustin T. Gibbs done:
1224717d4247SJustin T. Gibbs 	/*
1225717d4247SJustin T. Gibbs 	 * Disable parity error reporting until we
1226717d4247SJustin T. Gibbs 	 * can load instruction ram.
1227717d4247SJustin T. Gibbs 	 */
1228717d4247SJustin T. Gibbs 	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
1229717d4247SJustin T. Gibbs 	/* Clear any latched parity error */
1230717d4247SJustin T. Gibbs 	ahc_outb(ahc, CLRINT, CLRPARERR);
1231717d4247SJustin T. Gibbs 	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
1232717d4247SJustin T. Gibbs 	if (bootverbose && enable) {
1233717d4247SJustin T. Gibbs 		printf("%s: External SRAM, %s access%s, %dbytes/SCB\n",
1234717d4247SJustin T. Gibbs 		       ahc_name(ahc), fast ? "fast" : "slow",
1235717d4247SJustin T. Gibbs 		       pcheck ? ", parity checking enabled" : "",
1236717d4247SJustin T. Gibbs 		       large ? 64 : 32);
1237717d4247SJustin T. Gibbs 	}
1238717d4247SJustin T. Gibbs 	ahc_scbram_config(ahc, enable, pcheck, fast, large);
1239717d4247SJustin T. Gibbs }
1240717d4247SJustin T. Gibbs 
1241717d4247SJustin T. Gibbs /*
1242dc67dad8SScott Long  * Perform some simple tests that should catch situations where
1243dc67dad8SScott Long  * our registers are invalidly mapped.
1244dc67dad8SScott Long  */
1245dc67dad8SScott Long int
1246dc67dad8SScott Long ahc_pci_test_register_access(struct ahc_softc *ahc)
1247dc67dad8SScott Long {
124897cae63dSScott Long 	int	 error;
1249dc67dad8SScott Long 	u_int	 status1;
125070b41139SJustin T. Gibbs 	uint32_t cmd;
125170b41139SJustin T. Gibbs 	uint8_t	 hcntrl;
125297cae63dSScott Long 
125397cae63dSScott Long 	error = EIO;
125497cae63dSScott Long 
125570b41139SJustin T. Gibbs 	/*
125670b41139SJustin T. Gibbs 	 * Enable PCI error interrupt status, but suppress NMIs
125770b41139SJustin T. Gibbs 	 * generated by SERR raised due to target aborts.
125870b41139SJustin T. Gibbs 	 */
1259b3b25f2cSJustin T. Gibbs 	cmd = aic_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
1260b3b25f2cSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
126170b41139SJustin T. Gibbs 			     cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
1262dc67dad8SScott Long 
1263dc67dad8SScott Long 	/*
1264dc67dad8SScott Long 	 * First a simple test to see if any
1265dc67dad8SScott Long 	 * registers can be read.  Reading
1266dc67dad8SScott Long 	 * HCNTRL has no side effects and has
1267dc67dad8SScott Long 	 * at least one bit that is guaranteed to
1268dc67dad8SScott Long 	 * be zero so it is a good register to
1269dc67dad8SScott Long 	 * use for this test.
1270dc67dad8SScott Long 	 */
127170b41139SJustin T. Gibbs 	hcntrl = ahc_inb(ahc, HCNTRL);
1272b3b25f2cSJustin T. Gibbs 
127370b41139SJustin T. Gibbs 	if (hcntrl == 0xFF)
127497cae63dSScott Long 		goto fail;
1275dc67dad8SScott Long 
1276b3b25f2cSJustin T. Gibbs 	if ((hcntrl & CHIPRST) != 0) {
1277b3b25f2cSJustin T. Gibbs 		/*
1278b3b25f2cSJustin T. Gibbs 		 * The chip has not been initialized since
1279b3b25f2cSJustin T. Gibbs 		 * PCI/EISA/VLB bus reset.  Don't trust
1280b3b25f2cSJustin T. Gibbs 		 * "left over BIOS data".
1281b3b25f2cSJustin T. Gibbs 		 */
1282b3b25f2cSJustin T. Gibbs 		ahc->flags |= AHC_NO_BIOS_INIT;
1283b3b25f2cSJustin T. Gibbs 	}
1284b3b25f2cSJustin T. Gibbs 
1285dc67dad8SScott Long 	/*
1286dc67dad8SScott Long 	 * Next create a situation where write combining
1287dc67dad8SScott Long 	 * or read prefetching could be initiated by the
1288dc67dad8SScott Long 	 * CPU or host bridge.  Our device does not support
1289dc67dad8SScott Long 	 * either, so look for data corruption and/or flagged
1290ba079c0dSScott Long 	 * PCI errors.  First pause without causing another
1291ba079c0dSScott Long 	 * chip reset.
1292dc67dad8SScott Long 	 */
1293ba079c0dSScott Long 	hcntrl &= ~CHIPRST;
129470b41139SJustin T. Gibbs 	ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
129570b41139SJustin T. Gibbs 	while (ahc_is_paused(ahc) == 0)
129670b41139SJustin T. Gibbs 		;
1297176b648eSJustin T. Gibbs 
1298176b648eSJustin T. Gibbs 	/* Clear any PCI errors that occurred before our driver attached. */
1299b3b25f2cSJustin T. Gibbs 	status1 = aic_pci_read_config(ahc->dev_softc,
1300176b648eSJustin T. Gibbs 				      PCIR_STATUS + 1, /*bytes*/1);
1301b3b25f2cSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
1302176b648eSJustin T. Gibbs 			     status1, /*bytes*/1);
1303176b648eSJustin T. Gibbs 	ahc_outb(ahc, CLRINT, CLRPARERR);
1304176b648eSJustin T. Gibbs 
130570b41139SJustin T. Gibbs 	ahc_outb(ahc, SEQCTL, PERRORDIS);
130670b41139SJustin T. Gibbs 	ahc_outb(ahc, SCBPTR, 0);
130770b41139SJustin T. Gibbs 	ahc_outl(ahc, SCB_BASE, 0x5aa555aa);
130870b41139SJustin T. Gibbs 	if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa)
130997cae63dSScott Long 		goto fail;
1310dc67dad8SScott Long 
1311b3b25f2cSJustin T. Gibbs 	status1 = aic_pci_read_config(ahc->dev_softc,
1312dc67dad8SScott Long 				      PCIR_STATUS + 1, /*bytes*/1);
131397cae63dSScott Long 	if ((status1 & STA) != 0)
131497cae63dSScott Long 		goto fail;
1315dc67dad8SScott Long 
131697cae63dSScott Long 	error = 0;
131797cae63dSScott Long 
131897cae63dSScott Long fail:
1319dc67dad8SScott Long 	/* Silently clear any latched errors. */
1320b3b25f2cSJustin T. Gibbs 	status1 = aic_pci_read_config(ahc->dev_softc,
132197cae63dSScott Long 				      PCIR_STATUS + 1, /*bytes*/1);
1322b3b25f2cSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
1323dc67dad8SScott Long 			     status1, /*bytes*/1);
1324dc67dad8SScott Long 	ahc_outb(ahc, CLRINT, CLRPARERR);
132570b41139SJustin T. Gibbs 	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
1326b3b25f2cSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
132797cae63dSScott Long 	return (error);
1328dc67dad8SScott Long }
1329dc67dad8SScott Long 
1330dc67dad8SScott Long /*
1331717d4247SJustin T. Gibbs  * Check the external port logic for a serial eeprom
1332717d4247SJustin T. Gibbs  * and termination/cable detection contrls.
1333717d4247SJustin T. Gibbs  */
1334717d4247SJustin T. Gibbs static void
1335717d4247SJustin T. Gibbs check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
1336717d4247SJustin T. Gibbs {
1337717d4247SJustin T. Gibbs 	struct	seeprom_descriptor sd;
1338274c4127SJustin T. Gibbs 	struct	seeprom_config *sc;
1339717d4247SJustin T. Gibbs 	int	have_seeprom;
1340717d4247SJustin T. Gibbs 	int	have_autoterm;
1341717d4247SJustin T. Gibbs 
1342717d4247SJustin T. Gibbs 	sd.sd_ahc = ahc;
1343717d4247SJustin T. Gibbs 	sd.sd_control_offset = SEECTL;
1344717d4247SJustin T. Gibbs 	sd.sd_status_offset = SEECTL;
1345717d4247SJustin T. Gibbs 	sd.sd_dataout_offset = SEECTL;
1346274c4127SJustin T. Gibbs 	sc = ahc->seep_config;
1347717d4247SJustin T. Gibbs 
1348717d4247SJustin T. Gibbs 	/*
1349717d4247SJustin T. Gibbs 	 * For some multi-channel devices, the c46 is simply too
1350717d4247SJustin T. Gibbs 	 * small to work.  For the other controller types, we can
1351717d4247SJustin T. Gibbs 	 * get our information from either SEEPROM type.  Set the
1352717d4247SJustin T. Gibbs 	 * type to start our probe with accordingly.
1353717d4247SJustin T. Gibbs 	 */
1354717d4247SJustin T. Gibbs 	if (ahc->flags & AHC_LARGE_SEEPROM)
1355717d4247SJustin T. Gibbs 		sd.sd_chip = C56_66;
1356717d4247SJustin T. Gibbs 	else
1357717d4247SJustin T. Gibbs 		sd.sd_chip = C46;
1358717d4247SJustin T. Gibbs 
1359717d4247SJustin T. Gibbs 	sd.sd_MS = SEEMS;
1360717d4247SJustin T. Gibbs 	sd.sd_RDY = SEERDY;
1361717d4247SJustin T. Gibbs 	sd.sd_CS = SEECS;
1362717d4247SJustin T. Gibbs 	sd.sd_CK = SEECK;
1363717d4247SJustin T. Gibbs 	sd.sd_DO = SEEDO;
1364717d4247SJustin T. Gibbs 	sd.sd_DI = SEEDI;
1365717d4247SJustin T. Gibbs 
13668f214efcSJustin T. Gibbs 	have_seeprom = ahc_acquire_seeprom(ahc, &sd);
1367717d4247SJustin T. Gibbs 	if (have_seeprom) {
1368717d4247SJustin T. Gibbs 		if (bootverbose)
1369717d4247SJustin T. Gibbs 			printf("%s: Reading SEEPROM...", ahc_name(ahc));
1370717d4247SJustin T. Gibbs 
1371717d4247SJustin T. Gibbs 		for (;;) {
1372717d4247SJustin T. Gibbs 			u_int start_addr;
1373717d4247SJustin T. Gibbs 
1374717d4247SJustin T. Gibbs 			start_addr = 32 * (ahc->channel - 'A');
1375717d4247SJustin T. Gibbs 
1376274c4127SJustin T. Gibbs 			have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,
13778f214efcSJustin T. Gibbs 							start_addr,
1378274c4127SJustin T. Gibbs 							sizeof(*sc)/2);
1379717d4247SJustin T. Gibbs 
1380717d4247SJustin T. Gibbs 			if (have_seeprom)
1381274c4127SJustin T. Gibbs 				have_seeprom = ahc_verify_cksum(sc);
1382717d4247SJustin T. Gibbs 
1383717d4247SJustin T. Gibbs 			if (have_seeprom != 0 || sd.sd_chip == C56_66) {
1384717d4247SJustin T. Gibbs 				if (bootverbose) {
1385717d4247SJustin T. Gibbs 					if (have_seeprom == 0)
1386717d4247SJustin T. Gibbs 						printf ("checksum error\n");
1387717d4247SJustin T. Gibbs 					else
1388717d4247SJustin T. Gibbs 						printf ("done.\n");
1389717d4247SJustin T. Gibbs 				}
1390717d4247SJustin T. Gibbs 				break;
1391717d4247SJustin T. Gibbs 			}
1392717d4247SJustin T. Gibbs 			sd.sd_chip = C56_66;
1393717d4247SJustin T. Gibbs 		}
13948f214efcSJustin T. Gibbs 		ahc_release_seeprom(&sd);
1395b3b25f2cSJustin T. Gibbs 
1396b3b25f2cSJustin T. Gibbs 		/* Remember the SEEPROM type for later */
1397b3b25f2cSJustin T. Gibbs 		if (sd.sd_chip == C56_66)
1398b3b25f2cSJustin T. Gibbs 			ahc->flags |= AHC_LARGE_SEEPROM;
1399717d4247SJustin T. Gibbs 	}
1400717d4247SJustin T. Gibbs 
1401717d4247SJustin T. Gibbs 	if (!have_seeprom) {
1402717d4247SJustin T. Gibbs 		/*
1403717d4247SJustin T. Gibbs 		 * Pull scratch ram settings and treat them as
1404717d4247SJustin T. Gibbs 		 * if they are the contents of an seeprom if
1405717d4247SJustin T. Gibbs 		 * the 'ADPT' signature is found in SCB2.
14066fb77fefSJustin T. Gibbs 		 * We manually compose the data as 16bit values
14076fb77fefSJustin T. Gibbs 		 * to avoid endian issues.
1408717d4247SJustin T. Gibbs 		 */
1409717d4247SJustin T. Gibbs 		ahc_outb(ahc, SCBPTR, 2);
1410717d4247SJustin T. Gibbs 		if (ahc_inb(ahc, SCB_BASE) == 'A'
1411717d4247SJustin T. Gibbs 		 && ahc_inb(ahc, SCB_BASE + 1) == 'D'
1412717d4247SJustin T. Gibbs 		 && ahc_inb(ahc, SCB_BASE + 2) == 'P'
1413717d4247SJustin T. Gibbs 		 && ahc_inb(ahc, SCB_BASE + 3) == 'T') {
14146fb77fefSJustin T. Gibbs 			uint16_t *sc_data;
1415717d4247SJustin T. Gibbs 			int	  i;
1416717d4247SJustin T. Gibbs 
1417274c4127SJustin T. Gibbs 			sc_data = (uint16_t *)sc;
1418274c4127SJustin T. Gibbs 			for (i = 0; i < 32; i++, sc_data++) {
14196fb77fefSJustin T. Gibbs 				int	j;
14206fb77fefSJustin T. Gibbs 
14216fb77fefSJustin T. Gibbs 				j = i * 2;
1422274c4127SJustin T. Gibbs 				*sc_data = ahc_inb(ahc, SRAM_BASE + j)
14236fb77fefSJustin T. Gibbs 					 | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
14246fb77fefSJustin T. Gibbs 			}
1425274c4127SJustin T. Gibbs 			have_seeprom = ahc_verify_cksum(sc);
1426274c4127SJustin T. Gibbs 			if (have_seeprom)
1427274c4127SJustin T. Gibbs 				ahc->flags |= AHC_SCB_CONFIG_USED;
1428717d4247SJustin T. Gibbs 		}
14298f214efcSJustin T. Gibbs 		/*
14308f214efcSJustin T. Gibbs 		 * Clear any SCB parity errors in case this data and
14318f214efcSJustin T. Gibbs 		 * its associated parity was not initialized by the BIOS
14328f214efcSJustin T. Gibbs 		 */
14338f214efcSJustin T. Gibbs 		ahc_outb(ahc, CLRINT, CLRPARERR);
14348f214efcSJustin T. Gibbs 		ahc_outb(ahc, CLRINT, CLRBRKADRINT);
1435717d4247SJustin T. Gibbs 	}
1436717d4247SJustin T. Gibbs 
1437717d4247SJustin T. Gibbs 	if (!have_seeprom) {
1438717d4247SJustin T. Gibbs 		if (bootverbose)
1439717d4247SJustin T. Gibbs 			printf("%s: No SEEPROM available.\n", ahc_name(ahc));
1440717d4247SJustin T. Gibbs 		ahc->flags |= AHC_USEDEFAULTS;
1441274c4127SJustin T. Gibbs 		free(ahc->seep_config, M_DEVBUF);
1442274c4127SJustin T. Gibbs 		ahc->seep_config = NULL;
1443274c4127SJustin T. Gibbs 		sc = NULL;
1444717d4247SJustin T. Gibbs 	} else {
1445274c4127SJustin T. Gibbs 		ahc_parse_pci_eeprom(ahc, sc);
1446274c4127SJustin T. Gibbs 	}
1447274c4127SJustin T. Gibbs 
1448274c4127SJustin T. Gibbs 	/*
1449274c4127SJustin T. Gibbs 	 * Cards that have the external logic necessary to talk to
1450274c4127SJustin T. Gibbs 	 * a SEEPROM, are almost certain to have the remaining logic
1451274c4127SJustin T. Gibbs 	 * necessary for auto-termination control.  This assumption
1452274c4127SJustin T. Gibbs 	 * hasn't failed yet...
1453274c4127SJustin T. Gibbs 	 */
1454274c4127SJustin T. Gibbs 	have_autoterm = have_seeprom;
1455274c4127SJustin T. Gibbs 
1456274c4127SJustin T. Gibbs 	/*
1457274c4127SJustin T. Gibbs 	 * Some low-cost chips have SEEPROM and auto-term control built
1458274c4127SJustin T. Gibbs 	 * in, instead of using a GAL.  They can tell us directly
1459274c4127SJustin T. Gibbs 	 * if the termination logic is enabled.
1460274c4127SJustin T. Gibbs 	 */
1461274c4127SJustin T. Gibbs 	if ((ahc->features & AHC_SPIOCAP) != 0) {
1462274c4127SJustin T. Gibbs 		if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0)
1463274c4127SJustin T. Gibbs 			have_autoterm = FALSE;
1464274c4127SJustin T. Gibbs 	}
1465274c4127SJustin T. Gibbs 
1466274c4127SJustin T. Gibbs 	if (have_autoterm) {
14679bf327a7SJustin T. Gibbs 		ahc->flags |= AHC_HAS_TERM_LOGIC;
1468274c4127SJustin T. Gibbs 		ahc_acquire_seeprom(ahc, &sd);
1469274c4127SJustin T. Gibbs 		configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1);
1470274c4127SJustin T. Gibbs 		ahc_release_seeprom(&sd);
1471274c4127SJustin T. Gibbs 	} else if (have_seeprom) {
1472274c4127SJustin T. Gibbs 		*sxfrctl1 &= ~STPWEN;
1473274c4127SJustin T. Gibbs 		if ((sc->adapter_control & CFSTERM) != 0)
1474274c4127SJustin T. Gibbs 			*sxfrctl1 |= STPWEN;
1475274c4127SJustin T. Gibbs 		if (bootverbose)
1476274c4127SJustin T. Gibbs 			printf("%s: Low byte termination %sabled\n",
1477274c4127SJustin T. Gibbs 			       ahc_name(ahc),
1478274c4127SJustin T. Gibbs 			       (*sxfrctl1 & STPWEN) ? "en" : "dis");
1479274c4127SJustin T. Gibbs 	}
1480274c4127SJustin T. Gibbs }
1481274c4127SJustin T. Gibbs 
1482274c4127SJustin T. Gibbs static void
1483274c4127SJustin T. Gibbs ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc)
1484274c4127SJustin T. Gibbs {
1485717d4247SJustin T. Gibbs 	/*
1486717d4247SJustin T. Gibbs 	 * Put the data we've collected down into SRAM
1487717d4247SJustin T. Gibbs 	 * where ahc_init will find it.
1488717d4247SJustin T. Gibbs 	 */
1489717d4247SJustin T. Gibbs 	int	 i;
1490274c4127SJustin T. Gibbs 	int	 max_targ = sc->max_targets & CFMAXTARG;
1491274c4127SJustin T. Gibbs 	u_int	 scsi_conf;
1492717d4247SJustin T. Gibbs 	uint16_t discenable;
1493717d4247SJustin T. Gibbs 	uint16_t ultraenb;
1494717d4247SJustin T. Gibbs 
1495717d4247SJustin T. Gibbs 	discenable = 0;
1496717d4247SJustin T. Gibbs 	ultraenb = 0;
1497274c4127SJustin T. Gibbs 	if ((sc->adapter_control & CFULTRAEN) != 0) {
1498717d4247SJustin T. Gibbs 		/*
1499717d4247SJustin T. Gibbs 		 * Determine if this adapter has a "newstyle"
1500717d4247SJustin T. Gibbs 		 * SEEPROM format.
1501717d4247SJustin T. Gibbs 		 */
1502717d4247SJustin T. Gibbs 		for (i = 0; i < max_targ; i++) {
1503274c4127SJustin T. Gibbs 			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) {
1504717d4247SJustin T. Gibbs 				ahc->flags |= AHC_NEWEEPROM_FMT;
1505717d4247SJustin T. Gibbs 				break;
1506717d4247SJustin T. Gibbs 			}
1507717d4247SJustin T. Gibbs 		}
1508717d4247SJustin T. Gibbs 	}
1509717d4247SJustin T. Gibbs 
1510717d4247SJustin T. Gibbs 	for (i = 0; i < max_targ; i++) {
1511717d4247SJustin T. Gibbs 		u_int     scsirate;
1512717d4247SJustin T. Gibbs 		uint16_t target_mask;
1513717d4247SJustin T. Gibbs 
1514717d4247SJustin T. Gibbs 		target_mask = 0x01 << i;
1515274c4127SJustin T. Gibbs 		if (sc->device_flags[i] & CFDISC)
1516717d4247SJustin T. Gibbs 			discenable |= target_mask;
1517717d4247SJustin T. Gibbs 		if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) {
1518274c4127SJustin T. Gibbs 			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0)
1519717d4247SJustin T. Gibbs 				ultraenb |= target_mask;
1520274c4127SJustin T. Gibbs 		} else if ((sc->adapter_control & CFULTRAEN) != 0) {
1521717d4247SJustin T. Gibbs 			ultraenb |= target_mask;
1522717d4247SJustin T. Gibbs 		}
1523274c4127SJustin T. Gibbs 		if ((sc->device_flags[i] & CFXFER) == 0x04
1524717d4247SJustin T. Gibbs 		 && (ultraenb & target_mask) != 0) {
1525717d4247SJustin T. Gibbs 			/* Treat 10MHz as a non-ultra speed */
1526274c4127SJustin T. Gibbs 			sc->device_flags[i] &= ~CFXFER;
1527717d4247SJustin T. Gibbs 		 	ultraenb &= ~target_mask;
1528717d4247SJustin T. Gibbs 		}
1529717d4247SJustin T. Gibbs 		if ((ahc->features & AHC_ULTRA2) != 0) {
1530717d4247SJustin T. Gibbs 			u_int offset;
1531717d4247SJustin T. Gibbs 
1532274c4127SJustin T. Gibbs 			if (sc->device_flags[i] & CFSYNCH)
1533717d4247SJustin T. Gibbs 				offset = MAX_OFFSET_ULTRA2;
1534717d4247SJustin T. Gibbs 			else
1535717d4247SJustin T. Gibbs 				offset = 0;
1536717d4247SJustin T. Gibbs 			ahc_outb(ahc, TARG_OFFSET + i, offset);
1537717d4247SJustin T. Gibbs 
1538717d4247SJustin T. Gibbs 			/*
1539717d4247SJustin T. Gibbs 			 * The ultra enable bits contain the
1540717d4247SJustin T. Gibbs 			 * high bit of the ultra2 sync rate
1541717d4247SJustin T. Gibbs 			 * field.
1542717d4247SJustin T. Gibbs 			 */
1543274c4127SJustin T. Gibbs 			scsirate = (sc->device_flags[i] & CFXFER)
1544274c4127SJustin T. Gibbs 				 | ((ultraenb & target_mask) ? 0x8 : 0x0);
1545274c4127SJustin T. Gibbs 			if (sc->device_flags[i] & CFWIDEB)
1546717d4247SJustin T. Gibbs 				scsirate |= WIDEXFER;
1547717d4247SJustin T. Gibbs 		} else {
1548274c4127SJustin T. Gibbs 			scsirate = (sc->device_flags[i] & CFXFER) << 4;
1549274c4127SJustin T. Gibbs 			if (sc->device_flags[i] & CFSYNCH)
1550717d4247SJustin T. Gibbs 				scsirate |= SOFS;
1551274c4127SJustin T. Gibbs 			if (sc->device_flags[i] & CFWIDEB)
1552717d4247SJustin T. Gibbs 				scsirate |= WIDEXFER;
1553717d4247SJustin T. Gibbs 		}
1554717d4247SJustin T. Gibbs 		ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);
1555717d4247SJustin T. Gibbs 	}
1556274c4127SJustin T. Gibbs 	ahc->our_id = sc->brtime_id & CFSCSIID;
1557717d4247SJustin T. Gibbs 
1558717d4247SJustin T. Gibbs 	scsi_conf = (ahc->our_id & 0x7);
1559274c4127SJustin T. Gibbs 	if (sc->adapter_control & CFSPARITY)
1560717d4247SJustin T. Gibbs 		scsi_conf |= ENSPCHK;
1561274c4127SJustin T. Gibbs 	if (sc->adapter_control & CFRESETB)
1562717d4247SJustin T. Gibbs 		scsi_conf |= RESET_SCSI;
1563717d4247SJustin T. Gibbs 
1564274c4127SJustin T. Gibbs 	ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;
1565bfadd24dSJustin T. Gibbs 
1566274c4127SJustin T. Gibbs 	if (sc->bios_control & CFEXTEND)
1567717d4247SJustin T. Gibbs 		ahc->flags |= AHC_EXTENDED_TRANS_A;
1568bfadd24dSJustin T. Gibbs 
1569274c4127SJustin T. Gibbs 	if (sc->bios_control & CFBIOSEN)
1570bfadd24dSJustin T. Gibbs 		ahc->flags |= AHC_BIOS_ENABLED;
1571717d4247SJustin T. Gibbs 	if (ahc->features & AHC_ULTRA
1572717d4247SJustin T. Gibbs 	 && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {
1573717d4247SJustin T. Gibbs 		/* Should we enable Ultra mode? */
1574274c4127SJustin T. Gibbs 		if (!(sc->adapter_control & CFULTRAEN))
1575717d4247SJustin T. Gibbs 			/* Treat us as a non-ultra card */
1576717d4247SJustin T. Gibbs 			ultraenb = 0;
1577717d4247SJustin T. Gibbs 	}
1578717d4247SJustin T. Gibbs 
1579274c4127SJustin T. Gibbs 	if (sc->signature == CFSIGNATURE
1580274c4127SJustin T. Gibbs 	 || sc->signature == CFSIGNATURE2) {
1581717d4247SJustin T. Gibbs 		uint32_t devconfig;
1582717d4247SJustin T. Gibbs 
1583717d4247SJustin T. Gibbs 		/* Honor the STPWLEVEL settings */
1584b3b25f2cSJustin T. Gibbs 		devconfig = aic_pci_read_config(ahc->dev_softc,
1585717d4247SJustin T. Gibbs 						DEVCONFIG, /*bytes*/4);
1586717d4247SJustin T. Gibbs 		devconfig &= ~STPWLEVEL;
1587274c4127SJustin T. Gibbs 		if ((sc->bios_control & CFSTPWLEVEL) != 0)
1588717d4247SJustin T. Gibbs 			devconfig |= STPWLEVEL;
1589b3b25f2cSJustin T. Gibbs 		aic_pci_write_config(ahc->dev_softc, DEVCONFIG,
1590717d4247SJustin T. Gibbs 				     devconfig, /*bytes*/4);
1591717d4247SJustin T. Gibbs 	}
1592717d4247SJustin T. Gibbs 	/* Set SCSICONF info */
1593717d4247SJustin T. Gibbs 	ahc_outb(ahc, SCSICONF, scsi_conf);
1594717d4247SJustin T. Gibbs 	ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
1595717d4247SJustin T. Gibbs 	ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
1596717d4247SJustin T. Gibbs 	ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff);
1597717d4247SJustin T. Gibbs 	ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);
1598717d4247SJustin T. Gibbs }
1599717d4247SJustin T. Gibbs 
1600717d4247SJustin T. Gibbs static void
1601717d4247SJustin T. Gibbs configure_termination(struct ahc_softc *ahc,
1602717d4247SJustin T. Gibbs 		      struct seeprom_descriptor *sd,
1603717d4247SJustin T. Gibbs 		      u_int adapter_control,
1604717d4247SJustin T. Gibbs 		      u_int *sxfrctl1)
1605717d4247SJustin T. Gibbs {
1606717d4247SJustin T. Gibbs 	uint8_t brddat;
1607717d4247SJustin T. Gibbs 
1608717d4247SJustin T. Gibbs 	brddat = 0;
1609717d4247SJustin T. Gibbs 
1610717d4247SJustin T. Gibbs 	/*
1611717d4247SJustin T. Gibbs 	 * Update the settings in sxfrctl1 to match the
1612717d4247SJustin T. Gibbs 	 * termination settings
1613717d4247SJustin T. Gibbs 	 */
1614717d4247SJustin T. Gibbs 	*sxfrctl1 = 0;
1615717d4247SJustin T. Gibbs 
1616717d4247SJustin T. Gibbs 	/*
1617717d4247SJustin T. Gibbs 	 * SEECS must be on for the GALS to latch
1618717d4247SJustin T. Gibbs 	 * the data properly.  Be sure to leave MS
1619717d4247SJustin T. Gibbs 	 * on or we will release the seeprom.
1620717d4247SJustin T. Gibbs 	 */
1621717d4247SJustin T. Gibbs 	SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS);
1622717d4247SJustin T. Gibbs 	if ((adapter_control & CFAUTOTERM) != 0
1623717d4247SJustin T. Gibbs 	 || (ahc->features & AHC_NEW_TERMCTL) != 0) {
1624717d4247SJustin T. Gibbs 		int internal50_present;
1625717d4247SJustin T. Gibbs 		int internal68_present;
1626717d4247SJustin T. Gibbs 		int externalcable_present;
1627717d4247SJustin T. Gibbs 		int eeprom_present;
1628717d4247SJustin T. Gibbs 		int enableSEC_low;
1629717d4247SJustin T. Gibbs 		int enableSEC_high;
1630717d4247SJustin T. Gibbs 		int enablePRI_low;
1631717d4247SJustin T. Gibbs 		int enablePRI_high;
1632a5847d5cSJustin T. Gibbs 		int sum;
1633717d4247SJustin T. Gibbs 
1634717d4247SJustin T. Gibbs 		enableSEC_low = 0;
1635717d4247SJustin T. Gibbs 		enableSEC_high = 0;
1636717d4247SJustin T. Gibbs 		enablePRI_low = 0;
1637717d4247SJustin T. Gibbs 		enablePRI_high = 0;
1638717d4247SJustin T. Gibbs 		if ((ahc->features & AHC_NEW_TERMCTL) != 0) {
1639717d4247SJustin T. Gibbs 			ahc_new_term_detect(ahc, &enableSEC_low,
1640717d4247SJustin T. Gibbs 					    &enableSEC_high,
1641717d4247SJustin T. Gibbs 					    &enablePRI_low,
1642717d4247SJustin T. Gibbs 					    &enablePRI_high,
1643717d4247SJustin T. Gibbs 					    &eeprom_present);
1644717d4247SJustin T. Gibbs 			if ((adapter_control & CFSEAUTOTERM) == 0) {
1645717d4247SJustin T. Gibbs 				if (bootverbose)
1646717d4247SJustin T. Gibbs 					printf("%s: Manual SE Termination\n",
1647717d4247SJustin T. Gibbs 					       ahc_name(ahc));
1648717d4247SJustin T. Gibbs 				enableSEC_low = (adapter_control & CFSELOWTERM);
1649717d4247SJustin T. Gibbs 				enableSEC_high =
1650717d4247SJustin T. Gibbs 				    (adapter_control & CFSEHIGHTERM);
1651717d4247SJustin T. Gibbs 			}
1652717d4247SJustin T. Gibbs 			if ((adapter_control & CFAUTOTERM) == 0) {
1653717d4247SJustin T. Gibbs 				if (bootverbose)
1654717d4247SJustin T. Gibbs 					printf("%s: Manual LVD Termination\n",
1655717d4247SJustin T. Gibbs 					       ahc_name(ahc));
1656717d4247SJustin T. Gibbs 				enablePRI_low = (adapter_control & CFSTERM);
1657717d4247SJustin T. Gibbs 				enablePRI_high = (adapter_control & CFWSTERM);
1658717d4247SJustin T. Gibbs 			}
1659717d4247SJustin T. Gibbs 			/* Make the table calculations below happy */
1660717d4247SJustin T. Gibbs 			internal50_present = 0;
1661717d4247SJustin T. Gibbs 			internal68_present = 1;
1662717d4247SJustin T. Gibbs 			externalcable_present = 1;
1663717d4247SJustin T. Gibbs 		} else if ((ahc->features & AHC_SPIOCAP) != 0) {
1664717d4247SJustin T. Gibbs 			aic785X_cable_detect(ahc, &internal50_present,
1665717d4247SJustin T. Gibbs 					     &externalcable_present,
1666717d4247SJustin T. Gibbs 					     &eeprom_present);
1667274c4127SJustin T. Gibbs 			/* Can never support a wide connector. */
1668274c4127SJustin T. Gibbs 			internal68_present = 0;
1669717d4247SJustin T. Gibbs 		} else {
1670717d4247SJustin T. Gibbs 			aic787X_cable_detect(ahc, &internal50_present,
1671717d4247SJustin T. Gibbs 					     &internal68_present,
1672717d4247SJustin T. Gibbs 					     &externalcable_present,
1673717d4247SJustin T. Gibbs 					     &eeprom_present);
1674717d4247SJustin T. Gibbs 		}
1675717d4247SJustin T. Gibbs 
1676717d4247SJustin T. Gibbs 		if ((ahc->features & AHC_WIDE) == 0)
1677717d4247SJustin T. Gibbs 			internal68_present = 0;
1678717d4247SJustin T. Gibbs 
1679a5847d5cSJustin T. Gibbs 		if (bootverbose
1680a5847d5cSJustin T. Gibbs 		 && (ahc->features & AHC_ULTRA2) == 0) {
1681a5847d5cSJustin T. Gibbs 			printf("%s: internal 50 cable %s present",
1682717d4247SJustin T. Gibbs 			       ahc_name(ahc),
1683a5847d5cSJustin T. Gibbs 			       internal50_present ? "is":"not");
1684717d4247SJustin T. Gibbs 
1685a5847d5cSJustin T. Gibbs 			if ((ahc->features & AHC_WIDE) != 0)
1686a5847d5cSJustin T. Gibbs 				printf(", internal 68 cable %s present",
1687a5847d5cSJustin T. Gibbs 				       internal68_present ? "is":"not");
1688a5847d5cSJustin T. Gibbs 			printf("\n%s: external cable %s present\n",
1689717d4247SJustin T. Gibbs 			       ahc_name(ahc),
1690717d4247SJustin T. Gibbs 			       externalcable_present ? "is":"not");
1691717d4247SJustin T. Gibbs 		}
1692a5847d5cSJustin T. Gibbs 		if (bootverbose)
1693717d4247SJustin T. Gibbs 			printf("%s: BIOS eeprom %s present\n",
1694717d4247SJustin T. Gibbs 			       ahc_name(ahc), eeprom_present ? "is" : "not");
1695717d4247SJustin T. Gibbs 
1696717d4247SJustin T. Gibbs 		if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) {
1697717d4247SJustin T. Gibbs 			/*
1698717d4247SJustin T. Gibbs 			 * The 50 pin connector is a separate bus,
1699717d4247SJustin T. Gibbs 			 * so force it to always be terminated.
1700717d4247SJustin T. Gibbs 			 * In the future, perform current sensing
1701717d4247SJustin T. Gibbs 			 * to determine if we are in the middle of
1702717d4247SJustin T. Gibbs 			 * a properly terminated bus.
1703717d4247SJustin T. Gibbs 			 */
1704717d4247SJustin T. Gibbs 			internal50_present = 0;
1705717d4247SJustin T. Gibbs 		}
1706717d4247SJustin T. Gibbs 
1707717d4247SJustin T. Gibbs 		/*
1708717d4247SJustin T. Gibbs 		 * Now set the termination based on what
1709717d4247SJustin T. Gibbs 		 * we found.
1710717d4247SJustin T. Gibbs 		 * Flash Enable = BRDDAT7
1711717d4247SJustin T. Gibbs 		 * Secondary High Term Enable = BRDDAT6
1712717d4247SJustin T. Gibbs 		 * Secondary Low Term Enable = BRDDAT5 (7890)
1713717d4247SJustin T. Gibbs 		 * Primary High Term Enable = BRDDAT4 (7890)
1714717d4247SJustin T. Gibbs 		 */
1715717d4247SJustin T. Gibbs 		if ((ahc->features & AHC_ULTRA2) == 0
1716717d4247SJustin T. Gibbs 		 && (internal50_present != 0)
1717717d4247SJustin T. Gibbs 		 && (internal68_present != 0)
1718717d4247SJustin T. Gibbs 		 && (externalcable_present != 0)) {
1719717d4247SJustin T. Gibbs 			printf("%s: Illegal cable configuration!!. "
1720717d4247SJustin T. Gibbs 			       "Only two connectors on the "
1721717d4247SJustin T. Gibbs 			       "adapter may be used at a "
1722717d4247SJustin T. Gibbs 			       "time!\n", ahc_name(ahc));
17238f214efcSJustin T. Gibbs 
17248f214efcSJustin T. Gibbs 			/*
17258f214efcSJustin T. Gibbs 			 * Pretend there are no cables in the hope
17268f214efcSJustin T. Gibbs 			 * that having all of the termination on
17278f214efcSJustin T. Gibbs 			 * gives us a more stable bus.
17288f214efcSJustin T. Gibbs 			 */
17298f214efcSJustin T. Gibbs 		 	internal50_present = 0;
17308f214efcSJustin T. Gibbs 			internal68_present = 0;
17318f214efcSJustin T. Gibbs 			externalcable_present = 0;
1732717d4247SJustin T. Gibbs 		}
1733717d4247SJustin T. Gibbs 
1734717d4247SJustin T. Gibbs 		if ((ahc->features & AHC_WIDE) != 0
1735717d4247SJustin T. Gibbs 		 && ((externalcable_present == 0)
1736717d4247SJustin T. Gibbs 		  || (internal68_present == 0)
1737717d4247SJustin T. Gibbs 		  || (enableSEC_high != 0))) {
1738717d4247SJustin T. Gibbs 			brddat |= BRDDAT6;
1739717d4247SJustin T. Gibbs 			if (bootverbose) {
1740717d4247SJustin T. Gibbs 				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
1741717d4247SJustin T. Gibbs 					printf("%s: 68 pin termination "
1742717d4247SJustin T. Gibbs 					       "Enabled\n", ahc_name(ahc));
1743717d4247SJustin T. Gibbs 				else
1744717d4247SJustin T. Gibbs 					printf("%s: %sHigh byte termination "
1745717d4247SJustin T. Gibbs 					       "Enabled\n", ahc_name(ahc),
1746717d4247SJustin T. Gibbs 					       enableSEC_high ? "Secondary "
1747717d4247SJustin T. Gibbs 							      : "");
1748717d4247SJustin T. Gibbs 			}
1749717d4247SJustin T. Gibbs 		}
1750717d4247SJustin T. Gibbs 
1751a5847d5cSJustin T. Gibbs 		sum = internal50_present + internal68_present
1752a5847d5cSJustin T. Gibbs 		    + externalcable_present;
1753a5847d5cSJustin T. Gibbs 		if (sum < 2 || (enableSEC_low != 0)) {
1754717d4247SJustin T. Gibbs 			if ((ahc->features & AHC_ULTRA2) != 0)
1755717d4247SJustin T. Gibbs 				brddat |= BRDDAT5;
1756717d4247SJustin T. Gibbs 			else
1757717d4247SJustin T. Gibbs 				*sxfrctl1 |= STPWEN;
1758717d4247SJustin T. Gibbs 			if (bootverbose) {
1759717d4247SJustin T. Gibbs 				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
1760717d4247SJustin T. Gibbs 					printf("%s: 50 pin termination "
1761717d4247SJustin T. Gibbs 					       "Enabled\n", ahc_name(ahc));
1762717d4247SJustin T. Gibbs 				else
1763717d4247SJustin T. Gibbs 					printf("%s: %sLow byte termination "
1764717d4247SJustin T. Gibbs 					       "Enabled\n", ahc_name(ahc),
1765717d4247SJustin T. Gibbs 					       enableSEC_low ? "Secondary "
1766717d4247SJustin T. Gibbs 							     : "");
1767717d4247SJustin T. Gibbs 			}
1768717d4247SJustin T. Gibbs 		}
1769717d4247SJustin T. Gibbs 
1770717d4247SJustin T. Gibbs 		if (enablePRI_low != 0) {
1771717d4247SJustin T. Gibbs 			*sxfrctl1 |= STPWEN;
1772717d4247SJustin T. Gibbs 			if (bootverbose)
1773717d4247SJustin T. Gibbs 				printf("%s: Primary Low Byte termination "
1774717d4247SJustin T. Gibbs 				       "Enabled\n", ahc_name(ahc));
1775717d4247SJustin T. Gibbs 		}
1776717d4247SJustin T. Gibbs 
1777717d4247SJustin T. Gibbs 		/*
1778717d4247SJustin T. Gibbs 		 * Setup STPWEN before setting up the rest of
1779717d4247SJustin T. Gibbs 		 * the termination per the tech note on the U160 cards.
1780717d4247SJustin T. Gibbs 		 */
1781717d4247SJustin T. Gibbs 		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
1782717d4247SJustin T. Gibbs 
1783717d4247SJustin T. Gibbs 		if (enablePRI_high != 0) {
1784717d4247SJustin T. Gibbs 			brddat |= BRDDAT4;
1785717d4247SJustin T. Gibbs 			if (bootverbose)
1786717d4247SJustin T. Gibbs 				printf("%s: Primary High Byte "
1787717d4247SJustin T. Gibbs 				       "termination Enabled\n",
1788717d4247SJustin T. Gibbs 				       ahc_name(ahc));
1789717d4247SJustin T. Gibbs 		}
1790717d4247SJustin T. Gibbs 
1791717d4247SJustin T. Gibbs 		write_brdctl(ahc, brddat);
1792717d4247SJustin T. Gibbs 
1793717d4247SJustin T. Gibbs 	} else {
1794717d4247SJustin T. Gibbs 		if ((adapter_control & CFSTERM) != 0) {
1795717d4247SJustin T. Gibbs 			*sxfrctl1 |= STPWEN;
1796717d4247SJustin T. Gibbs 
1797717d4247SJustin T. Gibbs 			if (bootverbose)
1798717d4247SJustin T. Gibbs 				printf("%s: %sLow byte termination Enabled\n",
1799717d4247SJustin T. Gibbs 				       ahc_name(ahc),
1800717d4247SJustin T. Gibbs 				       (ahc->features & AHC_ULTRA2) ? "Primary "
1801717d4247SJustin T. Gibbs 								    : "");
1802717d4247SJustin T. Gibbs 		}
1803717d4247SJustin T. Gibbs 
1804a5847d5cSJustin T. Gibbs 		if ((adapter_control & CFWSTERM) != 0
1805a5847d5cSJustin T. Gibbs 		 && (ahc->features & AHC_WIDE) != 0) {
1806717d4247SJustin T. Gibbs 			brddat |= BRDDAT6;
1807717d4247SJustin T. Gibbs 			if (bootverbose)
1808717d4247SJustin T. Gibbs 				printf("%s: %sHigh byte termination Enabled\n",
1809717d4247SJustin T. Gibbs 				       ahc_name(ahc),
1810717d4247SJustin T. Gibbs 				       (ahc->features & AHC_ULTRA2)
1811717d4247SJustin T. Gibbs 				     ? "Secondary " : "");
1812717d4247SJustin T. Gibbs 		}
1813717d4247SJustin T. Gibbs 
1814717d4247SJustin T. Gibbs 		/*
1815717d4247SJustin T. Gibbs 		 * Setup STPWEN before setting up the rest of
1816717d4247SJustin T. Gibbs 		 * the termination per the tech note on the U160 cards.
1817717d4247SJustin T. Gibbs 		 */
1818717d4247SJustin T. Gibbs 		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
1819717d4247SJustin T. Gibbs 
1820a5847d5cSJustin T. Gibbs 		if ((ahc->features & AHC_WIDE) != 0)
1821717d4247SJustin T. Gibbs 			write_brdctl(ahc, brddat);
1822717d4247SJustin T. Gibbs 	}
1823717d4247SJustin T. Gibbs 	SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */
1824717d4247SJustin T. Gibbs }
1825717d4247SJustin T. Gibbs 
1826717d4247SJustin T. Gibbs static void
1827717d4247SJustin T. Gibbs ahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low,
1828717d4247SJustin T. Gibbs 		    int *enableSEC_high, int *enablePRI_low,
1829717d4247SJustin T. Gibbs 		    int *enablePRI_high, int *eeprom_present)
1830717d4247SJustin T. Gibbs {
1831717d4247SJustin T. Gibbs 	uint8_t brdctl;
1832717d4247SJustin T. Gibbs 
1833717d4247SJustin T. Gibbs 	/*
1834717d4247SJustin T. Gibbs 	 * BRDDAT7 = Eeprom
1835717d4247SJustin T. Gibbs 	 * BRDDAT6 = Enable Secondary High Byte termination
1836717d4247SJustin T. Gibbs 	 * BRDDAT5 = Enable Secondary Low Byte termination
1837717d4247SJustin T. Gibbs 	 * BRDDAT4 = Enable Primary high byte termination
1838717d4247SJustin T. Gibbs 	 * BRDDAT3 = Enable Primary low byte termination
1839717d4247SJustin T. Gibbs 	 */
1840717d4247SJustin T. Gibbs 	brdctl = read_brdctl(ahc);
1841717d4247SJustin T. Gibbs 	*eeprom_present = brdctl & BRDDAT7;
1842717d4247SJustin T. Gibbs 	*enableSEC_high = (brdctl & BRDDAT6);
1843717d4247SJustin T. Gibbs 	*enableSEC_low = (brdctl & BRDDAT5);
1844717d4247SJustin T. Gibbs 	*enablePRI_high = (brdctl & BRDDAT4);
1845717d4247SJustin T. Gibbs 	*enablePRI_low = (brdctl & BRDDAT3);
1846717d4247SJustin T. Gibbs }
1847717d4247SJustin T. Gibbs 
1848717d4247SJustin T. Gibbs static void
1849717d4247SJustin T. Gibbs aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
1850717d4247SJustin T. Gibbs 		     int *internal68_present, int *externalcable_present,
1851717d4247SJustin T. Gibbs 		     int *eeprom_present)
1852717d4247SJustin T. Gibbs {
1853717d4247SJustin T. Gibbs 	uint8_t brdctl;
1854717d4247SJustin T. Gibbs 
1855717d4247SJustin T. Gibbs 	/*
1856717d4247SJustin T. Gibbs 	 * First read the status of our cables.
1857717d4247SJustin T. Gibbs 	 * Set the rom bank to 0 since the
1858717d4247SJustin T. Gibbs 	 * bank setting serves as a multiplexor
1859717d4247SJustin T. Gibbs 	 * for the cable detection logic.
1860717d4247SJustin T. Gibbs 	 * BRDDAT5 controls the bank switch.
1861717d4247SJustin T. Gibbs 	 */
1862717d4247SJustin T. Gibbs 	write_brdctl(ahc, 0);
1863717d4247SJustin T. Gibbs 
1864717d4247SJustin T. Gibbs 	/*
1865717d4247SJustin T. Gibbs 	 * Now read the state of the internal
1866717d4247SJustin T. Gibbs 	 * connectors.  BRDDAT6 is INT50 and
1867717d4247SJustin T. Gibbs 	 * BRDDAT7 is INT68.
1868717d4247SJustin T. Gibbs 	 */
1869717d4247SJustin T. Gibbs 	brdctl = read_brdctl(ahc);
1870a5847d5cSJustin T. Gibbs 	*internal50_present = (brdctl & BRDDAT6) ? 0 : 1;
1871a5847d5cSJustin T. Gibbs 	*internal68_present = (brdctl & BRDDAT7) ? 0 : 1;
1872717d4247SJustin T. Gibbs 
1873717d4247SJustin T. Gibbs 	/*
1874717d4247SJustin T. Gibbs 	 * Set the rom bank to 1 and determine
1875717d4247SJustin T. Gibbs 	 * the other signals.
1876717d4247SJustin T. Gibbs 	 */
1877717d4247SJustin T. Gibbs 	write_brdctl(ahc, BRDDAT5);
1878717d4247SJustin T. Gibbs 
1879717d4247SJustin T. Gibbs 	/*
1880717d4247SJustin T. Gibbs 	 * Now read the state of the external
1881717d4247SJustin T. Gibbs 	 * connectors.  BRDDAT6 is EXT68 and
1882717d4247SJustin T. Gibbs 	 * BRDDAT7 is EPROMPS.
1883717d4247SJustin T. Gibbs 	 */
1884717d4247SJustin T. Gibbs 	brdctl = read_brdctl(ahc);
1885a5847d5cSJustin T. Gibbs 	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
1886a5847d5cSJustin T. Gibbs 	*eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;
1887717d4247SJustin T. Gibbs }
1888717d4247SJustin T. Gibbs 
1889717d4247SJustin T. Gibbs static void
1890717d4247SJustin T. Gibbs aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
1891717d4247SJustin T. Gibbs 		     int *externalcable_present, int *eeprom_present)
1892717d4247SJustin T. Gibbs {
1893717d4247SJustin T. Gibbs 	uint8_t brdctl;
1894274c4127SJustin T. Gibbs 	uint8_t spiocap;
1895717d4247SJustin T. Gibbs 
1896274c4127SJustin T. Gibbs 	spiocap = ahc_inb(ahc, SPIOCAP);
1897274c4127SJustin T. Gibbs 	spiocap &= ~SOFTCMDEN;
1898274c4127SJustin T. Gibbs 	spiocap |= EXT_BRDCTL;
1899274c4127SJustin T. Gibbs 	ahc_outb(ahc, SPIOCAP, spiocap);
1900717d4247SJustin T. Gibbs 	ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
19019bf327a7SJustin T. Gibbs 	ahc_flush_device_writes(ahc);
1902b3b25f2cSJustin T. Gibbs 	aic_delay(500);
1903717d4247SJustin T. Gibbs 	ahc_outb(ahc, BRDCTL, 0);
19049bf327a7SJustin T. Gibbs 	ahc_flush_device_writes(ahc);
1905b3b25f2cSJustin T. Gibbs 	aic_delay(500);
1906717d4247SJustin T. Gibbs 	brdctl = ahc_inb(ahc, BRDCTL);
1907a5847d5cSJustin T. Gibbs 	*internal50_present = (brdctl & BRDDAT5) ? 0 : 1;
1908a5847d5cSJustin T. Gibbs 	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
1909a5847d5cSJustin T. Gibbs 	*eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
1910717d4247SJustin T. Gibbs }
1911717d4247SJustin T. Gibbs 
19128f214efcSJustin T. Gibbs int
19138f214efcSJustin T. Gibbs ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
1914717d4247SJustin T. Gibbs {
1915717d4247SJustin T. Gibbs 	int wait;
1916717d4247SJustin T. Gibbs 
1917717d4247SJustin T. Gibbs 	if ((ahc->features & AHC_SPIOCAP) != 0
1918717d4247SJustin T. Gibbs 	 && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0)
1919717d4247SJustin T. Gibbs 		return (0);
1920717d4247SJustin T. Gibbs 
1921717d4247SJustin T. Gibbs 	/*
1922717d4247SJustin T. Gibbs 	 * Request access of the memory port.  When access is
1923717d4247SJustin T. Gibbs 	 * granted, SEERDY will go high.  We use a 1 second
1924717d4247SJustin T. Gibbs 	 * timeout which should be near 1 second more than
1925717d4247SJustin T. Gibbs 	 * is needed.  Reason: after the chip reset, there
1926717d4247SJustin T. Gibbs 	 * should be no contention.
1927717d4247SJustin T. Gibbs 	 */
1928717d4247SJustin T. Gibbs 	SEEPROM_OUTB(sd, sd->sd_MS);
1929717d4247SJustin T. Gibbs 	wait = 1000;  /* 1 second timeout in msec */
1930717d4247SJustin T. Gibbs 	while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
1931b3b25f2cSJustin T. Gibbs 		aic_delay(1000);  /* delay 1 msec */
1932717d4247SJustin T. Gibbs 	}
1933717d4247SJustin T. Gibbs 	if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
1934717d4247SJustin T. Gibbs 		SEEPROM_OUTB(sd, 0);
1935717d4247SJustin T. Gibbs 		return (0);
1936717d4247SJustin T. Gibbs 	}
1937717d4247SJustin T. Gibbs 	return(1);
1938717d4247SJustin T. Gibbs }
1939717d4247SJustin T. Gibbs 
19408f214efcSJustin T. Gibbs void
19418f214efcSJustin T. Gibbs ahc_release_seeprom(struct seeprom_descriptor *sd)
1942717d4247SJustin T. Gibbs {
1943717d4247SJustin T. Gibbs 	/* Release access to the memory port and the serial EEPROM. */
1944717d4247SJustin T. Gibbs 	SEEPROM_OUTB(sd, 0);
1945717d4247SJustin T. Gibbs }
1946717d4247SJustin T. Gibbs 
1947717d4247SJustin T. Gibbs static void
1948717d4247SJustin T. Gibbs write_brdctl(struct ahc_softc *ahc, uint8_t value)
1949717d4247SJustin T. Gibbs {
1950717d4247SJustin T. Gibbs 	uint8_t brdctl;
1951717d4247SJustin T. Gibbs 
1952717d4247SJustin T. Gibbs 	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
1953717d4247SJustin T. Gibbs 		brdctl = BRDSTB;
1954717d4247SJustin T. Gibbs 	 	if (ahc->channel == 'B')
1955717d4247SJustin T. Gibbs 			brdctl |= BRDCS;
1956717d4247SJustin T. Gibbs 	} else if ((ahc->features & AHC_ULTRA2) != 0) {
1957717d4247SJustin T. Gibbs 		brdctl = 0;
1958717d4247SJustin T. Gibbs 	} else {
1959717d4247SJustin T. Gibbs 		brdctl = BRDSTB|BRDCS;
1960717d4247SJustin T. Gibbs 	}
1961717d4247SJustin T. Gibbs 	ahc_outb(ahc, BRDCTL, brdctl);
1962a5847d5cSJustin T. Gibbs 	ahc_flush_device_writes(ahc);
1963717d4247SJustin T. Gibbs 	brdctl |= value;
1964717d4247SJustin T. Gibbs 	ahc_outb(ahc, BRDCTL, brdctl);
1965a5847d5cSJustin T. Gibbs 	ahc_flush_device_writes(ahc);
1966717d4247SJustin T. Gibbs 	if ((ahc->features & AHC_ULTRA2) != 0)
1967717d4247SJustin T. Gibbs 		brdctl |= BRDSTB_ULTRA2;
1968717d4247SJustin T. Gibbs 	else
1969717d4247SJustin T. Gibbs 		brdctl &= ~BRDSTB;
1970717d4247SJustin T. Gibbs 	ahc_outb(ahc, BRDCTL, brdctl);
1971a5847d5cSJustin T. Gibbs 	ahc_flush_device_writes(ahc);
1972717d4247SJustin T. Gibbs 	if ((ahc->features & AHC_ULTRA2) != 0)
1973717d4247SJustin T. Gibbs 		brdctl = 0;
1974717d4247SJustin T. Gibbs 	else
1975717d4247SJustin T. Gibbs 		brdctl &= ~BRDCS;
1976717d4247SJustin T. Gibbs 	ahc_outb(ahc, BRDCTL, brdctl);
1977717d4247SJustin T. Gibbs }
1978717d4247SJustin T. Gibbs 
1979717d4247SJustin T. Gibbs static uint8_t
19803baccea6SJustin T. Gibbs read_brdctl(struct ahc_softc *ahc)
1981717d4247SJustin T. Gibbs {
1982717d4247SJustin T. Gibbs 	uint8_t brdctl;
1983717d4247SJustin T. Gibbs 	uint8_t value;
1984717d4247SJustin T. Gibbs 
1985717d4247SJustin T. Gibbs 	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
1986717d4247SJustin T. Gibbs 		brdctl = BRDRW;
1987717d4247SJustin T. Gibbs 	 	if (ahc->channel == 'B')
1988717d4247SJustin T. Gibbs 			brdctl |= BRDCS;
1989717d4247SJustin T. Gibbs 	} else if ((ahc->features & AHC_ULTRA2) != 0) {
1990717d4247SJustin T. Gibbs 		brdctl = BRDRW_ULTRA2;
1991717d4247SJustin T. Gibbs 	} else {
1992717d4247SJustin T. Gibbs 		brdctl = BRDRW|BRDCS;
1993717d4247SJustin T. Gibbs 	}
1994717d4247SJustin T. Gibbs 	ahc_outb(ahc, BRDCTL, brdctl);
1995a5847d5cSJustin T. Gibbs 	ahc_flush_device_writes(ahc);
1996717d4247SJustin T. Gibbs 	value = ahc_inb(ahc, BRDCTL);
1997717d4247SJustin T. Gibbs 	ahc_outb(ahc, BRDCTL, 0);
1998717d4247SJustin T. Gibbs 	return (value);
1999717d4247SJustin T. Gibbs }
2000717d4247SJustin T. Gibbs 
20019bf327a7SJustin T. Gibbs static void
2002717d4247SJustin T. Gibbs ahc_pci_intr(struct ahc_softc *ahc)
2003717d4247SJustin T. Gibbs {
2004c498406dSJustin T. Gibbs 	u_int error;
2005c498406dSJustin T. Gibbs 	u_int status1;
2006c498406dSJustin T. Gibbs 
2007c498406dSJustin T. Gibbs 	error = ahc_inb(ahc, ERROR);
2008c498406dSJustin T. Gibbs 	if ((error & PCIERRSTAT) == 0)
2009c498406dSJustin T. Gibbs 		return;
2010717d4247SJustin T. Gibbs 
2011b3b25f2cSJustin T. Gibbs 	status1 = aic_pci_read_config(ahc->dev_softc,
2012717d4247SJustin T. Gibbs 				      PCIR_STATUS + 1, /*bytes*/1);
2013717d4247SJustin T. Gibbs 
2014ad3d2a4dSJustin T. Gibbs 	if ((status1 & ~DPE) != 0
2015ad3d2a4dSJustin T. Gibbs 	 || (ahc->flags & AHC_DISABLE_PCI_PERR) == 0) {
2016c498406dSJustin T. Gibbs 		printf("%s: PCI error Interrupt at seqaddr = 0x%x\n",
2017717d4247SJustin T. Gibbs 		       ahc_name(ahc),
2018717d4247SJustin T. Gibbs 		       ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
2019ad3d2a4dSJustin T. Gibbs 	}
2020c498406dSJustin T. Gibbs 
2021ad3d2a4dSJustin T. Gibbs 	if (status1 & DPE
2022ad3d2a4dSJustin T. Gibbs 	 && (ahc->flags & AHC_DISABLE_PCI_PERR) == 0) {
20239bf327a7SJustin T. Gibbs 		ahc->pci_target_perr_count++;
2024717d4247SJustin T. Gibbs 		printf("%s: Data Parity Error Detected during address "
2025717d4247SJustin T. Gibbs 		       "or write data phase\n", ahc_name(ahc));
2026717d4247SJustin T. Gibbs 	}
2027717d4247SJustin T. Gibbs 	if (status1 & SSE) {
2028a49630acSJustin T. Gibbs 		printf("%s: Signal System Error Detected\n", ahc_name(ahc));
2029717d4247SJustin T. Gibbs 	}
2030717d4247SJustin T. Gibbs 	if (status1 & RMA) {
2031a49630acSJustin T. Gibbs 		printf("%s: Received a Master Abort\n", ahc_name(ahc));
2032717d4247SJustin T. Gibbs 	}
2033717d4247SJustin T. Gibbs 	if (status1 & RTA) {
2034717d4247SJustin T. Gibbs 		printf("%s: Received a Target Abort\n", ahc_name(ahc));
2035717d4247SJustin T. Gibbs 	}
2036717d4247SJustin T. Gibbs 	if (status1 & STA) {
2037717d4247SJustin T. Gibbs 		printf("%s: Signaled a Target Abort\n", ahc_name(ahc));
2038717d4247SJustin T. Gibbs 	}
2039717d4247SJustin T. Gibbs 	if (status1 & DPR) {
2040717d4247SJustin T. Gibbs 		printf("%s: Data Parity Error has been reported via PERR#\n",
2041717d4247SJustin T. Gibbs 		       ahc_name(ahc));
2042717d4247SJustin T. Gibbs 	}
2043cd036e89SJustin T. Gibbs 
2044cd036e89SJustin T. Gibbs 	/* Clear latched errors. */
2045b3b25f2cSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
2046717d4247SJustin T. Gibbs 			     status1, /*bytes*/1);
2047717d4247SJustin T. Gibbs 
2048cd036e89SJustin T. Gibbs 	if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) {
2049cd036e89SJustin T. Gibbs 		printf("%s: Latched PCIERR interrupt with "
2050cd036e89SJustin T. Gibbs 		       "no status bits set\n", ahc_name(ahc));
2051cd036e89SJustin T. Gibbs 	} else {
2052717d4247SJustin T. Gibbs 		ahc_outb(ahc, CLRINT, CLRPARERR);
2053717d4247SJustin T. Gibbs 	}
2054c498406dSJustin T. Gibbs 
2055ad3d2a4dSJustin T. Gibbs 	if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH
2056ad3d2a4dSJustin T. Gibbs 	 && (ahc->flags & AHC_DISABLE_PCI_PERR) == 0) {
20579bf327a7SJustin T. Gibbs 		printf(
20589bf327a7SJustin T. Gibbs "%s: WARNING WARNING WARNING WARNING\n"
20599bf327a7SJustin T. Gibbs "%s: Too many PCI parity errors observed as a target.\n"
2060ad3d2a4dSJustin T. Gibbs "%s: Some device on this PCI bus is generating bad parity.\n"
2061ad3d2a4dSJustin T. Gibbs "%s: This is an error *observed by*, not *generated by*, %s.\n"
20629bf327a7SJustin T. Gibbs "%s: PCI parity error checking has been disabled.\n"
20639bf327a7SJustin T. Gibbs "%s: WARNING WARNING WARNING WARNING\n",
20649bf327a7SJustin T. Gibbs 		       ahc_name(ahc), ahc_name(ahc), ahc_name(ahc),
2065ad3d2a4dSJustin T. Gibbs 		       ahc_name(ahc), ahc_name(ahc), ahc_name(ahc),
2066ad3d2a4dSJustin T. Gibbs 		       ahc_name(ahc));
2067e4e6e6d6SJustin T. Gibbs 		ahc->seqctl |= FAILDIS;
2068ad3d2a4dSJustin T. Gibbs 		ahc->flags |= AHC_DISABLE_PCI_PERR;
2069e4e6e6d6SJustin T. Gibbs 		ahc_outb(ahc, SEQCTL, ahc->seqctl);
20709bf327a7SJustin T. Gibbs 	}
20716fb77fefSJustin T. Gibbs 	ahc_unpause(ahc);
2072717d4247SJustin T. Gibbs }
2073717d4247SJustin T. Gibbs 
2074717d4247SJustin T. Gibbs static int
20759bf327a7SJustin T. Gibbs ahc_pci_chip_init(struct ahc_softc *ahc)
20769bf327a7SJustin T. Gibbs {
20779bf327a7SJustin T. Gibbs 	ahc_outb(ahc, DSCOMMAND0, ahc->bus_softc.pci_softc.dscommand0);
20789bf327a7SJustin T. Gibbs 	ahc_outb(ahc, DSPCISTATUS, ahc->bus_softc.pci_softc.dspcistatus);
20799bf327a7SJustin T. Gibbs 	if ((ahc->features & AHC_DT) != 0) {
20809bf327a7SJustin T. Gibbs 		u_int sfunct;
20819bf327a7SJustin T. Gibbs 
20829bf327a7SJustin T. Gibbs 		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
20839bf327a7SJustin T. Gibbs 		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
20849bf327a7SJustin T. Gibbs 		ahc_outb(ahc, OPTIONMODE, ahc->bus_softc.pci_softc.optionmode);
20859bf327a7SJustin T. Gibbs 		ahc_outw(ahc, TARGCRCCNT, ahc->bus_softc.pci_softc.targcrccnt);
20869bf327a7SJustin T. Gibbs 		ahc_outb(ahc, SFUNCT, sfunct);
20879bf327a7SJustin T. Gibbs 		ahc_outb(ahc, CRCCONTROL1,
20889bf327a7SJustin T. Gibbs 			 ahc->bus_softc.pci_softc.crccontrol1);
20899bf327a7SJustin T. Gibbs 	}
20909bf327a7SJustin T. Gibbs 	if ((ahc->features & AHC_MULTI_FUNC) != 0)
20919bf327a7SJustin T. Gibbs 		ahc_outb(ahc, SCBBADDR, ahc->bus_softc.pci_softc.scbbaddr);
20929bf327a7SJustin T. Gibbs 
20939bf327a7SJustin T. Gibbs 	if ((ahc->features & AHC_ULTRA2) != 0)
20949bf327a7SJustin T. Gibbs 		ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh);
20959bf327a7SJustin T. Gibbs 
20969bf327a7SJustin T. Gibbs 	return (ahc_chip_init(ahc));
20979bf327a7SJustin T. Gibbs }
20989bf327a7SJustin T. Gibbs 
20999bf327a7SJustin T. Gibbs static int
21009bf327a7SJustin T. Gibbs ahc_pci_suspend(struct ahc_softc *ahc)
21019bf327a7SJustin T. Gibbs {
21029bf327a7SJustin T. Gibbs 	return (ahc_suspend(ahc));
21039bf327a7SJustin T. Gibbs }
21049bf327a7SJustin T. Gibbs 
21059bf327a7SJustin T. Gibbs static int
21069bf327a7SJustin T. Gibbs ahc_pci_resume(struct ahc_softc *ahc)
21079bf327a7SJustin T. Gibbs {
21089bf327a7SJustin T. Gibbs 
2109b3b25f2cSJustin T. Gibbs 	aic_power_state_change(ahc, AIC_POWER_STATE_D0);
21109bf327a7SJustin T. Gibbs 
21119bf327a7SJustin T. Gibbs 	/*
21129bf327a7SJustin T. Gibbs 	 * We assume that the OS has restored our register
21139bf327a7SJustin T. Gibbs 	 * mappings, etc.  Just update the config space registers
21149bf327a7SJustin T. Gibbs 	 * that the OS doesn't know about and rely on our chip
21159bf327a7SJustin T. Gibbs 	 * reset handler to handle the rest.
21169bf327a7SJustin T. Gibbs 	 */
211725edba1eSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, DEVCONFIG,
211825edba1eSJustin T. Gibbs 			     ahc->bus_softc.pci_softc.devconfig, /*bytes*/4);
211925edba1eSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
212025edba1eSJustin T. Gibbs 			     ahc->bus_softc.pci_softc.command, /*bytes*/1);
212125edba1eSJustin T. Gibbs 	aic_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
212225edba1eSJustin T. Gibbs 			     ahc->bus_softc.pci_softc.csize_lattime,
212325edba1eSJustin T. Gibbs 			     /*bytes*/1);
21249bf327a7SJustin T. Gibbs 	if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
21259bf327a7SJustin T. Gibbs 		struct	seeprom_descriptor sd;
21269bf327a7SJustin T. Gibbs 		u_int	sxfrctl1;
21279bf327a7SJustin T. Gibbs 
21289bf327a7SJustin T. Gibbs 		sd.sd_ahc = ahc;
21299bf327a7SJustin T. Gibbs 		sd.sd_control_offset = SEECTL;
21309bf327a7SJustin T. Gibbs 		sd.sd_status_offset = SEECTL;
21319bf327a7SJustin T. Gibbs 		sd.sd_dataout_offset = SEECTL;
21329bf327a7SJustin T. Gibbs 
21339bf327a7SJustin T. Gibbs 		ahc_acquire_seeprom(ahc, &sd);
21349bf327a7SJustin T. Gibbs 		configure_termination(ahc, &sd,
21359bf327a7SJustin T. Gibbs 				      ahc->seep_config->adapter_control,
21369bf327a7SJustin T. Gibbs 				      &sxfrctl1);
21379bf327a7SJustin T. Gibbs 		ahc_release_seeprom(&sd);
21389bf327a7SJustin T. Gibbs 	}
21399bf327a7SJustin T. Gibbs 	return (ahc_resume(ahc));
21409bf327a7SJustin T. Gibbs }
21419bf327a7SJustin T. Gibbs 
21429bf327a7SJustin T. Gibbs static int
2143cd036e89SJustin T. Gibbs ahc_aic785X_setup(struct ahc_softc *ahc)
2144717d4247SJustin T. Gibbs {
2145b3b25f2cSJustin T. Gibbs 	aic_dev_softc_t pci;
21466fb77fefSJustin T. Gibbs 	uint8_t rev;
21476fb77fefSJustin T. Gibbs 
2148cd036e89SJustin T. Gibbs 	pci = ahc->dev_softc;
2149cd036e89SJustin T. Gibbs 	ahc->channel = 'A';
2150cd036e89SJustin T. Gibbs 	ahc->chip = AHC_AIC7850;
2151cd036e89SJustin T. Gibbs 	ahc->features = AHC_AIC7850_FE;
2152cd036e89SJustin T. Gibbs 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2153b3b25f2cSJustin T. Gibbs 	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
21546fb77fefSJustin T. Gibbs 	if (rev >= 1)
2155cd036e89SJustin T. Gibbs 		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
21569bf327a7SJustin T. Gibbs 	ahc->instruction_ram_size = 512;
2157717d4247SJustin T. Gibbs 	return (0);
2158717d4247SJustin T. Gibbs }
2159717d4247SJustin T. Gibbs 
2160717d4247SJustin T. Gibbs static int
2161cd036e89SJustin T. Gibbs ahc_aic7860_setup(struct ahc_softc *ahc)
2162717d4247SJustin T. Gibbs {
2163b3b25f2cSJustin T. Gibbs 	aic_dev_softc_t pci;
2164717d4247SJustin T. Gibbs 	uint8_t rev;
2165717d4247SJustin T. Gibbs 
2166cd036e89SJustin T. Gibbs 	pci = ahc->dev_softc;
2167cd036e89SJustin T. Gibbs 	ahc->channel = 'A';
2168cd036e89SJustin T. Gibbs 	ahc->chip = AHC_AIC7860;
2169cd036e89SJustin T. Gibbs 	ahc->features = AHC_AIC7860_FE;
2170cd036e89SJustin T. Gibbs 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2171b3b25f2cSJustin T. Gibbs 	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
2172717d4247SJustin T. Gibbs 	if (rev >= 1)
2173cd036e89SJustin T. Gibbs 		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
21749bf327a7SJustin T. Gibbs 	ahc->instruction_ram_size = 512;
2175717d4247SJustin T. Gibbs 	return (0);
2176717d4247SJustin T. Gibbs }
2177717d4247SJustin T. Gibbs 
2178717d4247SJustin T. Gibbs static int
2179cd036e89SJustin T. Gibbs ahc_apa1480_setup(struct ahc_softc *ahc)
2180a5847d5cSJustin T. Gibbs {
2181a5847d5cSJustin T. Gibbs 	int error;
2182a5847d5cSJustin T. Gibbs 
2183cd036e89SJustin T. Gibbs 	error = ahc_aic7860_setup(ahc);
2184a5847d5cSJustin T. Gibbs 	if (error != 0)
2185a5847d5cSJustin T. Gibbs 		return (error);
2186cd036e89SJustin T. Gibbs 	ahc->features |= AHC_REMOVABLE;
2187a5847d5cSJustin T. Gibbs 	return (0);
2188a5847d5cSJustin T. Gibbs }
2189a5847d5cSJustin T. Gibbs 
2190a5847d5cSJustin T. Gibbs static int
2191cd036e89SJustin T. Gibbs ahc_aic7870_setup(struct ahc_softc *ahc)
2192717d4247SJustin T. Gibbs {
2193cd036e89SJustin T. Gibbs 
2194cd036e89SJustin T. Gibbs 	ahc->channel = 'A';
2195cd036e89SJustin T. Gibbs 	ahc->chip = AHC_AIC7870;
2196cd036e89SJustin T. Gibbs 	ahc->features = AHC_AIC7870_FE;
2197cd036e89SJustin T. Gibbs 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
21989bf327a7SJustin T. Gibbs 	ahc->instruction_ram_size = 512;
2199717d4247SJustin T. Gibbs 	return (0);
2200717d4247SJustin T. Gibbs }
2201717d4247SJustin T. Gibbs 
2202717d4247SJustin T. Gibbs static int
2203cd036e89SJustin T. Gibbs ahc_aha394X_setup(struct ahc_softc *ahc)
2204717d4247SJustin T. Gibbs {
2205717d4247SJustin T. Gibbs 	int error;
2206717d4247SJustin T. Gibbs 
2207cd036e89SJustin T. Gibbs 	error = ahc_aic7870_setup(ahc);
2208717d4247SJustin T. Gibbs 	if (error == 0)
2209cd036e89SJustin T. Gibbs 		error = ahc_aha394XX_setup(ahc);
2210717d4247SJustin T. Gibbs 	return (error);
2211717d4247SJustin T. Gibbs }
2212717d4247SJustin T. Gibbs 
2213717d4247SJustin T. Gibbs static int
2214cd036e89SJustin T. Gibbs ahc_aha398X_setup(struct ahc_softc *ahc)
2215717d4247SJustin T. Gibbs {
2216717d4247SJustin T. Gibbs 	int error;
2217717d4247SJustin T. Gibbs 
2218cd036e89SJustin T. Gibbs 	error = ahc_aic7870_setup(ahc);
2219717d4247SJustin T. Gibbs 	if (error == 0)
2220cd036e89SJustin T. Gibbs 		error = ahc_aha398XX_setup(ahc);
2221717d4247SJustin T. Gibbs 	return (error);
2222717d4247SJustin T. Gibbs }
2223717d4247SJustin T. Gibbs 
2224717d4247SJustin T. Gibbs static int
2225cd036e89SJustin T. Gibbs ahc_aha494X_setup(struct ahc_softc *ahc)
2226717d4247SJustin T. Gibbs {
2227717d4247SJustin T. Gibbs 	int error;
2228717d4247SJustin T. Gibbs 
2229cd036e89SJustin T. Gibbs 	error = ahc_aic7870_setup(ahc);
2230717d4247SJustin T. Gibbs 	if (error == 0)
2231cd036e89SJustin T. Gibbs 		error = ahc_aha494XX_setup(ahc);
2232717d4247SJustin T. Gibbs 	return (error);
2233717d4247SJustin T. Gibbs }
2234717d4247SJustin T. Gibbs 
2235717d4247SJustin T. Gibbs static int
2236cd036e89SJustin T. Gibbs ahc_aic7880_setup(struct ahc_softc *ahc)
2237717d4247SJustin T. Gibbs {
2238b3b25f2cSJustin T. Gibbs 	aic_dev_softc_t pci;
2239717d4247SJustin T. Gibbs 	uint8_t rev;
2240717d4247SJustin T. Gibbs 
2241cd036e89SJustin T. Gibbs 	pci = ahc->dev_softc;
2242cd036e89SJustin T. Gibbs 	ahc->channel = 'A';
2243cd036e89SJustin T. Gibbs 	ahc->chip = AHC_AIC7880;
2244cd036e89SJustin T. Gibbs 	ahc->features = AHC_AIC7880_FE;
2245cd036e89SJustin T. Gibbs 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
2246b3b25f2cSJustin T. Gibbs 	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
2247717d4247SJustin T. Gibbs 	if (rev >= 1) {
2248cd036e89SJustin T. Gibbs 		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
2249717d4247SJustin T. Gibbs 	} else {
2250cd036e89SJustin T. Gibbs 		ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2251717d4247SJustin T. Gibbs 	}
22529bf327a7SJustin T. Gibbs 	ahc->instruction_ram_size = 512;
2253717d4247SJustin T. Gibbs 	return (0);
2254717d4247SJustin T. Gibbs }
2255717d4247SJustin T. Gibbs 
2256717d4247SJustin T. Gibbs static int
2257cd036e89SJustin T. Gibbs ahc_aha2940Pro_setup(struct ahc_softc *ahc)
2258717d4247SJustin T. Gibbs {
2259717d4247SJustin T. Gibbs 
2260cd036e89SJustin T. Gibbs 	ahc->flags |= AHC_INT50_SPEEDFLEX;
2261274c4127SJustin T. Gibbs 	return (ahc_aic7880_setup(ahc));
2262717d4247SJustin T. Gibbs }
2263717d4247SJustin T. Gibbs 
2264717d4247SJustin T. Gibbs static int
2265cd036e89SJustin T. Gibbs ahc_aha394XU_setup(struct ahc_softc *ahc)
2266717d4247SJustin T. Gibbs {
2267717d4247SJustin T. Gibbs 	int error;
2268717d4247SJustin T. Gibbs 
2269cd036e89SJustin T. Gibbs 	error = ahc_aic7880_setup(ahc);
2270717d4247SJustin T. Gibbs 	if (error == 0)
2271cd036e89SJustin T. Gibbs 		error = ahc_aha394XX_setup(ahc);
2272717d4247SJustin T. Gibbs 	return (error);
2273717d4247SJustin T. Gibbs }
2274717d4247SJustin T. Gibbs 
2275717d4247SJustin T. Gibbs static int
2276cd036e89SJustin T. Gibbs ahc_aha398XU_setup(struct ahc_softc *ahc)
2277717d4247SJustin T. Gibbs {
2278717d4247SJustin T. Gibbs 	int error;
2279717d4247SJustin T. Gibbs 
2280cd036e89SJustin T. Gibbs 	error = ahc_aic7880_setup(ahc);
2281717d4247SJustin T. Gibbs 	if (error == 0)
2282cd036e89SJustin T. Gibbs 		error = ahc_aha398XX_setup(ahc);
2283717d4247SJustin T. Gibbs 	return (error);
2284717d4247SJustin T. Gibbs }
2285717d4247SJustin T. Gibbs 
2286717d4247SJustin T. Gibbs static int
2287cd036e89SJustin T. Gibbs ahc_aic7890_setup(struct ahc_softc *ahc)
2288717d4247SJustin T. Gibbs {
2289b3b25f2cSJustin T. Gibbs 	aic_dev_softc_t pci;
2290717d4247SJustin T. Gibbs 	uint8_t rev;
2291717d4247SJustin T. Gibbs 
2292cd036e89SJustin T. Gibbs 	pci = ahc->dev_softc;
2293cd036e89SJustin T. Gibbs 	ahc->channel = 'A';
2294cd036e89SJustin T. Gibbs 	ahc->chip = AHC_AIC7890;
2295cd036e89SJustin T. Gibbs 	ahc->features = AHC_AIC7890_FE;
2296cd036e89SJustin T. Gibbs 	ahc->flags |= AHC_NEWEEPROM_FMT;
2297b3b25f2cSJustin T. Gibbs 	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
2298717d4247SJustin T. Gibbs 	if (rev == 0)
2299cd036e89SJustin T. Gibbs 		ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG;
23009bf327a7SJustin T. Gibbs 	ahc->instruction_ram_size = 768;
2301717d4247SJustin T. Gibbs 	return (0);
2302717d4247SJustin T. Gibbs }
2303717d4247SJustin T. Gibbs 
2304717d4247SJustin T. Gibbs static int
2305cd036e89SJustin T. Gibbs ahc_aic7892_setup(struct ahc_softc *ahc)
2306717d4247SJustin T. Gibbs {
2307cd036e89SJustin T. Gibbs 
2308cd036e89SJustin T. Gibbs 	ahc->channel = 'A';
2309cd036e89SJustin T. Gibbs 	ahc->chip = AHC_AIC7892;
2310cd036e89SJustin T. Gibbs 	ahc->features = AHC_AIC7892_FE;
2311cd036e89SJustin T. Gibbs 	ahc->flags |= AHC_NEWEEPROM_FMT;
2312cd036e89SJustin T. Gibbs 	ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
23139bf327a7SJustin T. Gibbs 	ahc->instruction_ram_size = 1024;
2314717d4247SJustin T. Gibbs 	return (0);
2315717d4247SJustin T. Gibbs }
2316717d4247SJustin T. Gibbs 
2317717d4247SJustin T. Gibbs static int
2318cd036e89SJustin T. Gibbs ahc_aic7895_setup(struct ahc_softc *ahc)
2319717d4247SJustin T. Gibbs {
2320b3b25f2cSJustin T. Gibbs 	aic_dev_softc_t pci;
2321717d4247SJustin T. Gibbs 	uint8_t rev;
2322717d4247SJustin T. Gibbs 
2323cd036e89SJustin T. Gibbs 	pci = ahc->dev_softc;
2324b3b25f2cSJustin T. Gibbs 	ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A';
2325717d4247SJustin T. Gibbs 	/*
2326717d4247SJustin T. Gibbs 	 * The 'C' revision of the aic7895 has a few additional features.
2327717d4247SJustin T. Gibbs 	 */
2328b3b25f2cSJustin T. Gibbs 	rev = aic_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
2329717d4247SJustin T. Gibbs 	if (rev >= 4) {
2330cd036e89SJustin T. Gibbs 		ahc->chip = AHC_AIC7895C;
2331cd036e89SJustin T. Gibbs 		ahc->features = AHC_AIC7895C_FE;
2332717d4247SJustin T. Gibbs 	} else  {
2333717d4247SJustin T. Gibbs 		u_int command;
2334717d4247SJustin T. Gibbs 
2335cd036e89SJustin T. Gibbs 		ahc->chip = AHC_AIC7895;
2336cd036e89SJustin T. Gibbs 		ahc->features = AHC_AIC7895_FE;
2337717d4247SJustin T. Gibbs 
2338717d4247SJustin T. Gibbs 		/*
2339717d4247SJustin T. Gibbs 		 * The BIOS disables the use of MWI transactions
2340717d4247SJustin T. Gibbs 		 * since it does not have the MWI bug work around
2341717d4247SJustin T. Gibbs 		 * we have.  Disabling MWI reduces performance, so
2342717d4247SJustin T. Gibbs 		 * turn it on again.
2343717d4247SJustin T. Gibbs 		 */
2344b3b25f2cSJustin T. Gibbs 		command = aic_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1);
2345717d4247SJustin T. Gibbs 		command |= PCIM_CMD_MWRICEN;
2346b3b25f2cSJustin T. Gibbs 		aic_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1);
2347cd036e89SJustin T. Gibbs 		ahc->bugs |= AHC_PCI_MWI_BUG;
2348717d4247SJustin T. Gibbs 	}
2349717d4247SJustin T. Gibbs 	/*
2350717d4247SJustin T. Gibbs 	 * XXX Does CACHETHEN really not work???  What about PCI retry?
2351717d4247SJustin T. Gibbs 	 * on C level chips.  Need to test, but for now, play it safe.
2352717d4247SJustin T. Gibbs 	 */
2353cd036e89SJustin T. Gibbs 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG
2354717d4247SJustin T. Gibbs 		  |  AHC_CACHETHEN_BUG;
2355717d4247SJustin T. Gibbs 
2356717d4247SJustin T. Gibbs #if 0
2357717d4247SJustin T. Gibbs 	uint32_t devconfig;
2358717d4247SJustin T. Gibbs 
2359717d4247SJustin T. Gibbs 	/*
2360717d4247SJustin T. Gibbs 	 * Cachesize must also be zero due to stray DAC
2361717d4247SJustin T. Gibbs 	 * problem when sitting behind some bridges.
2362717d4247SJustin T. Gibbs 	 */
2363b3b25f2cSJustin T. Gibbs 	aic_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1);
2364b3b25f2cSJustin T. Gibbs 	devconfig = aic_pci_read_config(pci, DEVCONFIG, /*bytes*/1);
2365717d4247SJustin T. Gibbs 	devconfig |= MRDCEN;
2366b3b25f2cSJustin T. Gibbs 	aic_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1);
2367717d4247SJustin T. Gibbs #endif
2368cd036e89SJustin T. Gibbs 	ahc->flags |= AHC_NEWEEPROM_FMT;
23699bf327a7SJustin T. Gibbs 	ahc->instruction_ram_size = 512;
2370717d4247SJustin T. Gibbs 	return (0);
2371717d4247SJustin T. Gibbs }
2372717d4247SJustin T. Gibbs 
2373717d4247SJustin T. Gibbs static int
2374cd036e89SJustin T. Gibbs ahc_aic7896_setup(struct ahc_softc *ahc)
2375717d4247SJustin T. Gibbs {
2376b3b25f2cSJustin T. Gibbs 	aic_dev_softc_t pci;
2377cd036e89SJustin T. Gibbs 
2378cd036e89SJustin T. Gibbs 	pci = ahc->dev_softc;
2379b3b25f2cSJustin T. Gibbs 	ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A';
2380cd036e89SJustin T. Gibbs 	ahc->chip = AHC_AIC7896;
2381cd036e89SJustin T. Gibbs 	ahc->features = AHC_AIC7896_FE;
2382cd036e89SJustin T. Gibbs 	ahc->flags |= AHC_NEWEEPROM_FMT;
2383cd036e89SJustin T. Gibbs 	ahc->bugs |= AHC_CACHETHEN_DIS_BUG;
23849bf327a7SJustin T. Gibbs 	ahc->instruction_ram_size = 768;
2385717d4247SJustin T. Gibbs 	return (0);
2386717d4247SJustin T. Gibbs }
2387717d4247SJustin T. Gibbs 
2388717d4247SJustin T. Gibbs static int
2389cd036e89SJustin T. Gibbs ahc_aic7899_setup(struct ahc_softc *ahc)
2390717d4247SJustin T. Gibbs {
2391b3b25f2cSJustin T. Gibbs 	aic_dev_softc_t pci;
2392cd036e89SJustin T. Gibbs 
2393cd036e89SJustin T. Gibbs 	pci = ahc->dev_softc;
2394b3b25f2cSJustin T. Gibbs 	ahc->channel = aic_get_pci_function(pci) == 1 ? 'B' : 'A';
2395cd036e89SJustin T. Gibbs 	ahc->chip = AHC_AIC7899;
2396cd036e89SJustin T. Gibbs 	ahc->features = AHC_AIC7899_FE;
2397cd036e89SJustin T. Gibbs 	ahc->flags |= AHC_NEWEEPROM_FMT;
2398cd036e89SJustin T. Gibbs 	ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
23999bf327a7SJustin T. Gibbs 	ahc->instruction_ram_size = 1024;
2400717d4247SJustin T. Gibbs 	return (0);
2401717d4247SJustin T. Gibbs }
2402717d4247SJustin T. Gibbs 
2403717d4247SJustin T. Gibbs static int
2404cd036e89SJustin T. Gibbs ahc_aha29160C_setup(struct ahc_softc *ahc)
2405a5847d5cSJustin T. Gibbs {
2406a5847d5cSJustin T. Gibbs 	int error;
2407a5847d5cSJustin T. Gibbs 
2408cd036e89SJustin T. Gibbs 	error = ahc_aic7899_setup(ahc);
2409a5847d5cSJustin T. Gibbs 	if (error != 0)
2410a5847d5cSJustin T. Gibbs 		return (error);
2411cd036e89SJustin T. Gibbs 	ahc->features |= AHC_REMOVABLE;
2412a5847d5cSJustin T. Gibbs 	return (0);
2413a5847d5cSJustin T. Gibbs }
2414a5847d5cSJustin T. Gibbs 
2415a5847d5cSJustin T. Gibbs static int
2416cd036e89SJustin T. Gibbs ahc_raid_setup(struct ahc_softc *ahc)
2417717d4247SJustin T. Gibbs {
2418717d4247SJustin T. Gibbs 	printf("RAID functionality unsupported\n");
2419717d4247SJustin T. Gibbs 	return (ENXIO);
2420717d4247SJustin T. Gibbs }
2421717d4247SJustin T. Gibbs 
2422717d4247SJustin T. Gibbs static int
2423cd036e89SJustin T. Gibbs ahc_aha394XX_setup(struct ahc_softc *ahc)
2424717d4247SJustin T. Gibbs {
2425b3b25f2cSJustin T. Gibbs 	aic_dev_softc_t pci;
2426cd036e89SJustin T. Gibbs 
2427cd036e89SJustin T. Gibbs 	pci = ahc->dev_softc;
2428b3b25f2cSJustin T. Gibbs 	switch (aic_get_pci_slot(pci)) {
2429717d4247SJustin T. Gibbs 	case AHC_394X_SLOT_CHANNEL_A:
2430cd036e89SJustin T. Gibbs 		ahc->channel = 'A';
2431717d4247SJustin T. Gibbs 		break;
2432717d4247SJustin T. Gibbs 	case AHC_394X_SLOT_CHANNEL_B:
2433cd036e89SJustin T. Gibbs 		ahc->channel = 'B';
2434717d4247SJustin T. Gibbs 		break;
2435717d4247SJustin T. Gibbs 	default:
2436717d4247SJustin T. Gibbs 		printf("adapter at unexpected slot %d\n"
2437717d4247SJustin T. Gibbs 		       "unable to map to a channel\n",
2438b3b25f2cSJustin T. Gibbs 		       aic_get_pci_slot(pci));
2439cd036e89SJustin T. Gibbs 		ahc->channel = 'A';
2440717d4247SJustin T. Gibbs 	}
2441717d4247SJustin T. Gibbs 	return (0);
2442717d4247SJustin T. Gibbs }
2443717d4247SJustin T. Gibbs 
2444717d4247SJustin T. Gibbs static int
2445cd036e89SJustin T. Gibbs ahc_aha398XX_setup(struct ahc_softc *ahc)
2446717d4247SJustin T. Gibbs {
2447b3b25f2cSJustin T. Gibbs 	aic_dev_softc_t pci;
2448cd036e89SJustin T. Gibbs 
2449cd036e89SJustin T. Gibbs 	pci = ahc->dev_softc;
2450b3b25f2cSJustin T. Gibbs 	switch (aic_get_pci_slot(pci)) {
2451717d4247SJustin T. Gibbs 	case AHC_398X_SLOT_CHANNEL_A:
2452cd036e89SJustin T. Gibbs 		ahc->channel = 'A';
2453717d4247SJustin T. Gibbs 		break;
2454717d4247SJustin T. Gibbs 	case AHC_398X_SLOT_CHANNEL_B:
2455cd036e89SJustin T. Gibbs 		ahc->channel = 'B';
2456717d4247SJustin T. Gibbs 		break;
2457717d4247SJustin T. Gibbs 	case AHC_398X_SLOT_CHANNEL_C:
2458cd036e89SJustin T. Gibbs 		ahc->channel = 'C';
2459717d4247SJustin T. Gibbs 		break;
2460717d4247SJustin T. Gibbs 	default:
2461717d4247SJustin T. Gibbs 		printf("adapter at unexpected slot %d\n"
2462717d4247SJustin T. Gibbs 		       "unable to map to a channel\n",
2463b3b25f2cSJustin T. Gibbs 		       aic_get_pci_slot(pci));
2464cd036e89SJustin T. Gibbs 		ahc->channel = 'A';
2465717d4247SJustin T. Gibbs 		break;
2466717d4247SJustin T. Gibbs 	}
2467cd036e89SJustin T. Gibbs 	ahc->flags |= AHC_LARGE_SEEPROM;
2468717d4247SJustin T. Gibbs 	return (0);
2469717d4247SJustin T. Gibbs }
2470717d4247SJustin T. Gibbs 
2471717d4247SJustin T. Gibbs static int
2472cd036e89SJustin T. Gibbs ahc_aha494XX_setup(struct ahc_softc *ahc)
2473717d4247SJustin T. Gibbs {
2474b3b25f2cSJustin T. Gibbs 	aic_dev_softc_t pci;
2475cd036e89SJustin T. Gibbs 
2476cd036e89SJustin T. Gibbs 	pci = ahc->dev_softc;
2477b3b25f2cSJustin T. Gibbs 	switch (aic_get_pci_slot(pci)) {
2478717d4247SJustin T. Gibbs 	case AHC_494X_SLOT_CHANNEL_A:
2479cd036e89SJustin T. Gibbs 		ahc->channel = 'A';
2480717d4247SJustin T. Gibbs 		break;
2481717d4247SJustin T. Gibbs 	case AHC_494X_SLOT_CHANNEL_B:
2482cd036e89SJustin T. Gibbs 		ahc->channel = 'B';
2483717d4247SJustin T. Gibbs 		break;
2484717d4247SJustin T. Gibbs 	case AHC_494X_SLOT_CHANNEL_C:
2485cd036e89SJustin T. Gibbs 		ahc->channel = 'C';
2486717d4247SJustin T. Gibbs 		break;
2487717d4247SJustin T. Gibbs 	case AHC_494X_SLOT_CHANNEL_D:
2488cd036e89SJustin T. Gibbs 		ahc->channel = 'D';
2489717d4247SJustin T. Gibbs 		break;
2490717d4247SJustin T. Gibbs 	default:
2491717d4247SJustin T. Gibbs 		printf("adapter at unexpected slot %d\n"
2492717d4247SJustin T. Gibbs 		       "unable to map to a channel\n",
2493b3b25f2cSJustin T. Gibbs 		       aic_get_pci_slot(pci));
2494cd036e89SJustin T. Gibbs 		ahc->channel = 'A';
2495717d4247SJustin T. Gibbs 	}
2496cd036e89SJustin T. Gibbs 	ahc->flags |= AHC_LARGE_SEEPROM;
2497717d4247SJustin T. Gibbs 	return (0);
2498717d4247SJustin T. Gibbs }
2499