xref: /OK3568_Linux_fs/kernel/drivers/scsi/aic7xxx/aic7xxx_pci.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun /*
2*4882a593Smuzhiyun  * Product specific probe and attach routines for:
3*4882a593Smuzhiyun  *      3940, 2940, aic7895, aic7890, aic7880,
4*4882a593Smuzhiyun  *	aic7870, aic7860 and aic7850 SCSI controllers
5*4882a593Smuzhiyun  *
6*4882a593Smuzhiyun  * Copyright (c) 1994-2001 Justin T. Gibbs.
7*4882a593Smuzhiyun  * Copyright (c) 2000-2001 Adaptec Inc.
8*4882a593Smuzhiyun  * All rights reserved.
9*4882a593Smuzhiyun  *
10*4882a593Smuzhiyun  * Redistribution and use in source and binary forms, with or without
11*4882a593Smuzhiyun  * modification, are permitted provided that the following conditions
12*4882a593Smuzhiyun  * are met:
13*4882a593Smuzhiyun  * 1. Redistributions of source code must retain the above copyright
14*4882a593Smuzhiyun  *    notice, this list of conditions, and the following disclaimer,
15*4882a593Smuzhiyun  *    without modification.
16*4882a593Smuzhiyun  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
17*4882a593Smuzhiyun  *    substantially similar to the "NO WARRANTY" disclaimer below
18*4882a593Smuzhiyun  *    ("Disclaimer") and any redistribution must be conditioned upon
19*4882a593Smuzhiyun  *    including a substantially similar Disclaimer requirement for further
20*4882a593Smuzhiyun  *    binary redistribution.
21*4882a593Smuzhiyun  * 3. Neither the names of the above-listed copyright holders nor the names
22*4882a593Smuzhiyun  *    of any contributors may be used to endorse or promote products derived
23*4882a593Smuzhiyun  *    from this software without specific prior written permission.
24*4882a593Smuzhiyun  *
25*4882a593Smuzhiyun  * Alternatively, this software may be distributed under the terms of the
26*4882a593Smuzhiyun  * GNU General Public License ("GPL") version 2 as published by the Free
27*4882a593Smuzhiyun  * Software Foundation.
28*4882a593Smuzhiyun  *
29*4882a593Smuzhiyun  * NO WARRANTY
30*4882a593Smuzhiyun  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
31*4882a593Smuzhiyun  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
32*4882a593Smuzhiyun  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
33*4882a593Smuzhiyun  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
34*4882a593Smuzhiyun  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
35*4882a593Smuzhiyun  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
36*4882a593Smuzhiyun  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
37*4882a593Smuzhiyun  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
38*4882a593Smuzhiyun  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
39*4882a593Smuzhiyun  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
40*4882a593Smuzhiyun  * POSSIBILITY OF SUCH DAMAGES.
41*4882a593Smuzhiyun  *
42*4882a593Smuzhiyun  * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#79 $
43*4882a593Smuzhiyun  */
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun #include "aic7xxx_osm.h"
46*4882a593Smuzhiyun #include "aic7xxx_inline.h"
47*4882a593Smuzhiyun #include "aic7xxx_93cx6.h"
48*4882a593Smuzhiyun #include "aic7xxx_pci.h"
49*4882a593Smuzhiyun 
50*4882a593Smuzhiyun static inline uint64_t
ahc_compose_id(u_int device,u_int vendor,u_int subdevice,u_int subvendor)51*4882a593Smuzhiyun ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
52*4882a593Smuzhiyun {
53*4882a593Smuzhiyun 	uint64_t id;
54*4882a593Smuzhiyun 
55*4882a593Smuzhiyun 	id = subvendor
56*4882a593Smuzhiyun 	   | (subdevice << 16)
57*4882a593Smuzhiyun 	   | ((uint64_t)vendor << 32)
58*4882a593Smuzhiyun 	   | ((uint64_t)device << 48);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	return (id);
61*4882a593Smuzhiyun }
62*4882a593Smuzhiyun 
63*4882a593Smuzhiyun #define AHC_PCI_IOADDR	PCIR_MAPS	/* I/O Address */
64*4882a593Smuzhiyun #define AHC_PCI_MEMADDR	(PCIR_MAPS + 4)	/* Mem I/O Address */
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun #define DEVID_9005_TYPE(id) ((id) & 0xF)
67*4882a593Smuzhiyun #define		DEVID_9005_TYPE_HBA		0x0	/* Standard Card */
68*4882a593Smuzhiyun #define		DEVID_9005_TYPE_AAA		0x3	/* RAID Card */
69*4882a593Smuzhiyun #define		DEVID_9005_TYPE_SISL		0x5	/* Container ROMB */
70*4882a593Smuzhiyun #define		DEVID_9005_TYPE_MB		0xF	/* On Motherboard */
71*4882a593Smuzhiyun 
72*4882a593Smuzhiyun #define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
73*4882a593Smuzhiyun #define		DEVID_9005_MAXRATE_U160		0x0
74*4882a593Smuzhiyun #define		DEVID_9005_MAXRATE_ULTRA2	0x1
75*4882a593Smuzhiyun #define		DEVID_9005_MAXRATE_ULTRA	0x2
76*4882a593Smuzhiyun #define		DEVID_9005_MAXRATE_FAST		0x3
77*4882a593Smuzhiyun 
78*4882a593Smuzhiyun #define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6)
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun #define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8)
81*4882a593Smuzhiyun #define		DEVID_9005_CLASS_SPI		0x0	/* Parallel SCSI */
82*4882a593Smuzhiyun 
83*4882a593Smuzhiyun #define SUBID_9005_TYPE(id) ((id) & 0xF)
84*4882a593Smuzhiyun #define		SUBID_9005_TYPE_MB		0xF	/* On Motherboard */
85*4882a593Smuzhiyun #define		SUBID_9005_TYPE_CARD		0x0	/* Standard Card */
86*4882a593Smuzhiyun #define		SUBID_9005_TYPE_LCCARD		0x1	/* Low Cost Card */
87*4882a593Smuzhiyun #define		SUBID_9005_TYPE_RAID		0x3	/* Combined with Raid */
88*4882a593Smuzhiyun 
89*4882a593Smuzhiyun #define SUBID_9005_TYPE_KNOWN(id)			\
90*4882a593Smuzhiyun 	  ((((id) & 0xF) == SUBID_9005_TYPE_MB)		\
91*4882a593Smuzhiyun 	|| (((id) & 0xF) == SUBID_9005_TYPE_CARD)	\
92*4882a593Smuzhiyun 	|| (((id) & 0xF) == SUBID_9005_TYPE_LCCARD)	\
93*4882a593Smuzhiyun 	|| (((id) & 0xF) == SUBID_9005_TYPE_RAID))
94*4882a593Smuzhiyun 
95*4882a593Smuzhiyun #define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
96*4882a593Smuzhiyun #define		SUBID_9005_MAXRATE_ULTRA2	0x0
97*4882a593Smuzhiyun #define		SUBID_9005_MAXRATE_ULTRA	0x1
98*4882a593Smuzhiyun #define		SUBID_9005_MAXRATE_U160		0x2
99*4882a593Smuzhiyun #define		SUBID_9005_MAXRATE_RESERVED	0x3
100*4882a593Smuzhiyun 
101*4882a593Smuzhiyun #define SUBID_9005_SEEPTYPE(id)						\
102*4882a593Smuzhiyun 	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
103*4882a593Smuzhiyun 	 ? ((id) & 0xC0) >> 6						\
104*4882a593Smuzhiyun 	 : ((id) & 0x300) >> 8)
105*4882a593Smuzhiyun #define		SUBID_9005_SEEPTYPE_NONE	0x0
106*4882a593Smuzhiyun #define		SUBID_9005_SEEPTYPE_1K		0x1
107*4882a593Smuzhiyun #define		SUBID_9005_SEEPTYPE_2K_4K	0x2
108*4882a593Smuzhiyun #define		SUBID_9005_SEEPTYPE_RESERVED	0x3
109*4882a593Smuzhiyun #define SUBID_9005_AUTOTERM(id)						\
110*4882a593Smuzhiyun 	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
111*4882a593Smuzhiyun 	 ? (((id) & 0x400) >> 10) == 0					\
112*4882a593Smuzhiyun 	 : (((id) & 0x40) >> 6) == 0)
113*4882a593Smuzhiyun 
114*4882a593Smuzhiyun #define SUBID_9005_NUMCHAN(id)						\
115*4882a593Smuzhiyun 	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
116*4882a593Smuzhiyun 	 ? ((id) & 0x300) >> 8						\
117*4882a593Smuzhiyun 	 : ((id) & 0xC00) >> 10)
118*4882a593Smuzhiyun 
119*4882a593Smuzhiyun #define SUBID_9005_LEGACYCONN(id)					\
120*4882a593Smuzhiyun 	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
121*4882a593Smuzhiyun 	 ? 0								\
122*4882a593Smuzhiyun 	 : ((id) & 0x80) >> 7)
123*4882a593Smuzhiyun 
124*4882a593Smuzhiyun #define SUBID_9005_MFUNCENB(id)						\
125*4882a593Smuzhiyun 	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
126*4882a593Smuzhiyun 	 ? ((id) & 0x800) >> 11						\
127*4882a593Smuzhiyun 	 : ((id) & 0x1000) >> 12)
128*4882a593Smuzhiyun /*
129*4882a593Smuzhiyun  * Informational only. Should use chip register to be
130*4882a593Smuzhiyun  * certain, but may be use in identification strings.
131*4882a593Smuzhiyun  */
132*4882a593Smuzhiyun #define SUBID_9005_CARD_SCSIWIDTH_MASK	0x2000
133*4882a593Smuzhiyun #define SUBID_9005_CARD_PCIWIDTH_MASK	0x4000
134*4882a593Smuzhiyun #define SUBID_9005_CARD_SEDIFF_MASK	0x8000
135*4882a593Smuzhiyun 
136*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic785X_setup;
137*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7860_setup;
138*4882a593Smuzhiyun static ahc_device_setup_t ahc_apa1480_setup;
139*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7870_setup;
140*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7870h_setup;
141*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha394X_setup;
142*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha394Xh_setup;
143*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha494X_setup;
144*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha494Xh_setup;
145*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha398X_setup;
146*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7880_setup;
147*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7880h_setup;
148*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha2940Pro_setup;
149*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha394XU_setup;
150*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha394XUh_setup;
151*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha398XU_setup;
152*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7890_setup;
153*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7892_setup;
154*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7895_setup;
155*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7895h_setup;
156*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7896_setup;
157*4882a593Smuzhiyun static ahc_device_setup_t ahc_aic7899_setup;
158*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha29160C_setup;
159*4882a593Smuzhiyun static ahc_device_setup_t ahc_raid_setup;
160*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha394XX_setup;
161*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha494XX_setup;
162*4882a593Smuzhiyun static ahc_device_setup_t ahc_aha398XX_setup;
163*4882a593Smuzhiyun 
164*4882a593Smuzhiyun static const struct ahc_pci_identity ahc_pci_ident_table[] = {
165*4882a593Smuzhiyun 	/* aic7850 based controllers */
166*4882a593Smuzhiyun 	{
167*4882a593Smuzhiyun 		ID_AHA_2902_04_10_15_20C_30C,
168*4882a593Smuzhiyun 		ID_ALL_MASK,
169*4882a593Smuzhiyun 		"Adaptec 2902/04/10/15/20C/30C SCSI adapter",
170*4882a593Smuzhiyun 		ahc_aic785X_setup
171*4882a593Smuzhiyun 	},
172*4882a593Smuzhiyun 	/* aic7860 based controllers */
173*4882a593Smuzhiyun 	{
174*4882a593Smuzhiyun 		ID_AHA_2930CU,
175*4882a593Smuzhiyun 		ID_ALL_MASK,
176*4882a593Smuzhiyun 		"Adaptec 2930CU SCSI adapter",
177*4882a593Smuzhiyun 		ahc_aic7860_setup
178*4882a593Smuzhiyun 	},
179*4882a593Smuzhiyun 	{
180*4882a593Smuzhiyun 		ID_AHA_1480A & ID_DEV_VENDOR_MASK,
181*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
182*4882a593Smuzhiyun 		"Adaptec 1480A Ultra SCSI adapter",
183*4882a593Smuzhiyun 		ahc_apa1480_setup
184*4882a593Smuzhiyun 	},
185*4882a593Smuzhiyun 	{
186*4882a593Smuzhiyun 		ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK,
187*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
188*4882a593Smuzhiyun 		"Adaptec 2940A Ultra SCSI adapter",
189*4882a593Smuzhiyun 		ahc_aic7860_setup
190*4882a593Smuzhiyun 	},
191*4882a593Smuzhiyun 	{
192*4882a593Smuzhiyun 		ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK,
193*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
194*4882a593Smuzhiyun 		"Adaptec 2940A/CN Ultra SCSI adapter",
195*4882a593Smuzhiyun 		ahc_aic7860_setup
196*4882a593Smuzhiyun 	},
197*4882a593Smuzhiyun 	{
198*4882a593Smuzhiyun 		ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK,
199*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
200*4882a593Smuzhiyun 		"Adaptec 2930C Ultra SCSI adapter (VAR)",
201*4882a593Smuzhiyun 		ahc_aic7860_setup
202*4882a593Smuzhiyun 	},
203*4882a593Smuzhiyun 	/* aic7870 based controllers */
204*4882a593Smuzhiyun 	{
205*4882a593Smuzhiyun 		ID_AHA_2940,
206*4882a593Smuzhiyun 		ID_ALL_MASK,
207*4882a593Smuzhiyun 		"Adaptec 2940 SCSI adapter",
208*4882a593Smuzhiyun 		ahc_aic7870_setup
209*4882a593Smuzhiyun 	},
210*4882a593Smuzhiyun 	{
211*4882a593Smuzhiyun 		ID_AHA_3940,
212*4882a593Smuzhiyun 		ID_ALL_MASK,
213*4882a593Smuzhiyun 		"Adaptec 3940 SCSI adapter",
214*4882a593Smuzhiyun 		ahc_aha394X_setup
215*4882a593Smuzhiyun 	},
216*4882a593Smuzhiyun 	{
217*4882a593Smuzhiyun 		ID_AHA_398X,
218*4882a593Smuzhiyun 		ID_ALL_MASK,
219*4882a593Smuzhiyun 		"Adaptec 398X SCSI RAID adapter",
220*4882a593Smuzhiyun 		ahc_aha398X_setup
221*4882a593Smuzhiyun 	},
222*4882a593Smuzhiyun 	{
223*4882a593Smuzhiyun 		ID_AHA_2944,
224*4882a593Smuzhiyun 		ID_ALL_MASK,
225*4882a593Smuzhiyun 		"Adaptec 2944 SCSI adapter",
226*4882a593Smuzhiyun 		ahc_aic7870h_setup
227*4882a593Smuzhiyun 	},
228*4882a593Smuzhiyun 	{
229*4882a593Smuzhiyun 		ID_AHA_3944,
230*4882a593Smuzhiyun 		ID_ALL_MASK,
231*4882a593Smuzhiyun 		"Adaptec 3944 SCSI adapter",
232*4882a593Smuzhiyun 		ahc_aha394Xh_setup
233*4882a593Smuzhiyun 	},
234*4882a593Smuzhiyun 	{
235*4882a593Smuzhiyun 		ID_AHA_4944,
236*4882a593Smuzhiyun 		ID_ALL_MASK,
237*4882a593Smuzhiyun 		"Adaptec 4944 SCSI adapter",
238*4882a593Smuzhiyun 		ahc_aha494Xh_setup
239*4882a593Smuzhiyun 	},
240*4882a593Smuzhiyun 	/* aic7880 based controllers */
241*4882a593Smuzhiyun 	{
242*4882a593Smuzhiyun 		ID_AHA_2940U & ID_DEV_VENDOR_MASK,
243*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
244*4882a593Smuzhiyun 		"Adaptec 2940 Ultra SCSI adapter",
245*4882a593Smuzhiyun 		ahc_aic7880_setup
246*4882a593Smuzhiyun 	},
247*4882a593Smuzhiyun 	{
248*4882a593Smuzhiyun 		ID_AHA_3940U & ID_DEV_VENDOR_MASK,
249*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
250*4882a593Smuzhiyun 		"Adaptec 3940 Ultra SCSI adapter",
251*4882a593Smuzhiyun 		ahc_aha394XU_setup
252*4882a593Smuzhiyun 	},
253*4882a593Smuzhiyun 	{
254*4882a593Smuzhiyun 		ID_AHA_2944U & ID_DEV_VENDOR_MASK,
255*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
256*4882a593Smuzhiyun 		"Adaptec 2944 Ultra SCSI adapter",
257*4882a593Smuzhiyun 		ahc_aic7880h_setup
258*4882a593Smuzhiyun 	},
259*4882a593Smuzhiyun 	{
260*4882a593Smuzhiyun 		ID_AHA_3944U & ID_DEV_VENDOR_MASK,
261*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
262*4882a593Smuzhiyun 		"Adaptec 3944 Ultra SCSI adapter",
263*4882a593Smuzhiyun 		ahc_aha394XUh_setup
264*4882a593Smuzhiyun 	},
265*4882a593Smuzhiyun 	{
266*4882a593Smuzhiyun 		ID_AHA_398XU & ID_DEV_VENDOR_MASK,
267*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
268*4882a593Smuzhiyun 		"Adaptec 398X Ultra SCSI RAID adapter",
269*4882a593Smuzhiyun 		ahc_aha398XU_setup
270*4882a593Smuzhiyun 	},
271*4882a593Smuzhiyun 	{
272*4882a593Smuzhiyun 		/*
273*4882a593Smuzhiyun 		 * XXX Don't know the slot numbers
274*4882a593Smuzhiyun 		 * so we can't identify channels
275*4882a593Smuzhiyun 		 */
276*4882a593Smuzhiyun 		ID_AHA_4944U & ID_DEV_VENDOR_MASK,
277*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
278*4882a593Smuzhiyun 		"Adaptec 4944 Ultra SCSI adapter",
279*4882a593Smuzhiyun 		ahc_aic7880h_setup
280*4882a593Smuzhiyun 	},
281*4882a593Smuzhiyun 	{
282*4882a593Smuzhiyun 		ID_AHA_2930U & ID_DEV_VENDOR_MASK,
283*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
284*4882a593Smuzhiyun 		"Adaptec 2930 Ultra SCSI adapter",
285*4882a593Smuzhiyun 		ahc_aic7880_setup
286*4882a593Smuzhiyun 	},
287*4882a593Smuzhiyun 	{
288*4882a593Smuzhiyun 		ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK,
289*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
290*4882a593Smuzhiyun 		"Adaptec 2940 Pro Ultra SCSI adapter",
291*4882a593Smuzhiyun 		ahc_aha2940Pro_setup
292*4882a593Smuzhiyun 	},
293*4882a593Smuzhiyun 	{
294*4882a593Smuzhiyun 		ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK,
295*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
296*4882a593Smuzhiyun 		"Adaptec 2940/CN Ultra SCSI adapter",
297*4882a593Smuzhiyun 		ahc_aic7880_setup
298*4882a593Smuzhiyun 	},
299*4882a593Smuzhiyun 	/* Ignore all SISL (AAC on MB) based controllers. */
300*4882a593Smuzhiyun 	{
301*4882a593Smuzhiyun 		ID_9005_SISL_ID,
302*4882a593Smuzhiyun 		ID_9005_SISL_MASK,
303*4882a593Smuzhiyun 		NULL,
304*4882a593Smuzhiyun 		NULL
305*4882a593Smuzhiyun 	},
306*4882a593Smuzhiyun 	/* aic7890 based controllers */
307*4882a593Smuzhiyun 	{
308*4882a593Smuzhiyun 		ID_AHA_2930U2,
309*4882a593Smuzhiyun 		ID_ALL_MASK,
310*4882a593Smuzhiyun 		"Adaptec 2930 Ultra2 SCSI adapter",
311*4882a593Smuzhiyun 		ahc_aic7890_setup
312*4882a593Smuzhiyun 	},
313*4882a593Smuzhiyun 	{
314*4882a593Smuzhiyun 		ID_AHA_2940U2B,
315*4882a593Smuzhiyun 		ID_ALL_MASK,
316*4882a593Smuzhiyun 		"Adaptec 2940B Ultra2 SCSI adapter",
317*4882a593Smuzhiyun 		ahc_aic7890_setup
318*4882a593Smuzhiyun 	},
319*4882a593Smuzhiyun 	{
320*4882a593Smuzhiyun 		ID_AHA_2940U2_OEM,
321*4882a593Smuzhiyun 		ID_ALL_MASK,
322*4882a593Smuzhiyun 		"Adaptec 2940 Ultra2 SCSI adapter (OEM)",
323*4882a593Smuzhiyun 		ahc_aic7890_setup
324*4882a593Smuzhiyun 	},
325*4882a593Smuzhiyun 	{
326*4882a593Smuzhiyun 		ID_AHA_2940U2,
327*4882a593Smuzhiyun 		ID_ALL_MASK,
328*4882a593Smuzhiyun 		"Adaptec 2940 Ultra2 SCSI adapter",
329*4882a593Smuzhiyun 		ahc_aic7890_setup
330*4882a593Smuzhiyun 	},
331*4882a593Smuzhiyun 	{
332*4882a593Smuzhiyun 		ID_AHA_2950U2B,
333*4882a593Smuzhiyun 		ID_ALL_MASK,
334*4882a593Smuzhiyun 		"Adaptec 2950 Ultra2 SCSI adapter",
335*4882a593Smuzhiyun 		ahc_aic7890_setup
336*4882a593Smuzhiyun 	},
337*4882a593Smuzhiyun 	{
338*4882a593Smuzhiyun 		ID_AIC7890_ARO,
339*4882a593Smuzhiyun 		ID_ALL_MASK,
340*4882a593Smuzhiyun 		"Adaptec aic7890/91 Ultra2 SCSI adapter (ARO)",
341*4882a593Smuzhiyun 		ahc_aic7890_setup
342*4882a593Smuzhiyun 	},
343*4882a593Smuzhiyun 	{
344*4882a593Smuzhiyun 		ID_AAA_131U2,
345*4882a593Smuzhiyun 		ID_ALL_MASK,
346*4882a593Smuzhiyun 		"Adaptec AAA-131 Ultra2 RAID adapter",
347*4882a593Smuzhiyun 		ahc_aic7890_setup
348*4882a593Smuzhiyun 	},
349*4882a593Smuzhiyun 	/* aic7892 based controllers */
350*4882a593Smuzhiyun 	{
351*4882a593Smuzhiyun 		ID_AHA_29160,
352*4882a593Smuzhiyun 		ID_ALL_MASK,
353*4882a593Smuzhiyun 		"Adaptec 29160 Ultra160 SCSI adapter",
354*4882a593Smuzhiyun 		ahc_aic7892_setup
355*4882a593Smuzhiyun 	},
356*4882a593Smuzhiyun 	{
357*4882a593Smuzhiyun 		ID_AHA_29160_CPQ,
358*4882a593Smuzhiyun 		ID_ALL_MASK,
359*4882a593Smuzhiyun 		"Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter",
360*4882a593Smuzhiyun 		ahc_aic7892_setup
361*4882a593Smuzhiyun 	},
362*4882a593Smuzhiyun 	{
363*4882a593Smuzhiyun 		ID_AHA_29160N,
364*4882a593Smuzhiyun 		ID_ALL_MASK,
365*4882a593Smuzhiyun 		"Adaptec 29160N Ultra160 SCSI adapter",
366*4882a593Smuzhiyun 		ahc_aic7892_setup
367*4882a593Smuzhiyun 	},
368*4882a593Smuzhiyun 	{
369*4882a593Smuzhiyun 		ID_AHA_29160C,
370*4882a593Smuzhiyun 		ID_ALL_MASK,
371*4882a593Smuzhiyun 		"Adaptec 29160C Ultra160 SCSI adapter",
372*4882a593Smuzhiyun 		ahc_aha29160C_setup
373*4882a593Smuzhiyun 	},
374*4882a593Smuzhiyun 	{
375*4882a593Smuzhiyun 		ID_AHA_29160B,
376*4882a593Smuzhiyun 		ID_ALL_MASK,
377*4882a593Smuzhiyun 		"Adaptec 29160B Ultra160 SCSI adapter",
378*4882a593Smuzhiyun 		ahc_aic7892_setup
379*4882a593Smuzhiyun 	},
380*4882a593Smuzhiyun 	{
381*4882a593Smuzhiyun 		ID_AHA_19160B,
382*4882a593Smuzhiyun 		ID_ALL_MASK,
383*4882a593Smuzhiyun 		"Adaptec 19160B Ultra160 SCSI adapter",
384*4882a593Smuzhiyun 		ahc_aic7892_setup
385*4882a593Smuzhiyun 	},
386*4882a593Smuzhiyun 	{
387*4882a593Smuzhiyun 		ID_AIC7892_ARO,
388*4882a593Smuzhiyun 		ID_ALL_MASK,
389*4882a593Smuzhiyun 		"Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
390*4882a593Smuzhiyun 		ahc_aic7892_setup
391*4882a593Smuzhiyun 	},
392*4882a593Smuzhiyun 	{
393*4882a593Smuzhiyun 		ID_AHA_2915_30LP,
394*4882a593Smuzhiyun 		ID_ALL_MASK,
395*4882a593Smuzhiyun 		"Adaptec 2915/30LP Ultra160 SCSI adapter",
396*4882a593Smuzhiyun 		ahc_aic7892_setup
397*4882a593Smuzhiyun 	},
398*4882a593Smuzhiyun 	/* aic7895 based controllers */
399*4882a593Smuzhiyun 	{
400*4882a593Smuzhiyun 		ID_AHA_2940U_DUAL,
401*4882a593Smuzhiyun 		ID_ALL_MASK,
402*4882a593Smuzhiyun 		"Adaptec 2940/DUAL Ultra SCSI adapter",
403*4882a593Smuzhiyun 		ahc_aic7895_setup
404*4882a593Smuzhiyun 	},
405*4882a593Smuzhiyun 	{
406*4882a593Smuzhiyun 		ID_AHA_3940AU,
407*4882a593Smuzhiyun 		ID_ALL_MASK,
408*4882a593Smuzhiyun 		"Adaptec 3940A Ultra SCSI adapter",
409*4882a593Smuzhiyun 		ahc_aic7895_setup
410*4882a593Smuzhiyun 	},
411*4882a593Smuzhiyun 	{
412*4882a593Smuzhiyun 		ID_AHA_3944AU,
413*4882a593Smuzhiyun 		ID_ALL_MASK,
414*4882a593Smuzhiyun 		"Adaptec 3944A Ultra SCSI adapter",
415*4882a593Smuzhiyun 		ahc_aic7895h_setup
416*4882a593Smuzhiyun 	},
417*4882a593Smuzhiyun 	{
418*4882a593Smuzhiyun 		ID_AIC7895_ARO,
419*4882a593Smuzhiyun 		ID_AIC7895_ARO_MASK,
420*4882a593Smuzhiyun 		"Adaptec aic7895 Ultra SCSI adapter (ARO)",
421*4882a593Smuzhiyun 		ahc_aic7895_setup
422*4882a593Smuzhiyun 	},
423*4882a593Smuzhiyun 	/* aic7896/97 based controllers */
424*4882a593Smuzhiyun 	{
425*4882a593Smuzhiyun 		ID_AHA_3950U2B_0,
426*4882a593Smuzhiyun 		ID_ALL_MASK,
427*4882a593Smuzhiyun 		"Adaptec 3950B Ultra2 SCSI adapter",
428*4882a593Smuzhiyun 		ahc_aic7896_setup
429*4882a593Smuzhiyun 	},
430*4882a593Smuzhiyun 	{
431*4882a593Smuzhiyun 		ID_AHA_3950U2B_1,
432*4882a593Smuzhiyun 		ID_ALL_MASK,
433*4882a593Smuzhiyun 		"Adaptec 3950B Ultra2 SCSI adapter",
434*4882a593Smuzhiyun 		ahc_aic7896_setup
435*4882a593Smuzhiyun 	},
436*4882a593Smuzhiyun 	{
437*4882a593Smuzhiyun 		ID_AHA_3950U2D_0,
438*4882a593Smuzhiyun 		ID_ALL_MASK,
439*4882a593Smuzhiyun 		"Adaptec 3950D Ultra2 SCSI adapter",
440*4882a593Smuzhiyun 		ahc_aic7896_setup
441*4882a593Smuzhiyun 	},
442*4882a593Smuzhiyun 	{
443*4882a593Smuzhiyun 		ID_AHA_3950U2D_1,
444*4882a593Smuzhiyun 		ID_ALL_MASK,
445*4882a593Smuzhiyun 		"Adaptec 3950D Ultra2 SCSI adapter",
446*4882a593Smuzhiyun 		ahc_aic7896_setup
447*4882a593Smuzhiyun 	},
448*4882a593Smuzhiyun 	{
449*4882a593Smuzhiyun 		ID_AIC7896_ARO,
450*4882a593Smuzhiyun 		ID_ALL_MASK,
451*4882a593Smuzhiyun 		"Adaptec aic7896/97 Ultra2 SCSI adapter (ARO)",
452*4882a593Smuzhiyun 		ahc_aic7896_setup
453*4882a593Smuzhiyun 	},
454*4882a593Smuzhiyun 	/* aic7899 based controllers */
455*4882a593Smuzhiyun 	{
456*4882a593Smuzhiyun 		ID_AHA_3960D,
457*4882a593Smuzhiyun 		ID_ALL_MASK,
458*4882a593Smuzhiyun 		"Adaptec 3960D Ultra160 SCSI adapter",
459*4882a593Smuzhiyun 		ahc_aic7899_setup
460*4882a593Smuzhiyun 	},
461*4882a593Smuzhiyun 	{
462*4882a593Smuzhiyun 		ID_AHA_3960D_CPQ,
463*4882a593Smuzhiyun 		ID_ALL_MASK,
464*4882a593Smuzhiyun 		"Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter",
465*4882a593Smuzhiyun 		ahc_aic7899_setup
466*4882a593Smuzhiyun 	},
467*4882a593Smuzhiyun 	{
468*4882a593Smuzhiyun 		ID_AIC7899_ARO,
469*4882a593Smuzhiyun 		ID_ALL_MASK,
470*4882a593Smuzhiyun 		"Adaptec aic7899 Ultra160 SCSI adapter (ARO)",
471*4882a593Smuzhiyun 		ahc_aic7899_setup
472*4882a593Smuzhiyun 	},
473*4882a593Smuzhiyun 	/* Generic chip probes for devices we don't know 'exactly' */
474*4882a593Smuzhiyun 	{
475*4882a593Smuzhiyun 		ID_AIC7850 & ID_DEV_VENDOR_MASK,
476*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
477*4882a593Smuzhiyun 		"Adaptec aic7850 SCSI adapter",
478*4882a593Smuzhiyun 		ahc_aic785X_setup
479*4882a593Smuzhiyun 	},
480*4882a593Smuzhiyun 	{
481*4882a593Smuzhiyun 		ID_AIC7855 & ID_DEV_VENDOR_MASK,
482*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
483*4882a593Smuzhiyun 		"Adaptec aic7855 SCSI adapter",
484*4882a593Smuzhiyun 		ahc_aic785X_setup
485*4882a593Smuzhiyun 	},
486*4882a593Smuzhiyun 	{
487*4882a593Smuzhiyun 		ID_AIC7859 & ID_DEV_VENDOR_MASK,
488*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
489*4882a593Smuzhiyun 		"Adaptec aic7859 SCSI adapter",
490*4882a593Smuzhiyun 		ahc_aic7860_setup
491*4882a593Smuzhiyun 	},
492*4882a593Smuzhiyun 	{
493*4882a593Smuzhiyun 		ID_AIC7860 & ID_DEV_VENDOR_MASK,
494*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
495*4882a593Smuzhiyun 		"Adaptec aic7860 Ultra SCSI adapter",
496*4882a593Smuzhiyun 		ahc_aic7860_setup
497*4882a593Smuzhiyun 	},
498*4882a593Smuzhiyun 	{
499*4882a593Smuzhiyun 		ID_AIC7870 & ID_DEV_VENDOR_MASK,
500*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
501*4882a593Smuzhiyun 		"Adaptec aic7870 SCSI adapter",
502*4882a593Smuzhiyun 		ahc_aic7870_setup
503*4882a593Smuzhiyun 	},
504*4882a593Smuzhiyun 	{
505*4882a593Smuzhiyun 		ID_AIC7880 & ID_DEV_VENDOR_MASK,
506*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
507*4882a593Smuzhiyun 		"Adaptec aic7880 Ultra SCSI adapter",
508*4882a593Smuzhiyun 		ahc_aic7880_setup
509*4882a593Smuzhiyun 	},
510*4882a593Smuzhiyun 	{
511*4882a593Smuzhiyun 		ID_AIC7890 & ID_9005_GENERIC_MASK,
512*4882a593Smuzhiyun 		ID_9005_GENERIC_MASK,
513*4882a593Smuzhiyun 		"Adaptec aic7890/91 Ultra2 SCSI adapter",
514*4882a593Smuzhiyun 		ahc_aic7890_setup
515*4882a593Smuzhiyun 	},
516*4882a593Smuzhiyun 	{
517*4882a593Smuzhiyun 		ID_AIC7892 & ID_9005_GENERIC_MASK,
518*4882a593Smuzhiyun 		ID_9005_GENERIC_MASK,
519*4882a593Smuzhiyun 		"Adaptec aic7892 Ultra160 SCSI adapter",
520*4882a593Smuzhiyun 		ahc_aic7892_setup
521*4882a593Smuzhiyun 	},
522*4882a593Smuzhiyun 	{
523*4882a593Smuzhiyun 		ID_AIC7895 & ID_DEV_VENDOR_MASK,
524*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
525*4882a593Smuzhiyun 		"Adaptec aic7895 Ultra SCSI adapter",
526*4882a593Smuzhiyun 		ahc_aic7895_setup
527*4882a593Smuzhiyun 	},
528*4882a593Smuzhiyun 	{
529*4882a593Smuzhiyun 		ID_AIC7896 & ID_9005_GENERIC_MASK,
530*4882a593Smuzhiyun 		ID_9005_GENERIC_MASK,
531*4882a593Smuzhiyun 		"Adaptec aic7896/97 Ultra2 SCSI adapter",
532*4882a593Smuzhiyun 		ahc_aic7896_setup
533*4882a593Smuzhiyun 	},
534*4882a593Smuzhiyun 	{
535*4882a593Smuzhiyun 		ID_AIC7899 & ID_9005_GENERIC_MASK,
536*4882a593Smuzhiyun 		ID_9005_GENERIC_MASK,
537*4882a593Smuzhiyun 		"Adaptec aic7899 Ultra160 SCSI adapter",
538*4882a593Smuzhiyun 		ahc_aic7899_setup
539*4882a593Smuzhiyun 	},
540*4882a593Smuzhiyun 	{
541*4882a593Smuzhiyun 		ID_AIC7810 & ID_DEV_VENDOR_MASK,
542*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
543*4882a593Smuzhiyun 		"Adaptec aic7810 RAID memory controller",
544*4882a593Smuzhiyun 		ahc_raid_setup
545*4882a593Smuzhiyun 	},
546*4882a593Smuzhiyun 	{
547*4882a593Smuzhiyun 		ID_AIC7815 & ID_DEV_VENDOR_MASK,
548*4882a593Smuzhiyun 		ID_DEV_VENDOR_MASK,
549*4882a593Smuzhiyun 		"Adaptec aic7815 RAID memory controller",
550*4882a593Smuzhiyun 		ahc_raid_setup
551*4882a593Smuzhiyun 	}
552*4882a593Smuzhiyun };
553*4882a593Smuzhiyun 
554*4882a593Smuzhiyun static const u_int ahc_num_pci_devs = ARRAY_SIZE(ahc_pci_ident_table);
555*4882a593Smuzhiyun 
556*4882a593Smuzhiyun #define AHC_394X_SLOT_CHANNEL_A	4
557*4882a593Smuzhiyun #define AHC_394X_SLOT_CHANNEL_B	5
558*4882a593Smuzhiyun 
559*4882a593Smuzhiyun #define AHC_398X_SLOT_CHANNEL_A	4
560*4882a593Smuzhiyun #define AHC_398X_SLOT_CHANNEL_B	8
561*4882a593Smuzhiyun #define AHC_398X_SLOT_CHANNEL_C	12
562*4882a593Smuzhiyun 
563*4882a593Smuzhiyun #define AHC_494X_SLOT_CHANNEL_A	4
564*4882a593Smuzhiyun #define AHC_494X_SLOT_CHANNEL_B	5
565*4882a593Smuzhiyun #define AHC_494X_SLOT_CHANNEL_C	6
566*4882a593Smuzhiyun #define AHC_494X_SLOT_CHANNEL_D	7
567*4882a593Smuzhiyun 
568*4882a593Smuzhiyun #define	DEVCONFIG		0x40
569*4882a593Smuzhiyun #define		PCIERRGENDIS	0x80000000ul
570*4882a593Smuzhiyun #define		SCBSIZE32	0x00010000ul	/* aic789X only */
571*4882a593Smuzhiyun #define		REXTVALID	0x00001000ul	/* ultra cards only */
572*4882a593Smuzhiyun #define		MPORTMODE	0x00000400ul	/* aic7870+ only */
573*4882a593Smuzhiyun #define		RAMPSM		0x00000200ul	/* aic7870+ only */
574*4882a593Smuzhiyun #define		VOLSENSE	0x00000100ul
575*4882a593Smuzhiyun #define		PCI64BIT	0x00000080ul	/* 64Bit PCI bus (Ultra2 Only)*/
576*4882a593Smuzhiyun #define		SCBRAMSEL	0x00000080ul
577*4882a593Smuzhiyun #define		MRDCEN		0x00000040ul
578*4882a593Smuzhiyun #define		EXTSCBTIME	0x00000020ul	/* aic7870 only */
579*4882a593Smuzhiyun #define		EXTSCBPEN	0x00000010ul	/* aic7870 only */
580*4882a593Smuzhiyun #define		BERREN		0x00000008ul
581*4882a593Smuzhiyun #define		DACEN		0x00000004ul
582*4882a593Smuzhiyun #define		STPWLEVEL	0x00000002ul
583*4882a593Smuzhiyun #define		DIFACTNEGEN	0x00000001ul	/* aic7870 only */
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun #define	CSIZE_LATTIME		0x0c
586*4882a593Smuzhiyun #define		CACHESIZE	0x0000003ful	/* only 5 bits */
587*4882a593Smuzhiyun #define		LATTIME		0x0000ff00ul
588*4882a593Smuzhiyun 
589*4882a593Smuzhiyun /* PCI STATUS definitions */
590*4882a593Smuzhiyun #define	DPE	0x80
591*4882a593Smuzhiyun #define SSE	0x40
592*4882a593Smuzhiyun #define	RMA	0x20
593*4882a593Smuzhiyun #define	RTA	0x10
594*4882a593Smuzhiyun #define STA	0x08
595*4882a593Smuzhiyun #define DPR	0x01
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun static int ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
598*4882a593Smuzhiyun 				     uint16_t subdevice, uint16_t subvendor);
599*4882a593Smuzhiyun static int ahc_ext_scbram_present(struct ahc_softc *ahc);
600*4882a593Smuzhiyun static void ahc_scbram_config(struct ahc_softc *ahc, int enable,
601*4882a593Smuzhiyun 				  int pcheck, int fast, int large);
602*4882a593Smuzhiyun static void ahc_probe_ext_scbram(struct ahc_softc *ahc);
603*4882a593Smuzhiyun static void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1);
604*4882a593Smuzhiyun static void ahc_parse_pci_eeprom(struct ahc_softc *ahc,
605*4882a593Smuzhiyun 				 struct seeprom_config *sc);
606*4882a593Smuzhiyun static void configure_termination(struct ahc_softc *ahc,
607*4882a593Smuzhiyun 				  struct seeprom_descriptor *sd,
608*4882a593Smuzhiyun 				  u_int adapter_control,
609*4882a593Smuzhiyun 	 			  u_int *sxfrctl1);
610*4882a593Smuzhiyun 
611*4882a593Smuzhiyun static void ahc_new_term_detect(struct ahc_softc *ahc,
612*4882a593Smuzhiyun 				int *enableSEC_low,
613*4882a593Smuzhiyun 				int *enableSEC_high,
614*4882a593Smuzhiyun 				int *enablePRI_low,
615*4882a593Smuzhiyun 				int *enablePRI_high,
616*4882a593Smuzhiyun 				int *eeprom_present);
617*4882a593Smuzhiyun static void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
618*4882a593Smuzhiyun 				 int *internal68_present,
619*4882a593Smuzhiyun 				 int *externalcable_present,
620*4882a593Smuzhiyun 				 int *eeprom_present);
621*4882a593Smuzhiyun static void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
622*4882a593Smuzhiyun 				 int *externalcable_present,
623*4882a593Smuzhiyun 				 int *eeprom_present);
624*4882a593Smuzhiyun static void    write_brdctl(struct ahc_softc *ahc, uint8_t value);
625*4882a593Smuzhiyun static uint8_t read_brdctl(struct ahc_softc *ahc);
626*4882a593Smuzhiyun static void ahc_pci_intr(struct ahc_softc *ahc);
627*4882a593Smuzhiyun static int  ahc_pci_chip_init(struct ahc_softc *ahc);
628*4882a593Smuzhiyun 
629*4882a593Smuzhiyun static int
ahc_9005_subdevinfo_valid(uint16_t device,uint16_t vendor,uint16_t subdevice,uint16_t subvendor)630*4882a593Smuzhiyun ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
631*4882a593Smuzhiyun 			  uint16_t subdevice, uint16_t subvendor)
632*4882a593Smuzhiyun {
633*4882a593Smuzhiyun 	int result;
634*4882a593Smuzhiyun 
635*4882a593Smuzhiyun 	/* Default to invalid. */
636*4882a593Smuzhiyun 	result = 0;
637*4882a593Smuzhiyun 	if (vendor == 0x9005
638*4882a593Smuzhiyun 	 && subvendor == 0x9005
639*4882a593Smuzhiyun          && subdevice != device
640*4882a593Smuzhiyun          && SUBID_9005_TYPE_KNOWN(subdevice) != 0) {
641*4882a593Smuzhiyun 
642*4882a593Smuzhiyun 		switch (SUBID_9005_TYPE(subdevice)) {
643*4882a593Smuzhiyun 		case SUBID_9005_TYPE_MB:
644*4882a593Smuzhiyun 			break;
645*4882a593Smuzhiyun 		case SUBID_9005_TYPE_CARD:
646*4882a593Smuzhiyun 		case SUBID_9005_TYPE_LCCARD:
647*4882a593Smuzhiyun 			/*
648*4882a593Smuzhiyun 			 * Currently only trust Adaptec cards to
649*4882a593Smuzhiyun 			 * get the sub device info correct.
650*4882a593Smuzhiyun 			 */
651*4882a593Smuzhiyun 			if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA)
652*4882a593Smuzhiyun 				result = 1;
653*4882a593Smuzhiyun 			break;
654*4882a593Smuzhiyun 		case SUBID_9005_TYPE_RAID:
655*4882a593Smuzhiyun 			break;
656*4882a593Smuzhiyun 		default:
657*4882a593Smuzhiyun 			break;
658*4882a593Smuzhiyun 		}
659*4882a593Smuzhiyun 	}
660*4882a593Smuzhiyun 	return (result);
661*4882a593Smuzhiyun }
662*4882a593Smuzhiyun 
663*4882a593Smuzhiyun const struct ahc_pci_identity *
ahc_find_pci_device(ahc_dev_softc_t pci)664*4882a593Smuzhiyun ahc_find_pci_device(ahc_dev_softc_t pci)
665*4882a593Smuzhiyun {
666*4882a593Smuzhiyun 	uint64_t  full_id;
667*4882a593Smuzhiyun 	uint16_t  device;
668*4882a593Smuzhiyun 	uint16_t  vendor;
669*4882a593Smuzhiyun 	uint16_t  subdevice;
670*4882a593Smuzhiyun 	uint16_t  subvendor;
671*4882a593Smuzhiyun 	const struct ahc_pci_identity *entry;
672*4882a593Smuzhiyun 	u_int	  i;
673*4882a593Smuzhiyun 
674*4882a593Smuzhiyun 	vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
675*4882a593Smuzhiyun 	device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
676*4882a593Smuzhiyun 	subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
677*4882a593Smuzhiyun 	subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
678*4882a593Smuzhiyun 	full_id = ahc_compose_id(device, vendor, subdevice, subvendor);
679*4882a593Smuzhiyun 
680*4882a593Smuzhiyun 	/*
681*4882a593Smuzhiyun 	 * If the second function is not hooked up, ignore it.
682*4882a593Smuzhiyun 	 * Unfortunately, not all MB vendors implement the
683*4882a593Smuzhiyun 	 * subdevice ID as per the Adaptec spec, so do our best
684*4882a593Smuzhiyun 	 * to sanity check it prior to accepting the subdevice
685*4882a593Smuzhiyun 	 * ID as valid.
686*4882a593Smuzhiyun 	 */
687*4882a593Smuzhiyun 	if (ahc_get_pci_function(pci) > 0
688*4882a593Smuzhiyun 	 && ahc_9005_subdevinfo_valid(device, vendor, subdevice, subvendor)
689*4882a593Smuzhiyun 	 && SUBID_9005_MFUNCENB(subdevice) == 0)
690*4882a593Smuzhiyun 		return (NULL);
691*4882a593Smuzhiyun 
692*4882a593Smuzhiyun 	for (i = 0; i < ahc_num_pci_devs; i++) {
693*4882a593Smuzhiyun 		entry = &ahc_pci_ident_table[i];
694*4882a593Smuzhiyun 		if (entry->full_id == (full_id & entry->id_mask)) {
695*4882a593Smuzhiyun 			/* Honor exclusion entries. */
696*4882a593Smuzhiyun 			if (entry->name == NULL)
697*4882a593Smuzhiyun 				return (NULL);
698*4882a593Smuzhiyun 			return (entry);
699*4882a593Smuzhiyun 		}
700*4882a593Smuzhiyun 	}
701*4882a593Smuzhiyun 	return (NULL);
702*4882a593Smuzhiyun }
703*4882a593Smuzhiyun 
704*4882a593Smuzhiyun int
ahc_pci_config(struct ahc_softc * ahc,const struct ahc_pci_identity * entry)705*4882a593Smuzhiyun ahc_pci_config(struct ahc_softc *ahc, const struct ahc_pci_identity *entry)
706*4882a593Smuzhiyun {
707*4882a593Smuzhiyun 	u_int	 command;
708*4882a593Smuzhiyun 	u_int	 our_id;
709*4882a593Smuzhiyun 	u_int	 sxfrctl1;
710*4882a593Smuzhiyun 	u_int	 scsiseq;
711*4882a593Smuzhiyun 	u_int	 dscommand0;
712*4882a593Smuzhiyun 	uint32_t devconfig;
713*4882a593Smuzhiyun 	int	 error;
714*4882a593Smuzhiyun 	uint8_t	 sblkctl;
715*4882a593Smuzhiyun 
716*4882a593Smuzhiyun 	our_id = 0;
717*4882a593Smuzhiyun 	error = entry->setup(ahc);
718*4882a593Smuzhiyun 	if (error != 0)
719*4882a593Smuzhiyun 		return (error);
720*4882a593Smuzhiyun 	ahc->chip |= AHC_PCI;
721*4882a593Smuzhiyun 	ahc->description = entry->name;
722*4882a593Smuzhiyun 
723*4882a593Smuzhiyun 	pci_set_power_state(ahc->dev_softc, AHC_POWER_STATE_D0);
724*4882a593Smuzhiyun 
725*4882a593Smuzhiyun 	error = ahc_pci_map_registers(ahc);
726*4882a593Smuzhiyun 	if (error != 0)
727*4882a593Smuzhiyun 		return (error);
728*4882a593Smuzhiyun 
729*4882a593Smuzhiyun 	/*
730*4882a593Smuzhiyun 	 * Before we continue probing the card, ensure that
731*4882a593Smuzhiyun 	 * its interrupts are *disabled*.  We don't want
732*4882a593Smuzhiyun 	 * a misstep to hang the machine in an interrupt
733*4882a593Smuzhiyun 	 * storm.
734*4882a593Smuzhiyun 	 */
735*4882a593Smuzhiyun 	ahc_intr_enable(ahc, FALSE);
736*4882a593Smuzhiyun 
737*4882a593Smuzhiyun 	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
738*4882a593Smuzhiyun 
739*4882a593Smuzhiyun 	/*
740*4882a593Smuzhiyun 	 * If we need to support high memory, enable dual
741*4882a593Smuzhiyun 	 * address cycles.  This bit must be set to enable
742*4882a593Smuzhiyun 	 * high address bit generation even if we are on a
743*4882a593Smuzhiyun 	 * 64bit bus (PCI64BIT set in devconfig).
744*4882a593Smuzhiyun 	 */
745*4882a593Smuzhiyun 	if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
746*4882a593Smuzhiyun 
747*4882a593Smuzhiyun 		if (bootverbose)
748*4882a593Smuzhiyun 			printk("%s: Enabling 39Bit Addressing\n",
749*4882a593Smuzhiyun 			       ahc_name(ahc));
750*4882a593Smuzhiyun 		devconfig |= DACEN;
751*4882a593Smuzhiyun 	}
752*4882a593Smuzhiyun 
753*4882a593Smuzhiyun 	/* Ensure that pci error generation, a test feature, is disabled. */
754*4882a593Smuzhiyun 	devconfig |= PCIERRGENDIS;
755*4882a593Smuzhiyun 
756*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
757*4882a593Smuzhiyun 
758*4882a593Smuzhiyun 	/* Ensure busmastering is enabled */
759*4882a593Smuzhiyun 	command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
760*4882a593Smuzhiyun 	command |= PCIM_CMD_BUSMASTEREN;
761*4882a593Smuzhiyun 
762*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2);
763*4882a593Smuzhiyun 
764*4882a593Smuzhiyun 	/* On all PCI adapters, we allow SCB paging */
765*4882a593Smuzhiyun 	ahc->flags |= AHC_PAGESCBS;
766*4882a593Smuzhiyun 
767*4882a593Smuzhiyun 	error = ahc_softc_init(ahc);
768*4882a593Smuzhiyun 	if (error != 0)
769*4882a593Smuzhiyun 		return (error);
770*4882a593Smuzhiyun 
771*4882a593Smuzhiyun 	/*
772*4882a593Smuzhiyun 	 * Disable PCI parity error checking.  Users typically
773*4882a593Smuzhiyun 	 * do this to work around broken PCI chipsets that get
774*4882a593Smuzhiyun 	 * the parity timing wrong and thus generate lots of spurious
775*4882a593Smuzhiyun 	 * errors.  The chip only allows us to disable *all* parity
776*4882a593Smuzhiyun 	 * error reporting when doing this, so CIO bus, scb ram, and
777*4882a593Smuzhiyun 	 * scratch ram parity errors will be ignored too.
778*4882a593Smuzhiyun 	 */
779*4882a593Smuzhiyun 	if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0)
780*4882a593Smuzhiyun 		ahc->seqctl |= FAILDIS;
781*4882a593Smuzhiyun 
782*4882a593Smuzhiyun 	ahc->bus_intr = ahc_pci_intr;
783*4882a593Smuzhiyun 	ahc->bus_chip_init = ahc_pci_chip_init;
784*4882a593Smuzhiyun 
785*4882a593Smuzhiyun 	/* Remember how the card was setup in case there is no SEEPROM */
786*4882a593Smuzhiyun 	if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
787*4882a593Smuzhiyun 		ahc_pause(ahc);
788*4882a593Smuzhiyun 		if ((ahc->features & AHC_ULTRA2) != 0)
789*4882a593Smuzhiyun 			our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID;
790*4882a593Smuzhiyun 		else
791*4882a593Smuzhiyun 			our_id = ahc_inb(ahc, SCSIID) & OID;
792*4882a593Smuzhiyun 		sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN;
793*4882a593Smuzhiyun 		scsiseq = ahc_inb(ahc, SCSISEQ);
794*4882a593Smuzhiyun 	} else {
795*4882a593Smuzhiyun 		sxfrctl1 = STPWEN;
796*4882a593Smuzhiyun 		our_id = 7;
797*4882a593Smuzhiyun 		scsiseq = 0;
798*4882a593Smuzhiyun 	}
799*4882a593Smuzhiyun 
800*4882a593Smuzhiyun 	error = ahc_reset(ahc, /*reinit*/FALSE);
801*4882a593Smuzhiyun 	if (error != 0)
802*4882a593Smuzhiyun 		return (ENXIO);
803*4882a593Smuzhiyun 
804*4882a593Smuzhiyun 	if ((ahc->features & AHC_DT) != 0) {
805*4882a593Smuzhiyun 		u_int sfunct;
806*4882a593Smuzhiyun 
807*4882a593Smuzhiyun 		/* Perform ALT-Mode Setup */
808*4882a593Smuzhiyun 		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
809*4882a593Smuzhiyun 		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
810*4882a593Smuzhiyun 		ahc_outb(ahc, OPTIONMODE,
811*4882a593Smuzhiyun 			 OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS);
812*4882a593Smuzhiyun 		ahc_outb(ahc, SFUNCT, sfunct);
813*4882a593Smuzhiyun 
814*4882a593Smuzhiyun 		/* Normal mode setup */
815*4882a593Smuzhiyun 		ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN
816*4882a593Smuzhiyun 					  |TARGCRCENDEN);
817*4882a593Smuzhiyun 	}
818*4882a593Smuzhiyun 
819*4882a593Smuzhiyun 	dscommand0 = ahc_inb(ahc, DSCOMMAND0);
820*4882a593Smuzhiyun 	dscommand0 |= MPARCKEN|CACHETHEN;
821*4882a593Smuzhiyun 	if ((ahc->features & AHC_ULTRA2) != 0) {
822*4882a593Smuzhiyun 
823*4882a593Smuzhiyun 		/*
824*4882a593Smuzhiyun 		 * DPARCKEN doesn't work correctly on
825*4882a593Smuzhiyun 		 * some MBs so don't use it.
826*4882a593Smuzhiyun 		 */
827*4882a593Smuzhiyun 		dscommand0 &= ~DPARCKEN;
828*4882a593Smuzhiyun 	}
829*4882a593Smuzhiyun 
830*4882a593Smuzhiyun 	/*
831*4882a593Smuzhiyun 	 * Handle chips that must have cache line
832*4882a593Smuzhiyun 	 * streaming (dis/en)abled.
833*4882a593Smuzhiyun 	 */
834*4882a593Smuzhiyun 	if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0)
835*4882a593Smuzhiyun 		dscommand0 |= CACHETHEN;
836*4882a593Smuzhiyun 
837*4882a593Smuzhiyun 	if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0)
838*4882a593Smuzhiyun 		dscommand0 &= ~CACHETHEN;
839*4882a593Smuzhiyun 
840*4882a593Smuzhiyun 	ahc_outb(ahc, DSCOMMAND0, dscommand0);
841*4882a593Smuzhiyun 
842*4882a593Smuzhiyun 	ahc->pci_cachesize =
843*4882a593Smuzhiyun 	    ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME,
844*4882a593Smuzhiyun 				/*bytes*/1) & CACHESIZE;
845*4882a593Smuzhiyun 	ahc->pci_cachesize *= 4;
846*4882a593Smuzhiyun 
847*4882a593Smuzhiyun 	if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0
848*4882a593Smuzhiyun 	 && ahc->pci_cachesize == 4) {
849*4882a593Smuzhiyun 
850*4882a593Smuzhiyun 		ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
851*4882a593Smuzhiyun 				     0, /*bytes*/1);
852*4882a593Smuzhiyun 		ahc->pci_cachesize = 0;
853*4882a593Smuzhiyun 	}
854*4882a593Smuzhiyun 
855*4882a593Smuzhiyun 	/*
856*4882a593Smuzhiyun 	 * We cannot perform ULTRA speeds without the presence
857*4882a593Smuzhiyun 	 * of the external precision resistor.
858*4882a593Smuzhiyun 	 */
859*4882a593Smuzhiyun 	if ((ahc->features & AHC_ULTRA) != 0) {
860*4882a593Smuzhiyun 		uint32_t devconfig;
861*4882a593Smuzhiyun 
862*4882a593Smuzhiyun 		devconfig = ahc_pci_read_config(ahc->dev_softc,
863*4882a593Smuzhiyun 						DEVCONFIG, /*bytes*/4);
864*4882a593Smuzhiyun 		if ((devconfig & REXTVALID) == 0)
865*4882a593Smuzhiyun 			ahc->features &= ~AHC_ULTRA;
866*4882a593Smuzhiyun 	}
867*4882a593Smuzhiyun 
868*4882a593Smuzhiyun 	/* See if we have a SEEPROM and perform auto-term */
869*4882a593Smuzhiyun 	check_extport(ahc, &sxfrctl1);
870*4882a593Smuzhiyun 
871*4882a593Smuzhiyun 	/*
872*4882a593Smuzhiyun 	 * Take the LED out of diagnostic mode
873*4882a593Smuzhiyun 	 */
874*4882a593Smuzhiyun 	sblkctl = ahc_inb(ahc, SBLKCTL);
875*4882a593Smuzhiyun 	ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));
876*4882a593Smuzhiyun 
877*4882a593Smuzhiyun 	if ((ahc->features & AHC_ULTRA2) != 0) {
878*4882a593Smuzhiyun 		ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX);
879*4882a593Smuzhiyun 	} else {
880*4882a593Smuzhiyun 		ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100);
881*4882a593Smuzhiyun 	}
882*4882a593Smuzhiyun 
883*4882a593Smuzhiyun 	if (ahc->flags & AHC_USEDEFAULTS) {
884*4882a593Smuzhiyun 		/*
885*4882a593Smuzhiyun 		 * PCI Adapter default setup
886*4882a593Smuzhiyun 		 * Should only be used if the adapter does not have
887*4882a593Smuzhiyun 		 * a SEEPROM.
888*4882a593Smuzhiyun 		 */
889*4882a593Smuzhiyun 		/* See if someone else set us up already */
890*4882a593Smuzhiyun 		if ((ahc->flags & AHC_NO_BIOS_INIT) == 0
891*4882a593Smuzhiyun 		 && scsiseq != 0) {
892*4882a593Smuzhiyun 			printk("%s: Using left over BIOS settings\n",
893*4882a593Smuzhiyun 				ahc_name(ahc));
894*4882a593Smuzhiyun 			ahc->flags &= ~AHC_USEDEFAULTS;
895*4882a593Smuzhiyun 			ahc->flags |= AHC_BIOS_ENABLED;
896*4882a593Smuzhiyun 		} else {
897*4882a593Smuzhiyun 			/*
898*4882a593Smuzhiyun 			 * Assume only one connector and always turn
899*4882a593Smuzhiyun 			 * on termination.
900*4882a593Smuzhiyun 			 */
901*4882a593Smuzhiyun  			our_id = 0x07;
902*4882a593Smuzhiyun 			sxfrctl1 = STPWEN;
903*4882a593Smuzhiyun 		}
904*4882a593Smuzhiyun 		ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI);
905*4882a593Smuzhiyun 
906*4882a593Smuzhiyun 		ahc->our_id = our_id;
907*4882a593Smuzhiyun 	}
908*4882a593Smuzhiyun 
909*4882a593Smuzhiyun 	/*
910*4882a593Smuzhiyun 	 * Take a look to see if we have external SRAM.
911*4882a593Smuzhiyun 	 * We currently do not attempt to use SRAM that is
912*4882a593Smuzhiyun 	 * shared among multiple controllers.
913*4882a593Smuzhiyun 	 */
914*4882a593Smuzhiyun 	ahc_probe_ext_scbram(ahc);
915*4882a593Smuzhiyun 
916*4882a593Smuzhiyun 	/*
917*4882a593Smuzhiyun 	 * Record our termination setting for the
918*4882a593Smuzhiyun 	 * generic initialization routine.
919*4882a593Smuzhiyun 	 */
920*4882a593Smuzhiyun 	if ((sxfrctl1 & STPWEN) != 0)
921*4882a593Smuzhiyun 		ahc->flags |= AHC_TERM_ENB_A;
922*4882a593Smuzhiyun 
923*4882a593Smuzhiyun 	/*
924*4882a593Smuzhiyun 	 * Save chip register configuration data for chip resets
925*4882a593Smuzhiyun 	 * that occur during runtime and resume events.
926*4882a593Smuzhiyun 	 */
927*4882a593Smuzhiyun 	ahc->bus_softc.pci_softc.devconfig =
928*4882a593Smuzhiyun 	    ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
929*4882a593Smuzhiyun 	ahc->bus_softc.pci_softc.command =
930*4882a593Smuzhiyun 	    ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
931*4882a593Smuzhiyun 	ahc->bus_softc.pci_softc.csize_lattime =
932*4882a593Smuzhiyun 	    ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1);
933*4882a593Smuzhiyun 	ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0);
934*4882a593Smuzhiyun 	ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS);
935*4882a593Smuzhiyun 	if ((ahc->features & AHC_DT) != 0) {
936*4882a593Smuzhiyun 		u_int sfunct;
937*4882a593Smuzhiyun 
938*4882a593Smuzhiyun 		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
939*4882a593Smuzhiyun 		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
940*4882a593Smuzhiyun 		ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE);
941*4882a593Smuzhiyun 		ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT);
942*4882a593Smuzhiyun 		ahc_outb(ahc, SFUNCT, sfunct);
943*4882a593Smuzhiyun 		ahc->bus_softc.pci_softc.crccontrol1 =
944*4882a593Smuzhiyun 		    ahc_inb(ahc, CRCCONTROL1);
945*4882a593Smuzhiyun 	}
946*4882a593Smuzhiyun 	if ((ahc->features & AHC_MULTI_FUNC) != 0)
947*4882a593Smuzhiyun 		ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR);
948*4882a593Smuzhiyun 
949*4882a593Smuzhiyun 	if ((ahc->features & AHC_ULTRA2) != 0)
950*4882a593Smuzhiyun 		ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH);
951*4882a593Smuzhiyun 
952*4882a593Smuzhiyun 	/* Core initialization */
953*4882a593Smuzhiyun 	error = ahc_init(ahc);
954*4882a593Smuzhiyun 	if (error != 0)
955*4882a593Smuzhiyun 		return (error);
956*4882a593Smuzhiyun 	ahc->init_level++;
957*4882a593Smuzhiyun 
958*4882a593Smuzhiyun 	/*
959*4882a593Smuzhiyun 	 * Allow interrupts now that we are completely setup.
960*4882a593Smuzhiyun 	 */
961*4882a593Smuzhiyun 	return ahc_pci_map_int(ahc);
962*4882a593Smuzhiyun }
963*4882a593Smuzhiyun 
964*4882a593Smuzhiyun /*
965*4882a593Smuzhiyun  * Test for the presence of external sram in an
966*4882a593Smuzhiyun  * "unshared" configuration.
967*4882a593Smuzhiyun  */
968*4882a593Smuzhiyun static int
ahc_ext_scbram_present(struct ahc_softc * ahc)969*4882a593Smuzhiyun ahc_ext_scbram_present(struct ahc_softc *ahc)
970*4882a593Smuzhiyun {
971*4882a593Smuzhiyun 	u_int chip;
972*4882a593Smuzhiyun 	int ramps;
973*4882a593Smuzhiyun 	int single_user;
974*4882a593Smuzhiyun 	uint32_t devconfig;
975*4882a593Smuzhiyun 
976*4882a593Smuzhiyun 	chip = ahc->chip & AHC_CHIPID_MASK;
977*4882a593Smuzhiyun 	devconfig = ahc_pci_read_config(ahc->dev_softc,
978*4882a593Smuzhiyun 					DEVCONFIG, /*bytes*/4);
979*4882a593Smuzhiyun 	single_user = (devconfig & MPORTMODE) != 0;
980*4882a593Smuzhiyun 
981*4882a593Smuzhiyun 	if ((ahc->features & AHC_ULTRA2) != 0)
982*4882a593Smuzhiyun 		ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0;
983*4882a593Smuzhiyun 	else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C)
984*4882a593Smuzhiyun 		/*
985*4882a593Smuzhiyun 		 * External SCBRAM arbitration is flakey
986*4882a593Smuzhiyun 		 * on these chips.  Unfortunately this means
987*4882a593Smuzhiyun 		 * we don't use the extra SCB ram space on the
988*4882a593Smuzhiyun 		 * 3940AUW.
989*4882a593Smuzhiyun 		 */
990*4882a593Smuzhiyun 		ramps = 0;
991*4882a593Smuzhiyun 	else if (chip >= AHC_AIC7870)
992*4882a593Smuzhiyun 		ramps = (devconfig & RAMPSM) != 0;
993*4882a593Smuzhiyun 	else
994*4882a593Smuzhiyun 		ramps = 0;
995*4882a593Smuzhiyun 
996*4882a593Smuzhiyun 	if (ramps && single_user)
997*4882a593Smuzhiyun 		return (1);
998*4882a593Smuzhiyun 	return (0);
999*4882a593Smuzhiyun }
1000*4882a593Smuzhiyun 
1001*4882a593Smuzhiyun /*
1002*4882a593Smuzhiyun  * Enable external scbram.
1003*4882a593Smuzhiyun  */
1004*4882a593Smuzhiyun static void
ahc_scbram_config(struct ahc_softc * ahc,int enable,int pcheck,int fast,int large)1005*4882a593Smuzhiyun ahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck,
1006*4882a593Smuzhiyun 		  int fast, int large)
1007*4882a593Smuzhiyun {
1008*4882a593Smuzhiyun 	uint32_t devconfig;
1009*4882a593Smuzhiyun 
1010*4882a593Smuzhiyun 	if (ahc->features & AHC_MULTI_FUNC) {
1011*4882a593Smuzhiyun 		/*
1012*4882a593Smuzhiyun 		 * Set the SCB Base addr (highest address bit)
1013*4882a593Smuzhiyun 		 * depending on which channel we are.
1014*4882a593Smuzhiyun 		 */
1015*4882a593Smuzhiyun 		ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc));
1016*4882a593Smuzhiyun 	}
1017*4882a593Smuzhiyun 
1018*4882a593Smuzhiyun 	ahc->flags &= ~AHC_LSCBS_ENABLED;
1019*4882a593Smuzhiyun 	if (large)
1020*4882a593Smuzhiyun 		ahc->flags |= AHC_LSCBS_ENABLED;
1021*4882a593Smuzhiyun 	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
1022*4882a593Smuzhiyun 	if ((ahc->features & AHC_ULTRA2) != 0) {
1023*4882a593Smuzhiyun 		u_int dscommand0;
1024*4882a593Smuzhiyun 
1025*4882a593Smuzhiyun 		dscommand0 = ahc_inb(ahc, DSCOMMAND0);
1026*4882a593Smuzhiyun 		if (enable)
1027*4882a593Smuzhiyun 			dscommand0 &= ~INTSCBRAMSEL;
1028*4882a593Smuzhiyun 		else
1029*4882a593Smuzhiyun 			dscommand0 |= INTSCBRAMSEL;
1030*4882a593Smuzhiyun 		if (large)
1031*4882a593Smuzhiyun 			dscommand0 &= ~USCBSIZE32;
1032*4882a593Smuzhiyun 		else
1033*4882a593Smuzhiyun 			dscommand0 |= USCBSIZE32;
1034*4882a593Smuzhiyun 		ahc_outb(ahc, DSCOMMAND0, dscommand0);
1035*4882a593Smuzhiyun 	} else {
1036*4882a593Smuzhiyun 		if (fast)
1037*4882a593Smuzhiyun 			devconfig &= ~EXTSCBTIME;
1038*4882a593Smuzhiyun 		else
1039*4882a593Smuzhiyun 			devconfig |= EXTSCBTIME;
1040*4882a593Smuzhiyun 		if (enable)
1041*4882a593Smuzhiyun 			devconfig &= ~SCBRAMSEL;
1042*4882a593Smuzhiyun 		else
1043*4882a593Smuzhiyun 			devconfig |= SCBRAMSEL;
1044*4882a593Smuzhiyun 		if (large)
1045*4882a593Smuzhiyun 			devconfig &= ~SCBSIZE32;
1046*4882a593Smuzhiyun 		else
1047*4882a593Smuzhiyun 			devconfig |= SCBSIZE32;
1048*4882a593Smuzhiyun 	}
1049*4882a593Smuzhiyun 	if (pcheck)
1050*4882a593Smuzhiyun 		devconfig |= EXTSCBPEN;
1051*4882a593Smuzhiyun 	else
1052*4882a593Smuzhiyun 		devconfig &= ~EXTSCBPEN;
1053*4882a593Smuzhiyun 
1054*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
1055*4882a593Smuzhiyun }
1056*4882a593Smuzhiyun 
1057*4882a593Smuzhiyun /*
1058*4882a593Smuzhiyun  * Take a look to see if we have external SRAM.
1059*4882a593Smuzhiyun  * We currently do not attempt to use SRAM that is
1060*4882a593Smuzhiyun  * shared among multiple controllers.
1061*4882a593Smuzhiyun  */
1062*4882a593Smuzhiyun static void
ahc_probe_ext_scbram(struct ahc_softc * ahc)1063*4882a593Smuzhiyun ahc_probe_ext_scbram(struct ahc_softc *ahc)
1064*4882a593Smuzhiyun {
1065*4882a593Smuzhiyun 	int num_scbs;
1066*4882a593Smuzhiyun 	int test_num_scbs;
1067*4882a593Smuzhiyun 	int enable;
1068*4882a593Smuzhiyun 	int pcheck;
1069*4882a593Smuzhiyun 	int fast;
1070*4882a593Smuzhiyun 	int large;
1071*4882a593Smuzhiyun 
1072*4882a593Smuzhiyun 	enable = FALSE;
1073*4882a593Smuzhiyun 	pcheck = FALSE;
1074*4882a593Smuzhiyun 	fast = FALSE;
1075*4882a593Smuzhiyun 	large = FALSE;
1076*4882a593Smuzhiyun 	num_scbs = 0;
1077*4882a593Smuzhiyun 
1078*4882a593Smuzhiyun 	if (ahc_ext_scbram_present(ahc) == 0)
1079*4882a593Smuzhiyun 		goto done;
1080*4882a593Smuzhiyun 
1081*4882a593Smuzhiyun 	/*
1082*4882a593Smuzhiyun 	 * Probe for the best parameters to use.
1083*4882a593Smuzhiyun 	 */
1084*4882a593Smuzhiyun 	ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large);
1085*4882a593Smuzhiyun 	num_scbs = ahc_probe_scbs(ahc);
1086*4882a593Smuzhiyun 	if (num_scbs == 0) {
1087*4882a593Smuzhiyun 		/* The SRAM wasn't really present. */
1088*4882a593Smuzhiyun 		goto done;
1089*4882a593Smuzhiyun 	}
1090*4882a593Smuzhiyun 	enable = TRUE;
1091*4882a593Smuzhiyun 
1092*4882a593Smuzhiyun 	/*
1093*4882a593Smuzhiyun 	 * Clear any outstanding parity error
1094*4882a593Smuzhiyun 	 * and ensure that parity error reporting
1095*4882a593Smuzhiyun 	 * is enabled.
1096*4882a593Smuzhiyun 	 */
1097*4882a593Smuzhiyun 	ahc_outb(ahc, SEQCTL, 0);
1098*4882a593Smuzhiyun 	ahc_outb(ahc, CLRINT, CLRPARERR);
1099*4882a593Smuzhiyun 	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
1100*4882a593Smuzhiyun 
1101*4882a593Smuzhiyun 	/* Now see if we can do parity */
1102*4882a593Smuzhiyun 	ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large);
1103*4882a593Smuzhiyun 	num_scbs = ahc_probe_scbs(ahc);
1104*4882a593Smuzhiyun 	if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
1105*4882a593Smuzhiyun 	 || (ahc_inb(ahc, ERROR) & MPARERR) == 0)
1106*4882a593Smuzhiyun 		pcheck = TRUE;
1107*4882a593Smuzhiyun 
1108*4882a593Smuzhiyun 	/* Clear any resulting parity error */
1109*4882a593Smuzhiyun 	ahc_outb(ahc, CLRINT, CLRPARERR);
1110*4882a593Smuzhiyun 	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
1111*4882a593Smuzhiyun 
1112*4882a593Smuzhiyun 	/* Now see if we can do fast timing */
1113*4882a593Smuzhiyun 	ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large);
1114*4882a593Smuzhiyun 	test_num_scbs = ahc_probe_scbs(ahc);
1115*4882a593Smuzhiyun 	if (test_num_scbs == num_scbs
1116*4882a593Smuzhiyun 	 && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
1117*4882a593Smuzhiyun 	  || (ahc_inb(ahc, ERROR) & MPARERR) == 0))
1118*4882a593Smuzhiyun 		fast = TRUE;
1119*4882a593Smuzhiyun 
1120*4882a593Smuzhiyun 	/*
1121*4882a593Smuzhiyun 	 * See if we can use large SCBs and still maintain
1122*4882a593Smuzhiyun 	 * the same overall count of SCBs.
1123*4882a593Smuzhiyun 	 */
1124*4882a593Smuzhiyun 	if ((ahc->features & AHC_LARGE_SCBS) != 0) {
1125*4882a593Smuzhiyun 		ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE);
1126*4882a593Smuzhiyun 		test_num_scbs = ahc_probe_scbs(ahc);
1127*4882a593Smuzhiyun 		if (test_num_scbs >= num_scbs) {
1128*4882a593Smuzhiyun 			large = TRUE;
1129*4882a593Smuzhiyun 			num_scbs = test_num_scbs;
1130*4882a593Smuzhiyun 	 		if (num_scbs >= 64) {
1131*4882a593Smuzhiyun 				/*
1132*4882a593Smuzhiyun 				 * We have enough space to move the
1133*4882a593Smuzhiyun 				 * "busy targets table" into SCB space
1134*4882a593Smuzhiyun 				 * and make it qualify all the way to the
1135*4882a593Smuzhiyun 				 * lun level.
1136*4882a593Smuzhiyun 				 */
1137*4882a593Smuzhiyun 				ahc->flags |= AHC_SCB_BTT;
1138*4882a593Smuzhiyun 			}
1139*4882a593Smuzhiyun 		}
1140*4882a593Smuzhiyun 	}
1141*4882a593Smuzhiyun done:
1142*4882a593Smuzhiyun 	/*
1143*4882a593Smuzhiyun 	 * Disable parity error reporting until we
1144*4882a593Smuzhiyun 	 * can load instruction ram.
1145*4882a593Smuzhiyun 	 */
1146*4882a593Smuzhiyun 	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
1147*4882a593Smuzhiyun 	/* Clear any latched parity error */
1148*4882a593Smuzhiyun 	ahc_outb(ahc, CLRINT, CLRPARERR);
1149*4882a593Smuzhiyun 	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
1150*4882a593Smuzhiyun 	if (bootverbose && enable) {
1151*4882a593Smuzhiyun 		printk("%s: External SRAM, %s access%s, %dbytes/SCB\n",
1152*4882a593Smuzhiyun 		       ahc_name(ahc), fast ? "fast" : "slow",
1153*4882a593Smuzhiyun 		       pcheck ? ", parity checking enabled" : "",
1154*4882a593Smuzhiyun 		       large ? 64 : 32);
1155*4882a593Smuzhiyun 	}
1156*4882a593Smuzhiyun 	ahc_scbram_config(ahc, enable, pcheck, fast, large);
1157*4882a593Smuzhiyun }
1158*4882a593Smuzhiyun 
1159*4882a593Smuzhiyun /*
1160*4882a593Smuzhiyun  * Perform some simple tests that should catch situations where
1161*4882a593Smuzhiyun  * our registers are invalidly mapped.
1162*4882a593Smuzhiyun  */
1163*4882a593Smuzhiyun int
ahc_pci_test_register_access(struct ahc_softc * ahc)1164*4882a593Smuzhiyun ahc_pci_test_register_access(struct ahc_softc *ahc)
1165*4882a593Smuzhiyun {
1166*4882a593Smuzhiyun 	int	 error;
1167*4882a593Smuzhiyun 	u_int	 status1;
1168*4882a593Smuzhiyun 	uint32_t cmd;
1169*4882a593Smuzhiyun 	uint8_t	 hcntrl;
1170*4882a593Smuzhiyun 
1171*4882a593Smuzhiyun 	error = EIO;
1172*4882a593Smuzhiyun 
1173*4882a593Smuzhiyun 	/*
1174*4882a593Smuzhiyun 	 * Enable PCI error interrupt status, but suppress NMIs
1175*4882a593Smuzhiyun 	 * generated by SERR raised due to target aborts.
1176*4882a593Smuzhiyun 	 */
1177*4882a593Smuzhiyun 	cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
1178*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
1179*4882a593Smuzhiyun 			     cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
1180*4882a593Smuzhiyun 
1181*4882a593Smuzhiyun 	/*
1182*4882a593Smuzhiyun 	 * First a simple test to see if any
1183*4882a593Smuzhiyun 	 * registers can be read.  Reading
1184*4882a593Smuzhiyun 	 * HCNTRL has no side effects and has
1185*4882a593Smuzhiyun 	 * at least one bit that is guaranteed to
1186*4882a593Smuzhiyun 	 * be zero so it is a good register to
1187*4882a593Smuzhiyun 	 * use for this test.
1188*4882a593Smuzhiyun 	 */
1189*4882a593Smuzhiyun 	hcntrl = ahc_inb(ahc, HCNTRL);
1190*4882a593Smuzhiyun 
1191*4882a593Smuzhiyun 	if (hcntrl == 0xFF)
1192*4882a593Smuzhiyun 		goto fail;
1193*4882a593Smuzhiyun 
1194*4882a593Smuzhiyun 	if ((hcntrl & CHIPRST) != 0) {
1195*4882a593Smuzhiyun 		/*
1196*4882a593Smuzhiyun 		 * The chip has not been initialized since
1197*4882a593Smuzhiyun 		 * PCI/EISA/VLB bus reset.  Don't trust
1198*4882a593Smuzhiyun 		 * "left over BIOS data".
1199*4882a593Smuzhiyun 		 */
1200*4882a593Smuzhiyun 		ahc->flags |= AHC_NO_BIOS_INIT;
1201*4882a593Smuzhiyun 	}
1202*4882a593Smuzhiyun 
1203*4882a593Smuzhiyun 	/*
1204*4882a593Smuzhiyun 	 * Next create a situation where write combining
1205*4882a593Smuzhiyun 	 * or read prefetching could be initiated by the
1206*4882a593Smuzhiyun 	 * CPU or host bridge.  Our device does not support
1207*4882a593Smuzhiyun 	 * either, so look for data corruption and/or flagged
1208*4882a593Smuzhiyun 	 * PCI errors.  First pause without causing another
1209*4882a593Smuzhiyun 	 * chip reset.
1210*4882a593Smuzhiyun 	 */
1211*4882a593Smuzhiyun 	hcntrl &= ~CHIPRST;
1212*4882a593Smuzhiyun 	ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
1213*4882a593Smuzhiyun 	while (ahc_is_paused(ahc) == 0)
1214*4882a593Smuzhiyun 		;
1215*4882a593Smuzhiyun 
1216*4882a593Smuzhiyun 	/* Clear any PCI errors that occurred before our driver attached. */
1217*4882a593Smuzhiyun 	status1 = ahc_pci_read_config(ahc->dev_softc,
1218*4882a593Smuzhiyun 				      PCIR_STATUS + 1, /*bytes*/1);
1219*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
1220*4882a593Smuzhiyun 			     status1, /*bytes*/1);
1221*4882a593Smuzhiyun 	ahc_outb(ahc, CLRINT, CLRPARERR);
1222*4882a593Smuzhiyun 
1223*4882a593Smuzhiyun 	ahc_outb(ahc, SEQCTL, PERRORDIS);
1224*4882a593Smuzhiyun 	ahc_outb(ahc, SCBPTR, 0);
1225*4882a593Smuzhiyun 	ahc_outl(ahc, SCB_BASE, 0x5aa555aa);
1226*4882a593Smuzhiyun 	if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa)
1227*4882a593Smuzhiyun 		goto fail;
1228*4882a593Smuzhiyun 
1229*4882a593Smuzhiyun 	status1 = ahc_pci_read_config(ahc->dev_softc,
1230*4882a593Smuzhiyun 				      PCIR_STATUS + 1, /*bytes*/1);
1231*4882a593Smuzhiyun 	if ((status1 & STA) != 0)
1232*4882a593Smuzhiyun 		goto fail;
1233*4882a593Smuzhiyun 
1234*4882a593Smuzhiyun 	error = 0;
1235*4882a593Smuzhiyun 
1236*4882a593Smuzhiyun fail:
1237*4882a593Smuzhiyun 	/* Silently clear any latched errors. */
1238*4882a593Smuzhiyun 	status1 = ahc_pci_read_config(ahc->dev_softc,
1239*4882a593Smuzhiyun 				      PCIR_STATUS + 1, /*bytes*/1);
1240*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
1241*4882a593Smuzhiyun 			     status1, /*bytes*/1);
1242*4882a593Smuzhiyun 	ahc_outb(ahc, CLRINT, CLRPARERR);
1243*4882a593Smuzhiyun 	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
1244*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
1245*4882a593Smuzhiyun 	return (error);
1246*4882a593Smuzhiyun }
1247*4882a593Smuzhiyun 
1248*4882a593Smuzhiyun /*
1249*4882a593Smuzhiyun  * Check the external port logic for a serial eeprom
1250*4882a593Smuzhiyun  * and termination/cable detection contrls.
1251*4882a593Smuzhiyun  */
1252*4882a593Smuzhiyun static void
check_extport(struct ahc_softc * ahc,u_int * sxfrctl1)1253*4882a593Smuzhiyun check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
1254*4882a593Smuzhiyun {
1255*4882a593Smuzhiyun 	struct	seeprom_descriptor sd;
1256*4882a593Smuzhiyun 	struct	seeprom_config *sc;
1257*4882a593Smuzhiyun 	int	have_seeprom;
1258*4882a593Smuzhiyun 	int	have_autoterm;
1259*4882a593Smuzhiyun 
1260*4882a593Smuzhiyun 	sd.sd_ahc = ahc;
1261*4882a593Smuzhiyun 	sd.sd_control_offset = SEECTL;
1262*4882a593Smuzhiyun 	sd.sd_status_offset = SEECTL;
1263*4882a593Smuzhiyun 	sd.sd_dataout_offset = SEECTL;
1264*4882a593Smuzhiyun 	sc = ahc->seep_config;
1265*4882a593Smuzhiyun 
1266*4882a593Smuzhiyun 	/*
1267*4882a593Smuzhiyun 	 * For some multi-channel devices, the c46 is simply too
1268*4882a593Smuzhiyun 	 * small to work.  For the other controller types, we can
1269*4882a593Smuzhiyun 	 * get our information from either SEEPROM type.  Set the
1270*4882a593Smuzhiyun 	 * type to start our probe with accordingly.
1271*4882a593Smuzhiyun 	 */
1272*4882a593Smuzhiyun 	if (ahc->flags & AHC_LARGE_SEEPROM)
1273*4882a593Smuzhiyun 		sd.sd_chip = C56_66;
1274*4882a593Smuzhiyun 	else
1275*4882a593Smuzhiyun 		sd.sd_chip = C46;
1276*4882a593Smuzhiyun 
1277*4882a593Smuzhiyun 	sd.sd_MS = SEEMS;
1278*4882a593Smuzhiyun 	sd.sd_RDY = SEERDY;
1279*4882a593Smuzhiyun 	sd.sd_CS = SEECS;
1280*4882a593Smuzhiyun 	sd.sd_CK = SEECK;
1281*4882a593Smuzhiyun 	sd.sd_DO = SEEDO;
1282*4882a593Smuzhiyun 	sd.sd_DI = SEEDI;
1283*4882a593Smuzhiyun 
1284*4882a593Smuzhiyun 	have_seeprom = ahc_acquire_seeprom(ahc, &sd);
1285*4882a593Smuzhiyun 	if (have_seeprom) {
1286*4882a593Smuzhiyun 
1287*4882a593Smuzhiyun 		if (bootverbose)
1288*4882a593Smuzhiyun 			printk("%s: Reading SEEPROM...", ahc_name(ahc));
1289*4882a593Smuzhiyun 
1290*4882a593Smuzhiyun 		for (;;) {
1291*4882a593Smuzhiyun 			u_int start_addr;
1292*4882a593Smuzhiyun 
1293*4882a593Smuzhiyun 			start_addr = 32 * (ahc->channel - 'A');
1294*4882a593Smuzhiyun 
1295*4882a593Smuzhiyun 			have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,
1296*4882a593Smuzhiyun 							start_addr,
1297*4882a593Smuzhiyun 							sizeof(*sc)/2);
1298*4882a593Smuzhiyun 
1299*4882a593Smuzhiyun 			if (have_seeprom)
1300*4882a593Smuzhiyun 				have_seeprom = ahc_verify_cksum(sc);
1301*4882a593Smuzhiyun 
1302*4882a593Smuzhiyun 			if (have_seeprom != 0 || sd.sd_chip == C56_66) {
1303*4882a593Smuzhiyun 				if (bootverbose) {
1304*4882a593Smuzhiyun 					if (have_seeprom == 0)
1305*4882a593Smuzhiyun 						printk ("checksum error\n");
1306*4882a593Smuzhiyun 					else
1307*4882a593Smuzhiyun 						printk ("done.\n");
1308*4882a593Smuzhiyun 				}
1309*4882a593Smuzhiyun 				break;
1310*4882a593Smuzhiyun 			}
1311*4882a593Smuzhiyun 			sd.sd_chip = C56_66;
1312*4882a593Smuzhiyun 		}
1313*4882a593Smuzhiyun 		ahc_release_seeprom(&sd);
1314*4882a593Smuzhiyun 
1315*4882a593Smuzhiyun 		/* Remember the SEEPROM type for later */
1316*4882a593Smuzhiyun 		if (sd.sd_chip == C56_66)
1317*4882a593Smuzhiyun 			ahc->flags |= AHC_LARGE_SEEPROM;
1318*4882a593Smuzhiyun 	}
1319*4882a593Smuzhiyun 
1320*4882a593Smuzhiyun 	if (!have_seeprom) {
1321*4882a593Smuzhiyun 		/*
1322*4882a593Smuzhiyun 		 * Pull scratch ram settings and treat them as
1323*4882a593Smuzhiyun 		 * if they are the contents of an seeprom if
1324*4882a593Smuzhiyun 		 * the 'ADPT' signature is found in SCB2.
1325*4882a593Smuzhiyun 		 * We manually compose the data as 16bit values
1326*4882a593Smuzhiyun 		 * to avoid endian issues.
1327*4882a593Smuzhiyun 		 */
1328*4882a593Smuzhiyun 		ahc_outb(ahc, SCBPTR, 2);
1329*4882a593Smuzhiyun 		if (ahc_inb(ahc, SCB_BASE) == 'A'
1330*4882a593Smuzhiyun 		 && ahc_inb(ahc, SCB_BASE + 1) == 'D'
1331*4882a593Smuzhiyun 		 && ahc_inb(ahc, SCB_BASE + 2) == 'P'
1332*4882a593Smuzhiyun 		 && ahc_inb(ahc, SCB_BASE + 3) == 'T') {
1333*4882a593Smuzhiyun 			uint16_t *sc_data;
1334*4882a593Smuzhiyun 			int	  i;
1335*4882a593Smuzhiyun 
1336*4882a593Smuzhiyun 			sc_data = (uint16_t *)sc;
1337*4882a593Smuzhiyun 			for (i = 0; i < 32; i++, sc_data++) {
1338*4882a593Smuzhiyun 				int	j;
1339*4882a593Smuzhiyun 
1340*4882a593Smuzhiyun 				j = i * 2;
1341*4882a593Smuzhiyun 				*sc_data = ahc_inb(ahc, SRAM_BASE + j)
1342*4882a593Smuzhiyun 					 | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
1343*4882a593Smuzhiyun 			}
1344*4882a593Smuzhiyun 			have_seeprom = ahc_verify_cksum(sc);
1345*4882a593Smuzhiyun 			if (have_seeprom)
1346*4882a593Smuzhiyun 				ahc->flags |= AHC_SCB_CONFIG_USED;
1347*4882a593Smuzhiyun 		}
1348*4882a593Smuzhiyun 		/*
1349*4882a593Smuzhiyun 		 * Clear any SCB parity errors in case this data and
1350*4882a593Smuzhiyun 		 * its associated parity was not initialized by the BIOS
1351*4882a593Smuzhiyun 		 */
1352*4882a593Smuzhiyun 		ahc_outb(ahc, CLRINT, CLRPARERR);
1353*4882a593Smuzhiyun 		ahc_outb(ahc, CLRINT, CLRBRKADRINT);
1354*4882a593Smuzhiyun 	}
1355*4882a593Smuzhiyun 
1356*4882a593Smuzhiyun 	if (!have_seeprom) {
1357*4882a593Smuzhiyun 		if (bootverbose)
1358*4882a593Smuzhiyun 			printk("%s: No SEEPROM available.\n", ahc_name(ahc));
1359*4882a593Smuzhiyun 		ahc->flags |= AHC_USEDEFAULTS;
1360*4882a593Smuzhiyun 		kfree(ahc->seep_config);
1361*4882a593Smuzhiyun 		ahc->seep_config = NULL;
1362*4882a593Smuzhiyun 		sc = NULL;
1363*4882a593Smuzhiyun 	} else {
1364*4882a593Smuzhiyun 		ahc_parse_pci_eeprom(ahc, sc);
1365*4882a593Smuzhiyun 	}
1366*4882a593Smuzhiyun 
1367*4882a593Smuzhiyun 	/*
1368*4882a593Smuzhiyun 	 * Cards that have the external logic necessary to talk to
1369*4882a593Smuzhiyun 	 * a SEEPROM, are almost certain to have the remaining logic
1370*4882a593Smuzhiyun 	 * necessary for auto-termination control.  This assumption
1371*4882a593Smuzhiyun 	 * hasn't failed yet...
1372*4882a593Smuzhiyun 	 */
1373*4882a593Smuzhiyun 	have_autoterm = have_seeprom;
1374*4882a593Smuzhiyun 
1375*4882a593Smuzhiyun 	/*
1376*4882a593Smuzhiyun 	 * Some low-cost chips have SEEPROM and auto-term control built
1377*4882a593Smuzhiyun 	 * in, instead of using a GAL.  They can tell us directly
1378*4882a593Smuzhiyun 	 * if the termination logic is enabled.
1379*4882a593Smuzhiyun 	 */
1380*4882a593Smuzhiyun 	if ((ahc->features & AHC_SPIOCAP) != 0) {
1381*4882a593Smuzhiyun 		if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0)
1382*4882a593Smuzhiyun 			have_autoterm = FALSE;
1383*4882a593Smuzhiyun 	}
1384*4882a593Smuzhiyun 
1385*4882a593Smuzhiyun 	if (have_autoterm) {
1386*4882a593Smuzhiyun 		ahc->flags |= AHC_HAS_TERM_LOGIC;
1387*4882a593Smuzhiyun 		ahc_acquire_seeprom(ahc, &sd);
1388*4882a593Smuzhiyun 		configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1);
1389*4882a593Smuzhiyun 		ahc_release_seeprom(&sd);
1390*4882a593Smuzhiyun 	} else if (have_seeprom) {
1391*4882a593Smuzhiyun 		*sxfrctl1 &= ~STPWEN;
1392*4882a593Smuzhiyun 		if ((sc->adapter_control & CFSTERM) != 0)
1393*4882a593Smuzhiyun 			*sxfrctl1 |= STPWEN;
1394*4882a593Smuzhiyun 		if (bootverbose)
1395*4882a593Smuzhiyun 			printk("%s: Low byte termination %sabled\n",
1396*4882a593Smuzhiyun 			       ahc_name(ahc),
1397*4882a593Smuzhiyun 			       (*sxfrctl1 & STPWEN) ? "en" : "dis");
1398*4882a593Smuzhiyun 	}
1399*4882a593Smuzhiyun }
1400*4882a593Smuzhiyun 
1401*4882a593Smuzhiyun static void
ahc_parse_pci_eeprom(struct ahc_softc * ahc,struct seeprom_config * sc)1402*4882a593Smuzhiyun ahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc)
1403*4882a593Smuzhiyun {
1404*4882a593Smuzhiyun 	/*
1405*4882a593Smuzhiyun 	 * Put the data we've collected down into SRAM
1406*4882a593Smuzhiyun 	 * where ahc_init will find it.
1407*4882a593Smuzhiyun 	 */
1408*4882a593Smuzhiyun 	int	 i;
1409*4882a593Smuzhiyun 	int	 max_targ = sc->max_targets & CFMAXTARG;
1410*4882a593Smuzhiyun 	u_int	 scsi_conf;
1411*4882a593Smuzhiyun 	uint16_t discenable;
1412*4882a593Smuzhiyun 	uint16_t ultraenb;
1413*4882a593Smuzhiyun 
1414*4882a593Smuzhiyun 	discenable = 0;
1415*4882a593Smuzhiyun 	ultraenb = 0;
1416*4882a593Smuzhiyun 	if ((sc->adapter_control & CFULTRAEN) != 0) {
1417*4882a593Smuzhiyun 		/*
1418*4882a593Smuzhiyun 		 * Determine if this adapter has a "newstyle"
1419*4882a593Smuzhiyun 		 * SEEPROM format.
1420*4882a593Smuzhiyun 		 */
1421*4882a593Smuzhiyun 		for (i = 0; i < max_targ; i++) {
1422*4882a593Smuzhiyun 			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) {
1423*4882a593Smuzhiyun 				ahc->flags |= AHC_NEWEEPROM_FMT;
1424*4882a593Smuzhiyun 				break;
1425*4882a593Smuzhiyun 			}
1426*4882a593Smuzhiyun 		}
1427*4882a593Smuzhiyun 	}
1428*4882a593Smuzhiyun 
1429*4882a593Smuzhiyun 	for (i = 0; i < max_targ; i++) {
1430*4882a593Smuzhiyun 		u_int     scsirate;
1431*4882a593Smuzhiyun 		uint16_t target_mask;
1432*4882a593Smuzhiyun 
1433*4882a593Smuzhiyun 		target_mask = 0x01 << i;
1434*4882a593Smuzhiyun 		if (sc->device_flags[i] & CFDISC)
1435*4882a593Smuzhiyun 			discenable |= target_mask;
1436*4882a593Smuzhiyun 		if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) {
1437*4882a593Smuzhiyun 			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0)
1438*4882a593Smuzhiyun 				ultraenb |= target_mask;
1439*4882a593Smuzhiyun 		} else if ((sc->adapter_control & CFULTRAEN) != 0) {
1440*4882a593Smuzhiyun 			ultraenb |= target_mask;
1441*4882a593Smuzhiyun 		}
1442*4882a593Smuzhiyun 		if ((sc->device_flags[i] & CFXFER) == 0x04
1443*4882a593Smuzhiyun 		 && (ultraenb & target_mask) != 0) {
1444*4882a593Smuzhiyun 			/* Treat 10MHz as a non-ultra speed */
1445*4882a593Smuzhiyun 			sc->device_flags[i] &= ~CFXFER;
1446*4882a593Smuzhiyun 		 	ultraenb &= ~target_mask;
1447*4882a593Smuzhiyun 		}
1448*4882a593Smuzhiyun 		if ((ahc->features & AHC_ULTRA2) != 0) {
1449*4882a593Smuzhiyun 			u_int offset;
1450*4882a593Smuzhiyun 
1451*4882a593Smuzhiyun 			if (sc->device_flags[i] & CFSYNCH)
1452*4882a593Smuzhiyun 				offset = MAX_OFFSET_ULTRA2;
1453*4882a593Smuzhiyun 			else
1454*4882a593Smuzhiyun 				offset = 0;
1455*4882a593Smuzhiyun 			ahc_outb(ahc, TARG_OFFSET + i, offset);
1456*4882a593Smuzhiyun 
1457*4882a593Smuzhiyun 			/*
1458*4882a593Smuzhiyun 			 * The ultra enable bits contain the
1459*4882a593Smuzhiyun 			 * high bit of the ultra2 sync rate
1460*4882a593Smuzhiyun 			 * field.
1461*4882a593Smuzhiyun 			 */
1462*4882a593Smuzhiyun 			scsirate = (sc->device_flags[i] & CFXFER)
1463*4882a593Smuzhiyun 				 | ((ultraenb & target_mask) ? 0x8 : 0x0);
1464*4882a593Smuzhiyun 			if (sc->device_flags[i] & CFWIDEB)
1465*4882a593Smuzhiyun 				scsirate |= WIDEXFER;
1466*4882a593Smuzhiyun 		} else {
1467*4882a593Smuzhiyun 			scsirate = (sc->device_flags[i] & CFXFER) << 4;
1468*4882a593Smuzhiyun 			if (sc->device_flags[i] & CFSYNCH)
1469*4882a593Smuzhiyun 				scsirate |= SOFS;
1470*4882a593Smuzhiyun 			if (sc->device_flags[i] & CFWIDEB)
1471*4882a593Smuzhiyun 				scsirate |= WIDEXFER;
1472*4882a593Smuzhiyun 		}
1473*4882a593Smuzhiyun 		ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);
1474*4882a593Smuzhiyun 	}
1475*4882a593Smuzhiyun 	ahc->our_id = sc->brtime_id & CFSCSIID;
1476*4882a593Smuzhiyun 
1477*4882a593Smuzhiyun 	scsi_conf = (ahc->our_id & 0x7);
1478*4882a593Smuzhiyun 	if (sc->adapter_control & CFSPARITY)
1479*4882a593Smuzhiyun 		scsi_conf |= ENSPCHK;
1480*4882a593Smuzhiyun 	if (sc->adapter_control & CFRESETB)
1481*4882a593Smuzhiyun 		scsi_conf |= RESET_SCSI;
1482*4882a593Smuzhiyun 
1483*4882a593Smuzhiyun 	ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;
1484*4882a593Smuzhiyun 
1485*4882a593Smuzhiyun 	if (sc->bios_control & CFEXTEND)
1486*4882a593Smuzhiyun 		ahc->flags |= AHC_EXTENDED_TRANS_A;
1487*4882a593Smuzhiyun 
1488*4882a593Smuzhiyun 	if (sc->bios_control & CFBIOSEN)
1489*4882a593Smuzhiyun 		ahc->flags |= AHC_BIOS_ENABLED;
1490*4882a593Smuzhiyun 	if (ahc->features & AHC_ULTRA
1491*4882a593Smuzhiyun 	 && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {
1492*4882a593Smuzhiyun 		/* Should we enable Ultra mode? */
1493*4882a593Smuzhiyun 		if (!(sc->adapter_control & CFULTRAEN))
1494*4882a593Smuzhiyun 			/* Treat us as a non-ultra card */
1495*4882a593Smuzhiyun 			ultraenb = 0;
1496*4882a593Smuzhiyun 	}
1497*4882a593Smuzhiyun 
1498*4882a593Smuzhiyun 	if (sc->signature == CFSIGNATURE
1499*4882a593Smuzhiyun 	 || sc->signature == CFSIGNATURE2) {
1500*4882a593Smuzhiyun 		uint32_t devconfig;
1501*4882a593Smuzhiyun 
1502*4882a593Smuzhiyun 		/* Honor the STPWLEVEL settings */
1503*4882a593Smuzhiyun 		devconfig = ahc_pci_read_config(ahc->dev_softc,
1504*4882a593Smuzhiyun 						DEVCONFIG, /*bytes*/4);
1505*4882a593Smuzhiyun 		devconfig &= ~STPWLEVEL;
1506*4882a593Smuzhiyun 		if ((sc->bios_control & CFSTPWLEVEL) != 0)
1507*4882a593Smuzhiyun 			devconfig |= STPWLEVEL;
1508*4882a593Smuzhiyun 		ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
1509*4882a593Smuzhiyun 				     devconfig, /*bytes*/4);
1510*4882a593Smuzhiyun 	}
1511*4882a593Smuzhiyun 	/* Set SCSICONF info */
1512*4882a593Smuzhiyun 	ahc_outb(ahc, SCSICONF, scsi_conf);
1513*4882a593Smuzhiyun 	ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
1514*4882a593Smuzhiyun 	ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
1515*4882a593Smuzhiyun 	ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff);
1516*4882a593Smuzhiyun 	ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);
1517*4882a593Smuzhiyun }
1518*4882a593Smuzhiyun 
1519*4882a593Smuzhiyun static void
configure_termination(struct ahc_softc * ahc,struct seeprom_descriptor * sd,u_int adapter_control,u_int * sxfrctl1)1520*4882a593Smuzhiyun configure_termination(struct ahc_softc *ahc,
1521*4882a593Smuzhiyun 		      struct seeprom_descriptor *sd,
1522*4882a593Smuzhiyun 		      u_int adapter_control,
1523*4882a593Smuzhiyun 		      u_int *sxfrctl1)
1524*4882a593Smuzhiyun {
1525*4882a593Smuzhiyun 	uint8_t brddat;
1526*4882a593Smuzhiyun 
1527*4882a593Smuzhiyun 	brddat = 0;
1528*4882a593Smuzhiyun 
1529*4882a593Smuzhiyun 	/*
1530*4882a593Smuzhiyun 	 * Update the settings in sxfrctl1 to match the
1531*4882a593Smuzhiyun 	 * termination settings
1532*4882a593Smuzhiyun 	 */
1533*4882a593Smuzhiyun 	*sxfrctl1 = 0;
1534*4882a593Smuzhiyun 
1535*4882a593Smuzhiyun 	/*
1536*4882a593Smuzhiyun 	 * SEECS must be on for the GALS to latch
1537*4882a593Smuzhiyun 	 * the data properly.  Be sure to leave MS
1538*4882a593Smuzhiyun 	 * on or we will release the seeprom.
1539*4882a593Smuzhiyun 	 */
1540*4882a593Smuzhiyun 	SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS);
1541*4882a593Smuzhiyun 	if ((adapter_control & CFAUTOTERM) != 0
1542*4882a593Smuzhiyun 	 || (ahc->features & AHC_NEW_TERMCTL) != 0) {
1543*4882a593Smuzhiyun 		int internal50_present;
1544*4882a593Smuzhiyun 		int internal68_present;
1545*4882a593Smuzhiyun 		int externalcable_present;
1546*4882a593Smuzhiyun 		int eeprom_present;
1547*4882a593Smuzhiyun 		int enableSEC_low;
1548*4882a593Smuzhiyun 		int enableSEC_high;
1549*4882a593Smuzhiyun 		int enablePRI_low;
1550*4882a593Smuzhiyun 		int enablePRI_high;
1551*4882a593Smuzhiyun 		int sum;
1552*4882a593Smuzhiyun 
1553*4882a593Smuzhiyun 		enableSEC_low = 0;
1554*4882a593Smuzhiyun 		enableSEC_high = 0;
1555*4882a593Smuzhiyun 		enablePRI_low = 0;
1556*4882a593Smuzhiyun 		enablePRI_high = 0;
1557*4882a593Smuzhiyun 		if ((ahc->features & AHC_NEW_TERMCTL) != 0) {
1558*4882a593Smuzhiyun 			ahc_new_term_detect(ahc, &enableSEC_low,
1559*4882a593Smuzhiyun 					    &enableSEC_high,
1560*4882a593Smuzhiyun 					    &enablePRI_low,
1561*4882a593Smuzhiyun 					    &enablePRI_high,
1562*4882a593Smuzhiyun 					    &eeprom_present);
1563*4882a593Smuzhiyun 			if ((adapter_control & CFSEAUTOTERM) == 0) {
1564*4882a593Smuzhiyun 				if (bootverbose)
1565*4882a593Smuzhiyun 					printk("%s: Manual SE Termination\n",
1566*4882a593Smuzhiyun 					       ahc_name(ahc));
1567*4882a593Smuzhiyun 				enableSEC_low = (adapter_control & CFSELOWTERM);
1568*4882a593Smuzhiyun 				enableSEC_high =
1569*4882a593Smuzhiyun 				    (adapter_control & CFSEHIGHTERM);
1570*4882a593Smuzhiyun 			}
1571*4882a593Smuzhiyun 			if ((adapter_control & CFAUTOTERM) == 0) {
1572*4882a593Smuzhiyun 				if (bootverbose)
1573*4882a593Smuzhiyun 					printk("%s: Manual LVD Termination\n",
1574*4882a593Smuzhiyun 					       ahc_name(ahc));
1575*4882a593Smuzhiyun 				enablePRI_low = (adapter_control & CFSTERM);
1576*4882a593Smuzhiyun 				enablePRI_high = (adapter_control & CFWSTERM);
1577*4882a593Smuzhiyun 			}
1578*4882a593Smuzhiyun 			/* Make the table calculations below happy */
1579*4882a593Smuzhiyun 			internal50_present = 0;
1580*4882a593Smuzhiyun 			internal68_present = 1;
1581*4882a593Smuzhiyun 			externalcable_present = 1;
1582*4882a593Smuzhiyun 		} else if ((ahc->features & AHC_SPIOCAP) != 0) {
1583*4882a593Smuzhiyun 			aic785X_cable_detect(ahc, &internal50_present,
1584*4882a593Smuzhiyun 					     &externalcable_present,
1585*4882a593Smuzhiyun 					     &eeprom_present);
1586*4882a593Smuzhiyun 			/* Can never support a wide connector. */
1587*4882a593Smuzhiyun 			internal68_present = 0;
1588*4882a593Smuzhiyun 		} else {
1589*4882a593Smuzhiyun 			aic787X_cable_detect(ahc, &internal50_present,
1590*4882a593Smuzhiyun 					     &internal68_present,
1591*4882a593Smuzhiyun 					     &externalcable_present,
1592*4882a593Smuzhiyun 					     &eeprom_present);
1593*4882a593Smuzhiyun 		}
1594*4882a593Smuzhiyun 
1595*4882a593Smuzhiyun 		if ((ahc->features & AHC_WIDE) == 0)
1596*4882a593Smuzhiyun 			internal68_present = 0;
1597*4882a593Smuzhiyun 
1598*4882a593Smuzhiyun 		if (bootverbose
1599*4882a593Smuzhiyun 		 && (ahc->features & AHC_ULTRA2) == 0) {
1600*4882a593Smuzhiyun 			printk("%s: internal 50 cable %s present",
1601*4882a593Smuzhiyun 			       ahc_name(ahc),
1602*4882a593Smuzhiyun 			       internal50_present ? "is":"not");
1603*4882a593Smuzhiyun 
1604*4882a593Smuzhiyun 			if ((ahc->features & AHC_WIDE) != 0)
1605*4882a593Smuzhiyun 				printk(", internal 68 cable %s present",
1606*4882a593Smuzhiyun 				       internal68_present ? "is":"not");
1607*4882a593Smuzhiyun 			printk("\n%s: external cable %s present\n",
1608*4882a593Smuzhiyun 			       ahc_name(ahc),
1609*4882a593Smuzhiyun 			       externalcable_present ? "is":"not");
1610*4882a593Smuzhiyun 		}
1611*4882a593Smuzhiyun 		if (bootverbose)
1612*4882a593Smuzhiyun 			printk("%s: BIOS eeprom %s present\n",
1613*4882a593Smuzhiyun 			       ahc_name(ahc), eeprom_present ? "is" : "not");
1614*4882a593Smuzhiyun 
1615*4882a593Smuzhiyun 		if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) {
1616*4882a593Smuzhiyun 			/*
1617*4882a593Smuzhiyun 			 * The 50 pin connector is a separate bus,
1618*4882a593Smuzhiyun 			 * so force it to always be terminated.
1619*4882a593Smuzhiyun 			 * In the future, perform current sensing
1620*4882a593Smuzhiyun 			 * to determine if we are in the middle of
1621*4882a593Smuzhiyun 			 * a properly terminated bus.
1622*4882a593Smuzhiyun 			 */
1623*4882a593Smuzhiyun 			internal50_present = 0;
1624*4882a593Smuzhiyun 		}
1625*4882a593Smuzhiyun 
1626*4882a593Smuzhiyun 		/*
1627*4882a593Smuzhiyun 		 * Now set the termination based on what
1628*4882a593Smuzhiyun 		 * we found.
1629*4882a593Smuzhiyun 		 * Flash Enable = BRDDAT7
1630*4882a593Smuzhiyun 		 * Secondary High Term Enable = BRDDAT6
1631*4882a593Smuzhiyun 		 * Secondary Low Term Enable = BRDDAT5 (7890)
1632*4882a593Smuzhiyun 		 * Primary High Term Enable = BRDDAT4 (7890)
1633*4882a593Smuzhiyun 		 */
1634*4882a593Smuzhiyun 		if ((ahc->features & AHC_ULTRA2) == 0
1635*4882a593Smuzhiyun 		 && (internal50_present != 0)
1636*4882a593Smuzhiyun 		 && (internal68_present != 0)
1637*4882a593Smuzhiyun 		 && (externalcable_present != 0)) {
1638*4882a593Smuzhiyun 			printk("%s: Illegal cable configuration!!. "
1639*4882a593Smuzhiyun 			       "Only two connectors on the "
1640*4882a593Smuzhiyun 			       "adapter may be used at a "
1641*4882a593Smuzhiyun 			       "time!\n", ahc_name(ahc));
1642*4882a593Smuzhiyun 
1643*4882a593Smuzhiyun 			/*
1644*4882a593Smuzhiyun 			 * Pretend there are no cables in the hope
1645*4882a593Smuzhiyun 			 * that having all of the termination on
1646*4882a593Smuzhiyun 			 * gives us a more stable bus.
1647*4882a593Smuzhiyun 			 */
1648*4882a593Smuzhiyun 		 	internal50_present = 0;
1649*4882a593Smuzhiyun 			internal68_present = 0;
1650*4882a593Smuzhiyun 			externalcable_present = 0;
1651*4882a593Smuzhiyun 		}
1652*4882a593Smuzhiyun 
1653*4882a593Smuzhiyun 		if ((ahc->features & AHC_WIDE) != 0
1654*4882a593Smuzhiyun 		 && ((externalcable_present == 0)
1655*4882a593Smuzhiyun 		  || (internal68_present == 0)
1656*4882a593Smuzhiyun 		  || (enableSEC_high != 0))) {
1657*4882a593Smuzhiyun 			brddat |= BRDDAT6;
1658*4882a593Smuzhiyun 			if (bootverbose) {
1659*4882a593Smuzhiyun 				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
1660*4882a593Smuzhiyun 					printk("%s: 68 pin termination "
1661*4882a593Smuzhiyun 					       "Enabled\n", ahc_name(ahc));
1662*4882a593Smuzhiyun 				else
1663*4882a593Smuzhiyun 					printk("%s: %sHigh byte termination "
1664*4882a593Smuzhiyun 					       "Enabled\n", ahc_name(ahc),
1665*4882a593Smuzhiyun 					       enableSEC_high ? "Secondary "
1666*4882a593Smuzhiyun 							      : "");
1667*4882a593Smuzhiyun 			}
1668*4882a593Smuzhiyun 		}
1669*4882a593Smuzhiyun 
1670*4882a593Smuzhiyun 		sum = internal50_present + internal68_present
1671*4882a593Smuzhiyun 		    + externalcable_present;
1672*4882a593Smuzhiyun 		if (sum < 2 || (enableSEC_low != 0)) {
1673*4882a593Smuzhiyun 			if ((ahc->features & AHC_ULTRA2) != 0)
1674*4882a593Smuzhiyun 				brddat |= BRDDAT5;
1675*4882a593Smuzhiyun 			else
1676*4882a593Smuzhiyun 				*sxfrctl1 |= STPWEN;
1677*4882a593Smuzhiyun 			if (bootverbose) {
1678*4882a593Smuzhiyun 				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
1679*4882a593Smuzhiyun 					printk("%s: 50 pin termination "
1680*4882a593Smuzhiyun 					       "Enabled\n", ahc_name(ahc));
1681*4882a593Smuzhiyun 				else
1682*4882a593Smuzhiyun 					printk("%s: %sLow byte termination "
1683*4882a593Smuzhiyun 					       "Enabled\n", ahc_name(ahc),
1684*4882a593Smuzhiyun 					       enableSEC_low ? "Secondary "
1685*4882a593Smuzhiyun 							     : "");
1686*4882a593Smuzhiyun 			}
1687*4882a593Smuzhiyun 		}
1688*4882a593Smuzhiyun 
1689*4882a593Smuzhiyun 		if (enablePRI_low != 0) {
1690*4882a593Smuzhiyun 			*sxfrctl1 |= STPWEN;
1691*4882a593Smuzhiyun 			if (bootverbose)
1692*4882a593Smuzhiyun 				printk("%s: Primary Low Byte termination "
1693*4882a593Smuzhiyun 				       "Enabled\n", ahc_name(ahc));
1694*4882a593Smuzhiyun 		}
1695*4882a593Smuzhiyun 
1696*4882a593Smuzhiyun 		/*
1697*4882a593Smuzhiyun 		 * Setup STPWEN before setting up the rest of
1698*4882a593Smuzhiyun 		 * the termination per the tech note on the U160 cards.
1699*4882a593Smuzhiyun 		 */
1700*4882a593Smuzhiyun 		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
1701*4882a593Smuzhiyun 
1702*4882a593Smuzhiyun 		if (enablePRI_high != 0) {
1703*4882a593Smuzhiyun 			brddat |= BRDDAT4;
1704*4882a593Smuzhiyun 			if (bootverbose)
1705*4882a593Smuzhiyun 				printk("%s: Primary High Byte "
1706*4882a593Smuzhiyun 				       "termination Enabled\n",
1707*4882a593Smuzhiyun 				       ahc_name(ahc));
1708*4882a593Smuzhiyun 		}
1709*4882a593Smuzhiyun 
1710*4882a593Smuzhiyun 		write_brdctl(ahc, brddat);
1711*4882a593Smuzhiyun 
1712*4882a593Smuzhiyun 	} else {
1713*4882a593Smuzhiyun 		if ((adapter_control & CFSTERM) != 0) {
1714*4882a593Smuzhiyun 			*sxfrctl1 |= STPWEN;
1715*4882a593Smuzhiyun 
1716*4882a593Smuzhiyun 			if (bootverbose)
1717*4882a593Smuzhiyun 				printk("%s: %sLow byte termination Enabled\n",
1718*4882a593Smuzhiyun 				       ahc_name(ahc),
1719*4882a593Smuzhiyun 				       (ahc->features & AHC_ULTRA2) ? "Primary "
1720*4882a593Smuzhiyun 								    : "");
1721*4882a593Smuzhiyun 		}
1722*4882a593Smuzhiyun 
1723*4882a593Smuzhiyun 		if ((adapter_control & CFWSTERM) != 0
1724*4882a593Smuzhiyun 		 && (ahc->features & AHC_WIDE) != 0) {
1725*4882a593Smuzhiyun 			brddat |= BRDDAT6;
1726*4882a593Smuzhiyun 			if (bootverbose)
1727*4882a593Smuzhiyun 				printk("%s: %sHigh byte termination Enabled\n",
1728*4882a593Smuzhiyun 				       ahc_name(ahc),
1729*4882a593Smuzhiyun 				       (ahc->features & AHC_ULTRA2)
1730*4882a593Smuzhiyun 				     ? "Secondary " : "");
1731*4882a593Smuzhiyun 		}
1732*4882a593Smuzhiyun 
1733*4882a593Smuzhiyun 		/*
1734*4882a593Smuzhiyun 		 * Setup STPWEN before setting up the rest of
1735*4882a593Smuzhiyun 		 * the termination per the tech note on the U160 cards.
1736*4882a593Smuzhiyun 		 */
1737*4882a593Smuzhiyun 		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
1738*4882a593Smuzhiyun 
1739*4882a593Smuzhiyun 		if ((ahc->features & AHC_WIDE) != 0)
1740*4882a593Smuzhiyun 			write_brdctl(ahc, brddat);
1741*4882a593Smuzhiyun 	}
1742*4882a593Smuzhiyun 	SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */
1743*4882a593Smuzhiyun }
1744*4882a593Smuzhiyun 
1745*4882a593Smuzhiyun static void
ahc_new_term_detect(struct ahc_softc * ahc,int * enableSEC_low,int * enableSEC_high,int * enablePRI_low,int * enablePRI_high,int * eeprom_present)1746*4882a593Smuzhiyun ahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low,
1747*4882a593Smuzhiyun 		    int *enableSEC_high, int *enablePRI_low,
1748*4882a593Smuzhiyun 		    int *enablePRI_high, int *eeprom_present)
1749*4882a593Smuzhiyun {
1750*4882a593Smuzhiyun 	uint8_t brdctl;
1751*4882a593Smuzhiyun 
1752*4882a593Smuzhiyun 	/*
1753*4882a593Smuzhiyun 	 * BRDDAT7 = Eeprom
1754*4882a593Smuzhiyun 	 * BRDDAT6 = Enable Secondary High Byte termination
1755*4882a593Smuzhiyun 	 * BRDDAT5 = Enable Secondary Low Byte termination
1756*4882a593Smuzhiyun 	 * BRDDAT4 = Enable Primary high byte termination
1757*4882a593Smuzhiyun 	 * BRDDAT3 = Enable Primary low byte termination
1758*4882a593Smuzhiyun 	 */
1759*4882a593Smuzhiyun 	brdctl = read_brdctl(ahc);
1760*4882a593Smuzhiyun 	*eeprom_present = brdctl & BRDDAT7;
1761*4882a593Smuzhiyun 	*enableSEC_high = (brdctl & BRDDAT6);
1762*4882a593Smuzhiyun 	*enableSEC_low = (brdctl & BRDDAT5);
1763*4882a593Smuzhiyun 	*enablePRI_high = (brdctl & BRDDAT4);
1764*4882a593Smuzhiyun 	*enablePRI_low = (brdctl & BRDDAT3);
1765*4882a593Smuzhiyun }
1766*4882a593Smuzhiyun 
1767*4882a593Smuzhiyun static void
aic787X_cable_detect(struct ahc_softc * ahc,int * internal50_present,int * internal68_present,int * externalcable_present,int * eeprom_present)1768*4882a593Smuzhiyun aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
1769*4882a593Smuzhiyun 		     int *internal68_present, int *externalcable_present,
1770*4882a593Smuzhiyun 		     int *eeprom_present)
1771*4882a593Smuzhiyun {
1772*4882a593Smuzhiyun 	uint8_t brdctl;
1773*4882a593Smuzhiyun 
1774*4882a593Smuzhiyun 	/*
1775*4882a593Smuzhiyun 	 * First read the status of our cables.
1776*4882a593Smuzhiyun 	 * Set the rom bank to 0 since the
1777*4882a593Smuzhiyun 	 * bank setting serves as a multiplexor
1778*4882a593Smuzhiyun 	 * for the cable detection logic.
1779*4882a593Smuzhiyun 	 * BRDDAT5 controls the bank switch.
1780*4882a593Smuzhiyun 	 */
1781*4882a593Smuzhiyun 	write_brdctl(ahc, 0);
1782*4882a593Smuzhiyun 
1783*4882a593Smuzhiyun 	/*
1784*4882a593Smuzhiyun 	 * Now read the state of the internal
1785*4882a593Smuzhiyun 	 * connectors.  BRDDAT6 is INT50 and
1786*4882a593Smuzhiyun 	 * BRDDAT7 is INT68.
1787*4882a593Smuzhiyun 	 */
1788*4882a593Smuzhiyun 	brdctl = read_brdctl(ahc);
1789*4882a593Smuzhiyun 	*internal50_present = (brdctl & BRDDAT6) ? 0 : 1;
1790*4882a593Smuzhiyun 	*internal68_present = (brdctl & BRDDAT7) ? 0 : 1;
1791*4882a593Smuzhiyun 
1792*4882a593Smuzhiyun 	/*
1793*4882a593Smuzhiyun 	 * Set the rom bank to 1 and determine
1794*4882a593Smuzhiyun 	 * the other signals.
1795*4882a593Smuzhiyun 	 */
1796*4882a593Smuzhiyun 	write_brdctl(ahc, BRDDAT5);
1797*4882a593Smuzhiyun 
1798*4882a593Smuzhiyun 	/*
1799*4882a593Smuzhiyun 	 * Now read the state of the external
1800*4882a593Smuzhiyun 	 * connectors.  BRDDAT6 is EXT68 and
1801*4882a593Smuzhiyun 	 * BRDDAT7 is EPROMPS.
1802*4882a593Smuzhiyun 	 */
1803*4882a593Smuzhiyun 	brdctl = read_brdctl(ahc);
1804*4882a593Smuzhiyun 	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
1805*4882a593Smuzhiyun 	*eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;
1806*4882a593Smuzhiyun }
1807*4882a593Smuzhiyun 
1808*4882a593Smuzhiyun static void
aic785X_cable_detect(struct ahc_softc * ahc,int * internal50_present,int * externalcable_present,int * eeprom_present)1809*4882a593Smuzhiyun aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
1810*4882a593Smuzhiyun 		     int *externalcable_present, int *eeprom_present)
1811*4882a593Smuzhiyun {
1812*4882a593Smuzhiyun 	uint8_t brdctl;
1813*4882a593Smuzhiyun 	uint8_t spiocap;
1814*4882a593Smuzhiyun 
1815*4882a593Smuzhiyun 	spiocap = ahc_inb(ahc, SPIOCAP);
1816*4882a593Smuzhiyun 	spiocap &= ~SOFTCMDEN;
1817*4882a593Smuzhiyun 	spiocap |= EXT_BRDCTL;
1818*4882a593Smuzhiyun 	ahc_outb(ahc, SPIOCAP, spiocap);
1819*4882a593Smuzhiyun 	ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
1820*4882a593Smuzhiyun 	ahc_flush_device_writes(ahc);
1821*4882a593Smuzhiyun 	ahc_delay(500);
1822*4882a593Smuzhiyun 	ahc_outb(ahc, BRDCTL, 0);
1823*4882a593Smuzhiyun 	ahc_flush_device_writes(ahc);
1824*4882a593Smuzhiyun 	ahc_delay(500);
1825*4882a593Smuzhiyun 	brdctl = ahc_inb(ahc, BRDCTL);
1826*4882a593Smuzhiyun 	*internal50_present = (brdctl & BRDDAT5) ? 0 : 1;
1827*4882a593Smuzhiyun 	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
1828*4882a593Smuzhiyun 	*eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
1829*4882a593Smuzhiyun }
1830*4882a593Smuzhiyun 
1831*4882a593Smuzhiyun int
ahc_acquire_seeprom(struct ahc_softc * ahc,struct seeprom_descriptor * sd)1832*4882a593Smuzhiyun ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
1833*4882a593Smuzhiyun {
1834*4882a593Smuzhiyun 	int wait;
1835*4882a593Smuzhiyun 
1836*4882a593Smuzhiyun 	if ((ahc->features & AHC_SPIOCAP) != 0
1837*4882a593Smuzhiyun 	 && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0)
1838*4882a593Smuzhiyun 		return (0);
1839*4882a593Smuzhiyun 
1840*4882a593Smuzhiyun 	/*
1841*4882a593Smuzhiyun 	 * Request access of the memory port.  When access is
1842*4882a593Smuzhiyun 	 * granted, SEERDY will go high.  We use a 1 second
1843*4882a593Smuzhiyun 	 * timeout which should be near 1 second more than
1844*4882a593Smuzhiyun 	 * is needed.  Reason: after the chip reset, there
1845*4882a593Smuzhiyun 	 * should be no contention.
1846*4882a593Smuzhiyun 	 */
1847*4882a593Smuzhiyun 	SEEPROM_OUTB(sd, sd->sd_MS);
1848*4882a593Smuzhiyun 	wait = 1000;  /* 1 second timeout in msec */
1849*4882a593Smuzhiyun 	while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
1850*4882a593Smuzhiyun 		ahc_delay(1000);  /* delay 1 msec */
1851*4882a593Smuzhiyun 	}
1852*4882a593Smuzhiyun 	if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
1853*4882a593Smuzhiyun 		SEEPROM_OUTB(sd, 0);
1854*4882a593Smuzhiyun 		return (0);
1855*4882a593Smuzhiyun 	}
1856*4882a593Smuzhiyun 	return(1);
1857*4882a593Smuzhiyun }
1858*4882a593Smuzhiyun 
1859*4882a593Smuzhiyun void
ahc_release_seeprom(struct seeprom_descriptor * sd)1860*4882a593Smuzhiyun ahc_release_seeprom(struct seeprom_descriptor *sd)
1861*4882a593Smuzhiyun {
1862*4882a593Smuzhiyun 	/* Release access to the memory port and the serial EEPROM. */
1863*4882a593Smuzhiyun 	SEEPROM_OUTB(sd, 0);
1864*4882a593Smuzhiyun }
1865*4882a593Smuzhiyun 
1866*4882a593Smuzhiyun static void
write_brdctl(struct ahc_softc * ahc,uint8_t value)1867*4882a593Smuzhiyun write_brdctl(struct ahc_softc *ahc, uint8_t value)
1868*4882a593Smuzhiyun {
1869*4882a593Smuzhiyun 	uint8_t brdctl;
1870*4882a593Smuzhiyun 
1871*4882a593Smuzhiyun 	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
1872*4882a593Smuzhiyun 		brdctl = BRDSTB;
1873*4882a593Smuzhiyun 	 	if (ahc->channel == 'B')
1874*4882a593Smuzhiyun 			brdctl |= BRDCS;
1875*4882a593Smuzhiyun 	} else if ((ahc->features & AHC_ULTRA2) != 0) {
1876*4882a593Smuzhiyun 		brdctl = 0;
1877*4882a593Smuzhiyun 	} else {
1878*4882a593Smuzhiyun 		brdctl = BRDSTB|BRDCS;
1879*4882a593Smuzhiyun 	}
1880*4882a593Smuzhiyun 	ahc_outb(ahc, BRDCTL, brdctl);
1881*4882a593Smuzhiyun 	ahc_flush_device_writes(ahc);
1882*4882a593Smuzhiyun 	brdctl |= value;
1883*4882a593Smuzhiyun 	ahc_outb(ahc, BRDCTL, brdctl);
1884*4882a593Smuzhiyun 	ahc_flush_device_writes(ahc);
1885*4882a593Smuzhiyun 	if ((ahc->features & AHC_ULTRA2) != 0)
1886*4882a593Smuzhiyun 		brdctl |= BRDSTB_ULTRA2;
1887*4882a593Smuzhiyun 	else
1888*4882a593Smuzhiyun 		brdctl &= ~BRDSTB;
1889*4882a593Smuzhiyun 	ahc_outb(ahc, BRDCTL, brdctl);
1890*4882a593Smuzhiyun 	ahc_flush_device_writes(ahc);
1891*4882a593Smuzhiyun 	if ((ahc->features & AHC_ULTRA2) != 0)
1892*4882a593Smuzhiyun 		brdctl = 0;
1893*4882a593Smuzhiyun 	else
1894*4882a593Smuzhiyun 		brdctl &= ~BRDCS;
1895*4882a593Smuzhiyun 	ahc_outb(ahc, BRDCTL, brdctl);
1896*4882a593Smuzhiyun }
1897*4882a593Smuzhiyun 
1898*4882a593Smuzhiyun static uint8_t
read_brdctl(struct ahc_softc * ahc)1899*4882a593Smuzhiyun read_brdctl(struct ahc_softc *ahc)
1900*4882a593Smuzhiyun {
1901*4882a593Smuzhiyun 	uint8_t brdctl;
1902*4882a593Smuzhiyun 	uint8_t value;
1903*4882a593Smuzhiyun 
1904*4882a593Smuzhiyun 	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
1905*4882a593Smuzhiyun 		brdctl = BRDRW;
1906*4882a593Smuzhiyun 	 	if (ahc->channel == 'B')
1907*4882a593Smuzhiyun 			brdctl |= BRDCS;
1908*4882a593Smuzhiyun 	} else if ((ahc->features & AHC_ULTRA2) != 0) {
1909*4882a593Smuzhiyun 		brdctl = BRDRW_ULTRA2;
1910*4882a593Smuzhiyun 	} else {
1911*4882a593Smuzhiyun 		brdctl = BRDRW|BRDCS;
1912*4882a593Smuzhiyun 	}
1913*4882a593Smuzhiyun 	ahc_outb(ahc, BRDCTL, brdctl);
1914*4882a593Smuzhiyun 	ahc_flush_device_writes(ahc);
1915*4882a593Smuzhiyun 	value = ahc_inb(ahc, BRDCTL);
1916*4882a593Smuzhiyun 	ahc_outb(ahc, BRDCTL, 0);
1917*4882a593Smuzhiyun 	return (value);
1918*4882a593Smuzhiyun }
1919*4882a593Smuzhiyun 
1920*4882a593Smuzhiyun static void
ahc_pci_intr(struct ahc_softc * ahc)1921*4882a593Smuzhiyun ahc_pci_intr(struct ahc_softc *ahc)
1922*4882a593Smuzhiyun {
1923*4882a593Smuzhiyun 	u_int error;
1924*4882a593Smuzhiyun 	u_int status1;
1925*4882a593Smuzhiyun 
1926*4882a593Smuzhiyun 	error = ahc_inb(ahc, ERROR);
1927*4882a593Smuzhiyun 	if ((error & PCIERRSTAT) == 0)
1928*4882a593Smuzhiyun 		return;
1929*4882a593Smuzhiyun 
1930*4882a593Smuzhiyun 	status1 = ahc_pci_read_config(ahc->dev_softc,
1931*4882a593Smuzhiyun 				      PCIR_STATUS + 1, /*bytes*/1);
1932*4882a593Smuzhiyun 
1933*4882a593Smuzhiyun 	printk("%s: PCI error Interrupt at seqaddr = 0x%x\n",
1934*4882a593Smuzhiyun 	      ahc_name(ahc),
1935*4882a593Smuzhiyun 	      ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
1936*4882a593Smuzhiyun 
1937*4882a593Smuzhiyun 	if (status1 & DPE) {
1938*4882a593Smuzhiyun 		ahc->pci_target_perr_count++;
1939*4882a593Smuzhiyun 		printk("%s: Data Parity Error Detected during address "
1940*4882a593Smuzhiyun 		       "or write data phase\n", ahc_name(ahc));
1941*4882a593Smuzhiyun 	}
1942*4882a593Smuzhiyun 	if (status1 & SSE) {
1943*4882a593Smuzhiyun 		printk("%s: Signal System Error Detected\n", ahc_name(ahc));
1944*4882a593Smuzhiyun 	}
1945*4882a593Smuzhiyun 	if (status1 & RMA) {
1946*4882a593Smuzhiyun 		printk("%s: Received a Master Abort\n", ahc_name(ahc));
1947*4882a593Smuzhiyun 	}
1948*4882a593Smuzhiyun 	if (status1 & RTA) {
1949*4882a593Smuzhiyun 		printk("%s: Received a Target Abort\n", ahc_name(ahc));
1950*4882a593Smuzhiyun 	}
1951*4882a593Smuzhiyun 	if (status1 & STA) {
1952*4882a593Smuzhiyun 		printk("%s: Signaled a Target Abort\n", ahc_name(ahc));
1953*4882a593Smuzhiyun 	}
1954*4882a593Smuzhiyun 	if (status1 & DPR) {
1955*4882a593Smuzhiyun 		printk("%s: Data Parity Error has been reported via PERR#\n",
1956*4882a593Smuzhiyun 		       ahc_name(ahc));
1957*4882a593Smuzhiyun 	}
1958*4882a593Smuzhiyun 
1959*4882a593Smuzhiyun 	/* Clear latched errors. */
1960*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
1961*4882a593Smuzhiyun 			     status1, /*bytes*/1);
1962*4882a593Smuzhiyun 
1963*4882a593Smuzhiyun 	if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) {
1964*4882a593Smuzhiyun 		printk("%s: Latched PCIERR interrupt with "
1965*4882a593Smuzhiyun 		       "no status bits set\n", ahc_name(ahc));
1966*4882a593Smuzhiyun 	} else {
1967*4882a593Smuzhiyun 		ahc_outb(ahc, CLRINT, CLRPARERR);
1968*4882a593Smuzhiyun 	}
1969*4882a593Smuzhiyun 
1970*4882a593Smuzhiyun 	if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) {
1971*4882a593Smuzhiyun 		printk(
1972*4882a593Smuzhiyun "%s: WARNING WARNING WARNING WARNING\n"
1973*4882a593Smuzhiyun "%s: Too many PCI parity errors observed as a target.\n"
1974*4882a593Smuzhiyun "%s: Some device on this bus is generating bad parity.\n"
1975*4882a593Smuzhiyun "%s: This is an error *observed by*, not *generated by*, this controller.\n"
1976*4882a593Smuzhiyun "%s: PCI parity error checking has been disabled.\n"
1977*4882a593Smuzhiyun "%s: WARNING WARNING WARNING WARNING\n",
1978*4882a593Smuzhiyun 		       ahc_name(ahc), ahc_name(ahc), ahc_name(ahc),
1979*4882a593Smuzhiyun 		       ahc_name(ahc), ahc_name(ahc), ahc_name(ahc));
1980*4882a593Smuzhiyun 		ahc->seqctl |= FAILDIS;
1981*4882a593Smuzhiyun 		ahc_outb(ahc, SEQCTL, ahc->seqctl);
1982*4882a593Smuzhiyun 	}
1983*4882a593Smuzhiyun 	ahc_unpause(ahc);
1984*4882a593Smuzhiyun }
1985*4882a593Smuzhiyun 
1986*4882a593Smuzhiyun static int
ahc_pci_chip_init(struct ahc_softc * ahc)1987*4882a593Smuzhiyun ahc_pci_chip_init(struct ahc_softc *ahc)
1988*4882a593Smuzhiyun {
1989*4882a593Smuzhiyun 	ahc_outb(ahc, DSCOMMAND0, ahc->bus_softc.pci_softc.dscommand0);
1990*4882a593Smuzhiyun 	ahc_outb(ahc, DSPCISTATUS, ahc->bus_softc.pci_softc.dspcistatus);
1991*4882a593Smuzhiyun 	if ((ahc->features & AHC_DT) != 0) {
1992*4882a593Smuzhiyun 		u_int sfunct;
1993*4882a593Smuzhiyun 
1994*4882a593Smuzhiyun 		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
1995*4882a593Smuzhiyun 		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
1996*4882a593Smuzhiyun 		ahc_outb(ahc, OPTIONMODE, ahc->bus_softc.pci_softc.optionmode);
1997*4882a593Smuzhiyun 		ahc_outw(ahc, TARGCRCCNT, ahc->bus_softc.pci_softc.targcrccnt);
1998*4882a593Smuzhiyun 		ahc_outb(ahc, SFUNCT, sfunct);
1999*4882a593Smuzhiyun 		ahc_outb(ahc, CRCCONTROL1,
2000*4882a593Smuzhiyun 			 ahc->bus_softc.pci_softc.crccontrol1);
2001*4882a593Smuzhiyun 	}
2002*4882a593Smuzhiyun 	if ((ahc->features & AHC_MULTI_FUNC) != 0)
2003*4882a593Smuzhiyun 		ahc_outb(ahc, SCBBADDR, ahc->bus_softc.pci_softc.scbbaddr);
2004*4882a593Smuzhiyun 
2005*4882a593Smuzhiyun 	if ((ahc->features & AHC_ULTRA2) != 0)
2006*4882a593Smuzhiyun 		ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh);
2007*4882a593Smuzhiyun 
2008*4882a593Smuzhiyun 	return (ahc_chip_init(ahc));
2009*4882a593Smuzhiyun }
2010*4882a593Smuzhiyun 
2011*4882a593Smuzhiyun #ifdef CONFIG_PM
2012*4882a593Smuzhiyun void
ahc_pci_resume(struct ahc_softc * ahc)2013*4882a593Smuzhiyun ahc_pci_resume(struct ahc_softc *ahc)
2014*4882a593Smuzhiyun {
2015*4882a593Smuzhiyun 	/*
2016*4882a593Smuzhiyun 	 * We assume that the OS has restored our register
2017*4882a593Smuzhiyun 	 * mappings, etc.  Just update the config space registers
2018*4882a593Smuzhiyun 	 * that the OS doesn't know about and rely on our chip
2019*4882a593Smuzhiyun 	 * reset handler to handle the rest.
2020*4882a593Smuzhiyun 	 */
2021*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
2022*4882a593Smuzhiyun 			     ahc->bus_softc.pci_softc.devconfig, /*bytes*/4);
2023*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
2024*4882a593Smuzhiyun 			     ahc->bus_softc.pci_softc.command, /*bytes*/1);
2025*4882a593Smuzhiyun 	ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
2026*4882a593Smuzhiyun 			     ahc->bus_softc.pci_softc.csize_lattime, /*bytes*/1);
2027*4882a593Smuzhiyun 	if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
2028*4882a593Smuzhiyun 		struct	seeprom_descriptor sd;
2029*4882a593Smuzhiyun 		u_int	sxfrctl1;
2030*4882a593Smuzhiyun 
2031*4882a593Smuzhiyun 		sd.sd_ahc = ahc;
2032*4882a593Smuzhiyun 		sd.sd_control_offset = SEECTL;
2033*4882a593Smuzhiyun 		sd.sd_status_offset = SEECTL;
2034*4882a593Smuzhiyun 		sd.sd_dataout_offset = SEECTL;
2035*4882a593Smuzhiyun 
2036*4882a593Smuzhiyun 		ahc_acquire_seeprom(ahc, &sd);
2037*4882a593Smuzhiyun 		configure_termination(ahc, &sd,
2038*4882a593Smuzhiyun 				      ahc->seep_config->adapter_control,
2039*4882a593Smuzhiyun 				      &sxfrctl1);
2040*4882a593Smuzhiyun 		ahc_release_seeprom(&sd);
2041*4882a593Smuzhiyun 	}
2042*4882a593Smuzhiyun }
2043*4882a593Smuzhiyun #endif
2044*4882a593Smuzhiyun 
2045*4882a593Smuzhiyun static int
ahc_aic785X_setup(struct ahc_softc * ahc)2046*4882a593Smuzhiyun ahc_aic785X_setup(struct ahc_softc *ahc)
2047*4882a593Smuzhiyun {
2048*4882a593Smuzhiyun 	ahc_dev_softc_t pci;
2049*4882a593Smuzhiyun 	uint8_t rev;
2050*4882a593Smuzhiyun 
2051*4882a593Smuzhiyun 	pci = ahc->dev_softc;
2052*4882a593Smuzhiyun 	ahc->channel = 'A';
2053*4882a593Smuzhiyun 	ahc->chip = AHC_AIC7850;
2054*4882a593Smuzhiyun 	ahc->features = AHC_AIC7850_FE;
2055*4882a593Smuzhiyun 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2056*4882a593Smuzhiyun 	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
2057*4882a593Smuzhiyun 	if (rev >= 1)
2058*4882a593Smuzhiyun 		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
2059*4882a593Smuzhiyun 	ahc->instruction_ram_size = 512;
2060*4882a593Smuzhiyun 	return (0);
2061*4882a593Smuzhiyun }
2062*4882a593Smuzhiyun 
2063*4882a593Smuzhiyun static int
ahc_aic7860_setup(struct ahc_softc * ahc)2064*4882a593Smuzhiyun ahc_aic7860_setup(struct ahc_softc *ahc)
2065*4882a593Smuzhiyun {
2066*4882a593Smuzhiyun 	ahc_dev_softc_t pci;
2067*4882a593Smuzhiyun 	uint8_t rev;
2068*4882a593Smuzhiyun 
2069*4882a593Smuzhiyun 	pci = ahc->dev_softc;
2070*4882a593Smuzhiyun 	ahc->channel = 'A';
2071*4882a593Smuzhiyun 	ahc->chip = AHC_AIC7860;
2072*4882a593Smuzhiyun 	ahc->features = AHC_AIC7860_FE;
2073*4882a593Smuzhiyun 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2074*4882a593Smuzhiyun 	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
2075*4882a593Smuzhiyun 	if (rev >= 1)
2076*4882a593Smuzhiyun 		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
2077*4882a593Smuzhiyun 	ahc->instruction_ram_size = 512;
2078*4882a593Smuzhiyun 	return (0);
2079*4882a593Smuzhiyun }
2080*4882a593Smuzhiyun 
2081*4882a593Smuzhiyun static int
ahc_apa1480_setup(struct ahc_softc * ahc)2082*4882a593Smuzhiyun ahc_apa1480_setup(struct ahc_softc *ahc)
2083*4882a593Smuzhiyun {
2084*4882a593Smuzhiyun 	int error;
2085*4882a593Smuzhiyun 
2086*4882a593Smuzhiyun 	error = ahc_aic7860_setup(ahc);
2087*4882a593Smuzhiyun 	if (error != 0)
2088*4882a593Smuzhiyun 		return (error);
2089*4882a593Smuzhiyun 	ahc->features |= AHC_REMOVABLE;
2090*4882a593Smuzhiyun 	return (0);
2091*4882a593Smuzhiyun }
2092*4882a593Smuzhiyun 
2093*4882a593Smuzhiyun static int
ahc_aic7870_setup(struct ahc_softc * ahc)2094*4882a593Smuzhiyun ahc_aic7870_setup(struct ahc_softc *ahc)
2095*4882a593Smuzhiyun {
2096*4882a593Smuzhiyun 
2097*4882a593Smuzhiyun 	ahc->channel = 'A';
2098*4882a593Smuzhiyun 	ahc->chip = AHC_AIC7870;
2099*4882a593Smuzhiyun 	ahc->features = AHC_AIC7870_FE;
2100*4882a593Smuzhiyun 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2101*4882a593Smuzhiyun 	ahc->instruction_ram_size = 512;
2102*4882a593Smuzhiyun 	return (0);
2103*4882a593Smuzhiyun }
2104*4882a593Smuzhiyun 
2105*4882a593Smuzhiyun static int
ahc_aic7870h_setup(struct ahc_softc * ahc)2106*4882a593Smuzhiyun ahc_aic7870h_setup(struct ahc_softc *ahc)
2107*4882a593Smuzhiyun {
2108*4882a593Smuzhiyun 	int error = ahc_aic7870_setup(ahc);
2109*4882a593Smuzhiyun 
2110*4882a593Smuzhiyun 	ahc->features |= AHC_HVD;
2111*4882a593Smuzhiyun 
2112*4882a593Smuzhiyun 	return error;
2113*4882a593Smuzhiyun }
2114*4882a593Smuzhiyun 
2115*4882a593Smuzhiyun static int
ahc_aha394X_setup(struct ahc_softc * ahc)2116*4882a593Smuzhiyun ahc_aha394X_setup(struct ahc_softc *ahc)
2117*4882a593Smuzhiyun {
2118*4882a593Smuzhiyun 	int error;
2119*4882a593Smuzhiyun 
2120*4882a593Smuzhiyun 	error = ahc_aic7870_setup(ahc);
2121*4882a593Smuzhiyun 	if (error == 0)
2122*4882a593Smuzhiyun 		error = ahc_aha394XX_setup(ahc);
2123*4882a593Smuzhiyun 	return (error);
2124*4882a593Smuzhiyun }
2125*4882a593Smuzhiyun 
2126*4882a593Smuzhiyun static int
ahc_aha394Xh_setup(struct ahc_softc * ahc)2127*4882a593Smuzhiyun ahc_aha394Xh_setup(struct ahc_softc *ahc)
2128*4882a593Smuzhiyun {
2129*4882a593Smuzhiyun 	int error = ahc_aha394X_setup(ahc);
2130*4882a593Smuzhiyun 
2131*4882a593Smuzhiyun 	ahc->features |= AHC_HVD;
2132*4882a593Smuzhiyun 
2133*4882a593Smuzhiyun 	return error;
2134*4882a593Smuzhiyun }
2135*4882a593Smuzhiyun 
2136*4882a593Smuzhiyun static int
ahc_aha398X_setup(struct ahc_softc * ahc)2137*4882a593Smuzhiyun ahc_aha398X_setup(struct ahc_softc *ahc)
2138*4882a593Smuzhiyun {
2139*4882a593Smuzhiyun 	int error;
2140*4882a593Smuzhiyun 
2141*4882a593Smuzhiyun 	error = ahc_aic7870_setup(ahc);
2142*4882a593Smuzhiyun 	if (error == 0)
2143*4882a593Smuzhiyun 		error = ahc_aha398XX_setup(ahc);
2144*4882a593Smuzhiyun 	return (error);
2145*4882a593Smuzhiyun }
2146*4882a593Smuzhiyun 
2147*4882a593Smuzhiyun static int
ahc_aha494X_setup(struct ahc_softc * ahc)2148*4882a593Smuzhiyun ahc_aha494X_setup(struct ahc_softc *ahc)
2149*4882a593Smuzhiyun {
2150*4882a593Smuzhiyun 	int error;
2151*4882a593Smuzhiyun 
2152*4882a593Smuzhiyun 	error = ahc_aic7870_setup(ahc);
2153*4882a593Smuzhiyun 	if (error == 0)
2154*4882a593Smuzhiyun 		error = ahc_aha494XX_setup(ahc);
2155*4882a593Smuzhiyun 	return (error);
2156*4882a593Smuzhiyun }
2157*4882a593Smuzhiyun 
2158*4882a593Smuzhiyun static int
ahc_aha494Xh_setup(struct ahc_softc * ahc)2159*4882a593Smuzhiyun ahc_aha494Xh_setup(struct ahc_softc *ahc)
2160*4882a593Smuzhiyun {
2161*4882a593Smuzhiyun 	int error = ahc_aha494X_setup(ahc);
2162*4882a593Smuzhiyun 
2163*4882a593Smuzhiyun 	ahc->features |= AHC_HVD;
2164*4882a593Smuzhiyun 
2165*4882a593Smuzhiyun 	return error;
2166*4882a593Smuzhiyun }
2167*4882a593Smuzhiyun 
2168*4882a593Smuzhiyun static int
ahc_aic7880_setup(struct ahc_softc * ahc)2169*4882a593Smuzhiyun ahc_aic7880_setup(struct ahc_softc *ahc)
2170*4882a593Smuzhiyun {
2171*4882a593Smuzhiyun 	ahc_dev_softc_t pci;
2172*4882a593Smuzhiyun 	uint8_t rev;
2173*4882a593Smuzhiyun 
2174*4882a593Smuzhiyun 	pci = ahc->dev_softc;
2175*4882a593Smuzhiyun 	ahc->channel = 'A';
2176*4882a593Smuzhiyun 	ahc->chip = AHC_AIC7880;
2177*4882a593Smuzhiyun 	ahc->features = AHC_AIC7880_FE;
2178*4882a593Smuzhiyun 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
2179*4882a593Smuzhiyun 	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
2180*4882a593Smuzhiyun 	if (rev >= 1) {
2181*4882a593Smuzhiyun 		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
2182*4882a593Smuzhiyun 	} else {
2183*4882a593Smuzhiyun 		ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2184*4882a593Smuzhiyun 	}
2185*4882a593Smuzhiyun 	ahc->instruction_ram_size = 512;
2186*4882a593Smuzhiyun 	return (0);
2187*4882a593Smuzhiyun }
2188*4882a593Smuzhiyun 
2189*4882a593Smuzhiyun static int
ahc_aic7880h_setup(struct ahc_softc * ahc)2190*4882a593Smuzhiyun ahc_aic7880h_setup(struct ahc_softc *ahc)
2191*4882a593Smuzhiyun {
2192*4882a593Smuzhiyun 	int error = ahc_aic7880_setup(ahc);
2193*4882a593Smuzhiyun 
2194*4882a593Smuzhiyun 	ahc->features |= AHC_HVD;
2195*4882a593Smuzhiyun 
2196*4882a593Smuzhiyun 	return error;
2197*4882a593Smuzhiyun }
2198*4882a593Smuzhiyun 
2199*4882a593Smuzhiyun 
2200*4882a593Smuzhiyun static int
ahc_aha2940Pro_setup(struct ahc_softc * ahc)2201*4882a593Smuzhiyun ahc_aha2940Pro_setup(struct ahc_softc *ahc)
2202*4882a593Smuzhiyun {
2203*4882a593Smuzhiyun 
2204*4882a593Smuzhiyun 	ahc->flags |= AHC_INT50_SPEEDFLEX;
2205*4882a593Smuzhiyun 	return (ahc_aic7880_setup(ahc));
2206*4882a593Smuzhiyun }
2207*4882a593Smuzhiyun 
2208*4882a593Smuzhiyun static int
ahc_aha394XU_setup(struct ahc_softc * ahc)2209*4882a593Smuzhiyun ahc_aha394XU_setup(struct ahc_softc *ahc)
2210*4882a593Smuzhiyun {
2211*4882a593Smuzhiyun 	int error;
2212*4882a593Smuzhiyun 
2213*4882a593Smuzhiyun 	error = ahc_aic7880_setup(ahc);
2214*4882a593Smuzhiyun 	if (error == 0)
2215*4882a593Smuzhiyun 		error = ahc_aha394XX_setup(ahc);
2216*4882a593Smuzhiyun 	return (error);
2217*4882a593Smuzhiyun }
2218*4882a593Smuzhiyun 
2219*4882a593Smuzhiyun static int
ahc_aha394XUh_setup(struct ahc_softc * ahc)2220*4882a593Smuzhiyun ahc_aha394XUh_setup(struct ahc_softc *ahc)
2221*4882a593Smuzhiyun {
2222*4882a593Smuzhiyun 	int error = ahc_aha394XU_setup(ahc);
2223*4882a593Smuzhiyun 
2224*4882a593Smuzhiyun 	ahc->features |= AHC_HVD;
2225*4882a593Smuzhiyun 
2226*4882a593Smuzhiyun 	return error;
2227*4882a593Smuzhiyun }
2228*4882a593Smuzhiyun 
2229*4882a593Smuzhiyun static int
ahc_aha398XU_setup(struct ahc_softc * ahc)2230*4882a593Smuzhiyun ahc_aha398XU_setup(struct ahc_softc *ahc)
2231*4882a593Smuzhiyun {
2232*4882a593Smuzhiyun 	int error;
2233*4882a593Smuzhiyun 
2234*4882a593Smuzhiyun 	error = ahc_aic7880_setup(ahc);
2235*4882a593Smuzhiyun 	if (error == 0)
2236*4882a593Smuzhiyun 		error = ahc_aha398XX_setup(ahc);
2237*4882a593Smuzhiyun 	return (error);
2238*4882a593Smuzhiyun }
2239*4882a593Smuzhiyun 
2240*4882a593Smuzhiyun static int
ahc_aic7890_setup(struct ahc_softc * ahc)2241*4882a593Smuzhiyun ahc_aic7890_setup(struct ahc_softc *ahc)
2242*4882a593Smuzhiyun {
2243*4882a593Smuzhiyun 	ahc_dev_softc_t pci;
2244*4882a593Smuzhiyun 	uint8_t rev;
2245*4882a593Smuzhiyun 
2246*4882a593Smuzhiyun 	pci = ahc->dev_softc;
2247*4882a593Smuzhiyun 	ahc->channel = 'A';
2248*4882a593Smuzhiyun 	ahc->chip = AHC_AIC7890;
2249*4882a593Smuzhiyun 	ahc->features = AHC_AIC7890_FE;
2250*4882a593Smuzhiyun 	ahc->flags |= AHC_NEWEEPROM_FMT;
2251*4882a593Smuzhiyun 	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
2252*4882a593Smuzhiyun 	if (rev == 0)
2253*4882a593Smuzhiyun 		ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG;
2254*4882a593Smuzhiyun 	ahc->instruction_ram_size = 768;
2255*4882a593Smuzhiyun 	return (0);
2256*4882a593Smuzhiyun }
2257*4882a593Smuzhiyun 
2258*4882a593Smuzhiyun static int
ahc_aic7892_setup(struct ahc_softc * ahc)2259*4882a593Smuzhiyun ahc_aic7892_setup(struct ahc_softc *ahc)
2260*4882a593Smuzhiyun {
2261*4882a593Smuzhiyun 
2262*4882a593Smuzhiyun 	ahc->channel = 'A';
2263*4882a593Smuzhiyun 	ahc->chip = AHC_AIC7892;
2264*4882a593Smuzhiyun 	ahc->features = AHC_AIC7892_FE;
2265*4882a593Smuzhiyun 	ahc->flags |= AHC_NEWEEPROM_FMT;
2266*4882a593Smuzhiyun 	ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
2267*4882a593Smuzhiyun 	ahc->instruction_ram_size = 1024;
2268*4882a593Smuzhiyun 	return (0);
2269*4882a593Smuzhiyun }
2270*4882a593Smuzhiyun 
2271*4882a593Smuzhiyun static int
ahc_aic7895_setup(struct ahc_softc * ahc)2272*4882a593Smuzhiyun ahc_aic7895_setup(struct ahc_softc *ahc)
2273*4882a593Smuzhiyun {
2274*4882a593Smuzhiyun 	ahc_dev_softc_t pci;
2275*4882a593Smuzhiyun 	uint8_t rev;
2276*4882a593Smuzhiyun 
2277*4882a593Smuzhiyun 	pci = ahc->dev_softc;
2278*4882a593Smuzhiyun 	ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
2279*4882a593Smuzhiyun 	/*
2280*4882a593Smuzhiyun 	 * The 'C' revision of the aic7895 has a few additional features.
2281*4882a593Smuzhiyun 	 */
2282*4882a593Smuzhiyun 	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
2283*4882a593Smuzhiyun 	if (rev >= 4) {
2284*4882a593Smuzhiyun 		ahc->chip = AHC_AIC7895C;
2285*4882a593Smuzhiyun 		ahc->features = AHC_AIC7895C_FE;
2286*4882a593Smuzhiyun 	} else  {
2287*4882a593Smuzhiyun 		u_int command;
2288*4882a593Smuzhiyun 
2289*4882a593Smuzhiyun 		ahc->chip = AHC_AIC7895;
2290*4882a593Smuzhiyun 		ahc->features = AHC_AIC7895_FE;
2291*4882a593Smuzhiyun 
2292*4882a593Smuzhiyun 		/*
2293*4882a593Smuzhiyun 		 * The BIOS disables the use of MWI transactions
2294*4882a593Smuzhiyun 		 * since it does not have the MWI bug work around
2295*4882a593Smuzhiyun 		 * we have.  Disabling MWI reduces performance, so
2296*4882a593Smuzhiyun 		 * turn it on again.
2297*4882a593Smuzhiyun 		 */
2298*4882a593Smuzhiyun 		command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1);
2299*4882a593Smuzhiyun 		command |= PCIM_CMD_MWRICEN;
2300*4882a593Smuzhiyun 		ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1);
2301*4882a593Smuzhiyun 		ahc->bugs |= AHC_PCI_MWI_BUG;
2302*4882a593Smuzhiyun 	}
2303*4882a593Smuzhiyun 	/*
2304*4882a593Smuzhiyun 	 * XXX Does CACHETHEN really not work???  What about PCI retry?
2305*4882a593Smuzhiyun 	 * on C level chips.  Need to test, but for now, play it safe.
2306*4882a593Smuzhiyun 	 */
2307*4882a593Smuzhiyun 	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG
2308*4882a593Smuzhiyun 		  |  AHC_CACHETHEN_BUG;
2309*4882a593Smuzhiyun 
2310*4882a593Smuzhiyun #if 0
2311*4882a593Smuzhiyun 	uint32_t devconfig;
2312*4882a593Smuzhiyun 
2313*4882a593Smuzhiyun 	/*
2314*4882a593Smuzhiyun 	 * Cachesize must also be zero due to stray DAC
2315*4882a593Smuzhiyun 	 * problem when sitting behind some bridges.
2316*4882a593Smuzhiyun 	 */
2317*4882a593Smuzhiyun 	ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1);
2318*4882a593Smuzhiyun 	devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1);
2319*4882a593Smuzhiyun 	devconfig |= MRDCEN;
2320*4882a593Smuzhiyun 	ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1);
2321*4882a593Smuzhiyun #endif
2322*4882a593Smuzhiyun 	ahc->flags |= AHC_NEWEEPROM_FMT;
2323*4882a593Smuzhiyun 	ahc->instruction_ram_size = 512;
2324*4882a593Smuzhiyun 	return (0);
2325*4882a593Smuzhiyun }
2326*4882a593Smuzhiyun 
2327*4882a593Smuzhiyun static int
ahc_aic7895h_setup(struct ahc_softc * ahc)2328*4882a593Smuzhiyun ahc_aic7895h_setup(struct ahc_softc *ahc)
2329*4882a593Smuzhiyun {
2330*4882a593Smuzhiyun 	int error = ahc_aic7895_setup(ahc);
2331*4882a593Smuzhiyun 
2332*4882a593Smuzhiyun 	ahc->features |= AHC_HVD;
2333*4882a593Smuzhiyun 
2334*4882a593Smuzhiyun 	return error;
2335*4882a593Smuzhiyun }
2336*4882a593Smuzhiyun 
2337*4882a593Smuzhiyun static int
ahc_aic7896_setup(struct ahc_softc * ahc)2338*4882a593Smuzhiyun ahc_aic7896_setup(struct ahc_softc *ahc)
2339*4882a593Smuzhiyun {
2340*4882a593Smuzhiyun 	ahc_dev_softc_t pci;
2341*4882a593Smuzhiyun 
2342*4882a593Smuzhiyun 	pci = ahc->dev_softc;
2343*4882a593Smuzhiyun 	ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
2344*4882a593Smuzhiyun 	ahc->chip = AHC_AIC7896;
2345*4882a593Smuzhiyun 	ahc->features = AHC_AIC7896_FE;
2346*4882a593Smuzhiyun 	ahc->flags |= AHC_NEWEEPROM_FMT;
2347*4882a593Smuzhiyun 	ahc->bugs |= AHC_CACHETHEN_DIS_BUG;
2348*4882a593Smuzhiyun 	ahc->instruction_ram_size = 768;
2349*4882a593Smuzhiyun 	return (0);
2350*4882a593Smuzhiyun }
2351*4882a593Smuzhiyun 
2352*4882a593Smuzhiyun static int
ahc_aic7899_setup(struct ahc_softc * ahc)2353*4882a593Smuzhiyun ahc_aic7899_setup(struct ahc_softc *ahc)
2354*4882a593Smuzhiyun {
2355*4882a593Smuzhiyun 	ahc_dev_softc_t pci;
2356*4882a593Smuzhiyun 
2357*4882a593Smuzhiyun 	pci = ahc->dev_softc;
2358*4882a593Smuzhiyun 	ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
2359*4882a593Smuzhiyun 	ahc->chip = AHC_AIC7899;
2360*4882a593Smuzhiyun 	ahc->features = AHC_AIC7899_FE;
2361*4882a593Smuzhiyun 	ahc->flags |= AHC_NEWEEPROM_FMT;
2362*4882a593Smuzhiyun 	ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
2363*4882a593Smuzhiyun 	ahc->instruction_ram_size = 1024;
2364*4882a593Smuzhiyun 	return (0);
2365*4882a593Smuzhiyun }
2366*4882a593Smuzhiyun 
2367*4882a593Smuzhiyun static int
ahc_aha29160C_setup(struct ahc_softc * ahc)2368*4882a593Smuzhiyun ahc_aha29160C_setup(struct ahc_softc *ahc)
2369*4882a593Smuzhiyun {
2370*4882a593Smuzhiyun 	int error;
2371*4882a593Smuzhiyun 
2372*4882a593Smuzhiyun 	error = ahc_aic7899_setup(ahc);
2373*4882a593Smuzhiyun 	if (error != 0)
2374*4882a593Smuzhiyun 		return (error);
2375*4882a593Smuzhiyun 	ahc->features |= AHC_REMOVABLE;
2376*4882a593Smuzhiyun 	return (0);
2377*4882a593Smuzhiyun }
2378*4882a593Smuzhiyun 
2379*4882a593Smuzhiyun static int
ahc_raid_setup(struct ahc_softc * ahc)2380*4882a593Smuzhiyun ahc_raid_setup(struct ahc_softc *ahc)
2381*4882a593Smuzhiyun {
2382*4882a593Smuzhiyun 	printk("RAID functionality unsupported\n");
2383*4882a593Smuzhiyun 	return (ENXIO);
2384*4882a593Smuzhiyun }
2385*4882a593Smuzhiyun 
2386*4882a593Smuzhiyun static int
ahc_aha394XX_setup(struct ahc_softc * ahc)2387*4882a593Smuzhiyun ahc_aha394XX_setup(struct ahc_softc *ahc)
2388*4882a593Smuzhiyun {
2389*4882a593Smuzhiyun 	ahc_dev_softc_t pci;
2390*4882a593Smuzhiyun 
2391*4882a593Smuzhiyun 	pci = ahc->dev_softc;
2392*4882a593Smuzhiyun 	switch (ahc_get_pci_slot(pci)) {
2393*4882a593Smuzhiyun 	case AHC_394X_SLOT_CHANNEL_A:
2394*4882a593Smuzhiyun 		ahc->channel = 'A';
2395*4882a593Smuzhiyun 		break;
2396*4882a593Smuzhiyun 	case AHC_394X_SLOT_CHANNEL_B:
2397*4882a593Smuzhiyun 		ahc->channel = 'B';
2398*4882a593Smuzhiyun 		break;
2399*4882a593Smuzhiyun 	default:
2400*4882a593Smuzhiyun 		printk("adapter at unexpected slot %d\n"
2401*4882a593Smuzhiyun 		       "unable to map to a channel\n",
2402*4882a593Smuzhiyun 		       ahc_get_pci_slot(pci));
2403*4882a593Smuzhiyun 		ahc->channel = 'A';
2404*4882a593Smuzhiyun 	}
2405*4882a593Smuzhiyun 	return (0);
2406*4882a593Smuzhiyun }
2407*4882a593Smuzhiyun 
2408*4882a593Smuzhiyun static int
ahc_aha398XX_setup(struct ahc_softc * ahc)2409*4882a593Smuzhiyun ahc_aha398XX_setup(struct ahc_softc *ahc)
2410*4882a593Smuzhiyun {
2411*4882a593Smuzhiyun 	ahc_dev_softc_t pci;
2412*4882a593Smuzhiyun 
2413*4882a593Smuzhiyun 	pci = ahc->dev_softc;
2414*4882a593Smuzhiyun 	switch (ahc_get_pci_slot(pci)) {
2415*4882a593Smuzhiyun 	case AHC_398X_SLOT_CHANNEL_A:
2416*4882a593Smuzhiyun 		ahc->channel = 'A';
2417*4882a593Smuzhiyun 		break;
2418*4882a593Smuzhiyun 	case AHC_398X_SLOT_CHANNEL_B:
2419*4882a593Smuzhiyun 		ahc->channel = 'B';
2420*4882a593Smuzhiyun 		break;
2421*4882a593Smuzhiyun 	case AHC_398X_SLOT_CHANNEL_C:
2422*4882a593Smuzhiyun 		ahc->channel = 'C';
2423*4882a593Smuzhiyun 		break;
2424*4882a593Smuzhiyun 	default:
2425*4882a593Smuzhiyun 		printk("adapter at unexpected slot %d\n"
2426*4882a593Smuzhiyun 		       "unable to map to a channel\n",
2427*4882a593Smuzhiyun 		       ahc_get_pci_slot(pci));
2428*4882a593Smuzhiyun 		ahc->channel = 'A';
2429*4882a593Smuzhiyun 		break;
2430*4882a593Smuzhiyun 	}
2431*4882a593Smuzhiyun 	ahc->flags |= AHC_LARGE_SEEPROM;
2432*4882a593Smuzhiyun 	return (0);
2433*4882a593Smuzhiyun }
2434*4882a593Smuzhiyun 
2435*4882a593Smuzhiyun static int
ahc_aha494XX_setup(struct ahc_softc * ahc)2436*4882a593Smuzhiyun ahc_aha494XX_setup(struct ahc_softc *ahc)
2437*4882a593Smuzhiyun {
2438*4882a593Smuzhiyun 	ahc_dev_softc_t pci;
2439*4882a593Smuzhiyun 
2440*4882a593Smuzhiyun 	pci = ahc->dev_softc;
2441*4882a593Smuzhiyun 	switch (ahc_get_pci_slot(pci)) {
2442*4882a593Smuzhiyun 	case AHC_494X_SLOT_CHANNEL_A:
2443*4882a593Smuzhiyun 		ahc->channel = 'A';
2444*4882a593Smuzhiyun 		break;
2445*4882a593Smuzhiyun 	case AHC_494X_SLOT_CHANNEL_B:
2446*4882a593Smuzhiyun 		ahc->channel = 'B';
2447*4882a593Smuzhiyun 		break;
2448*4882a593Smuzhiyun 	case AHC_494X_SLOT_CHANNEL_C:
2449*4882a593Smuzhiyun 		ahc->channel = 'C';
2450*4882a593Smuzhiyun 		break;
2451*4882a593Smuzhiyun 	case AHC_494X_SLOT_CHANNEL_D:
2452*4882a593Smuzhiyun 		ahc->channel = 'D';
2453*4882a593Smuzhiyun 		break;
2454*4882a593Smuzhiyun 	default:
2455*4882a593Smuzhiyun 		printk("adapter at unexpected slot %d\n"
2456*4882a593Smuzhiyun 		       "unable to map to a channel\n",
2457*4882a593Smuzhiyun 		       ahc_get_pci_slot(pci));
2458*4882a593Smuzhiyun 		ahc->channel = 'A';
2459*4882a593Smuzhiyun 	}
2460*4882a593Smuzhiyun 	ahc->flags |= AHC_LARGE_SEEPROM;
2461*4882a593Smuzhiyun 	return (0);
2462*4882a593Smuzhiyun }
2463