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