aic7xxx_pci.c revision 120445
165942Sgibbs/*
265942Sgibbs * Product specific probe and attach routines for:
365942Sgibbs *      3940, 2940, aic7895, aic7890, aic7880,
465942Sgibbs *	aic7870, aic7860 and aic7850 SCSI controllers
565942Sgibbs *
695378Sgibbs * Copyright (c) 1994-2001 Justin T. Gibbs.
795378Sgibbs * Copyright (c) 2000-2001 Adaptec Inc.
865942Sgibbs * All rights reserved.
965942Sgibbs *
1065942Sgibbs * Redistribution and use in source and binary forms, with or without
1165942Sgibbs * modification, are permitted provided that the following conditions
1265942Sgibbs * are met:
1365942Sgibbs * 1. Redistributions of source code must retain the above copyright
1465942Sgibbs *    notice, this list of conditions, and the following disclaimer,
1595378Sgibbs *    without modification.
1695378Sgibbs * 2. Redistributions in binary form must reproduce at minimum a disclaimer
1795378Sgibbs *    substantially similar to the "NO WARRANTY" disclaimer below
1895378Sgibbs *    ("Disclaimer") and any redistribution must be conditioned upon
1995378Sgibbs *    including a substantially similar Disclaimer requirement for further
2095378Sgibbs *    binary redistribution.
2195378Sgibbs * 3. Neither the names of the above-listed copyright holders nor the names
2295378Sgibbs *    of any contributors may be used to endorse or promote products derived
2395378Sgibbs *    from this software without specific prior written permission.
2465942Sgibbs *
2565942Sgibbs * Alternatively, this software may be distributed under the terms of the
2695378Sgibbs * GNU General Public License ("GPL") version 2 as published by the Free
2795378Sgibbs * Software Foundation.
2865942Sgibbs *
2995378Sgibbs * NO WARRANTY
3095378Sgibbs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
3195378Sgibbs * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3295378Sgibbs * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
3395378Sgibbs * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
3495378Sgibbs * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3565942Sgibbs * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3665942Sgibbs * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3795378Sgibbs * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
3895378Sgibbs * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
3995378Sgibbs * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
4095378Sgibbs * POSSIBILITY OF SUCH DAMAGES.
4165942Sgibbs *
42120445Sscottl * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#72 $
4365942Sgibbs */
4465942Sgibbs
45119418Sobrien#include <sys/cdefs.h>
46119418Sobrien__FBSDID("$FreeBSD: head/sys/dev/aic7xxx/aic7xxx_pci.c 120445 2003-09-25 23:36:41Z scottl $");
47119418Sobrien
4895378Sgibbs#ifdef __linux__
4995378Sgibbs#include "aic7xxx_osm.h"
5095378Sgibbs#include "aic7xxx_inline.h"
5195378Sgibbs#include "aic7xxx_93cx6.h"
5295378Sgibbs#else
5395378Sgibbs#include <dev/aic7xxx/aic7xxx_osm.h>
5465942Sgibbs#include <dev/aic7xxx/aic7xxx_inline.h>
5565942Sgibbs#include <dev/aic7xxx/aic7xxx_93cx6.h>
5695378Sgibbs#endif
5765942Sgibbs
58119690Sjhb#define AHC_PCI_IOADDR	PCIR_BAR(0)	/* I/O Address */
59119690Sjhb#define AHC_PCI_MEMADDR	PCIR_BAR(1)	/* Mem I/O Address */
6065942Sgibbs
6165942Sgibbsstatic __inline uint64_t
6265942Sgibbsahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
6365942Sgibbs{
6465942Sgibbs	uint64_t id;
6565942Sgibbs
6665942Sgibbs	id = subvendor
6765942Sgibbs	   | (subdevice << 16)
6865942Sgibbs	   | ((uint64_t)vendor << 32)
6965942Sgibbs	   | ((uint64_t)device << 48);
7065942Sgibbs
7165942Sgibbs	return (id);
7265942Sgibbs}
7365942Sgibbs
7474094Sgibbs#define ID_ALL_MASK			0xFFFFFFFFFFFFFFFFull
7574094Sgibbs#define ID_DEV_VENDOR_MASK		0xFFFFFFFF00000000ull
7674094Sgibbs#define ID_9005_GENERIC_MASK		0xFFF0FFFF00000000ull
7774094Sgibbs#define ID_9005_SISL_MASK		0x000FFFFF00000000ull
7874094Sgibbs#define ID_9005_SISL_ID			0x0005900500000000ull
7974094Sgibbs#define ID_AIC7850			0x5078900400000000ull
80115338Sgibbs#define ID_AHA_2902_04_10_15_20C_30C	0x5078900478509004ull
8174094Sgibbs#define ID_AIC7855			0x5578900400000000ull
8274094Sgibbs#define ID_AIC7859			0x3860900400000000ull
8374094Sgibbs#define ID_AHA_2930CU			0x3860900438699004ull
8474094Sgibbs#define ID_AIC7860			0x6078900400000000ull
8574094Sgibbs#define ID_AIC7860C			0x6078900478609004ull
8674094Sgibbs#define ID_AHA_1480A			0x6075900400000000ull
8774094Sgibbs#define ID_AHA_2940AU_0			0x6178900400000000ull
8874094Sgibbs#define ID_AHA_2940AU_1			0x6178900478619004ull
8974094Sgibbs#define ID_AHA_2940AU_CN		0x2178900478219004ull
9074094Sgibbs#define ID_AHA_2930C_VAR		0x6038900438689004ull
9165942Sgibbs
9274094Sgibbs#define ID_AIC7870			0x7078900400000000ull
9374094Sgibbs#define ID_AHA_2940			0x7178900400000000ull
9474094Sgibbs#define ID_AHA_3940			0x7278900400000000ull
9574094Sgibbs#define ID_AHA_398X			0x7378900400000000ull
9674094Sgibbs#define ID_AHA_2944			0x7478900400000000ull
9774094Sgibbs#define ID_AHA_3944			0x7578900400000000ull
9874094Sgibbs#define ID_AHA_4944			0x7678900400000000ull
9965942Sgibbs
10074094Sgibbs#define ID_AIC7880			0x8078900400000000ull
10174094Sgibbs#define ID_AIC7880_B			0x8078900478809004ull
10274094Sgibbs#define ID_AHA_2940U			0x8178900400000000ull
10374094Sgibbs#define ID_AHA_3940U			0x8278900400000000ull
10474094Sgibbs#define ID_AHA_2944U			0x8478900400000000ull
10574094Sgibbs#define ID_AHA_3944U			0x8578900400000000ull
10674094Sgibbs#define ID_AHA_398XU			0x8378900400000000ull
10774094Sgibbs#define ID_AHA_4944U			0x8678900400000000ull
10874094Sgibbs#define ID_AHA_2940UB			0x8178900478819004ull
10974094Sgibbs#define ID_AHA_2930U			0x8878900478889004ull
11074094Sgibbs#define ID_AHA_2940U_PRO		0x8778900478879004ull
11174094Sgibbs#define ID_AHA_2940U_CN			0x0078900478009004ull
11265942Sgibbs
11374094Sgibbs#define ID_AIC7895			0x7895900478959004ull
11474094Sgibbs#define ID_AIC7895_ARO			0x7890900478939004ull
11574094Sgibbs#define ID_AIC7895_ARO_MASK		0xFFF0FFFFFFFFFFFFull
11674094Sgibbs#define ID_AHA_2940U_DUAL		0x7895900478919004ull
11774094Sgibbs#define ID_AHA_3940AU			0x7895900478929004ull
11874094Sgibbs#define ID_AHA_3944AU			0x7895900478949004ull
11965942Sgibbs
12074094Sgibbs#define ID_AIC7890			0x001F9005000F9005ull
12174094Sgibbs#define ID_AIC7890_ARO			0x00139005000F9005ull
12274094Sgibbs#define ID_AAA_131U2			0x0013900500039005ull
12374094Sgibbs#define ID_AHA_2930U2			0x0011900501819005ull
12474094Sgibbs#define ID_AHA_2940U2B			0x00109005A1009005ull
12574094Sgibbs#define ID_AHA_2940U2_OEM		0x0010900521809005ull
12674094Sgibbs#define ID_AHA_2940U2			0x00109005A1809005ull
12774094Sgibbs#define ID_AHA_2950U2B			0x00109005E1009005ull
12865942Sgibbs
12974094Sgibbs#define ID_AIC7892			0x008F9005FFFF9005ull
13074094Sgibbs#define ID_AIC7892_ARO			0x00839005FFFF9005ull
13174094Sgibbs#define ID_AHA_29160			0x00809005E2A09005ull
13274094Sgibbs#define ID_AHA_29160_CPQ		0x00809005E2A00E11ull
13374094Sgibbs#define ID_AHA_29160N			0x0080900562A09005ull
13474094Sgibbs#define ID_AHA_29160C			0x0080900562209005ull
13574094Sgibbs#define ID_AHA_29160B			0x00809005E2209005ull
13674094Sgibbs#define ID_AHA_19160B			0x0081900562A19005ull
13765942Sgibbs
13874094Sgibbs#define ID_AIC7896			0x005F9005FFFF9005ull
13974094Sgibbs#define ID_AIC7896_ARO			0x00539005FFFF9005ull
14074094Sgibbs#define ID_AHA_3950U2B_0		0x00509005FFFF9005ull
14174094Sgibbs#define ID_AHA_3950U2B_1		0x00509005F5009005ull
14274094Sgibbs#define ID_AHA_3950U2D_0		0x00519005FFFF9005ull
14374094Sgibbs#define ID_AHA_3950U2D_1		0x00519005B5009005ull
14465942Sgibbs
14574094Sgibbs#define ID_AIC7899			0x00CF9005FFFF9005ull
14674094Sgibbs#define ID_AIC7899_ARO			0x00C39005FFFF9005ull
14774094Sgibbs#define ID_AHA_3960D			0x00C09005F6209005ull
14874094Sgibbs#define ID_AHA_3960D_CPQ		0x00C09005F6200E11ull
14965942Sgibbs
15074094Sgibbs#define ID_AIC7810			0x1078900400000000ull
15174094Sgibbs#define ID_AIC7815			0x7815900400000000ull
15265942Sgibbs
15372325Sgibbs#define DEVID_9005_TYPE(id) ((id) & 0xF)
15472325Sgibbs#define		DEVID_9005_TYPE_HBA		0x0	/* Standard Card */
15572325Sgibbs#define		DEVID_9005_TYPE_AAA		0x3	/* RAID Card */
15695378Sgibbs#define		DEVID_9005_TYPE_SISL		0x5	/* Container ROMB */
15772325Sgibbs#define		DEVID_9005_TYPE_MB		0xF	/* On Motherboard */
15872325Sgibbs
15972325Sgibbs#define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
16072325Sgibbs#define		DEVID_9005_MAXRATE_U160		0x0
16172325Sgibbs#define		DEVID_9005_MAXRATE_ULTRA2	0x1
16272325Sgibbs#define		DEVID_9005_MAXRATE_ULTRA	0x2
16372325Sgibbs#define		DEVID_9005_MAXRATE_FAST		0x3
16472325Sgibbs
16572325Sgibbs#define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6)
16672325Sgibbs
16772325Sgibbs#define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8)
16872325Sgibbs#define		DEVID_9005_CLASS_SPI		0x0	/* Parallel SCSI */
16972325Sgibbs
17070693Sgibbs#define SUBID_9005_TYPE(id) ((id) & 0xF)
17170693Sgibbs#define		SUBID_9005_TYPE_MB		0xF	/* On Motherboard */
17270693Sgibbs#define		SUBID_9005_TYPE_CARD		0x0	/* Standard Card */
17370693Sgibbs#define		SUBID_9005_TYPE_LCCARD		0x1	/* Low Cost Card */
17470693Sgibbs#define		SUBID_9005_TYPE_RAID		0x3	/* Combined with Raid */
17570204Sgibbs
17672811Sgibbs#define SUBID_9005_TYPE_KNOWN(id)			\
17772811Sgibbs	  ((((id) & 0xF) == SUBID_9005_TYPE_MB)		\
17872811Sgibbs	|| (((id) & 0xF) == SUBID_9005_TYPE_CARD)	\
17972811Sgibbs	|| (((id) & 0xF) == SUBID_9005_TYPE_LCCARD)	\
18072811Sgibbs	|| (((id) & 0xF) == SUBID_9005_TYPE_RAID))
18172811Sgibbs
18270693Sgibbs#define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
18370693Sgibbs#define		SUBID_9005_MAXRATE_ULTRA2	0x0
18470693Sgibbs#define		SUBID_9005_MAXRATE_ULTRA	0x1
18570693Sgibbs#define		SUBID_9005_MAXRATE_U160		0x2
18670693Sgibbs#define		SUBID_9005_MAXRATE_RESERVED	0x3
18770693Sgibbs
18870693Sgibbs#define SUBID_9005_SEEPTYPE(id)						\
18970693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
19070693Sgibbs	 ? ((id) & 0xC0) >> 6						\
19170693Sgibbs	 : ((id) & 0x300) >> 8)
19270693Sgibbs#define		SUBID_9005_SEEPTYPE_NONE	0x0
19370693Sgibbs#define		SUBID_9005_SEEPTYPE_1K		0x1
19470693Sgibbs#define		SUBID_9005_SEEPTYPE_2K_4K	0x2
19570693Sgibbs#define		SUBID_9005_SEEPTYPE_RESERVED	0x3
19670693Sgibbs#define SUBID_9005_AUTOTERM(id)						\
19770693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
19870693Sgibbs	 ? (((id) & 0x400) >> 10) == 0					\
19970693Sgibbs	 : (((id) & 0x40) >> 6) == 0)
20070693Sgibbs
20170693Sgibbs#define SUBID_9005_NUMCHAN(id)						\
20270693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
20370693Sgibbs	 ? ((id) & 0x300) >> 8						\
20470693Sgibbs	 : ((id) & 0xC00) >> 10)
20570693Sgibbs
20670693Sgibbs#define SUBID_9005_LEGACYCONN(id)					\
20770693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
20870693Sgibbs	 ? 0								\
20970693Sgibbs	 : ((id) & 0x80) >> 7)
21070693Sgibbs
21170693Sgibbs#define SUBID_9005_MFUNCENB(id)						\
21270693Sgibbs	((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB)			\
21370693Sgibbs	 ? ((id) & 0x800) >> 11						\
21470693Sgibbs	 : ((id) & 0x1000) >> 12)
21570693Sgibbs/*
21670693Sgibbs * Informational only. Should use chip register to be
21795378Sgibbs * certain, but may be use in identification strings.
21870693Sgibbs */
21970693Sgibbs#define SUBID_9005_CARD_SCSIWIDTH_MASK	0x2000
22070693Sgibbs#define SUBID_9005_CARD_PCIWIDTH_MASK	0x4000
22170693Sgibbs#define SUBID_9005_CARD_SEDIFF_MASK	0x8000
22270693Sgibbs
22374094Sgibbsstatic ahc_device_setup_t ahc_aic785X_setup;
22465942Sgibbsstatic ahc_device_setup_t ahc_aic7860_setup;
22571390Sgibbsstatic ahc_device_setup_t ahc_apa1480_setup;
22665942Sgibbsstatic ahc_device_setup_t ahc_aic7870_setup;
22765942Sgibbsstatic ahc_device_setup_t ahc_aha394X_setup;
22865942Sgibbsstatic ahc_device_setup_t ahc_aha494X_setup;
22965942Sgibbsstatic ahc_device_setup_t ahc_aha398X_setup;
23065942Sgibbsstatic ahc_device_setup_t ahc_aic7880_setup;
23171390Sgibbsstatic ahc_device_setup_t ahc_aha2940Pro_setup;
23265942Sgibbsstatic ahc_device_setup_t ahc_aha394XU_setup;
23365942Sgibbsstatic ahc_device_setup_t ahc_aha398XU_setup;
23465942Sgibbsstatic ahc_device_setup_t ahc_aic7890_setup;
23565942Sgibbsstatic ahc_device_setup_t ahc_aic7892_setup;
23665942Sgibbsstatic ahc_device_setup_t ahc_aic7895_setup;
23765942Sgibbsstatic ahc_device_setup_t ahc_aic7896_setup;
23865942Sgibbsstatic ahc_device_setup_t ahc_aic7899_setup;
23971390Sgibbsstatic ahc_device_setup_t ahc_aha29160C_setup;
24065942Sgibbsstatic ahc_device_setup_t ahc_raid_setup;
24165942Sgibbsstatic ahc_device_setup_t ahc_aha394XX_setup;
24265942Sgibbsstatic ahc_device_setup_t ahc_aha494XX_setup;
24365942Sgibbsstatic ahc_device_setup_t ahc_aha398XX_setup;
24465942Sgibbs
24565942Sgibbsstruct ahc_pci_identity ahc_pci_ident_table [] =
24665942Sgibbs{
24765942Sgibbs	/* aic7850 based controllers */
24865942Sgibbs	{
249115338Sgibbs		ID_AHA_2902_04_10_15_20C_30C,
25065942Sgibbs		ID_ALL_MASK,
251115338Sgibbs		"Adaptec 2902/04/10/15/20C/30C SCSI adapter",
25274094Sgibbs		ahc_aic785X_setup
25365942Sgibbs	},
25465942Sgibbs	/* aic7860 based controllers */
25565942Sgibbs	{
25665942Sgibbs		ID_AHA_2930CU,
25765942Sgibbs		ID_ALL_MASK,
25865942Sgibbs		"Adaptec 2930CU SCSI adapter",
25965942Sgibbs		ahc_aic7860_setup
26065942Sgibbs	},
26165942Sgibbs	{
26265942Sgibbs		ID_AHA_1480A & ID_DEV_VENDOR_MASK,
26365942Sgibbs		ID_DEV_VENDOR_MASK,
26465942Sgibbs		"Adaptec 1480A Ultra SCSI adapter",
26571390Sgibbs		ahc_apa1480_setup
26665942Sgibbs	},
26765942Sgibbs	{
26865942Sgibbs		ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK,
26965942Sgibbs		ID_DEV_VENDOR_MASK,
27065942Sgibbs		"Adaptec 2940A Ultra SCSI adapter",
27165942Sgibbs		ahc_aic7860_setup
27265942Sgibbs	},
27365942Sgibbs	{
27465942Sgibbs		ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK,
27565942Sgibbs		ID_DEV_VENDOR_MASK,
27665942Sgibbs		"Adaptec 2940A/CN Ultra SCSI adapter",
27765942Sgibbs		ahc_aic7860_setup
27865942Sgibbs	},
27965942Sgibbs	{
28065942Sgibbs		ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK,
28165942Sgibbs		ID_DEV_VENDOR_MASK,
28276634Sgibbs		"Adaptec 2930C Ultra SCSI adapter (VAR)",
28365942Sgibbs		ahc_aic7860_setup
28465942Sgibbs	},
28565942Sgibbs	/* aic7870 based controllers */
28665942Sgibbs	{
28765942Sgibbs		ID_AHA_2940,
28865942Sgibbs		ID_ALL_MASK,
28965942Sgibbs		"Adaptec 2940 SCSI adapter",
29065942Sgibbs		ahc_aic7870_setup
29165942Sgibbs	},
29265942Sgibbs	{
29365942Sgibbs		ID_AHA_3940,
29465942Sgibbs		ID_ALL_MASK,
29565942Sgibbs		"Adaptec 3940 SCSI adapter",
29665942Sgibbs		ahc_aha394X_setup
29765942Sgibbs	},
29865942Sgibbs	{
29965942Sgibbs		ID_AHA_398X,
30065942Sgibbs		ID_ALL_MASK,
30165942Sgibbs		"Adaptec 398X SCSI RAID adapter",
30265942Sgibbs		ahc_aha398X_setup
30365942Sgibbs	},
30465942Sgibbs	{
30565942Sgibbs		ID_AHA_2944,
30665942Sgibbs		ID_ALL_MASK,
30765942Sgibbs		"Adaptec 2944 SCSI adapter",
30865942Sgibbs		ahc_aic7870_setup
30965942Sgibbs	},
31065942Sgibbs	{
31165942Sgibbs		ID_AHA_3944,
31265942Sgibbs		ID_ALL_MASK,
31365942Sgibbs		"Adaptec 3944 SCSI adapter",
31465942Sgibbs		ahc_aha394X_setup
31565942Sgibbs	},
31665942Sgibbs	{
31765942Sgibbs		ID_AHA_4944,
31865942Sgibbs		ID_ALL_MASK,
31965942Sgibbs		"Adaptec 4944 SCSI adapter",
32065942Sgibbs		ahc_aha494X_setup
32165942Sgibbs	},
32265942Sgibbs	/* aic7880 based controllers */
32365942Sgibbs	{
32465942Sgibbs		ID_AHA_2940U & ID_DEV_VENDOR_MASK,
32565942Sgibbs		ID_DEV_VENDOR_MASK,
32665942Sgibbs		"Adaptec 2940 Ultra SCSI adapter",
32765942Sgibbs		ahc_aic7880_setup
32865942Sgibbs	},
32965942Sgibbs	{
33065942Sgibbs		ID_AHA_3940U & ID_DEV_VENDOR_MASK,
33165942Sgibbs		ID_DEV_VENDOR_MASK,
33265942Sgibbs		"Adaptec 3940 Ultra SCSI adapter",
33365942Sgibbs		ahc_aha394XU_setup
33465942Sgibbs	},
33565942Sgibbs	{
33665942Sgibbs		ID_AHA_2944U & ID_DEV_VENDOR_MASK,
33765942Sgibbs		ID_DEV_VENDOR_MASK,
33865942Sgibbs		"Adaptec 2944 Ultra SCSI adapter",
33965942Sgibbs		ahc_aic7880_setup
34065942Sgibbs	},
34165942Sgibbs	{
34265942Sgibbs		ID_AHA_3944U & ID_DEV_VENDOR_MASK,
34365942Sgibbs		ID_DEV_VENDOR_MASK,
34465942Sgibbs		"Adaptec 3944 Ultra SCSI adapter",
34565942Sgibbs		ahc_aha394XU_setup
34665942Sgibbs	},
34765942Sgibbs	{
34865942Sgibbs		ID_AHA_398XU & ID_DEV_VENDOR_MASK,
34965942Sgibbs		ID_DEV_VENDOR_MASK,
35065942Sgibbs		"Adaptec 398X Ultra SCSI RAID adapter",
35165942Sgibbs		ahc_aha398XU_setup
35265942Sgibbs	},
35365942Sgibbs	{
35465942Sgibbs		/*
35565942Sgibbs		 * XXX Don't know the slot numbers
35665942Sgibbs		 * so we can't identify channels
35765942Sgibbs		 */
35865942Sgibbs		ID_AHA_4944U & ID_DEV_VENDOR_MASK,
35965942Sgibbs		ID_DEV_VENDOR_MASK,
36065942Sgibbs		"Adaptec 4944 Ultra SCSI adapter",
36165942Sgibbs		ahc_aic7880_setup
36265942Sgibbs	},
36365942Sgibbs	{
36465942Sgibbs		ID_AHA_2930U & ID_DEV_VENDOR_MASK,
36565942Sgibbs		ID_DEV_VENDOR_MASK,
36665942Sgibbs		"Adaptec 2930 Ultra SCSI adapter",
36765942Sgibbs		ahc_aic7880_setup
36865942Sgibbs	},
36965942Sgibbs	{
37065942Sgibbs		ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK,
37165942Sgibbs		ID_DEV_VENDOR_MASK,
37265942Sgibbs		"Adaptec 2940 Pro Ultra SCSI adapter",
37371390Sgibbs		ahc_aha2940Pro_setup
37465942Sgibbs	},
37565942Sgibbs	{
37665942Sgibbs		ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK,
37765942Sgibbs		ID_DEV_VENDOR_MASK,
37865942Sgibbs		"Adaptec 2940/CN Ultra SCSI adapter",
37965942Sgibbs		ahc_aic7880_setup
38065942Sgibbs	},
38172811Sgibbs	/* Ignore all SISL (AAC on MB) based controllers. */
38272811Sgibbs	{
38372811Sgibbs		ID_9005_SISL_ID,
38472811Sgibbs		ID_9005_SISL_MASK,
38572811Sgibbs		NULL,
38672811Sgibbs		NULL
38772811Sgibbs	},
38865942Sgibbs	/* aic7890 based controllers */
38965942Sgibbs	{
39065942Sgibbs		ID_AHA_2930U2,
39165942Sgibbs		ID_ALL_MASK,
39265942Sgibbs		"Adaptec 2930 Ultra2 SCSI adapter",
39365942Sgibbs		ahc_aic7890_setup
39465942Sgibbs	},
39565942Sgibbs	{
39665942Sgibbs		ID_AHA_2940U2B,
39765942Sgibbs		ID_ALL_MASK,
39865942Sgibbs		"Adaptec 2940B Ultra2 SCSI adapter",
39965942Sgibbs		ahc_aic7890_setup
40065942Sgibbs	},
40165942Sgibbs	{
40265942Sgibbs		ID_AHA_2940U2_OEM,
40365942Sgibbs		ID_ALL_MASK,
40465942Sgibbs		"Adaptec 2940 Ultra2 SCSI adapter (OEM)",
40565942Sgibbs		ahc_aic7890_setup
40665942Sgibbs	},
40765942Sgibbs	{
40865942Sgibbs		ID_AHA_2940U2,
40965942Sgibbs		ID_ALL_MASK,
41065942Sgibbs		"Adaptec 2940 Ultra2 SCSI adapter",
41165942Sgibbs		ahc_aic7890_setup
41265942Sgibbs	},
41365942Sgibbs	{
41465942Sgibbs		ID_AHA_2950U2B,
41565942Sgibbs		ID_ALL_MASK,
41665942Sgibbs		"Adaptec 2950 Ultra2 SCSI adapter",
41765942Sgibbs		ahc_aic7890_setup
41865942Sgibbs	},
41965942Sgibbs	{
42072811Sgibbs		ID_AIC7890_ARO,
42172811Sgibbs		ID_ALL_MASK,
42272811Sgibbs		"Adaptec aic7890/91 Ultra2 SCSI adapter (ARO)",
42372811Sgibbs		ahc_aic7890_setup
42472811Sgibbs	},
42572811Sgibbs	{
42665942Sgibbs		ID_AAA_131U2,
42765942Sgibbs		ID_ALL_MASK,
42865942Sgibbs		"Adaptec AAA-131 Ultra2 RAID adapter",
42965942Sgibbs		ahc_aic7890_setup
43065942Sgibbs	},
43165942Sgibbs	/* aic7892 based controllers */
43265942Sgibbs	{
43365942Sgibbs		ID_AHA_29160,
43465942Sgibbs		ID_ALL_MASK,
43565942Sgibbs		"Adaptec 29160 Ultra160 SCSI adapter",
43665942Sgibbs		ahc_aic7892_setup
43765942Sgibbs	},
43865942Sgibbs	{
43965942Sgibbs		ID_AHA_29160_CPQ,
44065942Sgibbs		ID_ALL_MASK,
44165942Sgibbs		"Adaptec (Compaq OEM) 29160 Ultra160 SCSI adapter",
44265942Sgibbs		ahc_aic7892_setup
44365942Sgibbs	},
44465942Sgibbs	{
44565942Sgibbs		ID_AHA_29160N,
44665942Sgibbs		ID_ALL_MASK,
44765942Sgibbs		"Adaptec 29160N Ultra160 SCSI adapter",
44865942Sgibbs		ahc_aic7892_setup
44965942Sgibbs	},
45065942Sgibbs	{
45170204Sgibbs		ID_AHA_29160C,
45270204Sgibbs		ID_ALL_MASK,
45370204Sgibbs		"Adaptec 29160C Ultra160 SCSI adapter",
45471390Sgibbs		ahc_aha29160C_setup
45570204Sgibbs	},
45670204Sgibbs	{
45765942Sgibbs		ID_AHA_29160B,
45865942Sgibbs		ID_ALL_MASK,
45965942Sgibbs		"Adaptec 29160B Ultra160 SCSI adapter",
46065942Sgibbs		ahc_aic7892_setup
46165942Sgibbs	},
46265942Sgibbs	{
46365942Sgibbs		ID_AHA_19160B,
46465942Sgibbs		ID_ALL_MASK,
46565942Sgibbs		"Adaptec 19160B Ultra160 SCSI adapter",
46665942Sgibbs		ahc_aic7892_setup
46765942Sgibbs	},
46872811Sgibbs	{
46972811Sgibbs		ID_AIC7892_ARO,
47072811Sgibbs		ID_ALL_MASK,
47176634Sgibbs		"Adaptec aic7892 Ultra160 SCSI adapter (ARO)",
47272811Sgibbs		ahc_aic7892_setup
47372811Sgibbs	},
47465942Sgibbs	/* aic7895 based controllers */
47565942Sgibbs	{
47665942Sgibbs		ID_AHA_2940U_DUAL,
47765942Sgibbs		ID_ALL_MASK,
47865942Sgibbs		"Adaptec 2940/DUAL Ultra SCSI adapter",
47965942Sgibbs		ahc_aic7895_setup
48065942Sgibbs	},
48165942Sgibbs	{
48265942Sgibbs		ID_AHA_3940AU,
48365942Sgibbs		ID_ALL_MASK,
48465942Sgibbs		"Adaptec 3940A Ultra SCSI adapter",
48565942Sgibbs		ahc_aic7895_setup
48665942Sgibbs	},
48765942Sgibbs	{
48865942Sgibbs		ID_AHA_3944AU,
48965942Sgibbs		ID_ALL_MASK,
49065942Sgibbs		"Adaptec 3944A Ultra SCSI adapter",
49165942Sgibbs		ahc_aic7895_setup
49265942Sgibbs	},
49372811Sgibbs	{
49472811Sgibbs		ID_AIC7895_ARO,
49572811Sgibbs		ID_AIC7895_ARO_MASK,
49672811Sgibbs		"Adaptec aic7895 Ultra SCSI adapter (ARO)",
49772811Sgibbs		ahc_aic7895_setup
49872811Sgibbs	},
49965942Sgibbs	/* aic7896/97 based controllers */
50065942Sgibbs	{
50165942Sgibbs		ID_AHA_3950U2B_0,
50265942Sgibbs		ID_ALL_MASK,
50365942Sgibbs		"Adaptec 3950B Ultra2 SCSI adapter",
50465942Sgibbs		ahc_aic7896_setup
50565942Sgibbs	},
50665942Sgibbs	{
50765942Sgibbs		ID_AHA_3950U2B_1,
50865942Sgibbs		ID_ALL_MASK,
50965942Sgibbs		"Adaptec 3950B Ultra2 SCSI adapter",
51065942Sgibbs		ahc_aic7896_setup
51165942Sgibbs	},
51265942Sgibbs	{
51365942Sgibbs		ID_AHA_3950U2D_0,
51465942Sgibbs		ID_ALL_MASK,
51565942Sgibbs		"Adaptec 3950D Ultra2 SCSI adapter",
51665942Sgibbs		ahc_aic7896_setup
51765942Sgibbs	},
51865942Sgibbs	{
51965942Sgibbs		ID_AHA_3950U2D_1,
52065942Sgibbs		ID_ALL_MASK,
52165942Sgibbs		"Adaptec 3950D Ultra2 SCSI adapter",
52265942Sgibbs		ahc_aic7896_setup
52365942Sgibbs	},
52472811Sgibbs	{
52572811Sgibbs		ID_AIC7896_ARO,
52672811Sgibbs		ID_ALL_MASK,
52772811Sgibbs		"Adaptec aic7896/97 Ultra2 SCSI adapter (ARO)",
52872811Sgibbs		ahc_aic7896_setup
52972811Sgibbs	},
53065942Sgibbs	/* aic7899 based controllers */
53165942Sgibbs	{
53265942Sgibbs		ID_AHA_3960D,
53365942Sgibbs		ID_ALL_MASK,
53465942Sgibbs		"Adaptec 3960D Ultra160 SCSI adapter",
53565942Sgibbs		ahc_aic7899_setup
53665942Sgibbs	},
53765942Sgibbs	{
53865942Sgibbs		ID_AHA_3960D_CPQ,
53965942Sgibbs		ID_ALL_MASK,
54065942Sgibbs		"Adaptec (Compaq OEM) 3960D Ultra160 SCSI adapter",
54165942Sgibbs		ahc_aic7899_setup
54265942Sgibbs	},
54372811Sgibbs	{
54472811Sgibbs		ID_AIC7899_ARO,
54572811Sgibbs		ID_ALL_MASK,
54672811Sgibbs		"Adaptec aic7899 Ultra160 SCSI adapter (ARO)",
54772811Sgibbs		ahc_aic7899_setup
54872811Sgibbs	},
54965942Sgibbs	/* Generic chip probes for devices we don't know 'exactly' */
55065942Sgibbs	{
55165942Sgibbs		ID_AIC7850 & ID_DEV_VENDOR_MASK,
55265942Sgibbs		ID_DEV_VENDOR_MASK,
55365942Sgibbs		"Adaptec aic7850 SCSI adapter",
55474094Sgibbs		ahc_aic785X_setup
55565942Sgibbs	},
55665942Sgibbs	{
55765942Sgibbs		ID_AIC7855 & ID_DEV_VENDOR_MASK,
55865942Sgibbs		ID_DEV_VENDOR_MASK,
55965942Sgibbs		"Adaptec aic7855 SCSI adapter",
56074094Sgibbs		ahc_aic785X_setup
56165942Sgibbs	},
56265942Sgibbs	{
56365942Sgibbs		ID_AIC7859 & ID_DEV_VENDOR_MASK,
56465942Sgibbs		ID_DEV_VENDOR_MASK,
56576634Sgibbs		"Adaptec aic7859 SCSI adapter",
56665942Sgibbs		ahc_aic7860_setup
56765942Sgibbs	},
56865942Sgibbs	{
56965942Sgibbs		ID_AIC7860 & ID_DEV_VENDOR_MASK,
57065942Sgibbs		ID_DEV_VENDOR_MASK,
57176634Sgibbs		"Adaptec aic7860 Ultra SCSI adapter",
57265942Sgibbs		ahc_aic7860_setup
57365942Sgibbs	},
57465942Sgibbs	{
57565942Sgibbs		ID_AIC7870 & ID_DEV_VENDOR_MASK,
57665942Sgibbs		ID_DEV_VENDOR_MASK,
57765942Sgibbs		"Adaptec aic7870 SCSI adapter",
57865942Sgibbs		ahc_aic7870_setup
57965942Sgibbs	},
58065942Sgibbs	{
58165942Sgibbs		ID_AIC7880 & ID_DEV_VENDOR_MASK,
58265942Sgibbs		ID_DEV_VENDOR_MASK,
58365942Sgibbs		"Adaptec aic7880 Ultra SCSI adapter",
58465942Sgibbs		ahc_aic7880_setup
58565942Sgibbs	},
58665942Sgibbs	{
58772325Sgibbs		ID_AIC7890 & ID_9005_GENERIC_MASK,
58872325Sgibbs		ID_9005_GENERIC_MASK,
58965942Sgibbs		"Adaptec aic7890/91 Ultra2 SCSI adapter",
59065942Sgibbs		ahc_aic7890_setup
59165942Sgibbs	},
59265942Sgibbs	{
59372325Sgibbs		ID_AIC7892 & ID_9005_GENERIC_MASK,
59472325Sgibbs		ID_9005_GENERIC_MASK,
59565942Sgibbs		"Adaptec aic7892 Ultra160 SCSI adapter",
59665942Sgibbs		ahc_aic7892_setup
59765942Sgibbs	},
59865942Sgibbs	{
59965942Sgibbs		ID_AIC7895 & ID_DEV_VENDOR_MASK,
60065942Sgibbs		ID_DEV_VENDOR_MASK,
60165942Sgibbs		"Adaptec aic7895 Ultra SCSI adapter",
60265942Sgibbs		ahc_aic7895_setup
60365942Sgibbs	},
60465942Sgibbs	{
60572325Sgibbs		ID_AIC7896 & ID_9005_GENERIC_MASK,
60672325Sgibbs		ID_9005_GENERIC_MASK,
60765942Sgibbs		"Adaptec aic7896/97 Ultra2 SCSI adapter",
60865942Sgibbs		ahc_aic7896_setup
60965942Sgibbs	},
61065942Sgibbs	{
61172325Sgibbs		ID_AIC7899 & ID_9005_GENERIC_MASK,
61272325Sgibbs		ID_9005_GENERIC_MASK,
61365942Sgibbs		"Adaptec aic7899 Ultra160 SCSI adapter",
61465942Sgibbs		ahc_aic7899_setup
61565942Sgibbs	},
61665942Sgibbs	{
61765942Sgibbs		ID_AIC7810 & ID_DEV_VENDOR_MASK,
61865942Sgibbs		ID_DEV_VENDOR_MASK,
61965942Sgibbs		"Adaptec aic7810 RAID memory controller",
62065942Sgibbs		ahc_raid_setup
62165942Sgibbs	},
62265942Sgibbs	{
62365942Sgibbs		ID_AIC7815 & ID_DEV_VENDOR_MASK,
62465942Sgibbs		ID_DEV_VENDOR_MASK,
62565942Sgibbs		"Adaptec aic7815 RAID memory controller",
62665942Sgibbs		ahc_raid_setup
62765942Sgibbs	}
62865942Sgibbs};
62965942Sgibbs
63070204Sgibbsconst u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table);
63165942Sgibbs
63265942Sgibbs#define AHC_394X_SLOT_CHANNEL_A	4
63365942Sgibbs#define AHC_394X_SLOT_CHANNEL_B	5
63465942Sgibbs
63565942Sgibbs#define AHC_398X_SLOT_CHANNEL_A	4
63665942Sgibbs#define AHC_398X_SLOT_CHANNEL_B	8
63765942Sgibbs#define AHC_398X_SLOT_CHANNEL_C	12
63865942Sgibbs
63965942Sgibbs#define AHC_494X_SLOT_CHANNEL_A	4
64065942Sgibbs#define AHC_494X_SLOT_CHANNEL_B	5
64165942Sgibbs#define AHC_494X_SLOT_CHANNEL_C	6
64265942Sgibbs#define AHC_494X_SLOT_CHANNEL_D	7
64365942Sgibbs
64465942Sgibbs#define	DEVCONFIG		0x40
645109590Sgibbs#define		PCIERRGENDIS	0x80000000ul
64665942Sgibbs#define		SCBSIZE32	0x00010000ul	/* aic789X only */
64774094Sgibbs#define		REXTVALID	0x00001000ul	/* ultra cards only */
64879874Sgibbs#define		MPORTMODE	0x00000400ul	/* aic7870+ only */
64979874Sgibbs#define		RAMPSM		0x00000200ul	/* aic7870+ only */
65065942Sgibbs#define		VOLSENSE	0x00000100ul
65179874Sgibbs#define		PCI64BIT	0x00000080ul	/* 64Bit PCI bus (Ultra2 Only)*/
65265942Sgibbs#define		SCBRAMSEL	0x00000080ul
65365942Sgibbs#define		MRDCEN		0x00000040ul
65465942Sgibbs#define		EXTSCBTIME	0x00000020ul	/* aic7870 only */
65565942Sgibbs#define		EXTSCBPEN	0x00000010ul	/* aic7870 only */
65665942Sgibbs#define		BERREN		0x00000008ul
65765942Sgibbs#define		DACEN		0x00000004ul
65865942Sgibbs#define		STPWLEVEL	0x00000002ul
65965942Sgibbs#define		DIFACTNEGEN	0x00000001ul	/* aic7870 only */
66065942Sgibbs
66165942Sgibbs#define	CSIZE_LATTIME		0x0c
66265942Sgibbs#define		CACHESIZE	0x0000003ful	/* only 5 bits */
66365942Sgibbs#define		LATTIME		0x0000ff00ul
66465942Sgibbs
665107419Sscottl/* PCI STATUS definitions */
666107419Sscottl#define	DPE	0x80
667107419Sscottl#define SSE	0x40
668107419Sscottl#define	RMA	0x20
669107419Sscottl#define	RTA	0x10
670107419Sscottl#define STA	0x08
671107419Sscottl#define DPR	0x01
672107419Sscottl
67395378Sgibbsstatic int ahc_9005_subdevinfo_valid(uint16_t vendor, uint16_t device,
67495378Sgibbs				     uint16_t subvendor, uint16_t subdevice);
67565942Sgibbsstatic int ahc_ext_scbram_present(struct ahc_softc *ahc);
67665942Sgibbsstatic void ahc_scbram_config(struct ahc_softc *ahc, int enable,
67765942Sgibbs				  int pcheck, int fast, int large);
67865942Sgibbsstatic void ahc_probe_ext_scbram(struct ahc_softc *ahc);
67965942Sgibbsstatic void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1);
680102676Sgibbsstatic void ahc_parse_pci_eeprom(struct ahc_softc *ahc,
681102676Sgibbs				 struct seeprom_config *sc);
68265942Sgibbsstatic void configure_termination(struct ahc_softc *ahc,
68365942Sgibbs				  struct seeprom_descriptor *sd,
68465942Sgibbs				  u_int adapter_control,
68565942Sgibbs	 			  u_int *sxfrctl1);
68665942Sgibbs
68765942Sgibbsstatic void ahc_new_term_detect(struct ahc_softc *ahc,
68865942Sgibbs				int *enableSEC_low,
68965942Sgibbs				int *enableSEC_high,
69065942Sgibbs				int *enablePRI_low,
69165942Sgibbs				int *enablePRI_high,
69265942Sgibbs				int *eeprom_present);
69365942Sgibbsstatic void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
69465942Sgibbs				 int *internal68_present,
69565942Sgibbs				 int *externalcable_present,
69665942Sgibbs				 int *eeprom_present);
69765942Sgibbsstatic void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
69865942Sgibbs				 int *externalcable_present,
69965942Sgibbs				 int *eeprom_present);
700114621Sgibbsstatic void    write_brdctl(struct ahc_softc *ahc, uint8_t value);
70165942Sgibbsstatic uint8_t read_brdctl(struct ahc_softc *ahc);
702114621Sgibbsstatic void ahc_pci_intr(struct ahc_softc *ahc);
703114621Sgibbsstatic int  ahc_pci_chip_init(struct ahc_softc *ahc);
704114621Sgibbsstatic int  ahc_pci_suspend(struct ahc_softc *ahc);
705114621Sgibbsstatic int  ahc_pci_resume(struct ahc_softc *ahc);
70665942Sgibbs
70795378Sgibbsstatic int
70895378Sgibbsahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
70995378Sgibbs			  uint16_t subdevice, uint16_t subvendor)
71095378Sgibbs{
71195378Sgibbs	int result;
71295378Sgibbs
71395378Sgibbs	/* Default to invalid. */
71495378Sgibbs	result = 0;
71595378Sgibbs	if (vendor == 0x9005
71695378Sgibbs	 && subvendor == 0x9005
71795378Sgibbs         && subdevice != device
71895378Sgibbs         && SUBID_9005_TYPE_KNOWN(subdevice) != 0) {
71995378Sgibbs
72095378Sgibbs		switch (SUBID_9005_TYPE(subdevice)) {
72195378Sgibbs		case SUBID_9005_TYPE_MB:
72295378Sgibbs			break;
72395378Sgibbs		case SUBID_9005_TYPE_CARD:
72495378Sgibbs		case SUBID_9005_TYPE_LCCARD:
72595378Sgibbs			/*
72695378Sgibbs			 * Currently only trust Adaptec cards to
72795378Sgibbs			 * get the sub device info correct.
72895378Sgibbs			 */
72995378Sgibbs			if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA)
73095378Sgibbs				result = 1;
73195378Sgibbs			break;
73295378Sgibbs		case SUBID_9005_TYPE_RAID:
73395378Sgibbs			break;
73495378Sgibbs		default:
73595378Sgibbs			break;
73695378Sgibbs		}
73795378Sgibbs	}
73895378Sgibbs	return (result);
73995378Sgibbs}
74095378Sgibbs
74165942Sgibbsstruct ahc_pci_identity *
74265942Sgibbsahc_find_pci_device(ahc_dev_softc_t pci)
74365942Sgibbs{
74465942Sgibbs	uint64_t  full_id;
74565942Sgibbs	uint16_t  device;
74665942Sgibbs	uint16_t  vendor;
74765942Sgibbs	uint16_t  subdevice;
74865942Sgibbs	uint16_t  subvendor;
74965942Sgibbs	struct	  ahc_pci_identity *entry;
75065942Sgibbs	u_int	  i;
75165942Sgibbs
75265942Sgibbs	vendor = ahc_pci_read_config(pci, PCIR_DEVVENDOR, /*bytes*/2);
75365942Sgibbs	device = ahc_pci_read_config(pci, PCIR_DEVICE, /*bytes*/2);
75465942Sgibbs	subvendor = ahc_pci_read_config(pci, PCIR_SUBVEND_0, /*bytes*/2);
75565942Sgibbs	subdevice = ahc_pci_read_config(pci, PCIR_SUBDEV_0, /*bytes*/2);
756114621Sgibbs	full_id = ahc_compose_id(device, vendor, subdevice, subvendor);
75765942Sgibbs
75879874Sgibbs	/*
75979874Sgibbs	 * If the second function is not hooked up, ignore it.
76079874Sgibbs	 * Unfortunately, not all MB vendors implement the
76179874Sgibbs	 * subdevice ID as per the Adaptec spec, so do our best
76279874Sgibbs	 * to sanity check it prior to accepting the subdevice
76379874Sgibbs	 * ID as valid.
76479874Sgibbs	 */
76570204Sgibbs	if (ahc_get_pci_function(pci) > 0
76695378Sgibbs	 && ahc_9005_subdevinfo_valid(vendor, device, subvendor, subdevice)
76770693Sgibbs	 && SUBID_9005_MFUNCENB(subdevice) == 0)
76870204Sgibbs		return (NULL);
76970204Sgibbs
77065942Sgibbs	for (i = 0; i < ahc_num_pci_devs; i++) {
77165942Sgibbs		entry = &ahc_pci_ident_table[i];
77272811Sgibbs		if (entry->full_id == (full_id & entry->id_mask)) {
77372811Sgibbs			/* Honor exclusion entries. */
77472811Sgibbs			if (entry->name == NULL)
77572811Sgibbs				return (NULL);
77665942Sgibbs			return (entry);
77772811Sgibbs		}
77865942Sgibbs	}
77965942Sgibbs	return (NULL);
78065942Sgibbs}
78165942Sgibbs
78265942Sgibbsint
78365942Sgibbsahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
78465942Sgibbs{
785102676Sgibbs	u_long	 l;
786102676Sgibbs	u_int	 command;
787102676Sgibbs	u_int	 our_id;
788102676Sgibbs	u_int	 sxfrctl1;
789102676Sgibbs	u_int	 scsiseq;
790102676Sgibbs	u_int	 dscommand0;
791109590Sgibbs	uint32_t devconfig;
792102676Sgibbs	int	 error;
793102676Sgibbs	uint8_t	 sblkctl;
79465942Sgibbs
795102676Sgibbs	our_id = 0;
79679874Sgibbs	error = entry->setup(ahc);
79765942Sgibbs	if (error != 0)
79865942Sgibbs		return (error);
79979874Sgibbs	ahc->chip |= AHC_PCI;
80079874Sgibbs	ahc->description = entry->name;
80165942Sgibbs
80295378Sgibbs	ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
80395378Sgibbs
80465942Sgibbs	error = ahc_pci_map_registers(ahc);
80565942Sgibbs	if (error != 0)
80665942Sgibbs		return (error);
80765942Sgibbs
80895378Sgibbs	/*
80995378Sgibbs	 * Before we continue probing the card, ensure that
81095378Sgibbs	 * its interrupts are *disabled*.  We don't want
81195378Sgibbs	 * a misstep to hang the machine in an interrupt
81295378Sgibbs	 * storm.
81395378Sgibbs	 */
81495378Sgibbs	ahc_intr_enable(ahc, FALSE);
81570204Sgibbs
816109590Sgibbs	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
817109590Sgibbs
81879874Sgibbs	/*
81979874Sgibbs	 * If we need to support high memory, enable dual
82079874Sgibbs	 * address cycles.  This bit must be set to enable
82179874Sgibbs	 * high address bit generation even if we are on a
82279874Sgibbs	 * 64bit bus (PCI64BIT set in devconfig).
82379874Sgibbs	 */
82479874Sgibbs	if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
82579874Sgibbs
82679874Sgibbs		if (bootverbose)
82779874Sgibbs			printf("%s: Enabling 39Bit Addressing\n",
82879874Sgibbs			       ahc_name(ahc));
82979874Sgibbs		devconfig |= DACEN;
83079874Sgibbs	}
83179874Sgibbs
832109590Sgibbs	/* Ensure that pci error generation, a test feature, is disabled. */
833109590Sgibbs	devconfig |= PCIERRGENDIS;
834109590Sgibbs
835109590Sgibbs	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
836109590Sgibbs
83765942Sgibbs	/* Ensure busmastering is enabled */
838114621Sgibbs	command = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
83965942Sgibbs	command |= PCIM_CMD_BUSMASTEREN;
840109590Sgibbs
841114621Sgibbs	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, command, /*bytes*/2);
84265942Sgibbs
84365942Sgibbs	/* On all PCI adapters, we allow SCB paging */
84479874Sgibbs	ahc->flags |= AHC_PAGESCBS;
84565942Sgibbs
84679874Sgibbs	error = ahc_softc_init(ahc);
84765942Sgibbs	if (error != 0)
84865942Sgibbs		return (error);
84965942Sgibbs
850114621Sgibbs	/*
851114621Sgibbs	 * Disable PCI parity error checking.  Users typically
852114621Sgibbs	 * do this to work around broken PCI chipsets that get
853114621Sgibbs	 * the parity timing wrong and thus generate lots of spurious
854114621Sgibbs	 * errors.  The chip only allows us to disable *all* parity
855114621Sgibbs	 * error reporting when doing this, so CIO bus, scb ram, and
856114621Sgibbs	 * scratch ram parity errors will be ignored too.
857114621Sgibbs	 */
858115332Sgibbs	if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0)
859115332Sgibbs		ahc->seqctl |= FAILDIS;
860114621Sgibbs
86174972Sgibbs	ahc->bus_intr = ahc_pci_intr;
862114621Sgibbs	ahc->bus_chip_init = ahc_pci_chip_init;
863114621Sgibbs	ahc->bus_suspend = ahc_pci_suspend;
864114621Sgibbs	ahc->bus_resume = ahc_pci_resume;
86574972Sgibbs
86665942Sgibbs	/* Remeber how the card was setup in case there is no SEEPROM */
86770204Sgibbs	if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
86874094Sgibbs		ahc_pause(ahc);
86970204Sgibbs		if ((ahc->features & AHC_ULTRA2) != 0)
87070204Sgibbs			our_id = ahc_inb(ahc, SCSIID_ULTRA2) & OID;
87170204Sgibbs		else
87270204Sgibbs			our_id = ahc_inb(ahc, SCSIID) & OID;
87370204Sgibbs		sxfrctl1 = ahc_inb(ahc, SXFRCTL1) & STPWEN;
87470204Sgibbs		scsiseq = ahc_inb(ahc, SCSISEQ);
87570204Sgibbs	} else {
87670204Sgibbs		sxfrctl1 = STPWEN;
87770204Sgibbs		our_id = 7;
87870204Sgibbs		scsiseq = 0;
87970204Sgibbs	}
88065942Sgibbs
881115917Sgibbs	error = ahc_reset(ahc, /*reinit*/FALSE);
88265942Sgibbs	if (error != 0)
88365942Sgibbs		return (ENXIO);
88465942Sgibbs
88565942Sgibbs	if ((ahc->features & AHC_DT) != 0) {
88665942Sgibbs		u_int sfunct;
88765942Sgibbs
88865942Sgibbs		/* Perform ALT-Mode Setup */
88965942Sgibbs		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
89065942Sgibbs		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
89176634Sgibbs		ahc_outb(ahc, OPTIONMODE,
89276634Sgibbs			 OPTIONMODE_DEFAULTS|AUTOACKEN|BUSFREEREV|EXPPHASEDIS);
89365942Sgibbs		ahc_outb(ahc, SFUNCT, sfunct);
89465942Sgibbs
89565942Sgibbs		/* Normal mode setup */
89665942Sgibbs		ahc_outb(ahc, CRCCONTROL1, CRCVALCHKEN|CRCENDCHKEN|CRCREQCHKEN
89770204Sgibbs					  |TARGCRCENDEN);
89865942Sgibbs	}
89965942Sgibbs
90065942Sgibbs	dscommand0 = ahc_inb(ahc, DSCOMMAND0);
90166647Sgibbs	dscommand0 |= MPARCKEN|CACHETHEN;
90265942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
90365942Sgibbs
90465942Sgibbs		/*
90565942Sgibbs		 * DPARCKEN doesn't work correctly on
90665942Sgibbs		 * some MBs so don't use it.
90765942Sgibbs		 */
90865942Sgibbs		dscommand0 &= ~DPARCKEN;
90965942Sgibbs	}
91065942Sgibbs
91165942Sgibbs	/*
91265942Sgibbs	 * Handle chips that must have cache line
91365942Sgibbs	 * streaming (dis/en)abled.
91465942Sgibbs	 */
91565942Sgibbs	if ((ahc->bugs & AHC_CACHETHEN_DIS_BUG) != 0)
91665942Sgibbs		dscommand0 |= CACHETHEN;
91765942Sgibbs
91865942Sgibbs	if ((ahc->bugs & AHC_CACHETHEN_BUG) != 0)
91965942Sgibbs		dscommand0 &= ~CACHETHEN;
92065942Sgibbs
92165942Sgibbs	ahc_outb(ahc, DSCOMMAND0, dscommand0);
92265942Sgibbs
92365942Sgibbs	ahc->pci_cachesize =
92465942Sgibbs	    ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME,
92565942Sgibbs				/*bytes*/1) & CACHESIZE;
92665942Sgibbs	ahc->pci_cachesize *= 4;
92765942Sgibbs
92881170Sgibbs	if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0
92981170Sgibbs	 && ahc->pci_cachesize == 4) {
93081170Sgibbs
93181170Sgibbs		ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME,
93281170Sgibbs				     0, /*bytes*/1);
93381170Sgibbs		ahc->pci_cachesize = 0;
93481170Sgibbs	}
93581170Sgibbs
93676634Sgibbs	/*
93776634Sgibbs	 * We cannot perform ULTRA speeds without the presense
93876634Sgibbs	 * of the external precision resistor.
93976634Sgibbs	 */
94076634Sgibbs	if ((ahc->features & AHC_ULTRA) != 0) {
94176634Sgibbs		uint32_t devconfig;
94276634Sgibbs
94376634Sgibbs		devconfig = ahc_pci_read_config(ahc->dev_softc,
94476634Sgibbs						DEVCONFIG, /*bytes*/4);
94576634Sgibbs		if ((devconfig & REXTVALID) == 0)
94676634Sgibbs			ahc->features &= ~AHC_ULTRA;
94776634Sgibbs	}
94876634Sgibbs
94965942Sgibbs	/* See if we have a SEEPROM and perform auto-term */
95065942Sgibbs	check_extport(ahc, &sxfrctl1);
95165942Sgibbs
95265942Sgibbs	/*
95365942Sgibbs	 * Take the LED out of diagnostic mode
95465942Sgibbs	 */
95565942Sgibbs	sblkctl = ahc_inb(ahc, SBLKCTL);
95665942Sgibbs	ahc_outb(ahc, SBLKCTL, (sblkctl & ~(DIAGLEDEN|DIAGLEDON)));
95765942Sgibbs
95865942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
95968087Sgibbs		ahc_outb(ahc, DFF_THRSH, RD_DFTHRSH_MAX|WR_DFTHRSH_MAX);
96065942Sgibbs	} else {
96165942Sgibbs		ahc_outb(ahc, DSPCISTATUS, DFTHRSH_100);
96265942Sgibbs	}
96365942Sgibbs
96465942Sgibbs	if (ahc->flags & AHC_USEDEFAULTS) {
96565942Sgibbs		/*
96665942Sgibbs		 * PCI Adapter default setup
96765942Sgibbs		 * Should only be used if the adapter does not have
96865942Sgibbs		 * a SEEPROM.
96965942Sgibbs		 */
97065942Sgibbs		/* See if someone else set us up already */
971109590Sgibbs		if ((ahc->flags & AHC_NO_BIOS_INIT) == 0
972109590Sgibbs		 && scsiseq != 0) {
97365942Sgibbs			printf("%s: Using left over BIOS settings\n",
97465942Sgibbs				ahc_name(ahc));
97565942Sgibbs			ahc->flags &= ~AHC_USEDEFAULTS;
97672325Sgibbs			ahc->flags |= AHC_BIOS_ENABLED;
97765942Sgibbs		} else {
97865942Sgibbs			/*
97965942Sgibbs			 * Assume only one connector and always turn
98065942Sgibbs			 * on termination.
98165942Sgibbs			 */
98265942Sgibbs 			our_id = 0x07;
98365942Sgibbs			sxfrctl1 = STPWEN;
98465942Sgibbs		}
98565942Sgibbs		ahc_outb(ahc, SCSICONF, our_id|ENSPCHK|RESET_SCSI);
98665942Sgibbs
98765942Sgibbs		ahc->our_id = our_id;
98865942Sgibbs	}
98965942Sgibbs
99065942Sgibbs	/*
99165942Sgibbs	 * Take a look to see if we have external SRAM.
99265942Sgibbs	 * We currently do not attempt to use SRAM that is
99365942Sgibbs	 * shared among multiple controllers.
99465942Sgibbs	 */
99565942Sgibbs	ahc_probe_ext_scbram(ahc);
99665942Sgibbs
99765942Sgibbs	/*
99865942Sgibbs	 * Record our termination setting for the
99965942Sgibbs	 * generic initialization routine.
100065942Sgibbs	 */
100165942Sgibbs	if ((sxfrctl1 & STPWEN) != 0)
100265942Sgibbs		ahc->flags |= AHC_TERM_ENB_A;
100365942Sgibbs
1004114621Sgibbs	/*
1005114621Sgibbs	 * Save chip register configuration data for chip resets
1006114621Sgibbs	 * that occur during runtime and resume events.
1007114621Sgibbs	 */
1008114621Sgibbs	ahc->bus_softc.pci_softc.devconfig =
1009114621Sgibbs	    ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
1010114621Sgibbs	ahc->bus_softc.pci_softc.command =
1011114621Sgibbs	    ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1);
1012114621Sgibbs	ahc->bus_softc.pci_softc.csize_lattime =
1013114621Sgibbs	    ahc_pci_read_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1);
1014114621Sgibbs	ahc->bus_softc.pci_softc.dscommand0 = ahc_inb(ahc, DSCOMMAND0);
1015114621Sgibbs	ahc->bus_softc.pci_softc.dspcistatus = ahc_inb(ahc, DSPCISTATUS);
1016114621Sgibbs	if ((ahc->features & AHC_DT) != 0) {
1017114621Sgibbs		u_int sfunct;
1018114621Sgibbs
1019114621Sgibbs		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
1020114621Sgibbs		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
1021114621Sgibbs		ahc->bus_softc.pci_softc.optionmode = ahc_inb(ahc, OPTIONMODE);
1022114621Sgibbs		ahc->bus_softc.pci_softc.targcrccnt = ahc_inw(ahc, TARGCRCCNT);
1023114621Sgibbs		ahc_outb(ahc, SFUNCT, sfunct);
1024114621Sgibbs		ahc->bus_softc.pci_softc.crccontrol1 =
1025114621Sgibbs		    ahc_inb(ahc, CRCCONTROL1);
1026114621Sgibbs	}
1027114621Sgibbs	if ((ahc->features & AHC_MULTI_FUNC) != 0)
1028114621Sgibbs		ahc->bus_softc.pci_softc.scbbaddr = ahc_inb(ahc, SCBBADDR);
1029114621Sgibbs
1030114621Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
1031114621Sgibbs		ahc->bus_softc.pci_softc.dff_thrsh = ahc_inb(ahc, DFF_THRSH);
1032114621Sgibbs
103365942Sgibbs	/* Core initialization */
103465942Sgibbs	error = ahc_init(ahc);
103565942Sgibbs	if (error != 0)
103665942Sgibbs		return (error);
103765942Sgibbs
103865942Sgibbs	/*
103974972Sgibbs	 * Allow interrupts now that we are completely setup.
104074972Sgibbs	 */
104176634Sgibbs	error = ahc_pci_map_int(ahc);
104276634Sgibbs	if (error != 0)
104376634Sgibbs		return (error);
104476634Sgibbs
1045102676Sgibbs	ahc_list_lock(&l);
1046102676Sgibbs	/*
1047102676Sgibbs	 * Link this softc in with all other ahc instances.
1048102676Sgibbs	 */
1049102676Sgibbs	ahc_softc_insert(ahc);
1050102676Sgibbs	ahc_list_unlock(&l);
105165942Sgibbs	return (0);
105265942Sgibbs}
105365942Sgibbs
105465942Sgibbs/*
105565942Sgibbs * Test for the presense of external sram in an
105665942Sgibbs * "unshared" configuration.
105765942Sgibbs */
105865942Sgibbsstatic int
105965942Sgibbsahc_ext_scbram_present(struct ahc_softc *ahc)
106065942Sgibbs{
106168087Sgibbs	u_int chip;
106265942Sgibbs	int ramps;
106365942Sgibbs	int single_user;
106465942Sgibbs	uint32_t devconfig;
106565942Sgibbs
106668087Sgibbs	chip = ahc->chip & AHC_CHIPID_MASK;
106765942Sgibbs	devconfig = ahc_pci_read_config(ahc->dev_softc,
106865942Sgibbs					DEVCONFIG, /*bytes*/4);
106965942Sgibbs	single_user = (devconfig & MPORTMODE) != 0;
107065942Sgibbs
107165942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
107265942Sgibbs		ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0;
107395378Sgibbs	else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C)
107495378Sgibbs		/*
107595378Sgibbs		 * External SCBRAM arbitration is flakey
107695378Sgibbs		 * on these chips.  Unfortunately this means
107795378Sgibbs		 * we don't use the extra SCB ram space on the
107895378Sgibbs		 * 3940AUW.
107995378Sgibbs		 */
108095378Sgibbs		ramps = 0;
108168087Sgibbs	else if (chip >= AHC_AIC7870)
108265942Sgibbs		ramps = (devconfig & RAMPSM) != 0;
108365942Sgibbs	else
108465942Sgibbs		ramps = 0;
108565942Sgibbs
108665942Sgibbs	if (ramps && single_user)
108765942Sgibbs		return (1);
108865942Sgibbs	return (0);
108965942Sgibbs}
109065942Sgibbs
109165942Sgibbs/*
109265942Sgibbs * Enable external scbram.
109365942Sgibbs */
109465942Sgibbsstatic void
109565942Sgibbsahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck,
109665942Sgibbs		  int fast, int large)
109765942Sgibbs{
109865942Sgibbs	uint32_t devconfig;
109965942Sgibbs
110065942Sgibbs	if (ahc->features & AHC_MULTI_FUNC) {
110165942Sgibbs		/*
110265942Sgibbs		 * Set the SCB Base addr (highest address bit)
110365942Sgibbs		 * depending on which channel we are.
110465942Sgibbs		 */
110565942Sgibbs		ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc));
110665942Sgibbs	}
110765942Sgibbs
1108102676Sgibbs	ahc->flags &= ~AHC_LSCBS_ENABLED;
1109102676Sgibbs	if (large)
1110102676Sgibbs		ahc->flags |= AHC_LSCBS_ENABLED;
111165942Sgibbs	devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4);
111265942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0) {
111365942Sgibbs		u_int dscommand0;
111465942Sgibbs
111565942Sgibbs		dscommand0 = ahc_inb(ahc, DSCOMMAND0);
111665942Sgibbs		if (enable)
111765942Sgibbs			dscommand0 &= ~INTSCBRAMSEL;
111865942Sgibbs		else
111965942Sgibbs			dscommand0 |= INTSCBRAMSEL;
112065942Sgibbs		if (large)
112165942Sgibbs			dscommand0 &= ~USCBSIZE32;
112265942Sgibbs		else
112365942Sgibbs			dscommand0 |= USCBSIZE32;
112465942Sgibbs		ahc_outb(ahc, DSCOMMAND0, dscommand0);
112565942Sgibbs	} else {
112665942Sgibbs		if (fast)
112765942Sgibbs			devconfig &= ~EXTSCBTIME;
112865942Sgibbs		else
112965942Sgibbs			devconfig |= EXTSCBTIME;
113065942Sgibbs		if (enable)
113165942Sgibbs			devconfig &= ~SCBRAMSEL;
113265942Sgibbs		else
113365942Sgibbs			devconfig |= SCBRAMSEL;
113465942Sgibbs		if (large)
113565942Sgibbs			devconfig &= ~SCBSIZE32;
113665942Sgibbs		else
113765942Sgibbs			devconfig |= SCBSIZE32;
113865942Sgibbs	}
113965942Sgibbs	if (pcheck)
114065942Sgibbs		devconfig |= EXTSCBPEN;
114165942Sgibbs	else
114265942Sgibbs		devconfig &= ~EXTSCBPEN;
114365942Sgibbs
114465942Sgibbs	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, /*bytes*/4);
114565942Sgibbs}
114665942Sgibbs
114765942Sgibbs/*
114865942Sgibbs * Take a look to see if we have external SRAM.
114965942Sgibbs * We currently do not attempt to use SRAM that is
115065942Sgibbs * shared among multiple controllers.
115165942Sgibbs */
115265942Sgibbsstatic void
115365942Sgibbsahc_probe_ext_scbram(struct ahc_softc *ahc)
115465942Sgibbs{
115565942Sgibbs	int num_scbs;
115665942Sgibbs	int test_num_scbs;
115765942Sgibbs	int enable;
115865942Sgibbs	int pcheck;
115965942Sgibbs	int fast;
116065942Sgibbs	int large;
116165942Sgibbs
116265942Sgibbs	enable = FALSE;
116365942Sgibbs	pcheck = FALSE;
116465942Sgibbs	fast = FALSE;
116565942Sgibbs	large = FALSE;
116665942Sgibbs	num_scbs = 0;
116765942Sgibbs
116865942Sgibbs	if (ahc_ext_scbram_present(ahc) == 0)
116965942Sgibbs		goto done;
117065942Sgibbs
117165942Sgibbs	/*
117265942Sgibbs	 * Probe for the best parameters to use.
117365942Sgibbs	 */
117465942Sgibbs	ahc_scbram_config(ahc, /*enable*/TRUE, pcheck, fast, large);
117565942Sgibbs	num_scbs = ahc_probe_scbs(ahc);
117665942Sgibbs	if (num_scbs == 0) {
117765942Sgibbs		/* The SRAM wasn't really present. */
117865942Sgibbs		goto done;
117965942Sgibbs	}
118065942Sgibbs	enable = TRUE;
118165942Sgibbs
118265942Sgibbs	/*
118365942Sgibbs	 * Clear any outstanding parity error
118465942Sgibbs	 * and ensure that parity error reporting
118565942Sgibbs	 * is enabled.
118665942Sgibbs	 */
118765942Sgibbs	ahc_outb(ahc, SEQCTL, 0);
118865942Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
118965942Sgibbs	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
119065942Sgibbs
119165942Sgibbs	/* Now see if we can do parity */
119265942Sgibbs	ahc_scbram_config(ahc, enable, /*pcheck*/TRUE, fast, large);
119365942Sgibbs	num_scbs = ahc_probe_scbs(ahc);
119465942Sgibbs	if ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
119565942Sgibbs	 || (ahc_inb(ahc, ERROR) & MPARERR) == 0)
119665942Sgibbs		pcheck = TRUE;
119765942Sgibbs
119865942Sgibbs	/* Clear any resulting parity error */
119965942Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
120065942Sgibbs	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
120165942Sgibbs
120265942Sgibbs	/* Now see if we can do fast timing */
120365942Sgibbs	ahc_scbram_config(ahc, enable, pcheck, /*fast*/TRUE, large);
120465942Sgibbs	test_num_scbs = ahc_probe_scbs(ahc);
120565942Sgibbs	if (test_num_scbs == num_scbs
120665942Sgibbs	 && ((ahc_inb(ahc, INTSTAT) & BRKADRINT) == 0
120765942Sgibbs	  || (ahc_inb(ahc, ERROR) & MPARERR) == 0))
120865942Sgibbs		fast = TRUE;
120965942Sgibbs
121065942Sgibbs	/*
121165942Sgibbs	 * See if we can use large SCBs and still maintain
121265942Sgibbs	 * the same overall count of SCBs.
121365942Sgibbs	 */
121465942Sgibbs	if ((ahc->features & AHC_LARGE_SCBS) != 0) {
121565942Sgibbs		ahc_scbram_config(ahc, enable, pcheck, fast, /*large*/TRUE);
121665942Sgibbs		test_num_scbs = ahc_probe_scbs(ahc);
121765942Sgibbs		if (test_num_scbs >= num_scbs) {
121865942Sgibbs			large = TRUE;
121965942Sgibbs			num_scbs = test_num_scbs;
122065942Sgibbs	 		if (num_scbs >= 64) {
122165942Sgibbs				/*
122265942Sgibbs				 * We have enough space to move the
122365942Sgibbs				 * "busy targets table" into SCB space
122465942Sgibbs				 * and make it qualify all the way to the
122565942Sgibbs				 * lun level.
122665942Sgibbs				 */
122765942Sgibbs				ahc->flags |= AHC_SCB_BTT;
122865942Sgibbs			}
122965942Sgibbs		}
123065942Sgibbs	}
123165942Sgibbsdone:
123265942Sgibbs	/*
123365942Sgibbs	 * Disable parity error reporting until we
123465942Sgibbs	 * can load instruction ram.
123565942Sgibbs	 */
123665942Sgibbs	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
123765942Sgibbs	/* Clear any latched parity error */
123865942Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
123965942Sgibbs	ahc_outb(ahc, CLRINT, CLRBRKADRINT);
124065942Sgibbs	if (bootverbose && enable) {
124165942Sgibbs		printf("%s: External SRAM, %s access%s, %dbytes/SCB\n",
124265942Sgibbs		       ahc_name(ahc), fast ? "fast" : "slow",
124365942Sgibbs		       pcheck ? ", parity checking enabled" : "",
124465942Sgibbs		       large ? 64 : 32);
124565942Sgibbs	}
124665942Sgibbs	ahc_scbram_config(ahc, enable, pcheck, fast, large);
124765942Sgibbs}
124865942Sgibbs
124965942Sgibbs/*
1250107419Sscottl * Perform some simple tests that should catch situations where
1251107419Sscottl * our registers are invalidly mapped.
1252107419Sscottl */
1253107419Sscottlint
1254107419Sscottlahc_pci_test_register_access(struct ahc_softc *ahc)
1255107419Sscottl{
1256109590Sgibbs	int	 error;
1257109590Sgibbs	u_int	 status1;
1258109590Sgibbs	uint32_t cmd;
1259109590Sgibbs	uint8_t	 hcntrl;
1260107419Sscottl
1261107623Sscottl	error = EIO;
1262107623Sscottl
1263109590Sgibbs	/*
1264109590Sgibbs	 * Enable PCI error interrupt status, but suppress NMIs
1265109590Sgibbs	 * generated by SERR raised due to target aborts.
1266109590Sgibbs	 */
1267109590Sgibbs	cmd = ahc_pci_read_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/2);
1268109590Sgibbs	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND,
1269109590Sgibbs			     cmd & ~PCIM_CMD_SERRESPEN, /*bytes*/2);
1270107623Sscottl
1271107419Sscottl	/*
1272107419Sscottl	 * First a simple test to see if any
1273107419Sscottl	 * registers can be read.  Reading
1274107419Sscottl	 * HCNTRL has no side effects and has
1275107419Sscottl	 * at least one bit that is guaranteed to
1276107419Sscottl	 * be zero so it is a good register to
1277107419Sscottl	 * use for this test.
1278107419Sscottl	 */
1279109590Sgibbs	hcntrl = ahc_inb(ahc, HCNTRL);
1280109590Sgibbs	if (hcntrl == 0xFF)
1281107623Sscottl		goto fail;
1282107419Sscottl
1283107419Sscottl	/*
1284107419Sscottl	 * Next create a situation where write combining
1285107419Sscottl	 * or read prefetching could be initiated by the
1286107419Sscottl	 * CPU or host bridge.  Our device does not support
1287107419Sscottl	 * either, so look for data corruption and/or flagged
1288120445Sscottl	 * PCI errors.  First pause without causing another
1289120445Sscottl	 * chip reset.
1290107419Sscottl	 */
1291120445Sscottl	hcntrl &= ~CHIPRST;
1292109590Sgibbs	ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
1293109590Sgibbs	while (ahc_is_paused(ahc) == 0)
1294109590Sgibbs		;
1295115919Sgibbs
1296115919Sgibbs	/* Clear any PCI errors that occurred before our driver attached. */
1297115919Sgibbs	status1 = ahc_pci_read_config(ahc->dev_softc,
1298115919Sgibbs				      PCIR_STATUS + 1, /*bytes*/1);
1299115919Sgibbs	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
1300115919Sgibbs			     status1, /*bytes*/1);
1301115919Sgibbs	ahc_outb(ahc, CLRINT, CLRPARERR);
1302115919Sgibbs
1303109590Sgibbs	ahc_outb(ahc, SEQCTL, PERRORDIS);
1304109590Sgibbs	ahc_outb(ahc, SCBPTR, 0);
1305109590Sgibbs	ahc_outl(ahc, SCB_BASE, 0x5aa555aa);
1306109590Sgibbs	if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa)
1307107623Sscottl		goto fail;
1308107419Sscottl
1309107419Sscottl	status1 = ahc_pci_read_config(ahc->dev_softc,
1310107419Sscottl				      PCIR_STATUS + 1, /*bytes*/1);
1311107623Sscottl	if ((status1 & STA) != 0)
1312107623Sscottl		goto fail;
1313107419Sscottl
1314107623Sscottl	error = 0;
1315107419Sscottl
1316107623Sscottlfail:
1317107623Sscottl	/* Silently clear any latched errors. */
1318107623Sscottl	status1 = ahc_pci_read_config(ahc->dev_softc,
1319107623Sscottl				      PCIR_STATUS + 1, /*bytes*/1);
1320107623Sscottl	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
1321107623Sscottl			     status1, /*bytes*/1);
1322107623Sscottl	ahc_outb(ahc, CLRINT, CLRPARERR);
1323109590Sgibbs	ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
1324109590Sgibbs	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
1325107623Sscottl	return (error);
1326107419Sscottl}
1327107419Sscottl
1328107419Sscottl/*
132965942Sgibbs * Check the external port logic for a serial eeprom
133065942Sgibbs * and termination/cable detection contrls.
133165942Sgibbs */
133265942Sgibbsstatic void
133365942Sgibbscheck_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
133465942Sgibbs{
133565942Sgibbs	struct	seeprom_descriptor sd;
1336102676Sgibbs	struct	seeprom_config *sc;
133765942Sgibbs	int	have_seeprom;
133865942Sgibbs	int	have_autoterm;
133965942Sgibbs
134065942Sgibbs	sd.sd_ahc = ahc;
134165942Sgibbs	sd.sd_control_offset = SEECTL;
134265942Sgibbs	sd.sd_status_offset = SEECTL;
134365942Sgibbs	sd.sd_dataout_offset = SEECTL;
1344102676Sgibbs	sc = ahc->seep_config;
134565942Sgibbs
134665942Sgibbs	/*
134765942Sgibbs	 * For some multi-channel devices, the c46 is simply too
134865942Sgibbs	 * small to work.  For the other controller types, we can
134965942Sgibbs	 * get our information from either SEEPROM type.  Set the
135065942Sgibbs	 * type to start our probe with accordingly.
135165942Sgibbs	 */
135265942Sgibbs	if (ahc->flags & AHC_LARGE_SEEPROM)
135365942Sgibbs		sd.sd_chip = C56_66;
135465942Sgibbs	else
135565942Sgibbs		sd.sd_chip = C46;
135665942Sgibbs
135765942Sgibbs	sd.sd_MS = SEEMS;
135865942Sgibbs	sd.sd_RDY = SEERDY;
135965942Sgibbs	sd.sd_CS = SEECS;
136065942Sgibbs	sd.sd_CK = SEECK;
136165942Sgibbs	sd.sd_DO = SEEDO;
136265942Sgibbs	sd.sd_DI = SEEDI;
136365942Sgibbs
136495378Sgibbs	have_seeprom = ahc_acquire_seeprom(ahc, &sd);
136565942Sgibbs	if (have_seeprom) {
136665942Sgibbs
136765942Sgibbs		if (bootverbose)
136865942Sgibbs			printf("%s: Reading SEEPROM...", ahc_name(ahc));
136965942Sgibbs
137065942Sgibbs		for (;;) {
137165942Sgibbs			u_int start_addr;
137265942Sgibbs
137365942Sgibbs			start_addr = 32 * (ahc->channel - 'A');
137465942Sgibbs
1375102676Sgibbs			have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)sc,
137695378Sgibbs							start_addr,
1377102676Sgibbs							sizeof(*sc)/2);
137865942Sgibbs
137965942Sgibbs			if (have_seeprom)
1380102676Sgibbs				have_seeprom = ahc_verify_cksum(sc);
138165942Sgibbs
138265942Sgibbs			if (have_seeprom != 0 || sd.sd_chip == C56_66) {
138365942Sgibbs				if (bootverbose) {
138465942Sgibbs					if (have_seeprom == 0)
138565942Sgibbs						printf ("checksum error\n");
138665942Sgibbs					else
138765942Sgibbs						printf ("done.\n");
138865942Sgibbs				}
138965942Sgibbs				break;
139065942Sgibbs			}
139165942Sgibbs			sd.sd_chip = C56_66;
139265942Sgibbs		}
139395378Sgibbs		ahc_release_seeprom(&sd);
139465942Sgibbs	}
139565942Sgibbs
139665942Sgibbs	if (!have_seeprom) {
139765942Sgibbs		/*
139865942Sgibbs		 * Pull scratch ram settings and treat them as
139965942Sgibbs		 * if they are the contents of an seeprom if
140065942Sgibbs		 * the 'ADPT' signature is found in SCB2.
140174094Sgibbs		 * We manually compose the data as 16bit values
140274094Sgibbs		 * to avoid endian issues.
140365942Sgibbs		 */
140465942Sgibbs		ahc_outb(ahc, SCBPTR, 2);
140565942Sgibbs		if (ahc_inb(ahc, SCB_BASE) == 'A'
140665942Sgibbs		 && ahc_inb(ahc, SCB_BASE + 1) == 'D'
140765942Sgibbs		 && ahc_inb(ahc, SCB_BASE + 2) == 'P'
140865942Sgibbs		 && ahc_inb(ahc, SCB_BASE + 3) == 'T') {
140974094Sgibbs			uint16_t *sc_data;
141065942Sgibbs			int	  i;
141165942Sgibbs
1412102676Sgibbs			sc_data = (uint16_t *)sc;
1413102676Sgibbs			for (i = 0; i < 32; i++, sc_data++) {
1414102676Sgibbs				int	j;
141574094Sgibbs
141674094Sgibbs				j = i * 2;
1417102676Sgibbs				*sc_data = ahc_inb(ahc, SRAM_BASE + j)
1418102676Sgibbs					 | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
141974094Sgibbs			}
1420102676Sgibbs			have_seeprom = ahc_verify_cksum(sc);
1421102676Sgibbs			if (have_seeprom)
1422102676Sgibbs				ahc->flags |= AHC_SCB_CONFIG_USED;
142365942Sgibbs		}
142495378Sgibbs		/*
142595378Sgibbs		 * Clear any SCB parity errors in case this data and
142695378Sgibbs		 * its associated parity was not initialized by the BIOS
142795378Sgibbs		 */
142895378Sgibbs		ahc_outb(ahc, CLRINT, CLRPARERR);
142995378Sgibbs		ahc_outb(ahc, CLRINT, CLRBRKADRINT);
143065942Sgibbs	}
143165942Sgibbs
143265942Sgibbs	if (!have_seeprom) {
143365942Sgibbs		if (bootverbose)
143465942Sgibbs			printf("%s: No SEEPROM available.\n", ahc_name(ahc));
143565942Sgibbs		ahc->flags |= AHC_USEDEFAULTS;
1436102676Sgibbs		free(ahc->seep_config, M_DEVBUF);
1437102676Sgibbs		ahc->seep_config = NULL;
1438102676Sgibbs		sc = NULL;
143965942Sgibbs	} else {
1440102676Sgibbs		ahc_parse_pci_eeprom(ahc, sc);
144165942Sgibbs	}
144265942Sgibbs
144365942Sgibbs	/*
144465942Sgibbs	 * Cards that have the external logic necessary to talk to
144565942Sgibbs	 * a SEEPROM, are almost certain to have the remaining logic
144665942Sgibbs	 * necessary for auto-termination control.  This assumption
144765942Sgibbs	 * hasn't failed yet...
144865942Sgibbs	 */
144965942Sgibbs	have_autoterm = have_seeprom;
145065942Sgibbs
145165942Sgibbs	/*
145265942Sgibbs	 * Some low-cost chips have SEEPROM and auto-term control built
145365942Sgibbs	 * in, instead of using a GAL.  They can tell us directly
145465942Sgibbs	 * if the termination logic is enabled.
145565942Sgibbs	 */
145665942Sgibbs	if ((ahc->features & AHC_SPIOCAP) != 0) {
1457102676Sgibbs		if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) == 0)
145865942Sgibbs			have_autoterm = FALSE;
145965942Sgibbs	}
146065942Sgibbs
146174094Sgibbs	if (have_autoterm) {
1462114621Sgibbs		ahc->flags |= AHC_HAS_TERM_LOGIC;
146395378Sgibbs		ahc_acquire_seeprom(ahc, &sd);
1464102676Sgibbs		configure_termination(ahc, &sd, sc->adapter_control, sxfrctl1);
146595378Sgibbs		ahc_release_seeprom(&sd);
1466102676Sgibbs	} else if (have_seeprom) {
1467102676Sgibbs		*sxfrctl1 &= ~STPWEN;
1468102676Sgibbs		if ((sc->adapter_control & CFSTERM) != 0)
1469102676Sgibbs			*sxfrctl1 |= STPWEN;
1470102676Sgibbs		if (bootverbose)
1471102676Sgibbs			printf("%s: Low byte termination %sabled\n",
1472102676Sgibbs			       ahc_name(ahc),
1473102676Sgibbs			       (*sxfrctl1 & STPWEN) ? "en" : "dis");
147474094Sgibbs	}
147565942Sgibbs}
147665942Sgibbs
147765942Sgibbsstatic void
1478102676Sgibbsahc_parse_pci_eeprom(struct ahc_softc *ahc, struct seeprom_config *sc)
1479102676Sgibbs{
1480102676Sgibbs	/*
1481102676Sgibbs	 * Put the data we've collected down into SRAM
1482102676Sgibbs	 * where ahc_init will find it.
1483102676Sgibbs	 */
1484102676Sgibbs	int	 i;
1485102676Sgibbs	int	 max_targ = sc->max_targets & CFMAXTARG;
1486102676Sgibbs	u_int	 scsi_conf;
1487102676Sgibbs	uint16_t discenable;
1488102676Sgibbs	uint16_t ultraenb;
1489102676Sgibbs
1490102676Sgibbs	discenable = 0;
1491102676Sgibbs	ultraenb = 0;
1492102676Sgibbs	if ((sc->adapter_control & CFULTRAEN) != 0) {
1493102676Sgibbs		/*
1494102676Sgibbs		 * Determine if this adapter has a "newstyle"
1495102676Sgibbs		 * SEEPROM format.
1496102676Sgibbs		 */
1497102676Sgibbs		for (i = 0; i < max_targ; i++) {
1498102676Sgibbs			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0) {
1499102676Sgibbs				ahc->flags |= AHC_NEWEEPROM_FMT;
1500102676Sgibbs				break;
1501102676Sgibbs			}
1502102676Sgibbs		}
1503102676Sgibbs	}
1504102676Sgibbs
1505102676Sgibbs	for (i = 0; i < max_targ; i++) {
1506102676Sgibbs		u_int     scsirate;
1507102676Sgibbs		uint16_t target_mask;
1508102676Sgibbs
1509102676Sgibbs		target_mask = 0x01 << i;
1510102676Sgibbs		if (sc->device_flags[i] & CFDISC)
1511102676Sgibbs			discenable |= target_mask;
1512102676Sgibbs		if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) {
1513102676Sgibbs			if ((sc->device_flags[i] & CFSYNCHISULTRA) != 0)
1514102676Sgibbs				ultraenb |= target_mask;
1515102676Sgibbs		} else if ((sc->adapter_control & CFULTRAEN) != 0) {
1516102676Sgibbs			ultraenb |= target_mask;
1517102676Sgibbs		}
1518102676Sgibbs		if ((sc->device_flags[i] & CFXFER) == 0x04
1519102676Sgibbs		 && (ultraenb & target_mask) != 0) {
1520102676Sgibbs			/* Treat 10MHz as a non-ultra speed */
1521102676Sgibbs			sc->device_flags[i] &= ~CFXFER;
1522102676Sgibbs		 	ultraenb &= ~target_mask;
1523102676Sgibbs		}
1524102676Sgibbs		if ((ahc->features & AHC_ULTRA2) != 0) {
1525102676Sgibbs			u_int offset;
1526102676Sgibbs
1527102676Sgibbs			if (sc->device_flags[i] & CFSYNCH)
1528102676Sgibbs				offset = MAX_OFFSET_ULTRA2;
1529102676Sgibbs			else
1530102676Sgibbs				offset = 0;
1531102676Sgibbs			ahc_outb(ahc, TARG_OFFSET + i, offset);
1532102676Sgibbs
1533102676Sgibbs			/*
1534102676Sgibbs			 * The ultra enable bits contain the
1535102676Sgibbs			 * high bit of the ultra2 sync rate
1536102676Sgibbs			 * field.
1537102676Sgibbs			 */
1538102676Sgibbs			scsirate = (sc->device_flags[i] & CFXFER)
1539102676Sgibbs				 | ((ultraenb & target_mask) ? 0x8 : 0x0);
1540102676Sgibbs			if (sc->device_flags[i] & CFWIDEB)
1541102676Sgibbs				scsirate |= WIDEXFER;
1542102676Sgibbs		} else {
1543102676Sgibbs			scsirate = (sc->device_flags[i] & CFXFER) << 4;
1544102676Sgibbs			if (sc->device_flags[i] & CFSYNCH)
1545102676Sgibbs				scsirate |= SOFS;
1546102676Sgibbs			if (sc->device_flags[i] & CFWIDEB)
1547102676Sgibbs				scsirate |= WIDEXFER;
1548102676Sgibbs		}
1549102676Sgibbs		ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);
1550102676Sgibbs	}
1551102676Sgibbs	ahc->our_id = sc->brtime_id & CFSCSIID;
1552102676Sgibbs
1553102676Sgibbs	scsi_conf = (ahc->our_id & 0x7);
1554102676Sgibbs	if (sc->adapter_control & CFSPARITY)
1555102676Sgibbs		scsi_conf |= ENSPCHK;
1556102676Sgibbs	if (sc->adapter_control & CFRESETB)
1557102676Sgibbs		scsi_conf |= RESET_SCSI;
1558102676Sgibbs
1559102676Sgibbs	ahc->flags |= (sc->adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;
1560102676Sgibbs
1561102676Sgibbs	if (sc->bios_control & CFEXTEND)
1562102676Sgibbs		ahc->flags |= AHC_EXTENDED_TRANS_A;
1563102676Sgibbs
1564102676Sgibbs	if (sc->bios_control & CFBIOSEN)
1565102676Sgibbs		ahc->flags |= AHC_BIOS_ENABLED;
1566102676Sgibbs	if (ahc->features & AHC_ULTRA
1567102676Sgibbs	 && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {
1568102676Sgibbs		/* Should we enable Ultra mode? */
1569102676Sgibbs		if (!(sc->adapter_control & CFULTRAEN))
1570102676Sgibbs			/* Treat us as a non-ultra card */
1571102676Sgibbs			ultraenb = 0;
1572102676Sgibbs	}
1573102676Sgibbs
1574102676Sgibbs	if (sc->signature == CFSIGNATURE
1575102676Sgibbs	 || sc->signature == CFSIGNATURE2) {
1576102676Sgibbs		uint32_t devconfig;
1577102676Sgibbs
1578102676Sgibbs		/* Honor the STPWLEVEL settings */
1579102676Sgibbs		devconfig = ahc_pci_read_config(ahc->dev_softc,
1580102676Sgibbs						DEVCONFIG, /*bytes*/4);
1581102676Sgibbs		devconfig &= ~STPWLEVEL;
1582102676Sgibbs		if ((sc->bios_control & CFSTPWLEVEL) != 0)
1583102676Sgibbs			devconfig |= STPWLEVEL;
1584102676Sgibbs		ahc_pci_write_config(ahc->dev_softc, DEVCONFIG,
1585102676Sgibbs				     devconfig, /*bytes*/4);
1586102676Sgibbs	}
1587102676Sgibbs	/* Set SCSICONF info */
1588102676Sgibbs	ahc_outb(ahc, SCSICONF, scsi_conf);
1589102676Sgibbs	ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
1590102676Sgibbs	ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
1591102676Sgibbs	ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff);
1592102676Sgibbs	ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);
1593102676Sgibbs}
1594102676Sgibbs
1595102676Sgibbsstatic void
159665942Sgibbsconfigure_termination(struct ahc_softc *ahc,
159765942Sgibbs		      struct seeprom_descriptor *sd,
159865942Sgibbs		      u_int adapter_control,
159965942Sgibbs		      u_int *sxfrctl1)
160065942Sgibbs{
160165942Sgibbs	uint8_t brddat;
160265942Sgibbs
160365942Sgibbs	brddat = 0;
160465942Sgibbs
160565942Sgibbs	/*
160665942Sgibbs	 * Update the settings in sxfrctl1 to match the
160765942Sgibbs	 * termination settings
160865942Sgibbs	 */
160965942Sgibbs	*sxfrctl1 = 0;
161065942Sgibbs
161165942Sgibbs	/*
161265942Sgibbs	 * SEECS must be on for the GALS to latch
161365942Sgibbs	 * the data properly.  Be sure to leave MS
161465942Sgibbs	 * on or we will release the seeprom.
161565942Sgibbs	 */
161665942Sgibbs	SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS);
161765942Sgibbs	if ((adapter_control & CFAUTOTERM) != 0
161865942Sgibbs	 || (ahc->features & AHC_NEW_TERMCTL) != 0) {
161965942Sgibbs		int internal50_present;
162065942Sgibbs		int internal68_present;
162165942Sgibbs		int externalcable_present;
162265942Sgibbs		int eeprom_present;
162365942Sgibbs		int enableSEC_low;
162465942Sgibbs		int enableSEC_high;
162565942Sgibbs		int enablePRI_low;
162665942Sgibbs		int enablePRI_high;
162771390Sgibbs		int sum;
162865942Sgibbs
162965942Sgibbs		enableSEC_low = 0;
163065942Sgibbs		enableSEC_high = 0;
163165942Sgibbs		enablePRI_low = 0;
163265942Sgibbs		enablePRI_high = 0;
163365942Sgibbs		if ((ahc->features & AHC_NEW_TERMCTL) != 0) {
163465942Sgibbs			ahc_new_term_detect(ahc, &enableSEC_low,
1635102676Sgibbs					    &enableSEC_high,
1636102676Sgibbs					    &enablePRI_low,
1637102676Sgibbs					    &enablePRI_high,
1638102676Sgibbs					    &eeprom_present);
163965942Sgibbs			if ((adapter_control & CFSEAUTOTERM) == 0) {
164065942Sgibbs				if (bootverbose)
164165942Sgibbs					printf("%s: Manual SE Termination\n",
164265942Sgibbs					       ahc_name(ahc));
164365942Sgibbs				enableSEC_low = (adapter_control & CFSELOWTERM);
164465942Sgibbs				enableSEC_high =
164565942Sgibbs				    (adapter_control & CFSEHIGHTERM);
164665942Sgibbs			}
164765942Sgibbs			if ((adapter_control & CFAUTOTERM) == 0) {
164865942Sgibbs				if (bootverbose)
164965942Sgibbs					printf("%s: Manual LVD Termination\n",
165065942Sgibbs					       ahc_name(ahc));
165165942Sgibbs				enablePRI_low = (adapter_control & CFSTERM);
165265942Sgibbs				enablePRI_high = (adapter_control & CFWSTERM);
165365942Sgibbs			}
165465942Sgibbs			/* Make the table calculations below happy */
165565942Sgibbs			internal50_present = 0;
165665942Sgibbs			internal68_present = 1;
165765942Sgibbs			externalcable_present = 1;
165865942Sgibbs		} else if ((ahc->features & AHC_SPIOCAP) != 0) {
165965942Sgibbs			aic785X_cable_detect(ahc, &internal50_present,
166065942Sgibbs					     &externalcable_present,
166165942Sgibbs					     &eeprom_present);
1662102676Sgibbs			/* Can never support a wide connector. */
1663102676Sgibbs			internal68_present = 0;
166465942Sgibbs		} else {
166565942Sgibbs			aic787X_cable_detect(ahc, &internal50_present,
166665942Sgibbs					     &internal68_present,
166765942Sgibbs					     &externalcable_present,
166865942Sgibbs					     &eeprom_present);
166965942Sgibbs		}
167065942Sgibbs
167165942Sgibbs		if ((ahc->features & AHC_WIDE) == 0)
167265942Sgibbs			internal68_present = 0;
167365942Sgibbs
167471390Sgibbs		if (bootverbose
167571390Sgibbs		 && (ahc->features & AHC_ULTRA2) == 0) {
167671390Sgibbs			printf("%s: internal 50 cable %s present",
167771390Sgibbs			       ahc_name(ahc),
167871390Sgibbs			       internal50_present ? "is":"not");
167971390Sgibbs
168071390Sgibbs			if ((ahc->features & AHC_WIDE) != 0)
168171390Sgibbs				printf(", internal 68 cable %s present",
168265942Sgibbs				       internal68_present ? "is":"not");
168371390Sgibbs			printf("\n%s: external cable %s present\n",
168471390Sgibbs			       ahc_name(ahc),
168571390Sgibbs			       externalcable_present ? "is":"not");
168671390Sgibbs		}
168771390Sgibbs		if (bootverbose)
168865942Sgibbs			printf("%s: BIOS eeprom %s present\n",
168965942Sgibbs			       ahc_name(ahc), eeprom_present ? "is" : "not");
169065942Sgibbs
169165942Sgibbs		if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) {
169265942Sgibbs			/*
169365942Sgibbs			 * The 50 pin connector is a separate bus,
169465942Sgibbs			 * so force it to always be terminated.
169565942Sgibbs			 * In the future, perform current sensing
169665942Sgibbs			 * to determine if we are in the middle of
169765942Sgibbs			 * a properly terminated bus.
169865942Sgibbs			 */
169965942Sgibbs			internal50_present = 0;
170065942Sgibbs		}
170165942Sgibbs
170265942Sgibbs		/*
170365942Sgibbs		 * Now set the termination based on what
170465942Sgibbs		 * we found.
170565942Sgibbs		 * Flash Enable = BRDDAT7
170665942Sgibbs		 * Secondary High Term Enable = BRDDAT6
170765942Sgibbs		 * Secondary Low Term Enable = BRDDAT5 (7890)
170865942Sgibbs		 * Primary High Term Enable = BRDDAT4 (7890)
170965942Sgibbs		 */
171065942Sgibbs		if ((ahc->features & AHC_ULTRA2) == 0
171171390Sgibbs		 && (internal50_present != 0)
171271390Sgibbs		 && (internal68_present != 0)
171371390Sgibbs		 && (externalcable_present != 0)) {
171465942Sgibbs			printf("%s: Illegal cable configuration!!. "
171565942Sgibbs			       "Only two connectors on the "
171665942Sgibbs			       "adapter may be used at a "
171765942Sgibbs			       "time!\n", ahc_name(ahc));
171895378Sgibbs
171995378Sgibbs			/*
172095378Sgibbs			 * Pretend there are no cables in the hope
172195378Sgibbs			 * that having all of the termination on
172295378Sgibbs			 * gives us a more stable bus.
172395378Sgibbs			 */
172495378Sgibbs		 	internal50_present = 0;
172595378Sgibbs			internal68_present = 0;
172695378Sgibbs			externalcable_present = 0;
172765942Sgibbs		}
172865942Sgibbs
172965942Sgibbs		if ((ahc->features & AHC_WIDE) != 0
173065942Sgibbs		 && ((externalcable_present == 0)
173165942Sgibbs		  || (internal68_present == 0)
173265942Sgibbs		  || (enableSEC_high != 0))) {
173365942Sgibbs			brddat |= BRDDAT6;
173465942Sgibbs			if (bootverbose) {
173565942Sgibbs				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
173665942Sgibbs					printf("%s: 68 pin termination "
173765942Sgibbs					       "Enabled\n", ahc_name(ahc));
173865942Sgibbs				else
173965942Sgibbs					printf("%s: %sHigh byte termination "
174065942Sgibbs					       "Enabled\n", ahc_name(ahc),
174165942Sgibbs					       enableSEC_high ? "Secondary "
174265942Sgibbs							      : "");
174365942Sgibbs			}
174465942Sgibbs		}
174565942Sgibbs
174671390Sgibbs		sum = internal50_present + internal68_present
174771390Sgibbs		    + externalcable_present;
174871390Sgibbs		if (sum < 2 || (enableSEC_low != 0)) {
174965942Sgibbs			if ((ahc->features & AHC_ULTRA2) != 0)
175065942Sgibbs				brddat |= BRDDAT5;
175165942Sgibbs			else
175265942Sgibbs				*sxfrctl1 |= STPWEN;
175365942Sgibbs			if (bootverbose) {
175465942Sgibbs				if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
175565942Sgibbs					printf("%s: 50 pin termination "
175665942Sgibbs					       "Enabled\n", ahc_name(ahc));
175765942Sgibbs				else
175865942Sgibbs					printf("%s: %sLow byte termination "
175965942Sgibbs					       "Enabled\n", ahc_name(ahc),
176065942Sgibbs					       enableSEC_low ? "Secondary "
176165942Sgibbs							     : "");
176265942Sgibbs			}
176365942Sgibbs		}
176465942Sgibbs
176565942Sgibbs		if (enablePRI_low != 0) {
176665942Sgibbs			*sxfrctl1 |= STPWEN;
176765942Sgibbs			if (bootverbose)
176865942Sgibbs				printf("%s: Primary Low Byte termination "
176965942Sgibbs				       "Enabled\n", ahc_name(ahc));
177065942Sgibbs		}
177165942Sgibbs
177265942Sgibbs		/*
177365942Sgibbs		 * Setup STPWEN before setting up the rest of
177465942Sgibbs		 * the termination per the tech note on the U160 cards.
177565942Sgibbs		 */
177665942Sgibbs		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
177765942Sgibbs
177865942Sgibbs		if (enablePRI_high != 0) {
177965942Sgibbs			brddat |= BRDDAT4;
178065942Sgibbs			if (bootverbose)
178165942Sgibbs				printf("%s: Primary High Byte "
178265942Sgibbs				       "termination Enabled\n",
178365942Sgibbs				       ahc_name(ahc));
178465942Sgibbs		}
178565942Sgibbs
178665942Sgibbs		write_brdctl(ahc, brddat);
178765942Sgibbs
178865942Sgibbs	} else {
178965942Sgibbs		if ((adapter_control & CFSTERM) != 0) {
179065942Sgibbs			*sxfrctl1 |= STPWEN;
179165942Sgibbs
179265942Sgibbs			if (bootverbose)
179365942Sgibbs				printf("%s: %sLow byte termination Enabled\n",
179465942Sgibbs				       ahc_name(ahc),
179565942Sgibbs				       (ahc->features & AHC_ULTRA2) ? "Primary "
179665942Sgibbs								    : "");
179765942Sgibbs		}
179865942Sgibbs
179971390Sgibbs		if ((adapter_control & CFWSTERM) != 0
180071390Sgibbs		 && (ahc->features & AHC_WIDE) != 0) {
180165942Sgibbs			brddat |= BRDDAT6;
180265942Sgibbs			if (bootverbose)
180365942Sgibbs				printf("%s: %sHigh byte termination Enabled\n",
180465942Sgibbs				       ahc_name(ahc),
180565942Sgibbs				       (ahc->features & AHC_ULTRA2)
180665942Sgibbs				     ? "Secondary " : "");
180765942Sgibbs		}
180865942Sgibbs
180965942Sgibbs		/*
181065942Sgibbs		 * Setup STPWEN before setting up the rest of
181165942Sgibbs		 * the termination per the tech note on the U160 cards.
181265942Sgibbs		 */
181365942Sgibbs		ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
181465942Sgibbs
181571390Sgibbs		if ((ahc->features & AHC_WIDE) != 0)
181671390Sgibbs			write_brdctl(ahc, brddat);
181765942Sgibbs	}
181865942Sgibbs	SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */
181965942Sgibbs}
182065942Sgibbs
182165942Sgibbsstatic void
182265942Sgibbsahc_new_term_detect(struct ahc_softc *ahc, int *enableSEC_low,
182365942Sgibbs		    int *enableSEC_high, int *enablePRI_low,
182465942Sgibbs		    int *enablePRI_high, int *eeprom_present)
182565942Sgibbs{
182665942Sgibbs	uint8_t brdctl;
182765942Sgibbs
182865942Sgibbs	/*
182965942Sgibbs	 * BRDDAT7 = Eeprom
183065942Sgibbs	 * BRDDAT6 = Enable Secondary High Byte termination
183165942Sgibbs	 * BRDDAT5 = Enable Secondary Low Byte termination
183265942Sgibbs	 * BRDDAT4 = Enable Primary high byte termination
183365942Sgibbs	 * BRDDAT3 = Enable Primary low byte termination
183465942Sgibbs	 */
183565942Sgibbs	brdctl = read_brdctl(ahc);
183665942Sgibbs	*eeprom_present = brdctl & BRDDAT7;
183765942Sgibbs	*enableSEC_high = (brdctl & BRDDAT6);
183865942Sgibbs	*enableSEC_low = (brdctl & BRDDAT5);
183965942Sgibbs	*enablePRI_high = (brdctl & BRDDAT4);
184065942Sgibbs	*enablePRI_low = (brdctl & BRDDAT3);
184165942Sgibbs}
184265942Sgibbs
184365942Sgibbsstatic void
184465942Sgibbsaic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
184565942Sgibbs		     int *internal68_present, int *externalcable_present,
184665942Sgibbs		     int *eeprom_present)
184765942Sgibbs{
184865942Sgibbs	uint8_t brdctl;
184965942Sgibbs
185065942Sgibbs	/*
185165942Sgibbs	 * First read the status of our cables.
185265942Sgibbs	 * Set the rom bank to 0 since the
185365942Sgibbs	 * bank setting serves as a multiplexor
185465942Sgibbs	 * for the cable detection logic.
185565942Sgibbs	 * BRDDAT5 controls the bank switch.
185665942Sgibbs	 */
185765942Sgibbs	write_brdctl(ahc, 0);
185865942Sgibbs
185965942Sgibbs	/*
186065942Sgibbs	 * Now read the state of the internal
186165942Sgibbs	 * connectors.  BRDDAT6 is INT50 and
186265942Sgibbs	 * BRDDAT7 is INT68.
186365942Sgibbs	 */
186465942Sgibbs	brdctl = read_brdctl(ahc);
186571390Sgibbs	*internal50_present = (brdctl & BRDDAT6) ? 0 : 1;
186671390Sgibbs	*internal68_present = (brdctl & BRDDAT7) ? 0 : 1;
186765942Sgibbs
186865942Sgibbs	/*
186965942Sgibbs	 * Set the rom bank to 1 and determine
187065942Sgibbs	 * the other signals.
187165942Sgibbs	 */
187265942Sgibbs	write_brdctl(ahc, BRDDAT5);
187365942Sgibbs
187465942Sgibbs	/*
187565942Sgibbs	 * Now read the state of the external
187665942Sgibbs	 * connectors.  BRDDAT6 is EXT68 and
187765942Sgibbs	 * BRDDAT7 is EPROMPS.
187865942Sgibbs	 */
187965942Sgibbs	brdctl = read_brdctl(ahc);
188071390Sgibbs	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
188171390Sgibbs	*eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;
188265942Sgibbs}
188365942Sgibbs
188465942Sgibbsstatic void
188565942Sgibbsaic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
188665942Sgibbs		     int *externalcable_present, int *eeprom_present)
188765942Sgibbs{
188865942Sgibbs	uint8_t brdctl;
1889102676Sgibbs	uint8_t spiocap;
189065942Sgibbs
1891102676Sgibbs	spiocap = ahc_inb(ahc, SPIOCAP);
1892102676Sgibbs	spiocap &= ~SOFTCMDEN;
1893102676Sgibbs	spiocap |= EXT_BRDCTL;
1894102676Sgibbs	ahc_outb(ahc, SPIOCAP, spiocap);
189565942Sgibbs	ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
1896114621Sgibbs	ahc_flush_device_writes(ahc);
1897114621Sgibbs	ahc_delay(500);
189865942Sgibbs	ahc_outb(ahc, BRDCTL, 0);
1899114621Sgibbs	ahc_flush_device_writes(ahc);
1900114621Sgibbs	ahc_delay(500);
190165942Sgibbs	brdctl = ahc_inb(ahc, BRDCTL);
190271390Sgibbs	*internal50_present = (brdctl & BRDDAT5) ? 0 : 1;
190371390Sgibbs	*externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
190471390Sgibbs	*eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
190565942Sgibbs}
190665942Sgibbs
190795378Sgibbsint
190895378Sgibbsahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
190965942Sgibbs{
191065942Sgibbs	int wait;
191165942Sgibbs
191265942Sgibbs	if ((ahc->features & AHC_SPIOCAP) != 0
191365942Sgibbs	 && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0)
191465942Sgibbs		return (0);
191565942Sgibbs
191665942Sgibbs	/*
191765942Sgibbs	 * Request access of the memory port.  When access is
191865942Sgibbs	 * granted, SEERDY will go high.  We use a 1 second
191965942Sgibbs	 * timeout which should be near 1 second more than
192065942Sgibbs	 * is needed.  Reason: after the chip reset, there
192165942Sgibbs	 * should be no contention.
192265942Sgibbs	 */
192365942Sgibbs	SEEPROM_OUTB(sd, sd->sd_MS);
192465942Sgibbs	wait = 1000;  /* 1 second timeout in msec */
192565942Sgibbs	while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
192665942Sgibbs		ahc_delay(1000);  /* delay 1 msec */
192765942Sgibbs	}
192865942Sgibbs	if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
192965942Sgibbs		SEEPROM_OUTB(sd, 0);
193065942Sgibbs		return (0);
193165942Sgibbs	}
193265942Sgibbs	return(1);
193365942Sgibbs}
193465942Sgibbs
193595378Sgibbsvoid
193695378Sgibbsahc_release_seeprom(struct seeprom_descriptor *sd)
193765942Sgibbs{
193865942Sgibbs	/* Release access to the memory port and the serial EEPROM. */
193965942Sgibbs	SEEPROM_OUTB(sd, 0);
194065942Sgibbs}
194165942Sgibbs
194265942Sgibbsstatic void
194365942Sgibbswrite_brdctl(struct ahc_softc *ahc, uint8_t value)
194465942Sgibbs{
194565942Sgibbs	uint8_t brdctl;
194665942Sgibbs
194765942Sgibbs	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
194865942Sgibbs		brdctl = BRDSTB;
194965942Sgibbs	 	if (ahc->channel == 'B')
195065942Sgibbs			brdctl |= BRDCS;
195165942Sgibbs	} else if ((ahc->features & AHC_ULTRA2) != 0) {
195265942Sgibbs		brdctl = 0;
195365942Sgibbs	} else {
195465942Sgibbs		brdctl = BRDSTB|BRDCS;
195565942Sgibbs	}
195665942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
195771390Sgibbs	ahc_flush_device_writes(ahc);
195865942Sgibbs	brdctl |= value;
195965942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
196071390Sgibbs	ahc_flush_device_writes(ahc);
196165942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
196265942Sgibbs		brdctl |= BRDSTB_ULTRA2;
196365942Sgibbs	else
196465942Sgibbs		brdctl &= ~BRDSTB;
196565942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
196671390Sgibbs	ahc_flush_device_writes(ahc);
196765942Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
196865942Sgibbs		brdctl = 0;
196965942Sgibbs	else
197065942Sgibbs		brdctl &= ~BRDCS;
197165942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
197265942Sgibbs}
197365942Sgibbs
197465942Sgibbsstatic uint8_t
1975115328Sgibbsread_brdctl(struct ahc_softc *ahc)
197665942Sgibbs{
197765942Sgibbs	uint8_t brdctl;
197865942Sgibbs	uint8_t value;
197965942Sgibbs
198065942Sgibbs	if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
198165942Sgibbs		brdctl = BRDRW;
198265942Sgibbs	 	if (ahc->channel == 'B')
198365942Sgibbs			brdctl |= BRDCS;
198465942Sgibbs	} else if ((ahc->features & AHC_ULTRA2) != 0) {
198565942Sgibbs		brdctl = BRDRW_ULTRA2;
198665942Sgibbs	} else {
198765942Sgibbs		brdctl = BRDRW|BRDCS;
198865942Sgibbs	}
198965942Sgibbs	ahc_outb(ahc, BRDCTL, brdctl);
199071390Sgibbs	ahc_flush_device_writes(ahc);
199165942Sgibbs	value = ahc_inb(ahc, BRDCTL);
199265942Sgibbs	ahc_outb(ahc, BRDCTL, 0);
199365942Sgibbs	return (value);
199465942Sgibbs}
199565942Sgibbs
1996114621Sgibbsstatic void
199765942Sgibbsahc_pci_intr(struct ahc_softc *ahc)
199865942Sgibbs{
199966269Sgibbs	u_int error;
200066269Sgibbs	u_int status1;
200165942Sgibbs
200266269Sgibbs	error = ahc_inb(ahc, ERROR);
200366269Sgibbs	if ((error & PCIERRSTAT) == 0)
200466269Sgibbs		return;
200566269Sgibbs
200665942Sgibbs	status1 = ahc_pci_read_config(ahc->dev_softc,
200765942Sgibbs				      PCIR_STATUS + 1, /*bytes*/1);
200865942Sgibbs
200966269Sgibbs	printf("%s: PCI error Interrupt at seqaddr = 0x%x\n",
201066269Sgibbs	      ahc_name(ahc),
201166269Sgibbs	      ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
201266269Sgibbs
201365942Sgibbs	if (status1 & DPE) {
2014114621Sgibbs		ahc->pci_target_perr_count++;
201565942Sgibbs		printf("%s: Data Parity Error Detected during address "
201665942Sgibbs		       "or write data phase\n", ahc_name(ahc));
201765942Sgibbs	}
201865942Sgibbs	if (status1 & SSE) {
201966647Sgibbs		printf("%s: Signal System Error Detected\n", ahc_name(ahc));
202065942Sgibbs	}
202165942Sgibbs	if (status1 & RMA) {
202266647Sgibbs		printf("%s: Received a Master Abort\n", ahc_name(ahc));
202365942Sgibbs	}
202465942Sgibbs	if (status1 & RTA) {
202565942Sgibbs		printf("%s: Received a Target Abort\n", ahc_name(ahc));
202665942Sgibbs	}
202765942Sgibbs	if (status1 & STA) {
202865942Sgibbs		printf("%s: Signaled a Target Abort\n", ahc_name(ahc));
202965942Sgibbs	}
203065942Sgibbs	if (status1 & DPR) {
203165942Sgibbs		printf("%s: Data Parity Error has been reported via PERR#\n",
203265942Sgibbs		       ahc_name(ahc));
203365942Sgibbs	}
203479874Sgibbs
203579874Sgibbs	/* Clear latched errors. */
203679874Sgibbs	ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
203779874Sgibbs			     status1, /*bytes*/1);
203879874Sgibbs
203965942Sgibbs	if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) {
204065942Sgibbs		printf("%s: Latched PCIERR interrupt with "
204165942Sgibbs		       "no status bits set\n", ahc_name(ahc));
204279874Sgibbs	} else {
204365942Sgibbs		ahc_outb(ahc, CLRINT, CLRPARERR);
204465942Sgibbs	}
204566269Sgibbs
2046114621Sgibbs	if (ahc->pci_target_perr_count > AHC_PCI_TARGET_PERR_THRESH) {
2047114621Sgibbs		printf(
2048114621Sgibbs"%s: WARNING WARNING WARNING WARNING\n"
2049114621Sgibbs"%s: Too many PCI parity errors observed as a target.\n"
2050114621Sgibbs"%s: Some device on this bus is generating bad parity.\n"
2051114621Sgibbs"%s: This is an error *observed by*, not *generated by*, this controller.\n"
2052114621Sgibbs"%s: PCI parity error checking has been disabled.\n"
2053114621Sgibbs"%s: WARNING WARNING WARNING WARNING\n",
2054114621Sgibbs		       ahc_name(ahc), ahc_name(ahc), ahc_name(ahc),
2055114621Sgibbs		       ahc_name(ahc), ahc_name(ahc), ahc_name(ahc));
2056115332Sgibbs		ahc->seqctl |= FAILDIS;
2057115332Sgibbs		ahc_outb(ahc, SEQCTL, ahc->seqctl);
2058114621Sgibbs	}
205974094Sgibbs	ahc_unpause(ahc);
206065942Sgibbs}
206165942Sgibbs
206265942Sgibbsstatic int
2063114621Sgibbsahc_pci_chip_init(struct ahc_softc *ahc)
2064114621Sgibbs{
2065114621Sgibbs	ahc_outb(ahc, DSCOMMAND0, ahc->bus_softc.pci_softc.dscommand0);
2066114621Sgibbs	ahc_outb(ahc, DSPCISTATUS, ahc->bus_softc.pci_softc.dspcistatus);
2067114621Sgibbs	if ((ahc->features & AHC_DT) != 0) {
2068114621Sgibbs		u_int sfunct;
2069114621Sgibbs
2070114621Sgibbs		sfunct = ahc_inb(ahc, SFUNCT) & ~ALT_MODE;
2071114621Sgibbs		ahc_outb(ahc, SFUNCT, sfunct | ALT_MODE);
2072114621Sgibbs		ahc_outb(ahc, OPTIONMODE, ahc->bus_softc.pci_softc.optionmode);
2073114621Sgibbs		ahc_outw(ahc, TARGCRCCNT, ahc->bus_softc.pci_softc.targcrccnt);
2074114621Sgibbs		ahc_outb(ahc, SFUNCT, sfunct);
2075114621Sgibbs		ahc_outb(ahc, CRCCONTROL1,
2076114621Sgibbs			 ahc->bus_softc.pci_softc.crccontrol1);
2077114621Sgibbs	}
2078114621Sgibbs	if ((ahc->features & AHC_MULTI_FUNC) != 0)
2079114621Sgibbs		ahc_outb(ahc, SCBBADDR, ahc->bus_softc.pci_softc.scbbaddr);
2080114621Sgibbs
2081114621Sgibbs	if ((ahc->features & AHC_ULTRA2) != 0)
2082114621Sgibbs		ahc_outb(ahc, DFF_THRSH, ahc->bus_softc.pci_softc.dff_thrsh);
2083114621Sgibbs
2084114621Sgibbs	return (ahc_chip_init(ahc));
2085114621Sgibbs}
2086114621Sgibbs
2087114621Sgibbsstatic int
2088114621Sgibbsahc_pci_suspend(struct ahc_softc *ahc)
2089114621Sgibbs{
2090114621Sgibbs	return (ahc_suspend(ahc));
2091114621Sgibbs}
2092114621Sgibbs
2093114621Sgibbsstatic int
2094114621Sgibbsahc_pci_resume(struct ahc_softc *ahc)
2095114621Sgibbs{
2096114621Sgibbs
2097114621Sgibbs	ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
2098114621Sgibbs
2099114621Sgibbs	/*
2100114621Sgibbs	 * We assume that the OS has restored our register
2101114621Sgibbs	 * mappings, etc.  Just update the config space registers
2102114621Sgibbs	 * that the OS doesn't know about and rely on our chip
2103114621Sgibbs	 * reset handler to handle the rest.
2104114621Sgibbs	 */
2105114621Sgibbs	ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, /*bytes*/4,
2106114621Sgibbs			     ahc->bus_softc.pci_softc.devconfig);
2107114621Sgibbs	ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, /*bytes*/1,
2108114621Sgibbs			     ahc->bus_softc.pci_softc.command);
2109114621Sgibbs	ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, /*bytes*/1,
2110114621Sgibbs			     ahc->bus_softc.pci_softc.csize_lattime);
2111114621Sgibbs	if ((ahc->flags & AHC_HAS_TERM_LOGIC) != 0) {
2112114621Sgibbs		struct	seeprom_descriptor sd;
2113114621Sgibbs		u_int	sxfrctl1;
2114114621Sgibbs
2115114621Sgibbs		sd.sd_ahc = ahc;
2116114621Sgibbs		sd.sd_control_offset = SEECTL;
2117114621Sgibbs		sd.sd_status_offset = SEECTL;
2118114621Sgibbs		sd.sd_dataout_offset = SEECTL;
2119114621Sgibbs
2120114621Sgibbs		ahc_acquire_seeprom(ahc, &sd);
2121114621Sgibbs		configure_termination(ahc, &sd,
2122114621Sgibbs				      ahc->seep_config->adapter_control,
2123114621Sgibbs				      &sxfrctl1);
2124114621Sgibbs		ahc_release_seeprom(&sd);
2125114621Sgibbs	}
2126114621Sgibbs	return (ahc_resume(ahc));
2127114621Sgibbs}
2128114621Sgibbs
2129114621Sgibbsstatic int
213079874Sgibbsahc_aic785X_setup(struct ahc_softc *ahc)
213165942Sgibbs{
213279874Sgibbs	ahc_dev_softc_t pci;
213374094Sgibbs	uint8_t rev;
213474094Sgibbs
213579874Sgibbs	pci = ahc->dev_softc;
213679874Sgibbs	ahc->channel = 'A';
213779874Sgibbs	ahc->chip = AHC_AIC7850;
213879874Sgibbs	ahc->features = AHC_AIC7850_FE;
213979874Sgibbs	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
214074094Sgibbs	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
214174094Sgibbs	if (rev >= 1)
214279874Sgibbs		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
2143114621Sgibbs	ahc->instruction_ram_size = 512;
214465942Sgibbs	return (0);
214565942Sgibbs}
214665942Sgibbs
214765942Sgibbsstatic int
214879874Sgibbsahc_aic7860_setup(struct ahc_softc *ahc)
214965942Sgibbs{
215079874Sgibbs	ahc_dev_softc_t pci;
215165942Sgibbs	uint8_t rev;
215265942Sgibbs
215379874Sgibbs	pci = ahc->dev_softc;
215479874Sgibbs	ahc->channel = 'A';
215579874Sgibbs	ahc->chip = AHC_AIC7860;
215679874Sgibbs	ahc->features = AHC_AIC7860_FE;
215779874Sgibbs	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
215865942Sgibbs	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
215965942Sgibbs	if (rev >= 1)
216079874Sgibbs		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
2161114621Sgibbs	ahc->instruction_ram_size = 512;
216265942Sgibbs	return (0);
216365942Sgibbs}
216465942Sgibbs
216565942Sgibbsstatic int
216679874Sgibbsahc_apa1480_setup(struct ahc_softc *ahc)
216771390Sgibbs{
216871390Sgibbs	int error;
216971390Sgibbs
217079874Sgibbs	error = ahc_aic7860_setup(ahc);
217171390Sgibbs	if (error != 0)
217271390Sgibbs		return (error);
217379874Sgibbs	ahc->features |= AHC_REMOVABLE;
217471390Sgibbs	return (0);
217571390Sgibbs}
217671390Sgibbs
217771390Sgibbsstatic int
217879874Sgibbsahc_aic7870_setup(struct ahc_softc *ahc)
217965942Sgibbs{
218079874Sgibbs
218179874Sgibbs	ahc->channel = 'A';
218279874Sgibbs	ahc->chip = AHC_AIC7870;
218379874Sgibbs	ahc->features = AHC_AIC7870_FE;
218479874Sgibbs	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
2185114621Sgibbs	ahc->instruction_ram_size = 512;
218665942Sgibbs	return (0);
218765942Sgibbs}
218865942Sgibbs
218965942Sgibbsstatic int
219079874Sgibbsahc_aha394X_setup(struct ahc_softc *ahc)
219165942Sgibbs{
219265942Sgibbs	int error;
219365942Sgibbs
219479874Sgibbs	error = ahc_aic7870_setup(ahc);
219565942Sgibbs	if (error == 0)
219679874Sgibbs		error = ahc_aha394XX_setup(ahc);
219765942Sgibbs	return (error);
219865942Sgibbs}
219965942Sgibbs
220065942Sgibbsstatic int
220179874Sgibbsahc_aha398X_setup(struct ahc_softc *ahc)
220265942Sgibbs{
220365942Sgibbs	int error;
220465942Sgibbs
220579874Sgibbs	error = ahc_aic7870_setup(ahc);
220665942Sgibbs	if (error == 0)
220779874Sgibbs		error = ahc_aha398XX_setup(ahc);
220865942Sgibbs	return (error);
220965942Sgibbs}
221065942Sgibbs
221165942Sgibbsstatic int
221279874Sgibbsahc_aha494X_setup(struct ahc_softc *ahc)
221365942Sgibbs{
221465942Sgibbs	int error;
221565942Sgibbs
221679874Sgibbs	error = ahc_aic7870_setup(ahc);
221765942Sgibbs	if (error == 0)
221879874Sgibbs		error = ahc_aha494XX_setup(ahc);
221965942Sgibbs	return (error);
222065942Sgibbs}
222165942Sgibbs
222265942Sgibbsstatic int
222379874Sgibbsahc_aic7880_setup(struct ahc_softc *ahc)
222465942Sgibbs{
222579874Sgibbs	ahc_dev_softc_t pci;
222665942Sgibbs	uint8_t rev;
222765942Sgibbs
222879874Sgibbs	pci = ahc->dev_softc;
222979874Sgibbs	ahc->channel = 'A';
223079874Sgibbs	ahc->chip = AHC_AIC7880;
223179874Sgibbs	ahc->features = AHC_AIC7880_FE;
223279874Sgibbs	ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
223365942Sgibbs	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
223465942Sgibbs	if (rev >= 1) {
223579874Sgibbs		ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
223665942Sgibbs	} else {
223779874Sgibbs		ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
223865942Sgibbs	}
2239114621Sgibbs	ahc->instruction_ram_size = 512;
224065942Sgibbs	return (0);
224165942Sgibbs}
224265942Sgibbs
224365942Sgibbsstatic int
224479874Sgibbsahc_aha2940Pro_setup(struct ahc_softc *ahc)
224565942Sgibbs{
224665942Sgibbs
224779874Sgibbs	ahc->flags |= AHC_INT50_SPEEDFLEX;
2248102676Sgibbs	return (ahc_aic7880_setup(ahc));
224965942Sgibbs}
225065942Sgibbs
225165942Sgibbsstatic int
225279874Sgibbsahc_aha394XU_setup(struct ahc_softc *ahc)
225365942Sgibbs{
225465942Sgibbs	int error;
225565942Sgibbs
225679874Sgibbs	error = ahc_aic7880_setup(ahc);
225765942Sgibbs	if (error == 0)
225879874Sgibbs		error = ahc_aha394XX_setup(ahc);
225965942Sgibbs	return (error);
226065942Sgibbs}
226165942Sgibbs
226265942Sgibbsstatic int
226379874Sgibbsahc_aha398XU_setup(struct ahc_softc *ahc)
226465942Sgibbs{
226565942Sgibbs	int error;
226665942Sgibbs
226779874Sgibbs	error = ahc_aic7880_setup(ahc);
226865942Sgibbs	if (error == 0)
226979874Sgibbs		error = ahc_aha398XX_setup(ahc);
227065942Sgibbs	return (error);
227165942Sgibbs}
227265942Sgibbs
227365942Sgibbsstatic int
227479874Sgibbsahc_aic7890_setup(struct ahc_softc *ahc)
227565942Sgibbs{
227679874Sgibbs	ahc_dev_softc_t pci;
227765942Sgibbs	uint8_t rev;
227865942Sgibbs
227979874Sgibbs	pci = ahc->dev_softc;
228079874Sgibbs	ahc->channel = 'A';
228179874Sgibbs	ahc->chip = AHC_AIC7890;
228279874Sgibbs	ahc->features = AHC_AIC7890_FE;
228379874Sgibbs	ahc->flags |= AHC_NEWEEPROM_FMT;
228465942Sgibbs	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
228565942Sgibbs	if (rev == 0)
228679874Sgibbs		ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG;
2287114621Sgibbs	ahc->instruction_ram_size = 768;
228865942Sgibbs	return (0);
228965942Sgibbs}
229065942Sgibbs
229165942Sgibbsstatic int
229279874Sgibbsahc_aic7892_setup(struct ahc_softc *ahc)
229365942Sgibbs{
229479874Sgibbs
229579874Sgibbs	ahc->channel = 'A';
229679874Sgibbs	ahc->chip = AHC_AIC7892;
229779874Sgibbs	ahc->features = AHC_AIC7892_FE;
229879874Sgibbs	ahc->flags |= AHC_NEWEEPROM_FMT;
229979874Sgibbs	ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
2300114621Sgibbs	ahc->instruction_ram_size = 1024;
230165942Sgibbs	return (0);
230265942Sgibbs}
230365942Sgibbs
230465942Sgibbsstatic int
230579874Sgibbsahc_aic7895_setup(struct ahc_softc *ahc)
230665942Sgibbs{
230779874Sgibbs	ahc_dev_softc_t pci;
230865942Sgibbs	uint8_t rev;
230965942Sgibbs
231079874Sgibbs	pci = ahc->dev_softc;
231179874Sgibbs	ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
231265942Sgibbs	/*
231365942Sgibbs	 * The 'C' revision of the aic7895 has a few additional features.
231465942Sgibbs	 */
231565942Sgibbs	rev = ahc_pci_read_config(pci, PCIR_REVID, /*bytes*/1);
231665942Sgibbs	if (rev >= 4) {
231779874Sgibbs		ahc->chip = AHC_AIC7895C;
231879874Sgibbs		ahc->features = AHC_AIC7895C_FE;
231965942Sgibbs	} else  {
232065942Sgibbs		u_int command;
232165942Sgibbs
232279874Sgibbs		ahc->chip = AHC_AIC7895;
232379874Sgibbs		ahc->features = AHC_AIC7895_FE;
232465942Sgibbs
232565942Sgibbs		/*
232665942Sgibbs		 * The BIOS disables the use of MWI transactions
232765942Sgibbs		 * since it does not have the MWI bug work around
232865942Sgibbs		 * we have.  Disabling MWI reduces performance, so
232965942Sgibbs		 * turn it on again.
233065942Sgibbs		 */
233165942Sgibbs		command = ahc_pci_read_config(pci, PCIR_COMMAND, /*bytes*/1);
233265942Sgibbs		command |= PCIM_CMD_MWRICEN;
233365942Sgibbs		ahc_pci_write_config(pci, PCIR_COMMAND, command, /*bytes*/1);
233479874Sgibbs		ahc->bugs |= AHC_PCI_MWI_BUG;
233565942Sgibbs	}
233665942Sgibbs	/*
233765942Sgibbs	 * XXX Does CACHETHEN really not work???  What about PCI retry?
233865942Sgibbs	 * on C level chips.  Need to test, but for now, play it safe.
233965942Sgibbs	 */
234079874Sgibbs	ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG
234179874Sgibbs		  |  AHC_CACHETHEN_BUG;
234265942Sgibbs
234365942Sgibbs#if 0
234465942Sgibbs	uint32_t devconfig;
234565942Sgibbs
234665942Sgibbs	/*
234765942Sgibbs	 * Cachesize must also be zero due to stray DAC
234865942Sgibbs	 * problem when sitting behind some bridges.
234965942Sgibbs	 */
235065942Sgibbs	ahc_pci_write_config(pci, CSIZE_LATTIME, 0, /*bytes*/1);
235165942Sgibbs	devconfig = ahc_pci_read_config(pci, DEVCONFIG, /*bytes*/1);
235265942Sgibbs	devconfig |= MRDCEN;
235365942Sgibbs	ahc_pci_write_config(pci, DEVCONFIG, devconfig, /*bytes*/1);
235465942Sgibbs#endif
235579874Sgibbs	ahc->flags |= AHC_NEWEEPROM_FMT;
2356114621Sgibbs	ahc->instruction_ram_size = 512;
235765942Sgibbs	return (0);
235865942Sgibbs}
235965942Sgibbs
236065942Sgibbsstatic int
236179874Sgibbsahc_aic7896_setup(struct ahc_softc *ahc)
236265942Sgibbs{
236379874Sgibbs	ahc_dev_softc_t pci;
236479874Sgibbs
236579874Sgibbs	pci = ahc->dev_softc;
236679874Sgibbs	ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
236779874Sgibbs	ahc->chip = AHC_AIC7896;
236879874Sgibbs	ahc->features = AHC_AIC7896_FE;
236979874Sgibbs	ahc->flags |= AHC_NEWEEPROM_FMT;
237079874Sgibbs	ahc->bugs |= AHC_CACHETHEN_DIS_BUG;
2371114621Sgibbs	ahc->instruction_ram_size = 768;
237265942Sgibbs	return (0);
237365942Sgibbs}
237465942Sgibbs
237565942Sgibbsstatic int
237679874Sgibbsahc_aic7899_setup(struct ahc_softc *ahc)
237765942Sgibbs{
237879874Sgibbs	ahc_dev_softc_t pci;
237979874Sgibbs
238079874Sgibbs	pci = ahc->dev_softc;
238179874Sgibbs	ahc->channel = ahc_get_pci_function(pci) == 1 ? 'B' : 'A';
238279874Sgibbs	ahc->chip = AHC_AIC7899;
238379874Sgibbs	ahc->features = AHC_AIC7899_FE;
238479874Sgibbs	ahc->flags |= AHC_NEWEEPROM_FMT;
238579874Sgibbs	ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
2386114621Sgibbs	ahc->instruction_ram_size = 1024;
238765942Sgibbs	return (0);
238865942Sgibbs}
238965942Sgibbs
239065942Sgibbsstatic int
239179874Sgibbsahc_aha29160C_setup(struct ahc_softc *ahc)
239271390Sgibbs{
239371390Sgibbs	int error;
239471390Sgibbs
239579874Sgibbs	error = ahc_aic7899_setup(ahc);
239671390Sgibbs	if (error != 0)
239771390Sgibbs		return (error);
239879874Sgibbs	ahc->features |= AHC_REMOVABLE;
239971390Sgibbs	return (0);
240071390Sgibbs}
240171390Sgibbs
240271390Sgibbsstatic int
240379874Sgibbsahc_raid_setup(struct ahc_softc *ahc)
240465942Sgibbs{
240565942Sgibbs	printf("RAID functionality unsupported\n");
240665942Sgibbs	return (ENXIO);
240765942Sgibbs}
240865942Sgibbs
240965942Sgibbsstatic int
241079874Sgibbsahc_aha394XX_setup(struct ahc_softc *ahc)
241165942Sgibbs{
241279874Sgibbs	ahc_dev_softc_t pci;
241379874Sgibbs
241479874Sgibbs	pci = ahc->dev_softc;
241565942Sgibbs	switch (ahc_get_pci_slot(pci)) {
241665942Sgibbs	case AHC_394X_SLOT_CHANNEL_A:
241779874Sgibbs		ahc->channel = 'A';
241865942Sgibbs		break;
241965942Sgibbs	case AHC_394X_SLOT_CHANNEL_B:
242079874Sgibbs		ahc->channel = 'B';
242165942Sgibbs		break;
242265942Sgibbs	default:
242365942Sgibbs		printf("adapter at unexpected slot %d\n"
242465942Sgibbs		       "unable to map to a channel\n",
242565942Sgibbs		       ahc_get_pci_slot(pci));
242679874Sgibbs		ahc->channel = 'A';
242765942Sgibbs	}
242865942Sgibbs	return (0);
242965942Sgibbs}
243065942Sgibbs
243165942Sgibbsstatic int
243279874Sgibbsahc_aha398XX_setup(struct ahc_softc *ahc)
243365942Sgibbs{
243479874Sgibbs	ahc_dev_softc_t pci;
243579874Sgibbs
243679874Sgibbs	pci = ahc->dev_softc;
243765942Sgibbs	switch (ahc_get_pci_slot(pci)) {
243865942Sgibbs	case AHC_398X_SLOT_CHANNEL_A:
243979874Sgibbs		ahc->channel = 'A';
244065942Sgibbs		break;
244165942Sgibbs	case AHC_398X_SLOT_CHANNEL_B:
244279874Sgibbs		ahc->channel = 'B';
244365942Sgibbs		break;
244465942Sgibbs	case AHC_398X_SLOT_CHANNEL_C:
244579874Sgibbs		ahc->channel = 'C';
244665942Sgibbs		break;
244765942Sgibbs	default:
244865942Sgibbs		printf("adapter at unexpected slot %d\n"
244965942Sgibbs		       "unable to map to a channel\n",
245065942Sgibbs		       ahc_get_pci_slot(pci));
245179874Sgibbs		ahc->channel = 'A';
245265942Sgibbs		break;
245365942Sgibbs	}
245479874Sgibbs	ahc->flags |= AHC_LARGE_SEEPROM;
245565942Sgibbs	return (0);
245665942Sgibbs}
245765942Sgibbs
245865942Sgibbsstatic int
245979874Sgibbsahc_aha494XX_setup(struct ahc_softc *ahc)
246065942Sgibbs{
246179874Sgibbs	ahc_dev_softc_t pci;
246279874Sgibbs
246379874Sgibbs	pci = ahc->dev_softc;
246465942Sgibbs	switch (ahc_get_pci_slot(pci)) {
246565942Sgibbs	case AHC_494X_SLOT_CHANNEL_A:
246679874Sgibbs		ahc->channel = 'A';
246765942Sgibbs		break;
246865942Sgibbs	case AHC_494X_SLOT_CHANNEL_B:
246979874Sgibbs		ahc->channel = 'B';
247065942Sgibbs		break;
247165942Sgibbs	case AHC_494X_SLOT_CHANNEL_C:
247279874Sgibbs		ahc->channel = 'C';
247365942Sgibbs		break;
247465942Sgibbs	case AHC_494X_SLOT_CHANNEL_D:
247579874Sgibbs		ahc->channel = 'D';
247665942Sgibbs		break;
247765942Sgibbs	default:
247865942Sgibbs		printf("adapter at unexpected slot %d\n"
247965942Sgibbs		       "unable to map to a channel\n",
248065942Sgibbs		       ahc_get_pci_slot(pci));
248179874Sgibbs		ahc->channel = 'A';
248265942Sgibbs	}
248379874Sgibbs	ahc->flags |= AHC_LARGE_SEEPROM;
248465942Sgibbs	return (0);
248565942Sgibbs}
2486