aic7xxx_pci.c revision 72325
165942Sgibbs/*
265942Sgibbs * Product specific probe and attach routines for:
365942Sgibbs *      3940, 2940, aic7895, aic7890, aic7880,
465942Sgibbs *	aic7870, aic7860 and aic7850 SCSI controllers
565942Sgibbs *
671717Sgibbs * Copyright (c) 1995-2000 Justin T. Gibbs
765942Sgibbs * All rights reserved.
865942Sgibbs *
965942Sgibbs * Redistribution and use in source and binary forms, with or without
1065942Sgibbs * modification, are permitted provided that the following conditions
1165942Sgibbs * are met:
1265942Sgibbs * 1. Redistributions of source code must retain the above copyright
1365942Sgibbs *    notice, this list of conditions, and the following disclaimer,
1465942Sgibbs *    without modification, immediately at the beginning of the file.
1565942Sgibbs * 2. The name of the author may not be used to endorse or promote products
1665942Sgibbs *    derived from this software without specific prior written permission.
1765942Sgibbs *
1865942Sgibbs * Alternatively, this software may be distributed under the terms of the
1965942Sgibbs * GNU Public License ("GPL").
2065942Sgibbs *
2165942Sgibbs * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2265942Sgibbs * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2365942Sgibbs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2465942Sgibbs * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
2565942Sgibbs * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2665942Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2765942Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2865942Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
2965942Sgibbs * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3065942Sgibbs * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3165942Sgibbs * SUCH DAMAGE.
3265942Sgibbs *
3371390Sgibbs * $Id: //depot/src/aic7xxx/aic7xxx_pci.c#12 $
3465942Sgibbs *
3565942Sgibbs * $FreeBSD: head/sys/dev/aic7xxx/aic7xxx_pci.c 72325 2001-02-10 18:04:27Z gibbs $
3665942Sgibbs */
3765942Sgibbs
3865942Sgibbs#ifdef	__linux__
3965942Sgibbs#include "aic7xxx_linux.h"
4065942Sgibbs#include "aic7xxx_inline.h"
4165942Sgibbs#include "aic7xxx_93cx6.h"
4265942Sgibbs#endif
4365942Sgibbs
4465942Sgibbs#ifdef	__FreeBSD__
4565942Sgibbs#include <dev/aic7xxx/aic7xxx_freebsd.h>
4665942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h>
4765942Sgibbs#include <dev/aic7xxx/aic7xxx_93cx6.h>
4865942Sgibbs#endif
4965942Sgibbs
5065942Sgibbs#define AHC_PCI_IOADDR	PCIR_MAPS	/* I/O Address */
5165942Sgibbs#define AHC_PCI_MEMADDR	(PCIR_MAPS + 4)	/* Mem I/O Address */
5265942Sgibbs
5365942Sgibbsstatic __inline uint64_t
5465942Sgibbsahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
5565942Sgibbs{
5665942Sgibbs	uint64_t id;
5765942Sgibbs
5865942Sgibbs	id = subvendor
5965942Sgibbs	   | (subdevice << 16)
6065942Sgibbs	   | ((uint64_t)vendor << 32)
6165942Sgibbs	   | ((uint64_t)device << 48);
6265942Sgibbs
6365942Sgibbs	return (id);
6465942Sgibbs}
6565942Sgibbs
6665942Sgibbs#define ID_ALL_MASK		0xFFFFFFFFFFFFFFFFull
6765942Sgibbs#define ID_DEV_VENDOR_MASK	0xFFFFFFFF00000000ull
6872325Sgibbs#define ID_9005_GENERIC_MASK	0xFFF0FFFF00000000ull
6965942Sgibbs#define ID_AIC7850		0x5078900400000000ull
7065942Sgibbs#define ID_AHA_2910_15_20_30C	0x5078900478509004ull
7165942Sgibbs#define ID_AIC7855		0x5578900400000000ull
7265942Sgibbs#define ID_AIC7859		0x3860900400000000ull
7365942Sgibbs#define ID_AHA_2930CU		0x3860900438699004ull
7465942Sgibbs#define ID_AIC7860		0x6078900400000000ull
7565942Sgibbs#define ID_AIC7860C		0x6078900478609004ull
7665942Sgibbs#define ID_AHA_1480A		0x6075900400000000ull
7765942Sgibbs#define ID_AHA_2940AU_0		0x6178900400000000ull
7865942Sgibbs#define ID_AHA_2940AU_1		0x6178900478619004ull
7965942Sgibbs#define ID_AHA_2940AU_CN	0x2178900478219004ull
8065942Sgibbs#define ID_AHA_2930C_VAR	0x6038900438689004ull
8165942Sgibbs
8265942Sgibbs#define ID_AIC7870		0x7078900400000000ull
8365942Sgibbs#define ID_AHA_2940		0x7178900400000000ull
8465942Sgibbs#define ID_AHA_3940		0x7278900400000000ull
8565942Sgibbs#define ID_AHA_398X		0x7378900400000000ull
8665942Sgibbs#define ID_AHA_2944		0x7478900400000000ull
8765942Sgibbs#define ID_AHA_3944		0x7578900400000000ull
8865942Sgibbs#define ID_AHA_4944		0x7678900400000000ull
8965942Sgibbs
9065942Sgibbs#define ID_AIC7880		0x8078900400000000ull
9165942Sgibbs#define ID_AIC7880_B		0x8078900478809004ull
9265942Sgibbs#define ID_AHA_2940U		0x8178900400000000ull
9365942Sgibbs#define ID_AHA_3940U		0x8278900400000000ull
9465942Sgibbs#define ID_AHA_2944U		0x8478900400000000ull
9565942Sgibbs#define ID_AHA_3944U		0x8578900400000000ull
9665942Sgibbs#define ID_AHA_398XU		0x8378900400000000ull
9765942Sgibbs#define ID_AHA_4944U		0x8678900400000000ull
9865942Sgibbs#define ID_AHA_2940UB		0x8178900478819004ull
9965942Sgibbs#define ID_AHA_2930U		0x8878900478889004ull
10065942Sgibbs#define ID_AHA_2940U_PRO	0x8778900478879004ull
10165942Sgibbs#define ID_AHA_2940U_CN		0x0078900478009004ull
10265942Sgibbs
10365942Sgibbs#define ID_AIC7895		0x7895900478959004ull
10465942Sgibbs#define ID_AIC7895_RAID_PORT	0x7893900478939004ull
10565942Sgibbs#define ID_AHA_2940U_DUAL	0x7895900478919004ull
10665942Sgibbs#define ID_AHA_3940AU		0x7895900478929004ull
10765942Sgibbs#define ID_AHA_3944AU		0x7895900478949004ull
10865942Sgibbs
10965942Sgibbs#define ID_AIC7890		0x001F9005000F9005ull
11065942Sgibbs#define ID_AAA_131U2		0x0013900500039005ull
11165942Sgibbs#define ID_AHA_2930U2		0x0011900501819005ull
11265942Sgibbs#define ID_AHA_2940U2B		0x00109005A1009005ull
11365942Sgibbs#define ID_AHA_2940U2_OEM	0x0010900521809005ull
11465942Sgibbs#define ID_AHA_2940U2		0x00109005A1809005ull
11565942Sgibbs#define ID_AHA_2950U2B		0x00109005E1009005ull
11665942Sgibbs
11765942Sgibbs#define ID_AIC7892		0x008F9005FFFF9005ull
11865942Sgibbs#define ID_AHA_29160		0x00809005E2A09005ull
11965942Sgibbs#define ID_AHA_29160_CPQ	0x00809005E2A00E11ull
12065942Sgibbs#define ID_AHA_29160N		0x0080900562A09005ull
12170204Sgibbs#define ID_AHA_29160C		0x0080900562209005ull
12265942Sgibbs#define ID_AHA_29160B		0x00809005E2209005ull
12365942Sgibbs#define ID_AHA_19160B		0x0081900562A19005ull
12465942Sgibbs
12565942Sgibbs#define ID_AIC7896		0x005F9005FFFF9005ull
12665942Sgibbs#define ID_AHA_3950U2B_0	0x00509005FFFF9005ull
12765942Sgibbs#define ID_AHA_3950U2B_1	0x00509005F5009005ull
12865942Sgibbs#define ID_AHA_3950U2D_0	0x00519005FFFF9005ull
12965942Sgibbs#define ID_AHA_3950U2D_1	0x00519005B5009005ull
13065942Sgibbs
13165942Sgibbs#define ID_AIC7899		0x00CF9005FFFF9005ull
13265942Sgibbs#define ID_AHA_3960D		0x00C09005F6209005ull /* AKA AHA-39160 */
13365942Sgibbs#define ID_AHA_3960D_CPQ	0x00C09005F6200E11ull
13465942Sgibbs
13565942Sgibbs#define ID_AIC7810		0x1078900400000000ull
13665942Sgibbs#define ID_AIC7815		0x7815900400000000ull
13765942Sgibbs
13872325Sgibbs#define DEVID_9005_TYPE(id) ((id) & 0xF)
13972325Sgibbs#define		DEVID_9005_TYPE_HBA		0x0	/* Standard Card */
14072325Sgibbs#define		DEVID_9005_TYPE_AAA		0x3	/* RAID Card */
14172325Sgibbs#define		DEVID_9005_TYPE_SISL		0x5	/* Low Cost Card */
14272325Sgibbs#define		DEVID_9005_TYPE_MB		0xF	/* On Motherboard */
14372325Sgibbs
14472325Sgibbs#define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
14572325Sgibbs#define		DEVID_9005_MAXRATE_U160		0x0
14672325Sgibbs#define		DEVID_9005_MAXRATE_ULTRA2	0x1
14772325Sgibbs#define		DEVID_9005_MAXRATE_ULTRA	0x2
14872325Sgibbs#define		DEVID_9005_MAXRATE_FAST		0x3
14972325Sgibbs
15072325Sgibbs#define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6)
15172325Sgibbs
15272325Sgibbs#define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8)
15372325Sgibbs#define		DEVID_9005_CLASS_SPI		0x0	/* Parallel SCSI */
15472325Sgibbs
15570693Sgibbs#define SUBID_9005_TYPE(id) ((id) & 0xF)
15670693Sgibbs#define		SUBID_9005_TYPE_MB		0xF	/* On Motherboard */
15770693Sgibbs#define		SUBID_9005_TYPE_CARD		0x0	/* Standard Card */
15870693Sgibbs#define		SUBID_9005_TYPE_LCCARD		0x1	/* Low Cost Card */
15970693Sgibbs#define		SUBID_9005_TYPE_RAID		0x3	/* Combined with Raid */
16070204Sgibbs
16170693Sgibbs#define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
16270693Sgibbs#define		SUBID_9005_MAXRATE_ULTRA2	0x0
16370693Sgibbs#define		SUBID_9005_MAXRATE_ULTRA	0x1
16470693Sgibbs#define		SUBID_9005_MAXRATE_U160		0x2
16570693Sgibbs#define		SUBID_9005_MAXRATE_RESERVED	0x3
16670693Sgibbs
16770693Sgibbs#define SUBID_9005_SEEPTYPE(id)						\
16870693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
16970693Sgibbs	 ? ((id) & 0xC0) >> 6						\
17070693Sgibbs	 : ((id) & 0x300) >> 8)
17170693Sgibbs#define		SUBID_9005_SEEPTYPE_NONE	0x0
17270693Sgibbs#define		SUBID_9005_SEEPTYPE_1K		0x1
17370693Sgibbs#define		SUBID_9005_SEEPTYPE_2K_4K	0x2
17470693Sgibbs#define		SUBID_9005_SEEPTYPE_RESERVED	0x3
17570693Sgibbs#define SUBID_9005_AUTOTERM(id)						\
17670693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
17770693Sgibbs	 ? (((id) & 0x400) >> 10) == 0					\
17870693Sgibbs	 : (((id) & 0x40) >> 6) == 0)
17970693Sgibbs
18070693Sgibbs#define SUBID_9005_NUMCHAN(id)						\
18170693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
18270693Sgibbs	 ? ((id) & 0x300) >> 8						\
18370693Sgibbs	 : ((id) & 0xC00) >> 10)
18470693Sgibbs
18570693Sgibbs#define SUBID_9005_LEGACYCONN(id)					\
18670693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
18770693Sgibbs	 ? 0								\
18870693Sgibbs	 : ((id) & 0x80) >> 7)
18970693Sgibbs
19070693Sgibbs#define SUBID_9005_MFUNCENB(id)						\
19170693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
19270693Sgibbs	 ? ((id) & 0x800) >> 11						\
19370693Sgibbs	 : ((id) & 0x1000) >> 12)
19470693Sgibbs/*
19570693Sgibbs * Informational only. Should use chip register to be
19670693Sgibbs * ceratian, but may be use in identification strings.
19770693Sgibbs */
19870693Sgibbs#define SUBID_9005_CARD_SCSIWIDTH_MASK	0x2000
19970693Sgibbs#define SUBID_9005_CARD_PCIWIDTH_MASK	0x4000
20070693Sgibbs#define SUBID_9005_CARD_SEDIFF_MASK	0x8000
20170693Sgibbs
20265942Sgibbsstatic ahc_device_setup_t ahc_aic7850_setup;
20365942Sgibbsstatic ahc_device_setup_t ahc_aic7855_setup;
20465942Sgibbsstatic ahc_device_setup_t ahc_aic7860_setup;
20571390Sgibbsstatic ahc_device_setup_t ahc_apa1480_setup;
20665942Sgibbsstatic ahc_device_setup_t ahc_aic7870_setup;
20765942Sgibbsstatic ahc_device_setup_t ahc_aha394X_setup;
20865942Sgibbsstatic ahc_device_setup_t ahc_aha494X_setup;
20965942Sgibbsstatic ahc_device_setup_t ahc_aha398X_setup;
21065942Sgibbsstatic ahc_device_setup_t ahc_aic7880_setup;
21171390Sgibbsstatic ahc_device_setup_t ahc_aha2940Pro_setup;
21265942Sgibbsstatic ahc_device_setup_t ahc_aha394XU_setup;
21365942Sgibbsstatic ahc_device_setup_t ahc_aha398XU_setup;
21465942Sgibbsstatic ahc_device_setup_t ahc_aic7890_setup;
21565942Sgibbsstatic ahc_device_setup_t ahc_aic7892_setup;
21665942Sgibbsstatic ahc_device_setup_t ahc_aic7895_setup;
21765942Sgibbsstatic ahc_device_setup_t ahc_aic7896_setup;
21865942Sgibbsstatic ahc_device_setup_t ahc_aic7899_setup;
21971390Sgibbsstatic ahc_device_setup_t ahc_aha29160C_setup;
22065942Sgibbsstatic ahc_device_setup_t ahc_raid_setup;
22165942Sgibbsstatic ahc_device_setup_t ahc_aha394XX_setup;
22265942Sgibbsstatic ahc_device_setup_t ahc_aha494XX_setup;
22365942Sgibbsstatic ahc_device_setup_t ahc_aha398XX_setup;
22465942Sgibbs
22565942Sgibbsstruct ahc_pci_identity ahc_pci_ident_table [] =
22665942Sgibbs{
22765942Sgibbs	/* aic7850 based controllers */
22865942Sgibbs	{
22965942Sgibbs		ID_AHA_2910_15_20_30C,
23065942Sgibbs		ID_ALL_MASK,
23165942Sgibbs		"Adaptec 2910/15/20/30C SCSI adapter",
23265942Sgibbs		ahc_aic7850_setup
23365942Sgibbs	},
23465942Sgibbs	/* aic7860 based controllers */
23565942Sgibbs	{
23665942Sgibbs		ID_AHA_2930CU,
23765942Sgibbs		ID_ALL_MASK,
23865942Sgibbs		"Adaptec 2930CU SCSI adapter",
23965942Sgibbs		ahc_aic7860_setup
24065942Sgibbs	},
24165942Sgibbs	{
24265942Sgibbs		ID_AHA_1480A & ID_DEV_VENDOR_MASK,
24365942Sgibbs		ID_DEV_VENDOR_MASK,
24465942Sgibbs		"Adaptec 1480A Ultra SCSI adapter",
24571390Sgibbs		ahc_apa1480_setup
24665942Sgibbs	},
24765942Sgibbs	{
24865942Sgibbs		ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK,
24965942Sgibbs		ID_DEV_VENDOR_MASK,
25065942Sgibbs		"Adaptec 2940A Ultra SCSI adapter",
25165942Sgibbs		ahc_aic7860_setup
25265942Sgibbs	},
25365942Sgibbs	{
25465942Sgibbs		ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK,
25565942Sgibbs		ID_DEV_VENDOR_MASK,
25665942Sgibbs		"Adaptec 2940A/CN Ultra SCSI adapter",
25765942Sgibbs		ahc_aic7860_setup
25865942Sgibbs	},
25965942Sgibbs	{
26065942Sgibbs		ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK,
26165942Sgibbs		ID_DEV_VENDOR_MASK,
26265942Sgibbs		"Adaptec 2930C SCSI adapter (VAR)",
26365942Sgibbs		ahc_aic7860_setup
26465942Sgibbs	},
26565942Sgibbs	/* aic7870 based controllers */
26665942Sgibbs	{
26765942Sgibbs		ID_AHA_2940,
26865942Sgibbs		ID_ALL_MASK,
26965942Sgibbs		"Adaptec 2940 SCSI adapter",
27065942Sgibbs		ahc_aic7870_setup
27165942Sgibbs	},
27265942Sgibbs	{
27365942Sgibbs		ID_AHA_3940,
27465942Sgibbs		ID_ALL_MASK,
27565942Sgibbs		"Adaptec 3940 SCSI adapter",
27665942Sgibbs		ahc_aha394X_setup
27765942Sgibbs	},
27865942Sgibbs	{
27965942Sgibbs		ID_AHA_398X,
28065942Sgibbs		ID_ALL_MASK,
28165942Sgibbs		"Adaptec 398X SCSI RAID adapter",
28265942Sgibbs		ahc_aha398X_setup
28365942Sgibbs	},
28465942Sgibbs	{
28565942Sgibbs		ID_AHA_2944,
28665942Sgibbs		ID_ALL_MASK,
28765942Sgibbs		"Adaptec 2944 SCSI adapter",
28865942Sgibbs		ahc_aic7870_setup
28965942Sgibbs	},
29065942Sgibbs	{
29165942Sgibbs		ID_AHA_3944,
29265942Sgibbs		ID_ALL_MASK,
29365942Sgibbs		"Adaptec 3944 SCSI adapter",
29465942Sgibbs		ahc_aha394X_setup
29565942Sgibbs	},
29665942Sgibbs	{
29765942Sgibbs		ID_AHA_4944,
29865942Sgibbs		ID_ALL_MASK,
29965942Sgibbs		"Adaptec 4944 SCSI adapter",
30065942Sgibbs		ahc_aha494X_setup
30165942Sgibbs	},
30265942Sgibbs	/* aic7880 based controllers */
30365942Sgibbs	{
30465942Sgibbs		ID_AHA_2940U & ID_DEV_VENDOR_MASK,
30565942Sgibbs		ID_DEV_VENDOR_MASK,
30665942Sgibbs		"Adaptec 2940 Ultra SCSI adapter",
30765942Sgibbs		ahc_aic7880_setup
30865942Sgibbs	},
30965942Sgibbs	{
31065942Sgibbs		ID_AHA_3940U & ID_DEV_VENDOR_MASK,
31165942Sgibbs		ID_DEV_VENDOR_MASK,
31265942Sgibbs		"Adaptec 3940 Ultra SCSI adapter",
31365942Sgibbs		ahc_aha394XU_setup
31465942Sgibbs	},
31565942Sgibbs	{
31665942Sgibbs		ID_AHA_2944U & ID_DEV_VENDOR_MASK,
31765942Sgibbs		ID_DEV_VENDOR_MASK,
31865942Sgibbs		"Adaptec 2944 Ultra SCSI adapter",
31965942Sgibbs		ahc_aic7880_setup
32065942Sgibbs	},
32165942Sgibbs	{
32265942Sgibbs		ID_AHA_3944U & ID_DEV_VENDOR_MASK,
32365942Sgibbs		ID_DEV_VENDOR_MASK,
32465942Sgibbs		"Adaptec 3944 Ultra SCSI adapter",
32565942Sgibbs		ahc_aha394XU_setup
32665942Sgibbs	},
32765942Sgibbs	{
32865942Sgibbs		ID_AHA_398XU & ID_DEV_VENDOR_MASK,
32965942Sgibbs		ID_DEV_VENDOR_MASK,
33065942Sgibbs		"Adaptec 398X Ultra SCSI RAID adapter",
33165942Sgibbs		ahc_aha398XU_setup
33265942Sgibbs	},
33365942Sgibbs	{
33465942Sgibbs		/*
33565942Sgibbs		 * XXX Don't know the slot numbers
33665942Sgibbs		 * so we can't identify channels
33765942Sgibbs		 */
33865942Sgibbs		ID_AHA_4944U & ID_DEV_VENDOR_MASK,
33965942Sgibbs		ID_DEV_VENDOR_MASK,
34065942Sgibbs		"Adaptec 4944 Ultra SCSI adapter",
34165942Sgibbs		ahc_aic7880_setup
34265942Sgibbs	},
34365942Sgibbs	{
34465942Sgibbs		ID_AHA_2930U & ID_DEV_VENDOR_MASK,
34565942Sgibbs		ID_DEV_VENDOR_MASK,
34665942Sgibbs		"Adaptec 2930 Ultra SCSI adapter",
34765942Sgibbs		ahc_aic7880_setup
34865942Sgibbs	},
34965942Sgibbs	{
35065942Sgibbs		ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK,
35165942Sgibbs		ID_DEV_VENDOR_MASK,
35265942Sgibbs		"Adaptec 2940 Pro Ultra SCSI adapter",
35371390Sgibbs		ahc_aha2940Pro_setup
35465942Sgibbs	},
35565942Sgibbs	{
35665942Sgibbs		ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK,
35765942Sgibbs		ID_DEV_VENDOR_MASK,
35865942Sgibbs		"Adaptec 2940/CN Ultra SCSI adapter",
35965942Sgibbs		ahc_aic7880_setup
36065942Sgibbs	},
36165942Sgibbs	/* aic7890 based controllers */
36265942Sgibbs	{
36365942Sgibbs		ID_AHA_2930U2,
36465942Sgibbs		ID_ALL_MASK,
36565942Sgibbs		"Adaptec 2930 Ultra2 SCSI adapter",
36665942Sgibbs		ahc_aic7890_setup
36765942Sgibbs	},
36865942Sgibbs	{
36965942Sgibbs		ID_AHA_2940U2B,
37065942Sgibbs		ID_ALL_MASK,
37165942Sgibbs		"Adaptec 2940B Ultra2 SCSI adapter",
37265942Sgibbs		ahc_aic7890_setup
37365942Sgibbs	},
37465942Sgibbs	{
37565942Sgibbs		ID_AHA_2940U2_OEM,
37665942Sgibbs		ID_ALL_MASK,
37765942Sgibbs		"Adaptec 2940 Ultra2 SCSI adapter (OEM)",
37865942Sgibbs		ahc_aic7890_setup
37965942Sgibbs	},
38065942Sgibbs	{
38165942Sgibbs		ID_AHA_2940U2,
38265942Sgibbs		ID_ALL_MASK,
38365942Sgibbs		"Adaptec 2940 Ultra2 SCSI adapter",
38465942Sgibbs		ahc_aic7890_setup
38565942Sgibbs	},
38665942Sgibbs	{
38765942Sgibbs		ID_AHA_2950U2B,
38865942Sgibbs		ID_ALL_MASK,
38965942Sgibbs		"Adaptec 2950 Ultra2 SCSI adapter",
39065942Sgibbs		ahc_aic7890_setup
39165942Sgibbs	},
39265942Sgibbs	{
39365942Sgibbs		ID_AAA_131U2,
39465942Sgibbs		ID_ALL_MASK,
39565942Sgibbs		"Adaptec AAA-131 Ultra2 RAID adapter",
39665942Sgibbs		ahc_aic7890_setup
39765942Sgibbs	},
39865942Sgibbs	/* aic7892 based controllers */
39965942Sgibbs	{
40065942Sgibbs		ID_AHA_29160,
40165942Sgibbs		ID_ALL_MASK,
40265942Sgibbs		"Adaptec 29160 Ultra160 SCSI adapter",
40365942Sgibbs		ahc_aic7892_setup
40465942Sgibbs	},
40565942Sgibbs	{
40665942Sgibbs		ID_AHA_29160_CPQ,
40765942Sgibbs		ID_ALL_MASK,
40865942Sgibbs		"Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter",
40965942Sgibbs		ahc_aic7892_setup
41065942Sgibbs	},
41165942Sgibbs	{
41265942Sgibbs		ID_AHA_29160N,
41365942Sgibbs		ID_ALL_MASK,
41465942Sgibbs		"Adaptec 29160N Ultra160 SCSI adapter",
41565942Sgibbs		ahc_aic7892_setup
41665942Sgibbs	},
41765942Sgibbs	{
41870204Sgibbs		ID_AHA_29160C,
41970204Sgibbs		ID_ALL_MASK,
42070204Sgibbs		"Adaptec 29160C Ultra160 SCSI adapter",
42171390Sgibbs		ahc_aha29160C_setup
42270204Sgibbs	},
42370204Sgibbs	{
42465942Sgibbs		ID_AHA_29160B,
42565942Sgibbs		ID_ALL_MASK,
42665942Sgibbs		"Adaptec 29160B Ultra160 SCSI adapter",
42765942Sgibbs		ahc_aic7892_setup
42865942Sgibbs	},
42965942Sgibbs	{
43065942Sgibbs		ID_AHA_19160B,
43165942Sgibbs		ID_ALL_MASK,
43265942Sgibbs		"Adaptec 19160B Ultra160 SCSI adapter",
43365942Sgibbs		ahc_aic7892_setup
43465942Sgibbs	},
43565942Sgibbs	/* aic7895 based controllers */
43665942Sgibbs	{
43765942Sgibbs		ID_AHA_2940U_DUAL,
43865942Sgibbs		ID_ALL_MASK,
43965942Sgibbs		"Adaptec 2940/DUAL Ultra SCSI adapter",
44065942Sgibbs		ahc_aic7895_setup
44165942Sgibbs	},
44265942Sgibbs	{
44365942Sgibbs		ID_AHA_3940AU,
44465942Sgibbs		ID_ALL_MASK,
44565942Sgibbs		"Adaptec 3940A Ultra SCSI adapter",
44665942Sgibbs		ahc_aic7895_setup
44765942Sgibbs	},
44865942Sgibbs	{
44965942Sgibbs		ID_AHA_3944AU,
45065942Sgibbs		ID_ALL_MASK,
45165942Sgibbs		"Adaptec 3944A Ultra SCSI adapter",
45265942Sgibbs		ahc_aic7895_setup
45365942Sgibbs	},
45465942Sgibbs	/* aic7896/97 based controllers */
45565942Sgibbs	{
45665942Sgibbs		ID_AHA_3950U2B_0,
45765942Sgibbs		ID_ALL_MASK,
45865942Sgibbs		"Adaptec 3950B Ultra2 SCSI adapter",
45965942Sgibbs		ahc_aic7896_setup
46065942Sgibbs	},
46165942Sgibbs	{
46265942Sgibbs		ID_AHA_3950U2B_1,
46365942Sgibbs		ID_ALL_MASK,
46465942Sgibbs		"Adaptec 3950B Ultra2 SCSI adapter",
46565942Sgibbs		ahc_aic7896_setup
46665942Sgibbs	},
46765942Sgibbs	{
46865942Sgibbs		ID_AHA_3950U2D_0,
46965942Sgibbs		ID_ALL_MASK,
47065942Sgibbs		"Adaptec 3950D Ultra2 SCSI adapter",
47165942Sgibbs		ahc_aic7896_setup
47265942Sgibbs	},
47365942Sgibbs	{
47465942Sgibbs		ID_AHA_3950U2D_1,
47565942Sgibbs		ID_ALL_MASK,
47665942Sgibbs		"Adaptec 3950D Ultra2 SCSI adapter",
47765942Sgibbs		ahc_aic7896_setup
47865942Sgibbs	},
47965942Sgibbs	/* aic7899 based controllers */
48065942Sgibbs	{
48165942Sgibbs		ID_AHA_3960D,
48265942Sgibbs		ID_ALL_MASK,
48365942Sgibbs		"Adaptec 3960D Ultra160 SCSI adapter",
48465942Sgibbs		ahc_aic7899_setup
48565942Sgibbs	},
48665942Sgibbs	{
48765942Sgibbs		ID_AHA_3960D_CPQ,
48865942Sgibbs		ID_ALL_MASK,
48965942Sgibbs		"Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter",
49065942Sgibbs		ahc_aic7899_setup
49165942Sgibbs	},
49265942Sgibbs	/* Generic chip probes for devices we don't know 'exactly' */
49365942Sgibbs	{
49465942Sgibbs		ID_AIC7850 & ID_DEV_VENDOR_MASK,
49565942Sgibbs		ID_DEV_VENDOR_MASK,
49665942Sgibbs		"Adaptec aic7850 SCSI adapter",
49765942Sgibbs		ahc_aic7850_setup
49865942Sgibbs	},
49965942Sgibbs	{
50065942Sgibbs		ID_AIC7855 & ID_DEV_VENDOR_MASK,
50165942Sgibbs		ID_DEV_VENDOR_MASK,
50265942Sgibbs		"Adaptec aic7855 SCSI adapter",
50365942Sgibbs		ahc_aic7855_setup
50465942Sgibbs	},
50565942Sgibbs	{
50665942Sgibbs		ID_AIC7859 & ID_DEV_VENDOR_MASK,
50765942Sgibbs		ID_DEV_VENDOR_MASK,
50865942Sgibbs		"Adaptec aic7859 Ultra SCSI adapter",
50965942Sgibbs		ahc_aic7860_setup
51065942Sgibbs	},
51165942Sgibbs	{
51265942Sgibbs		ID_AIC7860 & ID_DEV_VENDOR_MASK,
51365942Sgibbs		ID_DEV_VENDOR_MASK,
51465942Sgibbs		"Adaptec aic7860 SCSI adapter",
51565942Sgibbs		ahc_aic7860_setup
51665942Sgibbs	},
51765942Sgibbs	{
51865942Sgibbs		ID_AIC7870 & ID_DEV_VENDOR_MASK,
51965942Sgibbs		ID_DEV_VENDOR_MASK,
52065942Sgibbs		"Adaptec aic7870 SCSI adapter",
52165942Sgibbs		ahc_aic7870_setup
52265942Sgibbs	},
52365942Sgibbs	{
52465942Sgibbs		ID_AIC7880 & ID_DEV_VENDOR_MASK,
52565942Sgibbs		ID_DEV_VENDOR_MASK,
52665942Sgibbs		"Adaptec aic7880 Ultra SCSI adapter",
52765942Sgibbs		ahc_aic7880_setup
52865942Sgibbs	},
52965942Sgibbs	{
53072325Sgibbs		ID_AIC7890 & ID_9005_GENERIC_MASK,
53172325Sgibbs		ID_9005_GENERIC_MASK,
53265942Sgibbs		"Adaptec aic7890/91 Ultra2 SCSI adapter",
53365942Sgibbs		ahc_aic7890_setup
53465942Sgibbs	},
53565942Sgibbs	{
53672325Sgibbs		ID_AIC7892 & ID_9005_GENERIC_MASK,
53772325Sgibbs		ID_9005_GENERIC_MASK,
53865942Sgibbs		"Adaptec aic7892 Ultra160 SCSI adapter",
53965942Sgibbs		ahc_aic7892_setup
54065942Sgibbs	},
54165942Sgibbs	{
54265942Sgibbs		ID_AIC7895 & ID_DEV_VENDOR_MASK,
54365942Sgibbs		ID_DEV_VENDOR_MASK,
54465942Sgibbs		"Adaptec aic7895 Ultra SCSI adapter",
54565942Sgibbs		ahc_aic7895_setup
54665942Sgibbs	},
54765942Sgibbs	{
54865942Sgibbs		ID_AIC7895_RAID_PORT & ID_DEV_VENDOR_MASK,
54965942Sgibbs		ID_DEV_VENDOR_MASK,
55065942Sgibbs		"Adaptec aic7895 Ultra SCSI adapter (RAID PORT)",
55165942Sgibbs		ahc_aic7895_setup
55265942Sgibbs	},
55365942Sgibbs	{
55472325Sgibbs		ID_AIC7896 & ID_9005_GENERIC_MASK,
55572325Sgibbs		ID_9005_GENERIC_MASK,
55665942Sgibbs		"Adaptec aic7896/97 Ultra2 SCSI adapter",
55765942Sgibbs		ahc_aic7896_setup
55865942Sgibbs	},
55965942Sgibbs	{
56072325Sgibbs		ID_AIC7899 & ID_9005_GENERIC_MASK,
56172325Sgibbs		ID_9005_GENERIC_MASK,
56265942Sgibbs		"Adaptec aic7899 Ultra160 SCSI adapter",
56365942Sgibbs		ahc_aic7899_setup
56465942Sgibbs	},
56565942Sgibbs	{
56665942Sgibbs		ID_AIC7810 & ID_DEV_VENDOR_MASK,
56765942Sgibbs		ID_DEV_VENDOR_MASK,
56865942Sgibbs		"Adaptec aic7810 RAID memory controller",
56965942Sgibbs		ahc_raid_setup
57065942Sgibbs	},
57165942Sgibbs	{
57265942Sgibbs		ID_AIC7815 & ID_DEV_VENDOR_MASK,
57365942Sgibbs		ID_DEV_VENDOR_MASK,
57465942Sgibbs		"Adaptec aic7815 RAID memory controller",
57565942Sgibbs		ahc_raid_setup
57665942Sgibbs	}
57765942Sgibbs};
57865942Sgibbs
57970204Sgibbsconst u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table);
58065942Sgibbs
58165942Sgibbs#define AHC_394X_SLOT_CHANNEL_A	4
58265942Sgibbs#define AHC_394X_SLOT_CHANNEL_B	5
58365942Sgibbs
58465942Sgibbs#define AHC_398X_SLOT_CHANNEL_A	4
58565942Sgibbs#define AHC_398X_SLOT_CHANNEL_B	8
58665942Sgibbs#define AHC_398X_SLOT_CHANNEL_C	12
58765942Sgibbs
58865942Sgibbs#define AHC_494X_SLOT_CHANNEL_A	4
58965942Sgibbs#define AHC_494X_SLOT_CHANNEL_B	5
59065942Sgibbs#define AHC_494X_SLOT_CHANNEL_C	6
59165942Sgibbs#define AHC_494X_SLOT_CHANNEL_D	7
59265942Sgibbs
59365942Sgibbs#define	DEVCONFIG		0x40
59465942Sgibbs#define		SCBSIZE32	0x00010000ul	/* aic789X only */
59565942Sgibbs#define		MPORTMODE	0x00000400ul	/* aic7870 only */
59665942Sgibbs#define		RAMPSM		0x00000200ul	/* aic7870 only */
59765942Sgibbs#define		VOLSENSE	0x00000100ul
59865942Sgibbs#define		SCBRAMSEL	0x00000080ul
59965942Sgibbs#define		MRDCEN		0x00000040ul
60065942Sgibbs#define		EXTSCBTIME	0x00000020ul	/* aic7870 only */
60165942Sgibbs#define		EXTSCBPEN	0x00000010ul	/* aic7870 only */
60265942Sgibbs#define		BERREN		0x00000008ul
60365942Sgibbs#define		DACEN		0x00000004ul
60465942Sgibbs#define		STPWLEVEL	0x00000002ul
60565942Sgibbs#define		DIFACTNEGEN	0x00000001ul	/* aic7870 only */
60665942Sgibbs
60765942Sgibbs#define	CSIZE_LATTIME		0x0c
60865942Sgibbs#define		CACHESIZE	0x0000003ful	/* only 5 bits */
60965942Sgibbs#define		LATTIME		0x0000ff00ul
61065942Sgibbs
61170204Sgibbstypedef enum
61270204Sgibbs{
61370204Sgibbs	AHC_POWER_STATE_D0,
61470204Sgibbs	AHC_POWER_STATE_D1,
61570204Sgibbs	AHC_POWER_STATE_D2,
61670204Sgibbs	AHC_POWER_STATE_D3
61770204Sgibbs} ahc_power_state;
61870204Sgibbs
61970204Sgibbsstatic void ahc_power_state_change(struct ahc_softc *ahc,
62070204Sgibbs				   ahc_power_state new_state);
62165942Sgibbsstatic int ahc_ext_scbram_present(struct ahc_softc *ahc);
62265942Sgibbsstatic void ahc_scbram_config(struct ahc_softc *ahc, int enable,
62365942Sgibbs				  int pcheck, int fast, int large);
62465942Sgibbsstatic void ahc_probe_ext_scbram(struct ahc_softc *ahc);
62565942Sgibbsstatic void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1);
62665942Sgibbsstatic void configure_termination(struct ahc_softc *ahc,
62765942Sgibbs				  struct seeprom_descriptor *sd,
62865942Sgibbs				  u_int adapter_control,
62965942Sgibbs	 			  u_int *sxfrctl1);
63065942Sgibbs
63165942Sgibbsstatic void ahc_new_term_detect(struct ahc_softc *ahc,
63265942Sgibbs				int *enableSEC_low,
63365942Sgibbs				int *enableSEC_high,
63465942Sgibbs				int *enablePRI_low,
63565942Sgibbs				int *enablePRI_high,
63665942Sgibbs				int *eeprom_present);
63765942Sgibbsstatic void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
63865942Sgibbs				 int *internal68_present,
63965942Sgibbs				 int *externalcable_present,
64065942Sgibbs				 int *eeprom_present);
64165942Sgibbsstatic void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
64265942Sgibbs				 int *externalcable_present,
64365942Sgibbs				 int *eeprom_present);
64465942Sgibbsstatic int acquire_seeprom(struct ahc_softc *ahc,
64565942Sgibbs			   struct seeprom_descriptor *sd);
64665942Sgibbsstatic void release_seeprom(struct seeprom_descriptor *sd);
64765942Sgibbsstatic void write_brdctl(struct ahc_softc *ahc, uint8_t value);
64865942Sgibbsstatic uint8_t read_brdctl(struct ahc_softc *ahc);
64965942Sgibbs
65065942Sgibbsstruct ahc_pci_identity *
65165942Sgibbsahc_find_pci_device(ahc_dev_softc_t pci)
65265942Sgibbs{
65365942Sgibbs	uint64_t  full_id;
65465942Sgibbs	uint16_t  device;
65565942Sgibbs	uint16_t  vendor;
65665942Sgibbs	uint16_t  subdevice;
65765942Sgibbs	uint16_t  subvendor;
65865942Sgibbs	struct	  ahc_pci_identity *entry;
65965942Sgibbs	u_int	  i;
66065942Sgibbs
66165942Sgibbs	vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
66265942Sgibbs	device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
66365942Sgibbs	subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
66465942Sgibbs	subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
66565942Sgibbs	full_id = ahc_compose_id(device,
66665942Sgibbs				 vendor,
66765942Sgibbs				 subdevice,
66865942Sgibbs				 subvendor);
66965942Sgibbs
67070204Sgibbs	/* If the second function is not hooked up, ignore it. */
67170204Sgibbs	if (ahc_get_pci_function(pci) > 0
67270204Sgibbs	 && subvendor == 0x9005
67370693Sgibbs	 && SUBID_9005_MFUNCENB(subdevice) == 0)
67470204Sgibbs		return (NULL);
67570204Sgibbs
67665942Sgibbs	for (i = 0; i < ahc_num_pci_devs; i++) {
67765942Sgibbs		entry = &ahc_pci_ident_table[i];
67865942Sgibbs		if (entry->full_id == (full_id & entry->id_mask))
67965942Sgibbs			return (entry);
68065942Sgibbs	}
68165942Sgibbs	return (NULL);
68265942Sgibbs}
68365942Sgibbs
68465942Sgibbsint
68565942Sgibbsahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
68665942Sgibbs{
68765942Sgibbs	struct		 ahc_probe_config probe_config;
68865942Sgibbs	struct scb_data *shared_scb_data;
68965942Sgibbs	u_int		 command;
69065942Sgibbs	u_int		 our_id = 0;
69165942Sgibbs	u_int		 sxfrctl1;
69265942Sgibbs	u_int		 scsiseq;
69365942Sgibbs	u_int		 dscommand0;
69465942Sgibbs	int		 error;
69565942Sgibbs	uint8_t		 sblkctl;
69665942Sgibbs
69765942Sgibbs	shared_scb_data = NULL;
69865942Sgibbs	ahc_init_probe_config(&probe_config);
69965942Sgibbs	error = entry->setup(ahc->dev_softc, &probe_config);
70065942Sgibbs	if (error != 0)
70165942Sgibbs		return (error);
70265942Sgibbs	probe_config.chip |= AHC_PCI;
70365942Sgibbs	probe_config.description = entry->name;
70465942Sgibbs
70565942Sgibbs	error = ahc_pci_map_registers(ahc);
70665942Sgibbs	if (error != 0)
70765942Sgibbs		return (error);
70865942Sgibbs
70970204Sgibbs	ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
71070204Sgibbs
71165942Sgibbs	/* Ensure busmastering is enabled */
71265942Sgibbs	command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
71365942Sgibbs	command |= PCIM_CMD_BUSMASTEREN;
71465942Sgibbs	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/1);
71565942Sgibbs
71665942Sgibbs	/* On all PCI adapters, we allow SCB paging */
71765942Sgibbs	probe_config.flags |= AHC_PAGESCBS;
71865942Sgibbs
71965942Sgibbs	error = ahc_softc_init(ahc, &probe_config);
72065942Sgibbs	if (error != 0)
72165942Sgibbs		return (error);
72265942Sgibbs
72365942Sgibbs	/* Remeber how the card was setup in case there is no SEEPROM */
72470204Sgibbs	if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
72570204Sgibbs		pause_sequencer(ahc);
72670204Sgibbs		if ((ahc->features & AHC_ULTRA2) != 0)
72770204Sgibbs			our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID;
72870204Sgibbs		else
72970204Sgibbs			our_id = ahc_inb(ahc, SCSIID) & OID;
73070204Sgibbs		sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN;
73170204Sgibbs		scsiseq = ahc_inb(ahc, SCSISEQ);
73270204Sgibbs	} else {
73370204Sgibbs		sxfrctl1 = STPWEN;
73470204Sgibbs		our_id = 7;
73570204Sgibbs		scsiseq = 0;
73670204Sgibbs	}
73765942Sgibbs
73865942Sgibbs	error = ahc_reset(ahc);
73965942Sgibbs	if (error != 0)
74065942Sgibbs		return (ENXIO);
74165942Sgibbs
74265942Sgibbs	if ((ahc->features & AHC_DT) != 0) {
74365942Sgibbs		u_int sfunct;
74465942Sgibbs
74565942Sgibbs		/* Perform ALT-Mode Setup */
74665942Sgibbs		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
74765942Sgibbs		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
74865942Sgibbs		ahc_outb(ahc, OPTIONMODE, OPTIONMODE_DEFAULTS);
74965942Sgibbs		ahc_outb(ahc, SFUNCT, sfunct);
75065942Sgibbs
75165942Sgibbs		/* Normal mode setup */
75265942Sgibbs		ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN
75370204Sgibbs					  |TARGCRCENDEN);
75465942Sgibbs	}
75565942Sgibbs
75665942Sgibbs	error = ahc_pci_map_int(ahc);
75765942Sgibbs	if (error != 0)
75865942Sgibbs		return (error);
75965942Sgibbs	dscommand0 = ahc_inb(ahc, DSCOMMAND0);
76066647Sgibbs	dscommand0 |= MPARCKEN|CACHETHEN;
76165942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
76265942Sgibbs
76365942Sgibbs		/*
76465942Sgibbs		 * DPARCKEN doesn't work correctly on
76565942Sgibbs		 * some MBs so don't use it.
76665942Sgibbs		 */
76765942Sgibbs		dscommand0 &= ~DPARCKEN;
76865942Sgibbs	}
76965942Sgibbs
77065942Sgibbs	/*
77165942Sgibbs	 * Handle chips that must have cache line
77265942Sgibbs	 * streaming (dis/en)abled.
77365942Sgibbs	 */
77465942Sgibbs	if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0)
77565942Sgibbs		dscommand0 |= CACHETHEN;
77665942Sgibbs
77765942Sgibbs	if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0)
77865942Sgibbs		dscommand0 &= ~CACHETHEN;
77965942Sgibbs
78065942Sgibbs	ahc_outb(ahc, DSCOMMAND0, dscommand0);
78165942Sgibbs
78265942Sgibbs	ahc->pci_cachesize =
78365942Sgibbs	    ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME,
78465942Sgibbs				/*bytes*/1) & CACHESIZE;
78565942Sgibbs	ahc->pci_cachesize *= 4;
78665942Sgibbs
78765942Sgibbs	/* See if we have a SEEPROM and perform auto-term */
78865942Sgibbs	check_extport(ahc, &sxfrctl1);
78965942Sgibbs
79065942Sgibbs	/*
79165942Sgibbs	 * Take the LED out of diagnostic mode
79265942Sgibbs	 */
79365942Sgibbs	sblkctl = ahc_inb(ahc, SBLKCTL);
79465942Sgibbs	ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));
79565942Sgibbs
79665942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
79768087Sgibbs		ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX);
79865942Sgibbs	} else {
79965942Sgibbs		ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100);
80065942Sgibbs	}
80165942Sgibbs
80265942Sgibbs	if (ahc->flags & AHC_USEDEFAULTS) {
80365942Sgibbs		/*
80465942Sgibbs		 * PCI Adapter default setup
80565942Sgibbs		 * Should only be used if the adapter does not have
80665942Sgibbs		 * a SEEPROM.
80765942Sgibbs		 */
80865942Sgibbs		/* See if someone else set us up already */
80965942Sgibbs		if (scsiseq != 0) {
81065942Sgibbs			printf("%s: Using left over BIOS settings\n",
81165942Sgibbs				ahc_name(ahc));
81265942Sgibbs			ahc->flags &= ~AHC_USEDEFAULTS;
81372325Sgibbs			ahc->flags |= AHC_BIOS_ENABLED;
81465942Sgibbs		} else {
81565942Sgibbs			/*
81665942Sgibbs			 * Assume only one connector and always turn
81765942Sgibbs			 * on termination.
81865942Sgibbs			 */
81965942Sgibbs 			our_id = 0x07;
82065942Sgibbs			sxfrctl1 = STPWEN;
82165942Sgibbs		}
82265942Sgibbs		ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI);
82365942Sgibbs
82465942Sgibbs		ahc->our_id = our_id;
82565942Sgibbs	}
82665942Sgibbs
82765942Sgibbs	/*
82865942Sgibbs	 * Take a look to see if we have external SRAM.
82965942Sgibbs	 * We currently do not attempt to use SRAM that is
83065942Sgibbs	 * shared among multiple controllers.
83165942Sgibbs	 */
83265942Sgibbs	ahc_probe_ext_scbram(ahc);
83365942Sgibbs
83465942Sgibbs	/*
83565942Sgibbs	 * Record our termination setting for the
83665942Sgibbs	 * generic initialization routine.
83765942Sgibbs	 */
83865942Sgibbs	if ((sxfrctl1 & STPWEN) != 0)
83965942Sgibbs		ahc->flags |= AHC_TERM_ENB_A;
84065942Sgibbs
84165942Sgibbs	/* Core initialization */
84265942Sgibbs	error = ahc_init(ahc);
84365942Sgibbs	if (error != 0)
84465942Sgibbs		return (error);
84565942Sgibbs
84665942Sgibbs	/*
84765942Sgibbs	 * Link this softc in with all other ahc instances.
84865942Sgibbs	 */
84965942Sgibbs	ahc_softc_insert(ahc);
85065942Sgibbs
85165942Sgibbs	return (0);
85265942Sgibbs}
85365942Sgibbs
85470204Sgibbsstatic void
85570204Sgibbsahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
85670204Sgibbs{
85770204Sgibbs	uint32_t cap;
85870204Sgibbs	u_int cap_offset;
85970204Sgibbs
86070204Sgibbs	/*
86170204Sgibbs	 * Traverse the capability list looking for
86270204Sgibbs	 * the power management capability.
86370204Sgibbs	 */
86470204Sgibbs	cap = 0;
86570204Sgibbs	cap_offset = ahc_pci_read_config(ahc->dev_softc,
86670204Sgibbs					 PCIR_CAP_PTR, /*bytes*/1);
86770204Sgibbs	while (cap_offset != 0) {
86870204Sgibbs
86970204Sgibbs		cap = ahc_pci_read_config(ahc->dev_softc,
87070204Sgibbs					  cap_offset, /*bytes*/4);
87170204Sgibbs		if ((cap & 0xFF) == 1
87270204Sgibbs		 && ((cap >> 16) & 0x3) > 0) {
87370204Sgibbs			uint32_t pm_control;
87470204Sgibbs
87570204Sgibbs			pm_control = ahc_pci_read_config(ahc->dev_softc,
87670204Sgibbs							 cap_offset + 4,
87770204Sgibbs							 /*bytes*/4);
87870204Sgibbs			pm_control &= ~0x3;
87970204Sgibbs			pm_control |= new_state;
88070204Sgibbs			ahc_pci_write_config(ahc->dev_softc,
88170204Sgibbs					     cap_offset + 4,
88270204Sgibbs					     pm_control, /*bytes*/2);
88370204Sgibbs			break;
88470204Sgibbs		}
88570204Sgibbs		cap_offset = (cap >> 8) & 0xFF;
88670204Sgibbs	}
88770204Sgibbs}
88870204Sgibbs
88965942Sgibbs/*
89065942Sgibbs * Test for the presense of external sram in an
89165942Sgibbs * "unshared" configuration.
89265942Sgibbs */
89365942Sgibbsstatic int
89465942Sgibbsahc_ext_scbram_present(struct ahc_softc *ahc)
89565942Sgibbs{
89668087Sgibbs	u_int chip;
89765942Sgibbs	int ramps;
89865942Sgibbs	int single_user;
89965942Sgibbs	uint32_t devconfig;
90065942Sgibbs
90168087Sgibbs	chip = ahc->chip & AHC_CHIPID_MASK;
90265942Sgibbs	devconfig = ahc_pci_read_config(ahc->dev_softc,
90365942Sgibbs					DEVCONFIG, /*bytes*/4);
90465942Sgibbs	single_user = (devconfig & MPORTMODE) != 0;
90565942Sgibbs
90665942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
90765942Sgibbs		ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0;
90868087Sgibbs	else if (chip >= AHC_AIC7870)
90965942Sgibbs		ramps = (devconfig & RAMPSM) != 0;
91065942Sgibbs	else
91165942Sgibbs		ramps = 0;
91265942Sgibbs
91365942Sgibbs	if (ramps && single_user)
91465942Sgibbs		return (1);
91565942Sgibbs	return (0);
91665942Sgibbs}
91765942Sgibbs
91865942Sgibbs/*
91965942Sgibbs * Enable external scbram.
92065942Sgibbs */
92165942Sgibbsstatic void
92265942Sgibbsahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck,
92365942Sgibbs		  int fast, int large)
92465942Sgibbs{
92565942Sgibbs	uint32_t devconfig;
92665942Sgibbs
92765942Sgibbs	if (ahc->features & AHC_MULTI_FUNC) {
92865942Sgibbs		/*
92965942Sgibbs		 * Set the SCB Base addr (highest address bit)
93065942Sgibbs		 * depending on which channel we are.
93165942Sgibbs		 */
93265942Sgibbs		ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc));
93365942Sgibbs	}
93465942Sgibbs
93565942Sgibbs	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
93665942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
93765942Sgibbs		u_int dscommand0;
93865942Sgibbs
93965942Sgibbs		dscommand0 = ahc_inb(ahc, DSCOMMAND0);
94065942Sgibbs		if (enable)
94165942Sgibbs			dscommand0 &= ~INTSCBRAMSEL;
94265942Sgibbs		else
94365942Sgibbs			dscommand0 |= INTSCBRAMSEL;
94465942Sgibbs		if (large)
94565942Sgibbs			dscommand0 &= ~USCBSIZE32;
94665942Sgibbs		else
94765942Sgibbs			dscommand0 |= USCBSIZE32;
94865942Sgibbs		ahc_outb(ahc, DSCOMMAND0, dscommand0);
94965942Sgibbs	} else {
95065942Sgibbs		if (fast)
95165942Sgibbs			devconfig &= ~EXTSCBTIME;
95265942Sgibbs		else
95365942Sgibbs			devconfig |= EXTSCBTIME;
95465942Sgibbs		if (enable)
95565942Sgibbs			devconfig &= ~SCBRAMSEL;
95665942Sgibbs		else
95765942Sgibbs			devconfig |= SCBRAMSEL;
95865942Sgibbs		if (large)
95965942Sgibbs			devconfig &= ~SCBSIZE32;
96065942Sgibbs		else
96165942Sgibbs			devconfig |= SCBSIZE32;
96265942Sgibbs	}
96365942Sgibbs	if (pcheck)
96465942Sgibbs		devconfig |= EXTSCBPEN;
96565942Sgibbs	else
96665942Sgibbs		devconfig &= ~EXTSCBPEN;
96765942Sgibbs
96865942Sgibbs	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
96965942Sgibbs}
97065942Sgibbs
97165942Sgibbs/*
97265942Sgibbs * Take a look to see if we have external SRAM.
97365942Sgibbs * We currently do not attempt to use SRAM that is
97465942Sgibbs * shared among multiple controllers.
97565942Sgibbs */
97665942Sgibbsstatic void
97765942Sgibbsahc_probe_ext_scbram(struct ahc_softc *ahc)
97865942Sgibbs{
97965942Sgibbs	int num_scbs;
98065942Sgibbs	int test_num_scbs;
98165942Sgibbs	int enable;
98265942Sgibbs	int pcheck;
98365942Sgibbs	int fast;
98465942Sgibbs	int large;
98565942Sgibbs
98665942Sgibbs	enable = FALSE;
98765942Sgibbs	pcheck = FALSE;
98865942Sgibbs	fast = FALSE;
98965942Sgibbs	large = FALSE;
99065942Sgibbs	num_scbs = 0;
99165942Sgibbs
99265942Sgibbs	if (ahc_ext_scbram_present(ahc) == 0)
99365942Sgibbs		goto done;
99465942Sgibbs
99565942Sgibbs	/*
99665942Sgibbs	 * Probe for the best parameters to use.
99765942Sgibbs	 */
99865942Sgibbs	ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large);
99965942Sgibbs	num_scbs = ahc_probe_scbs(ahc);
100065942Sgibbs	if (num_scbs == 0) {
100165942Sgibbs		/* The SRAM wasn't really present. */
100265942Sgibbs		goto done;
100365942Sgibbs	}
100465942Sgibbs	enable = TRUE;
100565942Sgibbs
100665942Sgibbs	/*
100765942Sgibbs	 * Clear any outstanding parity error
100865942Sgibbs	 * and ensure that parity error reporting
100965942Sgibbs	 * is enabled.
101065942Sgibbs	 */
101165942Sgibbs	ahc_outb(ahc, SEQCTL, 0);
101265942Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
101365942Sgibbs	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
101465942Sgibbs
101565942Sgibbs	/* Now see if we can do parity */
101665942Sgibbs	ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large);
101765942Sgibbs	num_scbs = ahc_probe_scbs(ahc);
101865942Sgibbs	if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
101965942Sgibbs	 || (ahc_inb(ahc, ERROR) & MPARERR) == 0)
102065942Sgibbs		pcheck = TRUE;
102165942Sgibbs
102265942Sgibbs	/* Clear any resulting parity error */
102365942Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
102465942Sgibbs	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
102565942Sgibbs
102665942Sgibbs	/* Now see if we can do fast timing */
102765942Sgibbs	ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large);
102865942Sgibbs	test_num_scbs = ahc_probe_scbs(ahc);
102965942Sgibbs	if (test_num_scbs == num_scbs
103065942Sgibbs	 && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
103165942Sgibbs	  || (ahc_inb(ahc, ERROR) & MPARERR) == 0))
103265942Sgibbs		fast = TRUE;
103365942Sgibbs
103465942Sgibbs	/*
103565942Sgibbs	 * See if we can use large SCBs and still maintain
103665942Sgibbs	 * the same overall count of SCBs.
103765942Sgibbs	 */
103865942Sgibbs	if ((ahc->features & AHC_LARGE_SCBS) != 0) {
103965942Sgibbs		ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE);
104065942Sgibbs		test_num_scbs = ahc_probe_scbs(ahc);
104165942Sgibbs		if (test_num_scbs >= num_scbs) {
104265942Sgibbs			large = TRUE;
104365942Sgibbs			num_scbs = test_num_scbs;
104465942Sgibbs	 		if (num_scbs >= 64) {
104565942Sgibbs				/*
104665942Sgibbs				 * We have enough space to move the
104765942Sgibbs				 * "busy targets table" into SCB space
104865942Sgibbs				 * and make it qualify all the way to the
104965942Sgibbs				 * lun level.
105065942Sgibbs				 */
105165942Sgibbs				ahc->flags |= AHC_SCB_BTT;
105265942Sgibbs			}
105365942Sgibbs		}
105465942Sgibbs	}
105565942Sgibbsdone:
105665942Sgibbs	/*
105765942Sgibbs	 * Disable parity error reporting until we
105865942Sgibbs	 * can load instruction ram.
105965942Sgibbs	 */
106065942Sgibbs	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
106165942Sgibbs	/* Clear any latched parity error */
106265942Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
106365942Sgibbs	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
106465942Sgibbs	if (bootverbose && enable) {
106565942Sgibbs		printf("%s: External SRAM, %s access%s, %dbytes/SCB\n",
106665942Sgibbs		       ahc_name(ahc), fast ? "fast" : "slow",
106765942Sgibbs		       pcheck ? ", parity checking enabled" : "",
106865942Sgibbs		       large ? 64 : 32);
106965942Sgibbs	}
107065942Sgibbs	ahc_scbram_config(ahc, enable, pcheck, fast, large);
107165942Sgibbs}
107265942Sgibbs
107365942Sgibbs/*
107465942Sgibbs * Check the external port logic for a serial eeprom
107565942Sgibbs * and termination/cable detection contrls.
107665942Sgibbs */
107765942Sgibbsstatic void
107865942Sgibbscheck_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
107965942Sgibbs{
108065942Sgibbs	struct	seeprom_descriptor sd;
108165942Sgibbs	struct	seeprom_config sc;
108265942Sgibbs	u_int	scsi_conf;
108365942Sgibbs	u_int	adapter_control;
108465942Sgibbs	int	have_seeprom;
108565942Sgibbs	int	have_autoterm;
108665942Sgibbs
108765942Sgibbs	sd.sd_ahc = ahc;
108865942Sgibbs	sd.sd_control_offset = SEECTL;
108965942Sgibbs	sd.sd_status_offset = SEECTL;
109065942Sgibbs	sd.sd_dataout_offset = SEECTL;
109165942Sgibbs
109265942Sgibbs	/*
109365942Sgibbs	 * For some multi-channel devices, the c46 is simply too
109465942Sgibbs	 * small to work.  For the other controller types, we can
109565942Sgibbs	 * get our information from either SEEPROM type.  Set the
109665942Sgibbs	 * type to start our probe with accordingly.
109765942Sgibbs	 */
109865942Sgibbs	if (ahc->flags & AHC_LARGE_SEEPROM)
109965942Sgibbs		sd.sd_chip = C56_66;
110065942Sgibbs	else
110165942Sgibbs		sd.sd_chip = C46;
110265942Sgibbs
110365942Sgibbs	sd.sd_MS = SEEMS;
110465942Sgibbs	sd.sd_RDY = SEERDY;
110565942Sgibbs	sd.sd_CS = SEECS;
110665942Sgibbs	sd.sd_CK = SEECK;
110765942Sgibbs	sd.sd_DO = SEEDO;
110865942Sgibbs	sd.sd_DI = SEEDI;
110965942Sgibbs
111065942Sgibbs	have_seeprom = acquire_seeprom(ahc, &sd);
111165942Sgibbs	if (have_seeprom) {
111265942Sgibbs
111365942Sgibbs		if (bootverbose)
111465942Sgibbs			printf("%s: Reading SEEPROM...", ahc_name(ahc));
111565942Sgibbs
111665942Sgibbs		for (;;) {
111765942Sgibbs			u_int start_addr;
111865942Sgibbs
111965942Sgibbs			start_addr = 32 * (ahc->channel - 'A');
112065942Sgibbs
112165942Sgibbs			have_seeprom = read_seeprom(&sd, (uint16_t *)&sc,
112265942Sgibbs						    start_addr, sizeof(sc)/2);
112365942Sgibbs
112465942Sgibbs			if (have_seeprom)
112565942Sgibbs				have_seeprom = verify_cksum(&sc);
112665942Sgibbs
112765942Sgibbs			if (have_seeprom != 0 || sd.sd_chip == C56_66) {
112865942Sgibbs				if (bootverbose) {
112965942Sgibbs					if (have_seeprom == 0)
113065942Sgibbs						printf ("checksum error\n");
113165942Sgibbs					else
113265942Sgibbs						printf ("done.\n");
113365942Sgibbs				}
113465942Sgibbs				break;
113565942Sgibbs			}
113665942Sgibbs			sd.sd_chip = C56_66;
113765942Sgibbs		}
113865942Sgibbs	}
113965942Sgibbs
114065942Sgibbs#if 0
114165942Sgibbs	if (!have_seeprom) {
114265942Sgibbs		/*
114365942Sgibbs		 * Pull scratch ram settings and treat them as
114465942Sgibbs		 * if they are the contents of an seeprom if
114565942Sgibbs		 * the 'ADPT' signature is found in SCB2.
114665942Sgibbs		 */
114765942Sgibbs		ahc_outb(ahc, SCBPTR, 2);
114865942Sgibbs		if (ahc_inb(ahc, SCB_BASE) == 'A'
114965942Sgibbs		 && ahc_inb(ahc, SCB_BASE + 1) == 'D'
115065942Sgibbs		 && ahc_inb(ahc, SCB_BASE + 2) == 'P'
115165942Sgibbs		 && ahc_inb(ahc, SCB_BASE + 3) == 'T') {
115265942Sgibbs			uint8_t *sc_bytes;
115365942Sgibbs			int	  i;
115465942Sgibbs
115565942Sgibbs			sc_bytes = (uint8_t *)&sc;
115665942Sgibbs			for (i = 0; i < 64; i++)
115765942Sgibbs				sc_bytes[i] = ahc_inb(ahc, TARG_SCSIRATE + i);
115865942Sgibbs			/* Byte 0x1c is stored in byte 4 of SCB2 */
115965942Sgibbs			sc_bytes[0x1c] = ahc_inb(ahc, SCB_BASE + 4);
116065942Sgibbs			have_seeprom = verify_cksum(&sc);
116165942Sgibbs		}
116265942Sgibbs	}
116365942Sgibbs#endif
116465942Sgibbs
116565942Sgibbs	if (!have_seeprom) {
116665942Sgibbs		if (bootverbose)
116765942Sgibbs			printf("%s: No SEEPROM available.\n", ahc_name(ahc));
116865942Sgibbs		ahc->flags |= AHC_USEDEFAULTS;
116965942Sgibbs	} else {
117065942Sgibbs		/*
117165942Sgibbs		 * Put the data we've collected down into SRAM
117265942Sgibbs		 * where ahc_init will find it.
117365942Sgibbs		 */
117465942Sgibbs		int i;
117565942Sgibbs		int max_targ = sc.max_targets & CFMAXTARG;
117665942Sgibbs		uint16_t discenable;
117765942Sgibbs		uint16_t ultraenb;
117865942Sgibbs
117965942Sgibbs		discenable = 0;
118065942Sgibbs		ultraenb = 0;
118165942Sgibbs		if ((sc.adapter_control & CFULTRAEN) != 0) {
118265942Sgibbs			/*
118365942Sgibbs			 * Determine if this adapter has a "newstyle"
118465942Sgibbs			 * SEEPROM format.
118565942Sgibbs			 */
118665942Sgibbs			for (i = 0; i < max_targ; i++) {
118765942Sgibbs				if ((sc.device_flags[i] & CFSYNCHISULTRA) != 0){
118865942Sgibbs					ahc->flags |= AHC_NEWEEPROM_FMT;
118965942Sgibbs					break;
119065942Sgibbs				}
119165942Sgibbs			}
119265942Sgibbs		}
119365942Sgibbs
119465942Sgibbs		for (i = 0; i < max_targ; i++) {
119565942Sgibbs			u_int     scsirate;
119665942Sgibbs			uint16_t target_mask;
119765942Sgibbs
119865942Sgibbs			target_mask = 0x01 << i;
119965942Sgibbs			if (sc.device_flags[i] & CFDISC)
120065942Sgibbs				discenable |= target_mask;
120165942Sgibbs			if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) {
120265942Sgibbs				if ((sc.device_flags[i] & CFSYNCHISULTRA) != 0)
120365942Sgibbs					ultraenb |= target_mask;
120465942Sgibbs			} else if ((sc.adapter_control & CFULTRAEN) != 0) {
120565942Sgibbs				ultraenb |= target_mask;
120665942Sgibbs			}
120765942Sgibbs			if ((sc.device_flags[i] & CFXFER) == 0x04
120865942Sgibbs			 && (ultraenb & target_mask) != 0) {
120965942Sgibbs				/* Treat 10MHz as a non-ultra speed */
121065942Sgibbs				sc.device_flags[i] &= ~CFXFER;
121165942Sgibbs			 	ultraenb &= ~target_mask;
121265942Sgibbs			}
121365942Sgibbs			if ((ahc->features & AHC_ULTRA2) != 0) {
121465942Sgibbs				u_int offset;
121565942Sgibbs
121665942Sgibbs				if (sc.device_flags[i] & CFSYNCH)
121765942Sgibbs					offset = MAX_OFFSET_ULTRA2;
121865942Sgibbs				else
121965942Sgibbs					offset = 0;
122065942Sgibbs				ahc_outb(ahc, TARG_OFFSET + i, offset);
122165942Sgibbs
122265942Sgibbs				/*
122365942Sgibbs				 * The ultra enable bits contain the
122465942Sgibbs				 * high bit of the ultra2 sync rate
122565942Sgibbs				 * field.
122665942Sgibbs				 */
122765942Sgibbs				scsirate = (sc.device_flags[i] & CFXFER)
122865942Sgibbs					 | ((ultraenb & target_mask)
122965942Sgibbs					    ? 0x8 : 0x0);
123065942Sgibbs				if (sc.device_flags[i] & CFWIDEB)
123165942Sgibbs					scsirate |= WIDEXFER;
123265942Sgibbs			} else {
123365942Sgibbs				scsirate = (sc.device_flags[i] & CFXFER) << 4;
123465942Sgibbs				if (sc.device_flags[i] & CFSYNCH)
123565942Sgibbs					scsirate |= SOFS;
123665942Sgibbs				if (sc.device_flags[i] & CFWIDEB)
123765942Sgibbs					scsirate |= WIDEXFER;
123865942Sgibbs			}
123965942Sgibbs			ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);
124065942Sgibbs		}
124165942Sgibbs		ahc->our_id = sc.brtime_id & CFSCSIID;
124265942Sgibbs
124365942Sgibbs		scsi_conf = (ahc->our_id & 0x7);
124465942Sgibbs		if (sc.adapter_control & CFSPARITY)
124565942Sgibbs			scsi_conf |= ENSPCHK;
124665942Sgibbs		if (sc.adapter_control & CFRESETB)
124765942Sgibbs			scsi_conf |= RESET_SCSI;
124865942Sgibbs
124972325Sgibbs		if ((sc.adapter_control & CFCHNLBPRIMARY) != 0
125072325Sgibbs		 && (ahc->features & AHC_MULTI_FUNC) != 0)
125172325Sgibbs			ahc->flags |= AHC_CHANNEL_B_PRIMARY;
125272325Sgibbs
125365942Sgibbs		if (sc.bios_control & CFEXTEND)
125465942Sgibbs			ahc->flags |= AHC_EXTENDED_TRANS_A;
125572325Sgibbs
125672325Sgibbs		if (sc.bios_control & CFBIOSEN)
125772325Sgibbs			ahc->flags |= AHC_BIOS_ENABLED;
125865942Sgibbs		if (ahc->features & AHC_ULTRA
125965942Sgibbs		 && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {
126065942Sgibbs			/* Should we enable Ultra mode? */
126165942Sgibbs			if (!(sc.adapter_control & CFULTRAEN))
126265942Sgibbs				/* Treat us as a non-ultra card */
126365942Sgibbs				ultraenb = 0;
126465942Sgibbs		}
126565942Sgibbs
126665942Sgibbs		if (sc.signature == CFSIGNATURE) {
126765942Sgibbs			uint32_t devconfig;
126865942Sgibbs
126965942Sgibbs			/* Honor the STPWLEVEL settings */
127065942Sgibbs			devconfig = ahc_pci_read_config(ahc->dev_softc,
127165942Sgibbs							DEVCONFIG, /*bytes*/4);
127265942Sgibbs			devconfig &= ~STPWLEVEL;
127365942Sgibbs			if ((sc.bios_control & CFSTPWLEVEL) != 0)
127465942Sgibbs				devconfig |= STPWLEVEL;
127565942Sgibbs			ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
127665942Sgibbs					     devconfig, /*bytes*/4);
127765942Sgibbs		}
127865942Sgibbs		/* Set SCSICONF info */
127965942Sgibbs		ahc_outb(ahc, SCSICONF, scsi_conf);
128065942Sgibbs		ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
128165942Sgibbs		ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
128265942Sgibbs		ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff);
128365942Sgibbs		ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);
128465942Sgibbs	}
128565942Sgibbs
128665942Sgibbs	/*
128765942Sgibbs	 * Cards that have the external logic necessary to talk to
128865942Sgibbs	 * a SEEPROM, are almost certain to have the remaining logic
128965942Sgibbs	 * necessary for auto-termination control.  This assumption
129065942Sgibbs	 * hasn't failed yet...
129165942Sgibbs	 */
129265942Sgibbs	have_autoterm = have_seeprom;
129365942Sgibbs	if (have_seeprom)
129465942Sgibbs		adapter_control = sc.adapter_control;
129565942Sgibbs	else
129665942Sgibbs		adapter_control = CFAUTOTERM;
129765942Sgibbs
129865942Sgibbs	/*
129965942Sgibbs	 * Some low-cost chips have SEEPROM and auto-term control built
130065942Sgibbs	 * in, instead of using a GAL.  They can tell us directly
130165942Sgibbs	 * if the termination logic is enabled.
130265942Sgibbs	 */
130365942Sgibbs	if ((ahc->features & AHC_SPIOCAP) != 0) {
130465942Sgibbs		if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) != 0)
130565942Sgibbs			have_autoterm = TRUE;
130665942Sgibbs		else
130765942Sgibbs			have_autoterm = FALSE;
130865942Sgibbs	}
130965942Sgibbs
131065942Sgibbs	if (have_autoterm)
131165942Sgibbs		configure_termination(ahc, &sd, adapter_control, sxfrctl1);
131265942Sgibbs
131365942Sgibbs	release_seeprom(&sd);
131465942Sgibbs}
131565942Sgibbs
131665942Sgibbsstatic void
131765942Sgibbsconfigure_termination(struct ahc_softc *ahc,
131865942Sgibbs		      struct seeprom_descriptor *sd,
131965942Sgibbs		      u_int adapter_control,
132065942Sgibbs		      u_int *sxfrctl1)
132165942Sgibbs{
132265942Sgibbs	uint8_t brddat;
132365942Sgibbs
132465942Sgibbs	brddat = 0;
132565942Sgibbs
132665942Sgibbs	/*
132765942Sgibbs	 * Update the settings in sxfrctl1 to match the
132865942Sgibbs	 * termination settings
132965942Sgibbs	 */
133065942Sgibbs	*sxfrctl1 = 0;
133165942Sgibbs
133265942Sgibbs	/*
133365942Sgibbs	 * SEECS must be on for the GALS to latch
133465942Sgibbs	 * the data properly.  Be sure to leave MS
133565942Sgibbs	 * on or we will release the seeprom.
133665942Sgibbs	 */
133765942Sgibbs	SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS);
133865942Sgibbs	if ((adapter_control & CFAUTOTERM) != 0
133965942Sgibbs	 || (ahc->features & AHC_NEW_TERMCTL) != 0) {
134065942Sgibbs		int internal50_present;
134165942Sgibbs		int internal68_present;
134265942Sgibbs		int externalcable_present;
134365942Sgibbs		int eeprom_present;
134465942Sgibbs		int enableSEC_low;
134565942Sgibbs		int enableSEC_high;
134665942Sgibbs		int enablePRI_low;
134765942Sgibbs		int enablePRI_high;
134871390Sgibbs		int sum;
134965942Sgibbs
135065942Sgibbs		enableSEC_low = 0;
135165942Sgibbs		enableSEC_high = 0;
135265942Sgibbs		enablePRI_low = 0;
135365942Sgibbs		enablePRI_high = 0;
135465942Sgibbs		if ((ahc->features & AHC_NEW_TERMCTL) != 0) {
135565942Sgibbs			ahc_new_term_detect(ahc, &enableSEC_low,
135665942Sgibbs					       &enableSEC_high,
135765942Sgibbs					       &enablePRI_low,
135865942Sgibbs					       &enablePRI_high,
135965942Sgibbs					       &eeprom_present);
136065942Sgibbs			if ((adapter_control & CFSEAUTOTERM) == 0) {
136165942Sgibbs				if (bootverbose)
136265942Sgibbs					printf("%s: Manual SE Termination\n",
136365942Sgibbs					       ahc_name(ahc));
136465942Sgibbs				enableSEC_low = (adapter_control & CFSELOWTERM);
136565942Sgibbs				enableSEC_high =
136665942Sgibbs				    (adapter_control & CFSEHIGHTERM);
136765942Sgibbs			}
136865942Sgibbs			if ((adapter_control & CFAUTOTERM) == 0) {
136965942Sgibbs				if (bootverbose)
137065942Sgibbs					printf("%s: Manual LVD Termination\n",
137165942Sgibbs					       ahc_name(ahc));
137265942Sgibbs				enablePRI_low = (adapter_control & CFSTERM);
137365942Sgibbs				enablePRI_high = (adapter_control & CFWSTERM);
137465942Sgibbs			}
137565942Sgibbs			/* Make the table calculations below happy */
137665942Sgibbs			internal50_present = 0;
137765942Sgibbs			internal68_present = 1;
137865942Sgibbs			externalcable_present = 1;
137965942Sgibbs		} else if ((ahc->features & AHC_SPIOCAP) != 0) {
138065942Sgibbs			aic785X_cable_detect(ahc, &internal50_present,
138165942Sgibbs					     &externalcable_present,
138265942Sgibbs					     &eeprom_present);
138365942Sgibbs		} else {
138465942Sgibbs			aic787X_cable_detect(ahc, &internal50_present,
138565942Sgibbs					     &internal68_present,
138665942Sgibbs					     &externalcable_present,
138765942Sgibbs					     &eeprom_present);
138865942Sgibbs		}
138965942Sgibbs
139065942Sgibbs		if ((ahc->features & AHC_WIDE) == 0)
139165942Sgibbs			internal68_present = 0;
139265942Sgibbs
139371390Sgibbs		if (bootverbose
139471390Sgibbs		 && (ahc->features & AHC_ULTRA2) == 0) {
139571390Sgibbs			printf("%s: internal 50 cable %s present",
139671390Sgibbs			       ahc_name(ahc),
139771390Sgibbs			       internal50_present ? "is":"not");
139871390Sgibbs
139971390Sgibbs			if ((ahc->features & AHC_WIDE) != 0)
140071390Sgibbs				printf(", internal 68 cable %s present",
140165942Sgibbs				       internal68_present ? "is":"not");
140271390Sgibbs			printf("\n%s: external cable %s present\n",
140371390Sgibbs			       ahc_name(ahc),
140471390Sgibbs			       externalcable_present ? "is":"not");
140571390Sgibbs		}
140671390Sgibbs		if (bootverbose)
140765942Sgibbs			printf("%s: BIOS eeprom %s present\n",
140865942Sgibbs			       ahc_name(ahc), eeprom_present ? "is" : "not");
140965942Sgibbs
141065942Sgibbs		if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) {
141165942Sgibbs			/*
141265942Sgibbs			 * The 50 pin connector is a separate bus,
141365942Sgibbs			 * so force it to always be terminated.
141465942Sgibbs			 * In the future, perform current sensing
141565942Sgibbs			 * to determine if we are in the middle of
141665942Sgibbs			 * a properly terminated bus.
141765942Sgibbs			 */
141865942Sgibbs			internal50_present = 0;
141965942Sgibbs		}
142065942Sgibbs
142165942Sgibbs		/*
142265942Sgibbs		 * Now set the termination based on what
142365942Sgibbs		 * we found.
142465942Sgibbs		 * Flash Enable = BRDDAT7
142565942Sgibbs		 * Secondary High Term Enable = BRDDAT6
142665942Sgibbs		 * Secondary Low Term Enable = BRDDAT5 (7890)
142765942Sgibbs		 * Primary High Term Enable = BRDDAT4 (7890)
142865942Sgibbs		 */
142965942Sgibbs		if ((ahc->features & AHC_ULTRA2) == 0
143071390Sgibbs		 && (internal50_present != 0)
143171390Sgibbs		 && (internal68_present != 0)
143271390Sgibbs		 && (externalcable_present != 0)) {
143365942Sgibbs			printf("%s: Illegal cable configuration!!. "
143465942Sgibbs			       "Only two connectors on the "
143565942Sgibbs			       "adapter may be used at a "
143665942Sgibbs			       "time!\n", ahc_name(ahc));
143765942Sgibbs		}
143865942Sgibbs
143965942Sgibbs		if ((ahc->features & AHC_WIDE) != 0
144065942Sgibbs		 && ((externalcable_present == 0)
144165942Sgibbs		  || (internal68_present == 0)
144265942Sgibbs		  || (enableSEC_high != 0))) {
144365942Sgibbs			brddat |= BRDDAT6;
144465942Sgibbs			if (bootverbose) {
144565942Sgibbs				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
144665942Sgibbs					printf("%s: 68 pin termination "
144765942Sgibbs					       "Enabled\n", ahc_name(ahc));
144865942Sgibbs				else
144965942Sgibbs					printf("%s: %sHigh byte termination "
145065942Sgibbs					       "Enabled\n", ahc_name(ahc),
145165942Sgibbs					       enableSEC_high ? "Secondary "
145265942Sgibbs							      : "");
145365942Sgibbs			}
145465942Sgibbs		}
145565942Sgibbs
145671390Sgibbs		sum = internal50_present + internal68_present
145771390Sgibbs		    + externalcable_present;
145871390Sgibbs		if (sum < 2 || (enableSEC_low != 0)) {
145965942Sgibbs			if ((ahc->features & AHC_ULTRA2) != 0)
146065942Sgibbs				brddat |= BRDDAT5;
146165942Sgibbs			else
146265942Sgibbs				*sxfrctl1 |= STPWEN;
146365942Sgibbs			if (bootverbose) {
146465942Sgibbs				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
146565942Sgibbs					printf("%s: 50 pin termination "
146665942Sgibbs					       "Enabled\n", ahc_name(ahc));
146765942Sgibbs				else
146865942Sgibbs					printf("%s: %sLow byte termination "
146965942Sgibbs					       "Enabled\n", ahc_name(ahc),
147065942Sgibbs					       enableSEC_low ? "Secondary "
147165942Sgibbs							     : "");
147265942Sgibbs			}
147365942Sgibbs		}
147465942Sgibbs
147565942Sgibbs		if (enablePRI_low != 0) {
147665942Sgibbs			*sxfrctl1 |= STPWEN;
147765942Sgibbs			if (bootverbose)
147865942Sgibbs				printf("%s: Primary Low Byte termination "
147965942Sgibbs				       "Enabled\n", ahc_name(ahc));
148065942Sgibbs		}
148165942Sgibbs
148265942Sgibbs		/*
148365942Sgibbs		 * Setup STPWEN before setting up the rest of
148465942Sgibbs		 * the termination per the tech note on the U160 cards.
148565942Sgibbs		 */
148665942Sgibbs		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
148765942Sgibbs
148865942Sgibbs		if (enablePRI_high != 0) {
148965942Sgibbs			brddat |= BRDDAT4;
149065942Sgibbs			if (bootverbose)
149165942Sgibbs				printf("%s: Primary High Byte "
149265942Sgibbs				       "termination Enabled\n",
149365942Sgibbs				       ahc_name(ahc));
149465942Sgibbs		}
149565942Sgibbs
149665942Sgibbs		write_brdctl(ahc, brddat);
149765942Sgibbs
149865942Sgibbs	} else {
149965942Sgibbs		if ((adapter_control & CFSTERM) != 0) {
150065942Sgibbs			*sxfrctl1 |= STPWEN;
150165942Sgibbs
150265942Sgibbs			if (bootverbose)
150365942Sgibbs				printf("%s: %sLow byte termination Enabled\n",
150465942Sgibbs				       ahc_name(ahc),
150565942Sgibbs				       (ahc->features & AHC_ULTRA2) ? "Primary "
150665942Sgibbs								    : "");
150765942Sgibbs		}
150865942Sgibbs
150971390Sgibbs		if ((adapter_control & CFWSTERM) != 0
151071390Sgibbs		 && (ahc->features & AHC_WIDE) != 0) {
151165942Sgibbs			brddat |= BRDDAT6;
151265942Sgibbs			if (bootverbose)
151365942Sgibbs				printf("%s: %sHigh byte termination Enabled\n",
151465942Sgibbs				       ahc_name(ahc),
151565942Sgibbs				       (ahc->features & AHC_ULTRA2)
151665942Sgibbs				     ? "Secondary " : "");
151765942Sgibbs		}
151865942Sgibbs
151965942Sgibbs		/*
152065942Sgibbs		 * Setup STPWEN before setting up the rest of
152165942Sgibbs		 * the termination per the tech note on the U160 cards.
152265942Sgibbs		 */
152365942Sgibbs		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
152465942Sgibbs
152571390Sgibbs		if ((ahc->features & AHC_WIDE) != 0)
152671390Sgibbs			write_brdctl(ahc, brddat);
152765942Sgibbs	}
152865942Sgibbs	SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */
152965942Sgibbs}
153065942Sgibbs
153165942Sgibbsstatic void
153265942Sgibbsahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low,
153365942Sgibbs		    int *enableSEC_high, int *enablePRI_low,
153465942Sgibbs		    int *enablePRI_high, int *eeprom_present)
153565942Sgibbs{
153665942Sgibbs	uint8_t brdctl;
153765942Sgibbs
153865942Sgibbs	/*
153965942Sgibbs	 * BRDDAT7 = Eeprom
154065942Sgibbs	 * BRDDAT6 = Enable Secondary High Byte termination
154165942Sgibbs	 * BRDDAT5 = Enable Secondary Low Byte termination
154265942Sgibbs	 * BRDDAT4 = Enable Primary high byte termination
154365942Sgibbs	 * BRDDAT3 = Enable Primary low byte termination
154465942Sgibbs	 */
154565942Sgibbs	brdctl = read_brdctl(ahc);
154665942Sgibbs	*eeprom_present = brdctl & BRDDAT7;
154765942Sgibbs	*enableSEC_high = (brdctl & BRDDAT6);
154865942Sgibbs	*enableSEC_low = (brdctl & BRDDAT5);
154965942Sgibbs	*enablePRI_high = (brdctl & BRDDAT4);
155065942Sgibbs	*enablePRI_low = (brdctl & BRDDAT3);
155165942Sgibbs}
155265942Sgibbs
155365942Sgibbsstatic void
155465942Sgibbsaic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
155565942Sgibbs		     int *internal68_present, int *externalcable_present,
155665942Sgibbs		     int *eeprom_present)
155765942Sgibbs{
155865942Sgibbs	uint8_t brdctl;
155965942Sgibbs
156065942Sgibbs	/*
156165942Sgibbs	 * First read the status of our cables.
156265942Sgibbs	 * Set the rom bank to 0 since the
156365942Sgibbs	 * bank setting serves as a multiplexor
156465942Sgibbs	 * for the cable detection logic.
156565942Sgibbs	 * BRDDAT5 controls the bank switch.
156665942Sgibbs	 */
156765942Sgibbs	write_brdctl(ahc, 0);
156865942Sgibbs
156965942Sgibbs	/*
157065942Sgibbs	 * Now read the state of the internal
157165942Sgibbs	 * connectors.  BRDDAT6 is INT50 and
157265942Sgibbs	 * BRDDAT7 is INT68.
157365942Sgibbs	 */
157465942Sgibbs	brdctl = read_brdctl(ahc);
157571390Sgibbs	*internal50_present = (brdctl & BRDDAT6) ? 0 : 1;
157671390Sgibbs	*internal68_present = (brdctl & BRDDAT7) ? 0 : 1;
157765942Sgibbs
157865942Sgibbs	/*
157965942Sgibbs	 * Set the rom bank to 1 and determine
158065942Sgibbs	 * the other signals.
158165942Sgibbs	 */
158265942Sgibbs	write_brdctl(ahc, BRDDAT5);
158365942Sgibbs
158465942Sgibbs	/*
158565942Sgibbs	 * Now read the state of the external
158665942Sgibbs	 * connectors.  BRDDAT6 is EXT68 and
158765942Sgibbs	 * BRDDAT7 is EPROMPS.
158865942Sgibbs	 */
158965942Sgibbs	brdctl = read_brdctl(ahc);
159071390Sgibbs	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
159171390Sgibbs	*eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;
159265942Sgibbs}
159365942Sgibbs
159465942Sgibbsstatic void
159565942Sgibbsaic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
159665942Sgibbs		     int *externalcable_present, int *eeprom_present)
159765942Sgibbs{
159865942Sgibbs	uint8_t brdctl;
159965942Sgibbs
160065942Sgibbs	ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
160165942Sgibbs	ahc_outb(ahc, BRDCTL, 0);
160265942Sgibbs	brdctl = ahc_inb(ahc, BRDCTL);
160371390Sgibbs	*internal50_present = (brdctl & BRDDAT5) ? 0 : 1;
160471390Sgibbs	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
160565942Sgibbs
160671390Sgibbs	*eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
160765942Sgibbs}
160865942Sgibbs
160965942Sgibbsstatic int
161065942Sgibbsacquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
161165942Sgibbs{
161265942Sgibbs	int wait;
161365942Sgibbs
161465942Sgibbs	if ((ahc->features & AHC_SPIOCAP) != 0
161565942Sgibbs	 && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0)
161665942Sgibbs		return (0);
161765942Sgibbs
161865942Sgibbs	/*
161965942Sgibbs	 * Request access of the memory port.  When access is
162065942Sgibbs	 * granted, SEERDY will go high.  We use a 1 second
162165942Sgibbs	 * timeout which should be near 1 second more than
162265942Sgibbs	 * is needed.  Reason: after the chip reset, there
162365942Sgibbs	 * should be no contention.
162465942Sgibbs	 */
162565942Sgibbs	SEEPROM_OUTB(sd, sd->sd_MS);
162665942Sgibbs	wait = 1000;  /* 1 second timeout in msec */
162765942Sgibbs	while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
162865942Sgibbs		ahc_delay(1000);  /* delay 1 msec */
162965942Sgibbs	}
163065942Sgibbs	if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
163165942Sgibbs		SEEPROM_OUTB(sd, 0);
163265942Sgibbs		return (0);
163365942Sgibbs	}
163465942Sgibbs	return(1);
163565942Sgibbs}
163665942Sgibbs
163765942Sgibbsstatic void
163865942Sgibbsrelease_seeprom(struct seeprom_descriptor *sd)
163965942Sgibbs{
164065942Sgibbs	/* Release access to the memory port and the serial EEPROM. */
164165942Sgibbs	SEEPROM_OUTB(sd, 0);
164265942Sgibbs}
164365942Sgibbs
164465942Sgibbsstatic void
164565942Sgibbswrite_brdctl(struct ahc_softc *ahc, uint8_t value)
164665942Sgibbs{
164765942Sgibbs	uint8_t brdctl;
164865942Sgibbs
164965942Sgibbs	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
165065942Sgibbs		brdctl = BRDSTB;
165165942Sgibbs	 	if (ahc->channel == 'B')
165265942Sgibbs			brdctl |= BRDCS;
165365942Sgibbs	} else if ((ahc->features & AHC_ULTRA2) != 0) {
165465942Sgibbs		brdctl = 0;
165565942Sgibbs	} else {
165665942Sgibbs		brdctl = BRDSTB|BRDCS;
165765942Sgibbs	}
165865942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
165971390Sgibbs	ahc_flush_device_writes(ahc);
166065942Sgibbs	brdctl |= value;
166165942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
166271390Sgibbs	ahc_flush_device_writes(ahc);
166365942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
166465942Sgibbs		brdctl |= BRDSTB_ULTRA2;
166565942Sgibbs	else
166665942Sgibbs		brdctl &= ~BRDSTB;
166765942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
166871390Sgibbs	ahc_flush_device_writes(ahc);
166965942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
167065942Sgibbs		brdctl = 0;
167165942Sgibbs	else
167265942Sgibbs		brdctl &= ~BRDCS;
167365942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
167465942Sgibbs}
167565942Sgibbs
167665942Sgibbsstatic uint8_t
167765942Sgibbsread_brdctl(ahc)
167865942Sgibbs	struct 	ahc_softc *ahc;
167965942Sgibbs{
168065942Sgibbs	uint8_t brdctl;
168165942Sgibbs	uint8_t value;
168265942Sgibbs
168365942Sgibbs	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
168465942Sgibbs		brdctl = BRDRW;
168565942Sgibbs	 	if (ahc->channel == 'B')
168665942Sgibbs			brdctl |= BRDCS;
168765942Sgibbs	} else if ((ahc->features & AHC_ULTRA2) != 0) {
168865942Sgibbs		brdctl = BRDRW_ULTRA2;
168965942Sgibbs	} else {
169065942Sgibbs		brdctl = BRDRW|BRDCS;
169165942Sgibbs	}
169265942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
169371390Sgibbs	ahc_flush_device_writes(ahc);
169465942Sgibbs	value = ahc_inb(ahc, BRDCTL);
169565942Sgibbs	ahc_outb(ahc, BRDCTL, 0);
169665942Sgibbs	return (value);
169765942Sgibbs}
169865942Sgibbs
169965942Sgibbs#define	DPE	0x80
170065942Sgibbs#define SSE	0x40
170165942Sgibbs#define	RMA	0x20
170265942Sgibbs#define	RTA	0x10
170365942Sgibbs#define STA	0x08
170465942Sgibbs#define DPR	0x01
170565942Sgibbs
170665942Sgibbsvoid
170765942Sgibbsahc_pci_intr(struct ahc_softc *ahc)
170865942Sgibbs{
170966269Sgibbs	u_int error;
171066269Sgibbs	u_int status1;
171165942Sgibbs
171266269Sgibbs	error = ahc_inb(ahc, ERROR);
171366269Sgibbs	if ((error & PCIERRSTAT) == 0)
171466269Sgibbs		return;
171566269Sgibbs
171665942Sgibbs	status1 = ahc_pci_read_config(ahc->dev_softc,
171765942Sgibbs				      PCIR_STATUS + 1, /*bytes*/1);
171865942Sgibbs
171966269Sgibbs	printf("%s: PCI error Interrupt at seqaddr = 0x%x\n",
172066269Sgibbs	      ahc_name(ahc),
172166269Sgibbs	      ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
172266269Sgibbs
172365942Sgibbs	if (status1 & DPE) {
172465942Sgibbs		printf("%s: Data Parity Error Detected during address "
172565942Sgibbs		       "or write data phase\n", ahc_name(ahc));
172665942Sgibbs	}
172765942Sgibbs	if (status1 & SSE) {
172866647Sgibbs		printf("%s: Signal System Error Detected\n", ahc_name(ahc));
172965942Sgibbs	}
173065942Sgibbs	if (status1 & RMA) {
173166647Sgibbs		printf("%s: Received a Master Abort\n", ahc_name(ahc));
173265942Sgibbs	}
173365942Sgibbs	if (status1 & RTA) {
173465942Sgibbs		printf("%s: Received a Target Abort\n", ahc_name(ahc));
173565942Sgibbs	}
173665942Sgibbs	if (status1 & STA) {
173765942Sgibbs		printf("%s: Signaled a Target Abort\n", ahc_name(ahc));
173865942Sgibbs	}
173965942Sgibbs	if (status1 & DPR) {
174065942Sgibbs		printf("%s: Data Parity Error has been reported via PERR#\n",
174165942Sgibbs		       ahc_name(ahc));
174265942Sgibbs	}
174365942Sgibbs	if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) {
174465942Sgibbs		printf("%s: Latched PCIERR interrupt with "
174565942Sgibbs		       "no status bits set\n", ahc_name(ahc));
174665942Sgibbs	}
174765942Sgibbs	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
174865942Sgibbs			     status1, /*bytes*/1);
174965942Sgibbs
175065942Sgibbs	if (status1 & (DPR|RMA|RTA)) {
175165942Sgibbs		ahc_outb(ahc, CLRINT, CLRPARERR);
175265942Sgibbs	}
175366269Sgibbs
175466269Sgibbs	unpause_sequencer(ahc);
175565942Sgibbs}
175665942Sgibbs
175765942Sgibbsstatic int
175865942Sgibbsahc_aic7850_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
175965942Sgibbs{
176065942Sgibbs	probe_config->channel = 'A';
176165942Sgibbs	probe_config->chip = AHC_AIC7850;
176265942Sgibbs	probe_config->features = AHC_AIC7850_FE;
176365942Sgibbs	probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG
176465942Sgibbs			   |  AHC_PCI_MWI_BUG;
176565942Sgibbs	return (0);
176665942Sgibbs}
176765942Sgibbs
176865942Sgibbsstatic int
176965942Sgibbsahc_aic7855_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
177065942Sgibbs{
177165942Sgibbs	probe_config->channel = 'A';
177265942Sgibbs	probe_config->chip = AHC_AIC7855;
177365942Sgibbs	probe_config->features = AHC_AIC7855_FE;
177465942Sgibbs	probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG
177565942Sgibbs			   |  AHC_PCI_MWI_BUG;
177665942Sgibbs	return (0);
177765942Sgibbs}
177865942Sgibbs
177965942Sgibbsstatic int
178065942Sgibbsahc_aic7860_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
178165942Sgibbs{
178265942Sgibbs	uint8_t rev;
178365942Sgibbs
178465942Sgibbs	probe_config->channel = 'A';
178565942Sgibbs	probe_config->chip = AHC_AIC7860;
178665942Sgibbs	probe_config->features = AHC_AIC7860_FE;
178765942Sgibbs	probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG
178865942Sgibbs			   |  AHC_PCI_MWI_BUG;
178965942Sgibbs	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
179065942Sgibbs	if (rev >= 1)
179165942Sgibbs		probe_config->bugs |= AHC_PCI_2_1_RETRY_BUG;
179265942Sgibbs	return (0);
179365942Sgibbs}
179465942Sgibbs
179565942Sgibbsstatic int
179671390Sgibbsahc_apa1480_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
179771390Sgibbs{
179871390Sgibbs	int error;
179971390Sgibbs
180071390Sgibbs	error = ahc_aic7860_setup(pci, probe_config);
180171390Sgibbs	if (error != 0)
180271390Sgibbs		return (error);
180371390Sgibbs	probe_config->features |= AHC_REMOVABLE;
180471390Sgibbs	return (0);
180571390Sgibbs}
180671390Sgibbs
180771390Sgibbsstatic int
180865942Sgibbsahc_aic7870_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
180965942Sgibbs{
181065942Sgibbs	probe_config->channel = 'A';
181165942Sgibbs	probe_config->chip = AHC_AIC7870;
181265942Sgibbs	probe_config->features = AHC_AIC7870_FE;
181365942Sgibbs	probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG
181465942Sgibbs			   |  AHC_PCI_MWI_BUG;
181565942Sgibbs	return (0);
181665942Sgibbs}
181765942Sgibbs
181865942Sgibbsstatic int
181965942Sgibbsahc_aha394X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
182065942Sgibbs{
182165942Sgibbs	int error;
182265942Sgibbs
182365942Sgibbs	error = ahc_aic7870_setup(pci, probe_config);
182465942Sgibbs	if (error == 0)
182565942Sgibbs		error = ahc_aha394XX_setup(pci, probe_config);
182665942Sgibbs	return (error);
182765942Sgibbs}
182865942Sgibbs
182965942Sgibbsstatic int
183065942Sgibbsahc_aha398X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
183165942Sgibbs{
183265942Sgibbs	int error;
183365942Sgibbs
183465942Sgibbs	error = ahc_aic7870_setup(pci, probe_config);
183565942Sgibbs	if (error == 0)
183665942Sgibbs		error = ahc_aha398XX_setup(pci, probe_config);
183765942Sgibbs	return (error);
183865942Sgibbs}
183965942Sgibbs
184065942Sgibbsstatic int
184165942Sgibbsahc_aha494X_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
184265942Sgibbs{
184365942Sgibbs	int error;
184465942Sgibbs
184565942Sgibbs	error = ahc_aic7870_setup(pci, probe_config);
184665942Sgibbs	if (error == 0)
184765942Sgibbs		error = ahc_aha494XX_setup(pci, probe_config);
184865942Sgibbs	return (error);
184965942Sgibbs}
185065942Sgibbs
185165942Sgibbsstatic int
185265942Sgibbsahc_aic7880_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
185365942Sgibbs{
185465942Sgibbs	uint8_t rev;
185565942Sgibbs
185665942Sgibbs	probe_config->channel = 'A';
185765942Sgibbs	probe_config->chip = AHC_AIC7880;
185865942Sgibbs	probe_config->features = AHC_AIC7880_FE;
185965942Sgibbs	probe_config->bugs |= AHC_TMODE_WIDEODD_BUG;
186065942Sgibbs	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
186165942Sgibbs	if (rev >= 1) {
186265942Sgibbs		probe_config->bugs |= AHC_PCI_2_1_RETRY_BUG;
186365942Sgibbs	} else {
186466845Sgibbs		probe_config->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
186565942Sgibbs	}
186665942Sgibbs	return (0);
186765942Sgibbs}
186865942Sgibbs
186965942Sgibbsstatic int
187071390Sgibbsahc_aha2940Pro_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
187165942Sgibbs{
187265942Sgibbs	int error;
187365942Sgibbs
187465942Sgibbs	probe_config->flags |= AHC_INT50_SPEEDFLEX;
187565942Sgibbs	error = ahc_aic7880_setup(pci, probe_config);
187665942Sgibbs	return (0);
187765942Sgibbs}
187865942Sgibbs
187965942Sgibbsstatic int
188065942Sgibbsahc_aha394XU_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
188165942Sgibbs{
188265942Sgibbs	int error;
188365942Sgibbs
188465942Sgibbs	error = ahc_aic7880_setup(pci, probe_config);
188565942Sgibbs	if (error == 0)
188665942Sgibbs		error = ahc_aha394XX_setup(pci, probe_config);
188765942Sgibbs	return (error);
188865942Sgibbs}
188965942Sgibbs
189065942Sgibbsstatic int
189165942Sgibbsahc_aha398XU_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
189265942Sgibbs{
189365942Sgibbs	int error;
189465942Sgibbs
189565942Sgibbs	error = ahc_aic7880_setup(pci, probe_config);
189665942Sgibbs	if (error == 0)
189765942Sgibbs		error = ahc_aha398XX_setup(pci, probe_config);
189865942Sgibbs	return (error);
189965942Sgibbs}
190065942Sgibbs
190165942Sgibbsstatic int
190265942Sgibbsahc_aic7890_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
190365942Sgibbs{
190465942Sgibbs	uint8_t rev;
190565942Sgibbs
190665942Sgibbs	probe_config->channel = 'A';
190765942Sgibbs	probe_config->chip = AHC_AIC7890;
190865942Sgibbs	probe_config->features = AHC_AIC7890_FE;
190965942Sgibbs	probe_config->flags |= AHC_NEWEEPROM_FMT;
191065942Sgibbs	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
191165942Sgibbs	if (rev == 0)
191265942Sgibbs		probe_config->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG;
191365942Sgibbs	return (0);
191465942Sgibbs}
191565942Sgibbs
191665942Sgibbsstatic int
191765942Sgibbsahc_aic7892_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
191865942Sgibbs{
191965942Sgibbs	probe_config->channel = 'A';
192065942Sgibbs	probe_config->chip = AHC_AIC7892;
192165942Sgibbs	probe_config->features = AHC_AIC7892_FE;
192265942Sgibbs	probe_config->flags |= AHC_NEWEEPROM_FMT;
192365942Sgibbs	probe_config->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
192465942Sgibbs	return (0);
192565942Sgibbs}
192665942Sgibbs
192765942Sgibbsstatic int
192865942Sgibbsahc_aic7895_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
192965942Sgibbs{
193065942Sgibbs	uint8_t rev;
193165942Sgibbs
193265942Sgibbs	probe_config->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
193365942Sgibbs	/*
193465942Sgibbs	 * The 'C' revision of the aic7895 has a few additional features.
193565942Sgibbs	 */
193665942Sgibbs	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
193765942Sgibbs	if (rev >= 4) {
193865942Sgibbs		probe_config->chip = AHC_AIC7895C;
193965942Sgibbs		probe_config->features = AHC_AIC7895C_FE;
194065942Sgibbs	} else  {
194165942Sgibbs		u_int command;
194265942Sgibbs
194365942Sgibbs		probe_config->chip = AHC_AIC7895;
194465942Sgibbs		probe_config->features = AHC_AIC7895_FE;
194565942Sgibbs
194665942Sgibbs		/*
194765942Sgibbs		 * The BIOS disables the use of MWI transactions
194865942Sgibbs		 * since it does not have the MWI bug work around
194965942Sgibbs		 * we have.  Disabling MWI reduces performance, so
195065942Sgibbs		 * turn it on again.
195165942Sgibbs		 */
195265942Sgibbs		command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1);
195365942Sgibbs		command |= PCIM_CMD_MWRICEN;
195465942Sgibbs		ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1);
195565942Sgibbs		probe_config->bugs |= AHC_PCI_MWI_BUG;
195665942Sgibbs	}
195765942Sgibbs	/*
195865942Sgibbs	 * XXX Does CACHETHEN really not work???  What about PCI retry?
195965942Sgibbs	 * on C level chips.  Need to test, but for now, play it safe.
196065942Sgibbs	 */
196165942Sgibbs	probe_config->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG
196265942Sgibbs			   |  AHC_CACHETHEN_BUG;
196365942Sgibbs
196465942Sgibbs#if 0
196565942Sgibbs	uint32_t devconfig;
196665942Sgibbs
196765942Sgibbs	/*
196865942Sgibbs	 * Cachesize must also be zero due to stray DAC
196965942Sgibbs	 * problem when sitting behind some bridges.
197065942Sgibbs	 */
197165942Sgibbs	ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1);
197265942Sgibbs	devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1);
197365942Sgibbs	devconfig |= MRDCEN;
197465942Sgibbs	ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1);
197565942Sgibbs#endif
197665942Sgibbs	probe_config->flags |= AHC_NEWEEPROM_FMT;
197765942Sgibbs	return (0);
197865942Sgibbs}
197965942Sgibbs
198065942Sgibbsstatic int
198165942Sgibbsahc_aic7896_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
198265942Sgibbs{
198365942Sgibbs	probe_config->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
198465942Sgibbs	probe_config->chip = AHC_AIC7896;
198565942Sgibbs	probe_config->features = AHC_AIC7896_FE;
198665942Sgibbs	probe_config->flags |= AHC_NEWEEPROM_FMT;
198765942Sgibbs	probe_config->bugs |= AHC_CACHETHEN_DIS_BUG;
198865942Sgibbs	return (0);
198965942Sgibbs}
199065942Sgibbs
199165942Sgibbsstatic int
199265942Sgibbsahc_aic7899_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
199365942Sgibbs{
199465942Sgibbs	probe_config->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
199565942Sgibbs	probe_config->chip = AHC_AIC7899;
199665942Sgibbs	probe_config->features = AHC_AIC7899_FE;
199765942Sgibbs	probe_config->flags |= AHC_NEWEEPROM_FMT;
199865942Sgibbs	probe_config->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
199965942Sgibbs	return (0);
200065942Sgibbs}
200165942Sgibbs
200265942Sgibbsstatic int
200371390Sgibbsahc_aha29160C_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
200471390Sgibbs{
200571390Sgibbs	int error;
200671390Sgibbs
200771390Sgibbs	error = ahc_aic7899_setup(pci, probe_config);
200871390Sgibbs	if (error != 0)
200971390Sgibbs		return (error);
201071390Sgibbs	probe_config->features |= AHC_REMOVABLE;
201171390Sgibbs	return (0);
201271390Sgibbs}
201371390Sgibbs
201471390Sgibbsstatic int
201565942Sgibbsahc_raid_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
201665942Sgibbs{
201765942Sgibbs	printf("RAID functionality unsupported\n");
201865942Sgibbs	return (ENXIO);
201965942Sgibbs}
202065942Sgibbs
202165942Sgibbsstatic int
202265942Sgibbsahc_aha394XX_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
202365942Sgibbs{
202465942Sgibbs	switch (ahc_get_pci_slot(pci)) {
202565942Sgibbs	case AHC_394X_SLOT_CHANNEL_A:
202665942Sgibbs		probe_config->channel = 'A';
202765942Sgibbs		break;
202865942Sgibbs	case AHC_394X_SLOT_CHANNEL_B:
202965942Sgibbs		probe_config->channel = 'B';
203065942Sgibbs		break;
203165942Sgibbs	default:
203265942Sgibbs		printf("adapter at unexpected slot %d\n"
203365942Sgibbs		       "unable to map to a channel\n",
203465942Sgibbs		       ahc_get_pci_slot(pci));
203565942Sgibbs		probe_config->channel = 'A';
203665942Sgibbs	}
203765942Sgibbs	return (0);
203865942Sgibbs}
203965942Sgibbs
204065942Sgibbsstatic int
204165942Sgibbsahc_aha398XX_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
204265942Sgibbs{
204365942Sgibbs	switch (ahc_get_pci_slot(pci)) {
204465942Sgibbs	case AHC_398X_SLOT_CHANNEL_A:
204565942Sgibbs		probe_config->channel = 'A';
204665942Sgibbs		break;
204765942Sgibbs	case AHC_398X_SLOT_CHANNEL_B:
204865942Sgibbs		probe_config->channel = 'B';
204965942Sgibbs		break;
205065942Sgibbs	case AHC_398X_SLOT_CHANNEL_C:
205165942Sgibbs		probe_config->channel = 'C';
205265942Sgibbs		break;
205365942Sgibbs	default:
205465942Sgibbs		printf("adapter at unexpected slot %d\n"
205565942Sgibbs		       "unable to map to a channel\n",
205665942Sgibbs		       ahc_get_pci_slot(pci));
205765942Sgibbs		probe_config->channel = 'A';
205865942Sgibbs		break;
205965942Sgibbs	}
206065942Sgibbs	probe_config->flags |= AHC_LARGE_SEEPROM;
206165942Sgibbs	return (0);
206265942Sgibbs}
206365942Sgibbs
206465942Sgibbsstatic int
206565942Sgibbsahc_aha494XX_setup(ahc_dev_softc_t pci, struct ahc_probe_config *probe_config)
206665942Sgibbs{
206765942Sgibbs	switch (ahc_get_pci_slot(pci)) {
206865942Sgibbs	case AHC_494X_SLOT_CHANNEL_A:
206965942Sgibbs		probe_config->channel = 'A';
207065942Sgibbs		break;
207165942Sgibbs	case AHC_494X_SLOT_CHANNEL_B:
207265942Sgibbs		probe_config->channel = 'B';
207365942Sgibbs		break;
207465942Sgibbs	case AHC_494X_SLOT_CHANNEL_C:
207565942Sgibbs		probe_config->channel = 'C';
207665942Sgibbs		break;
207765942Sgibbs	case AHC_494X_SLOT_CHANNEL_D:
207865942Sgibbs		probe_config->channel = 'D';
207965942Sgibbs		break;
208065942Sgibbs	default:
208165942Sgibbs		printf("adapter at unexpected slot %d\n"
208265942Sgibbs		       "unable to map to a channel\n",
208365942Sgibbs		       ahc_get_pci_slot(pci));
208465942Sgibbs		probe_config->channel = 'A';
208565942Sgibbs	}
208665942Sgibbs	probe_config->flags |= AHC_LARGE_SEEPROM;
208765942Sgibbs	return (0);
208865942Sgibbs}
2089