summaryrefslogtreecommitdiff
path: root/sys/dev/pci/ahc_pci.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/dev/pci/ahc_pci.c')
-rw-r--r--sys/dev/pci/ahc_pci.c2387
1 files changed, 1198 insertions, 1189 deletions
diff --git a/sys/dev/pci/ahc_pci.c b/sys/dev/pci/ahc_pci.c
index 3e17732547c..b15714f84a0 100644
--- a/sys/dev/pci/ahc_pci.c
+++ b/sys/dev/pci/ahc_pci.c
@@ -1,87 +1,597 @@
-/* $OpenBSD: ahc_pci.c,v 1.41 2003/09/25 07:11:15 deraadt Exp $ */
-/* $NetBSD: ahc_pci.c,v 1.9 1996/10/21 22:56:24 thorpej Exp $ */
-
+/* $OpenBSD: ahc_pci.c,v 1.42 2003/12/24 22:45:45 krw Exp $ */
/*
* Product specific probe and attach routines for:
- * 3940, 2940, aic7880, aic7870, aic7860 and aic7850 SCSI controllers
+ * 3940, 2940, aic7895, aic7890, aic7880,
+ * aic7870, aic7860 and aic7850 SCSI controllers
*
- * Copyright (c) 1995, 1996 Justin T. Gibbs.
+ * Copyright (c) 1994-2001 Justin T. Gibbs.
+ * Copyright (c) 2000-2001 Adaptec Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
- * notice immediately at the beginning of the file, without modification,
- * this list of conditions, and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * notice, this list of conditions, and the following disclaimer,
+ * without modification.
+ * 2. Redistributions in binary form must reproduce at minimum a disclaimer
+ * substantially similar to the "NO WARRANTY" disclaimer below
+ * ("Disclaimer") and any redistribution must be conditioned upon
+ * including a substantially similar Disclaimer requirement for further
+ * binary redistribution.
+ * 3. Neither the names of the above-listed copyright holders nor the names
+ * of any contributors may be used to endorse or promote products derived
+ * from this software without specific prior written permission.
+ *
+ * Alternatively, this software may be distributed under the terms of the
+ * GNU General Public License ("GPL") version 2 as published by the Free
+ * Software Foundation.
*
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE FOR
- * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * NO WARRANTY
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ * POSSIBILITY OF SUCH DAMAGES.
+ *
+ * $Id: ahc_pci.c,v 1.42 2003/12/24 22:45:45 krw Exp $
+ *
+ * //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#57 $
+ *
+ * $FreeBSD: /repoman/r/ncvs/src/sys/dev/aic7xxx/aic7xxx_pci.c,v 1.22 2003/01/20 20:44:55 gibbs Exp $
+ */
+/*
+ * Ported from FreeBSD by Pascal Renauld, Network Storage Solutions, Inc. - April 2003
*/
+#include <sys/cdefs.h>
+/* __KERNEL_RCSID(0, "$NetBSD: ahc_pci.c,v 1.43 2003/08/18 09:16:22 taca Exp $"); */
+
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/queue.h>
#include <sys/device.h>
+#include <sys/reboot.h>
+
#include <machine/bus.h>
#include <machine/intr.h>
-#include <scsi/scsi_all.h>
-#include <scsi/scsiconf.h>
-
#include <dev/pci/pcireg.h>
#include <dev/pci/pcivar.h>
-#include <dev/pci/pcidevs.h>
#define AHC_PCI_IOADDR PCI_MAPREG_START /* I/O Address */
#define AHC_PCI_MEMADDR (PCI_MAPREG_START + 4) /* Mem I/O Address */
-#include <dev/ic/aic7xxxreg.h>
#include <dev/ic/aic7xxx_openbsd.h>
#include <dev/ic/aic7xxx_inline.h>
+
#include <dev/ic/smc93cx6var.h>
-/*
- * XXX memory-mapped is busted on some i386 on-board chips.
- * for i386, we don't even try it. Also, suppress the damn
- * PCI bus errors messages on i386. They are not fatal, and are
- * usually caused by some other device on the PCI bus. But some
- * ahc cards won't work without ACKing them. So just ACK and go!
- * XXX- smurph
- */
-#ifndef i386
-#define AHC_ALLOW_MEMIO
-#define AHC_SHOW_PCI_ERRORS
-#endif
+static __inline uint64_t
+ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
+{
+ uint64_t id;
+
+ id = subvendor
+ | (subdevice << 16)
+ | ((uint64_t)vendor << 32)
+ | ((uint64_t)device << 48);
+
+ return (id);
+}
+
+#define ID_ALL_MASK 0xFFFFFFFFFFFFFFFFull
+#define ID_DEV_VENDOR_MASK 0xFFFFFFFF00000000ull
+#define ID_9005_GENERIC_MASK 0xFFF0FFFF00000000ull
+#define ID_9005_SISL_MASK 0x000FFFFF00000000ull
+#define ID_9005_SISL_ID 0x0005900500000000ull
+#define ID_AIC7850 0x5078900400000000ull
+#define ID_AHA_2902_04_10_15_20_30C 0x5078900478509004ull
+#define ID_AIC7855 0x5578900400000000ull
+#define ID_AIC7859 0x3860900400000000ull
+#define ID_AHA_2930CU 0x3860900438699004ull
+#define ID_AIC7860 0x6078900400000000ull
+#define ID_AIC7860C 0x6078900478609004ull
+#define ID_AHA_1480A 0x6075900400000000ull
+#define ID_AHA_2940AU_0 0x6178900400000000ull
+#define ID_AHA_2940AU_1 0x6178900478619004ull
+#define ID_AHA_2940AU_CN 0x2178900478219004ull
+#define ID_AHA_2930C_VAR 0x6038900438689004ull
+
+#define ID_AIC7870 0x7078900400000000ull
+#define ID_AHA_2940 0x7178900400000000ull
+#define ID_AHA_3940 0x7278900400000000ull
+#define ID_AHA_398X 0x7378900400000000ull
+#define ID_AHA_2944 0x7478900400000000ull
+#define ID_AHA_3944 0x7578900400000000ull
+#define ID_AHA_4944 0x7678900400000000ull
+
+#define ID_AIC7880 0x8078900400000000ull
+#define ID_AIC7880_B 0x8078900478809004ull
+#define ID_AHA_2940U 0x8178900400000000ull
+#define ID_AHA_3940U 0x8278900400000000ull
+#define ID_AHA_2944U 0x8478900400000000ull
+#define ID_AHA_3944U 0x8578900400000000ull
+#define ID_AHA_398XU 0x8378900400000000ull
+#define ID_AHA_4944U 0x8678900400000000ull
+#define ID_AHA_2940UB 0x8178900478819004ull
+#define ID_AHA_2930U 0x8878900478889004ull
+#define ID_AHA_2940U_PRO 0x8778900478879004ull
+#define ID_AHA_2940U_CN 0x0078900478009004ull
+
+#define ID_AIC7895 0x7895900478959004ull
+#define ID_AIC7895_ARO 0x7890900478939004ull
+#define ID_AIC7895_ARO_MASK 0xFFF0FFFFFFFFFFFFull
+#define ID_AHA_2940U_DUAL 0x7895900478919004ull
+#define ID_AHA_3940AU 0x7895900478929004ull
+#define ID_AHA_3944AU 0x7895900478949004ull
+
+#define ID_AIC7890 0x001F9005000F9005ull
+#define ID_AIC7890_ARO 0x00139005000F9005ull
+#define ID_AAA_131U2 0x0013900500039005ull
+#define ID_AHA_2930U2 0x0011900501819005ull
+#define ID_AHA_2940U2B 0x00109005A1009005ull
+#define ID_AHA_2940U2_OEM 0x0010900521809005ull
+#define ID_AHA_2940U2 0x00109005A1809005ull
+#define ID_AHA_2950U2B 0x00109005E1009005ull
+
+#define ID_AIC7892 0x008F9005FFFF9005ull
+#define ID_AIC7892_ARO 0x00839005FFFF9005ull
+#define ID_AHA_2915LP 0x0082900502109005ull
+#define ID_AHA_29160 0x00809005E2A09005ull
+#define ID_AHA_29160_CPQ 0x00809005E2A00E11ull
+#define ID_AHA_29160N 0x0080900562A09005ull
+#define ID_AHA_29160C 0x0080900562209005ull
+#define ID_AHA_29160B 0x00809005E2209005ull
+#define ID_AHA_19160B 0x0081900562A19005ull
+
+#define ID_AIC7896 0x005F9005FFFF9005ull
+#define ID_AIC7896_ARO 0x00539005FFFF9005ull
+#define ID_AHA_3950U2B_0 0x00509005FFFF9005ull
+#define ID_AHA_3950U2B_1 0x00509005F5009005ull
+#define ID_AHA_3950U2D_0 0x00519005FFFF9005ull
+#define ID_AHA_3950U2D_1 0x00519005B5009005ull
+
+#define ID_AIC7899 0x00CF9005FFFF9005ull
+#define ID_AIC7899_ARO 0x00C39005FFFF9005ull
+#define ID_AHA_3960D 0x00C09005F6209005ull
+#define ID_AHA_3960D_CPQ 0x00C09005F6200E11ull
+
+#define ID_AIC7810 0x1078900400000000ull
+#define ID_AIC7815 0x7815900400000000ull
+
+#define DEVID_9005_TYPE(id) ((id) & 0xF)
+#define DEVID_9005_TYPE_HBA 0x0 /* Standard Card */
+#define DEVID_9005_TYPE_AAA 0x3 /* RAID Card */
+#define DEVID_9005_TYPE_SISL 0x5 /* Container ROMB */
+#define DEVID_9005_TYPE_MB 0xF /* On Motherboard */
+
+#define DEVID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
+#define DEVID_9005_MAXRATE_U160 0x0
+#define DEVID_9005_MAXRATE_ULTRA2 0x1
+#define DEVID_9005_MAXRATE_ULTRA 0x2
+#define DEVID_9005_MAXRATE_FAST 0x3
+
+#define DEVID_9005_MFUNC(id) (((id) & 0x40) >> 6)
+
+#define DEVID_9005_CLASS(id) (((id) & 0xFF00) >> 8)
+#define DEVID_9005_CLASS_SPI 0x0 /* Parallel SCSI */
+
+#define SUBID_9005_TYPE(id) ((id) & 0xF)
+#define SUBID_9005_TYPE_MB 0xF /* On Motherboard */
+#define SUBID_9005_TYPE_CARD 0x0 /* Standard Card */
+#define SUBID_9005_TYPE_LCCARD 0x1 /* Low Cost Card */
+#define SUBID_9005_TYPE_RAID 0x3 /* Combined with Raid */
+
+#define SUBID_9005_TYPE_KNOWN(id) \
+ ((((id) & 0xF) == SUBID_9005_TYPE_MB) \
+ || (((id) & 0xF) == SUBID_9005_TYPE_CARD) \
+ || (((id) & 0xF) == SUBID_9005_TYPE_LCCARD) \
+ || (((id) & 0xF) == SUBID_9005_TYPE_RAID))
+
+#define SUBID_9005_MAXRATE(id) (((id) & 0x30) >> 4)
+#define SUBID_9005_MAXRATE_ULTRA2 0x0
+#define SUBID_9005_MAXRATE_ULTRA 0x1
+#define SUBID_9005_MAXRATE_U160 0x2
+#define SUBID_9005_MAXRATE_RESERVED 0x3
+
+#define SUBID_9005_SEEPTYPE(id) \
+ ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \
+ ? ((id) & 0xC0) >> 6 \
+ : ((id) & 0x300) >> 8)
+#define SUBID_9005_SEEPTYPE_NONE 0x0
+#define SUBID_9005_SEEPTYPE_1K 0x1
+#define SUBID_9005_SEEPTYPE_2K_4K 0x2
+#define SUBID_9005_SEEPTYPE_RESERVED 0x3
+#define SUBID_9005_AUTOTERM(id) \
+ ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \
+ ? (((id) & 0x400) >> 10) == 0 \
+ : (((id) & 0x40) >> 6) == 0)
+
+#define SUBID_9005_NUMCHAN(id) \
+ ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \
+ ? ((id) & 0x300) >> 8 \
+ : ((id) & 0xC00) >> 10)
+
+#define SUBID_9005_LEGACYCONN(id) \
+ ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \
+ ? 0 \
+ : ((id) & 0x80) >> 7)
+
+#define SUBID_9005_MFUNCENB(id) \
+ ((SUBID_9005_TYPE(id) == SUBID_9005_TYPE_MB) \
+ ? ((id) & 0x800) >> 11 \
+ : ((id) & 0x1000) >> 12)
/*
- * Under normal circumstances, these messages are unnecessary
- * and not terribly cosmetic.
+ * Informational only. Should use chip register to be
+ * certain, but may be use in identification strings.
*/
-#ifdef DEBUG
-#define bootverbose 1
-#else
-#define bootverbose 0
-#endif
-
-#define PCI_BASEADR0 PCI_MAPREG_START
+#define SUBID_9005_CARD_SCSIWIDTH_MASK 0x2000
+#define SUBID_9005_CARD_PCIWIDTH_MASK 0x4000
+#define SUBID_9005_CARD_SEDIFF_MASK 0x8000
+
+static ahc_device_setup_t ahc_aic785X_setup;
+static ahc_device_setup_t ahc_aic7860_setup;
+static ahc_device_setup_t ahc_apa1480_setup;
+static ahc_device_setup_t ahc_aic7870_setup;
+static ahc_device_setup_t ahc_aha394X_setup;
+static ahc_device_setup_t ahc_aha494X_setup;
+static ahc_device_setup_t ahc_aha398X_setup;
+static ahc_device_setup_t ahc_aic7880_setup;
+static ahc_device_setup_t ahc_aha2940Pro_setup;
+static ahc_device_setup_t ahc_aha394XU_setup;
+static ahc_device_setup_t ahc_aha398XU_setup;
+static ahc_device_setup_t ahc_aic7890_setup;
+static ahc_device_setup_t ahc_aic7892_setup;
+static ahc_device_setup_t ahc_aic7895_setup;
+static ahc_device_setup_t ahc_aic7896_setup;
+static ahc_device_setup_t ahc_aic7899_setup;
+static ahc_device_setup_t ahc_aha29160C_setup;
+static ahc_device_setup_t ahc_raid_setup;
+static ahc_device_setup_t ahc_aha394XX_setup;
+static ahc_device_setup_t ahc_aha494XX_setup;
+static ahc_device_setup_t ahc_aha398XX_setup;
+
+struct ahc_pci_identity ahc_pci_ident_table [] =
+{
+ /* aic7850 based controllers */
+ {
+ ID_AHA_2902_04_10_15_20_30C,
+ ID_ALL_MASK,
+ ahc_aic785X_setup
+ },
+ /* aic7860 based controllers */
+ {
+ ID_AHA_2930CU,
+ ID_ALL_MASK,
+ ahc_aic7860_setup
+ },
+ {
+ ID_AHA_1480A & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_apa1480_setup
+ },
+ {
+ ID_AHA_2940AU_0 & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7860_setup
+ },
+ {
+ ID_AHA_2940AU_CN & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7860_setup
+ },
+ {
+ ID_AHA_2930C_VAR & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7860_setup
+ },
+ /* aic7870 based controllers */
+ {
+ ID_AHA_2940,
+ ID_ALL_MASK,
+ ahc_aic7870_setup
+ },
+ {
+ ID_AHA_3940,
+ ID_ALL_MASK,
+ ahc_aha394X_setup
+ },
+ {
+ ID_AHA_398X,
+ ID_ALL_MASK,
+ ahc_aha398X_setup
+ },
+ {
+ ID_AHA_2944,
+ ID_ALL_MASK,
+ ahc_aic7870_setup
+ },
+ {
+ ID_AHA_3944,
+ ID_ALL_MASK,
+ ahc_aha394X_setup
+ },
+ {
+ ID_AHA_4944,
+ ID_ALL_MASK,
+ ahc_aha494X_setup
+ },
+ /* aic7880 based controllers */
+ {
+ ID_AHA_2940U & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7880_setup
+ },
+ {
+ ID_AHA_3940U & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aha394XU_setup
+ },
+ {
+ ID_AHA_2944U & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7880_setup
+ },
+ {
+ ID_AHA_3944U & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aha394XU_setup
+ },
+ {
+ ID_AHA_398XU & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aha398XU_setup
+ },
+ {
+ /*
+ * XXX Don't know the slot numbers
+ * so we can't identify channels
+ */
+ ID_AHA_4944U & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7880_setup
+ },
+ {
+ ID_AHA_2930U & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7880_setup
+ },
+ {
+ ID_AHA_2940U_PRO & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aha2940Pro_setup
+ },
+ {
+ ID_AHA_2940U_CN & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7880_setup
+ },
+ /* Ignore all SISL (AAC on MB) based controllers. */
+ {
+ ID_9005_SISL_ID,
+ ID_9005_SISL_MASK,
+ NULL
+ },
+ /* aic7890 based controllers */
+ {
+ ID_AHA_2930U2,
+ ID_ALL_MASK,
+ ahc_aic7890_setup
+ },
+ {
+ ID_AHA_2940U2B,
+ ID_ALL_MASK,
+ ahc_aic7890_setup
+ },
+ {
+ ID_AHA_2940U2_OEM,
+ ID_ALL_MASK,
+ ahc_aic7890_setup
+ },
+ {
+ ID_AHA_2940U2,
+ ID_ALL_MASK,
+ ahc_aic7890_setup
+ },
+ {
+ ID_AHA_2950U2B,
+ ID_ALL_MASK,
+ ahc_aic7890_setup
+ },
+ {
+ ID_AIC7890_ARO,
+ ID_ALL_MASK,
+ ahc_aic7890_setup
+ },
+ {
+ ID_AAA_131U2,
+ ID_ALL_MASK,
+ ahc_aic7890_setup
+ },
+ /* aic7892 based controllers */
+ {
+ ID_AHA_29160,
+ ID_ALL_MASK,
+ ahc_aic7892_setup
+ },
+ {
+ ID_AHA_29160_CPQ,
+ ID_ALL_MASK,
+ ahc_aic7892_setup
+ },
+ {
+ ID_AHA_29160N,
+ ID_ALL_MASK,
+ ahc_aic7892_setup
+ },
+ {
+ ID_AHA_29160C,
+ ID_ALL_MASK,
+ ahc_aha29160C_setup
+ },
+ {
+ ID_AHA_29160B,
+ ID_ALL_MASK,
+ ahc_aic7892_setup
+ },
+ {
+ ID_AHA_19160B,
+ ID_ALL_MASK,
+ ahc_aic7892_setup
+ },
+ {
+ ID_AIC7892_ARO,
+ ID_ALL_MASK,
+ ahc_aic7892_setup
+ },
+ {
+ ID_AHA_2915LP,
+ ID_ALL_MASK,
+ ahc_aic7892_setup
+ },
+ /* aic7895 based controllers */
+ {
+ ID_AHA_2940U_DUAL,
+ ID_ALL_MASK,
+ ahc_aic7895_setup
+ },
+ {
+ ID_AHA_3940AU,
+ ID_ALL_MASK,
+ ahc_aic7895_setup
+ },
+ {
+ ID_AHA_3944AU,
+ ID_ALL_MASK,
+ ahc_aic7895_setup
+ },
+ {
+ ID_AIC7895_ARO,
+ ID_AIC7895_ARO_MASK,
+ ahc_aic7895_setup
+ },
+ /* aic7896/97 based controllers */
+ {
+ ID_AHA_3950U2B_0,
+ ID_ALL_MASK,
+ ahc_aic7896_setup
+ },
+ {
+ ID_AHA_3950U2B_1,
+ ID_ALL_MASK,
+ ahc_aic7896_setup
+ },
+ {
+ ID_AHA_3950U2D_0,
+ ID_ALL_MASK,
+ ahc_aic7896_setup
+ },
+ {
+ ID_AHA_3950U2D_1,
+ ID_ALL_MASK,
+ ahc_aic7896_setup
+ },
+ {
+ ID_AIC7896_ARO,
+ ID_ALL_MASK,
+ ahc_aic7896_setup
+ },
+ /* aic7899 based controllers */
+ {
+ ID_AHA_3960D,
+ ID_ALL_MASK,
+ ahc_aic7899_setup
+ },
+ {
+ ID_AHA_3960D_CPQ,
+ ID_ALL_MASK,
+ ahc_aic7899_setup
+ },
+ {
+ ID_AIC7899_ARO,
+ ID_ALL_MASK,
+ ahc_aic7899_setup
+ },
+ /* Generic chip probes for devices we don't know 'exactly' */
+ {
+ ID_AIC7850 & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic785X_setup
+ },
+ {
+ ID_AIC7855 & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic785X_setup
+ },
+ {
+ ID_AIC7859 & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7860_setup
+ },
+ {
+ ID_AIC7860 & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7860_setup
+ },
+ {
+ ID_AIC7870 & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7870_setup
+ },
+ {
+ ID_AIC7880 & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7880_setup
+ },
+ {
+ ID_AIC7890 & ID_9005_GENERIC_MASK,
+ ID_9005_GENERIC_MASK,
+ ahc_aic7890_setup
+ },
+ {
+ ID_AIC7892 & ID_9005_GENERIC_MASK,
+ ID_9005_GENERIC_MASK,
+ ahc_aic7892_setup
+ },
+ {
+ ID_AIC7895 & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_aic7895_setup
+ },
+ {
+ ID_AIC7896 & ID_9005_GENERIC_MASK,
+ ID_9005_GENERIC_MASK,
+ ahc_aic7896_setup
+ },
+ {
+ ID_AIC7899 & ID_9005_GENERIC_MASK,
+ ID_9005_GENERIC_MASK,
+ ahc_aic7899_setup
+ },
+ {
+ ID_AIC7810 & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_raid_setup
+ },
+ {
+ ID_AIC7815 & ID_DEV_VENDOR_MASK,
+ ID_DEV_VENDOR_MASK,
+ ahc_raid_setup
+ }
+};
+const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table);
+
#define AHC_394X_SLOT_CHANNEL_A 4
#define AHC_394X_SLOT_CHANNEL_B 5
@@ -89,425 +599,201 @@
#define AHC_398X_SLOT_CHANNEL_B 8
#define AHC_398X_SLOT_CHANNEL_C 12
-#define EXROMBADR 0x30
-#define EXROMEN 0x00000001UL /* External Rom Enable */
+#define AHC_494X_SLOT_CHANNEL_A 4
+#define AHC_494X_SLOT_CHANNEL_B 5
+#define AHC_494X_SLOT_CHANNEL_C 6
+#define AHC_494X_SLOT_CHANNEL_D 7
#define DEVCONFIG 0x40
-#define SCBSIZE32 0x00010000UL /* aic789X only */
-#define REXTVALID 0x00001000UL /* ultra cards only */
-#define MPORTMODE 0x00000400UL /* aic7870+ only */
-#define RAMPSM 0x00000200UL /* aic7870+ only */
-#define VOLSENSE 0x00000100UL
-#define PCI64BIT 0x00000080UL /* 64Bit PCI bus (Ultra2 Only)*/
-#define SCBRAMSEL 0x00000080UL
-#define MRDCEN 0x00000040UL
-#define EXTSCBTIME 0x00000020UL /* aic7870 only */
-#define EXTSCBPEN 0x00000010UL /* aic7870 only */
-#define BERREN 0x00000008UL
-#define DACEN 0x00000004UL
-#define STPWLEVEL 0x00000002UL
-#define DIFACTNEGEN 0x00000001UL /* aic7870 only */
+#define PCIERRGENDIS 0x80000000ul
+#define SCBSIZE32 0x00010000ul /* aic789X only */
+#define REXTVALID 0x00001000ul /* ultra cards only */
+#define MPORTMODE 0x00000400ul /* aic7870+ only */
+#define RAMPSM 0x00000200ul /* aic7870+ only */
+#define VOLSENSE 0x00000100ul
+#define PCI64BIT 0x00000080ul /* 64Bit PCI bus (Ultra2 Only)*/
+#define SCBRAMSEL 0x00000080ul
+#define MRDCEN 0x00000040ul
+#define EXTSCBTIME 0x00000020ul /* aic7870 only */
+#define EXTSCBPEN 0x00000010ul /* aic7870 only */
+#define BERREN 0x00000008ul
+#define DACEN 0x00000004ul
+#define STPWLEVEL 0x00000002ul
+#define DIFACTNEGEN 0x00000001ul /* aic7870 only */
#define CSIZE_LATTIME 0x0c
-#define CACHESIZE 0x0000003fUL /* only 5 bits */
-#define LATTIME 0x0000ff00UL
-
-static int ahc_ext_scbram_present(struct ahc_softc *ahc);
+#define CACHESIZE 0x0000003ful /* only 5 bits */
+#define LATTIME 0x0000ff00ul
+
+/* PCI STATUS definitions */
+#define DPE 0x80
+#define SSE 0x40
+#define RMA 0x20
+#define RTA 0x10
+#define STA 0x08
+#define DPR 0x01
+
+static int ahc_9005_subdevinfo_valid(uint16_t vendor, uint16_t device,
+ uint16_t subvendor, uint16_t subdevice);
+static int ahc_ext_scbram_present(struct ahc_softc *ahc);
static void ahc_scbram_config(struct ahc_softc *ahc, int enable,
int pcheck, int fast, int large);
static void ahc_probe_ext_scbram(struct ahc_softc *ahc);
-static void check_extport(struct ahc_softc *ahc, u_int *sxfrctl1);
-static void configure_termination(struct ahc_softc *ahc,
- struct seeprom_descriptor *sd,
- u_int adapter_control,
- u_int *sxfrctl1);
-static void ahc_new_term_detect(struct ahc_softc *ahc,
- int *enableSEC_low,
- int *enableSEC_high,
- int *enablePRI_low,
- int *enablePRI_high,
- int *eeprom_present);
-static void aic787X_cable_detect(struct ahc_softc *ahc,
- int *internal50_present,
- int *internal68_present,
- int *externalcable_present,
- int *eeprom_present);
-static void aic785X_cable_detect(struct ahc_softc *ahc,
- int *internal50_present,
- int *externalcable_present,
- int *eeprom_present);
-static void write_brdctl(struct ahc_softc *ahc, u_int8_t value);
-static u_int8_t read_brdctl(struct ahc_softc *ahc);
-
-int ahc_do_pci_config(struct ahc_softc *ahc);
-
-void load_seeprom(struct ahc_softc *ahc);
-static int acquire_seeprom(struct ahc_softc *ahc,
- struct seeprom_descriptor *sd);
-static void release_seeprom(struct seeprom_descriptor *sd);
-static int verify_cksum(struct seeprom_config *);
-int ahc_probe_scbs(struct ahc_softc *ahc);
-
-static u_char aic3940_count;
int ahc_pci_probe(struct device *, void *, void *);
void ahc_pci_attach(struct device *, struct device *, void *);
+
struct cfattach ahc_pci_ca = {
sizeof(struct ahc_softc), ahc_pci_probe, ahc_pci_attach
};
-const struct pci_matchid ahc_pci_devices[] = {
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7810 },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7850 },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7855 },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7860 },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2940AU },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7870 },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2930CU },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2940 },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_3940 },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_3985 },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2944 },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_AIC7880 },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2940U },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_3940U },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_398XU },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2944U },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_2940UWPro },
- { PCI_VENDOR_ADP, PCI_PRODUCT_ADP_7895 },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_AAA131U2 },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_AIC7890 },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_2940U2 },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_2930U2 },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_AIC7892 },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_29160 },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_19160B },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_3950U2B },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_3950U2D },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_AIC7896 },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_AIC7899B },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_AIC7899D },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_AIC7899F },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_AIC7899 },
- { PCI_VENDOR_ADP2, PCI_PRODUCT_ADP2_3960D },
-};
+const struct ahc_pci_identity *
+ahc_find_pci_device(id, subid, func)
+ pcireg_t id, subid;
+ u_int func;
+{
+ u_int64_t full_id;
+ const struct ahc_pci_identity *entry;
+ u_int i;
+
+ full_id = ahc_compose_id(PCI_PRODUCT(id), PCI_VENDOR(id),
+ PCI_PRODUCT(subid), PCI_VENDOR(subid));
+
+ /*
+ * If the second function is not hooked up, ignore it.
+ * Unfortunately, not all MB vendors implement the
+ * subdevice ID as per the Adaptec spec, so do our best
+ * to sanity check it prior to accepting the subdevice
+ * ID as valid.
+ */
+ if (func > 0
+ && ahc_9005_subdevinfo_valid(PCI_VENDOR(id), PCI_PRODUCT(id),
+ PCI_VENDOR(subid), PCI_PRODUCT(subid))
+ && SUBID_9005_MFUNCENB(PCI_PRODUCT(subid)) == 0)
+ return (NULL);
+
+ for (i = 0; i < ahc_num_pci_devs; i++) {
+ entry = &ahc_pci_ident_table[i];
+ if (entry->full_id == (full_id & entry->id_mask))
+ return (entry);
+ }
+ return (NULL);
+}
int
ahc_pci_probe(parent, match, aux)
-struct device *parent;
-void *match, *aux;
+ struct device *parent;
+ void *match, *aux;
{
- return (pci_matchbyid((struct pci_attach_args *)aux, ahc_pci_devices,
- sizeof(ahc_pci_devices)/sizeof(ahc_pci_devices[0])));
+ struct pci_attach_args *pa = aux;
+ const struct ahc_pci_identity *entry;
+ pcireg_t subid;
+
+ subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
+ entry = ahc_find_pci_device(pa->pa_id, subid, pa->pa_function);
+ return (entry != NULL && entry->setup != NULL) ? 1 : 0;
}
void
ahc_pci_attach(parent, self, aux)
-struct device *parent, *self;
-void *aux;
+ struct device *parent, *self;
+ void *aux;
{
struct pci_attach_args *pa = aux;
- struct ahc_softc *ahc = (void *)self;
- pcireg_t devconfig;
- pcireg_t command;
+ const struct ahc_pci_identity *entry;
+ struct ahc_softc *ahc = (void *)self;
+ pcireg_t command;
+ u_int our_id = 0;
+ u_int sxfrctl1;
+ u_int scsiseq;
+ u_int sblkctl;
+ uint8_t dscommand0;
+ uint32_t devconfig;
+ int error;
+ pcireg_t subid;
+ int ioh_valid, memh_valid;
+ bus_space_tag_t st, iot;
+ bus_space_handle_t sh, ioh;
+#ifdef AHC_ALLOW_MEMIO
+ bus_space_tag_t memt;
+ bus_space_handle_t memh;
+ pcireg_t memtype;
+#endif
+ pci_intr_handle_t ih;
+ const char *intrstr;
+ struct ahc_pci_busdata *bd;
- /* setup the PCI stuff */
ahc->dev_softc = pa;
- /*
- * We really don't allocate our softc, but
- * we need to do the initialization. And this
- * also allocates the platform_data structure.
- */
- ahc_alloc(ahc, NULL);
ahc_set_name(ahc, ahc->sc_dev.dv_xname);
- ahc_set_unit(ahc, ahc->sc_dev.dv_unit);
-
- /* set dma tags */
ahc->parent_dmat = pa->pa_dmat;
- ahc->buffer_dmat = pa->pa_dmat;
- ahc->shared_data_dmat = pa->pa_dmat;
-
- /* card specific setup */
- switch (PCI_VENDOR(pa->pa_id)) {
- case PCI_VENDOR_ADP:
- switch (PCI_PRODUCT(pa->pa_id)) {
- case PCI_PRODUCT_ADP_7895:
- ahc->channel = pa->pa_function == 1 ? 'B' : 'A';
- /* The 'C' revision of the aic7895
- has a few additional features */
- if (PCI_REVISION(pa->pa_class) >= 4){
- ahc->chip |= AHC_AIC7895C;
- } else {
- ahc->chip |= AHC_AIC7895;
- }
- break;
- case PCI_PRODUCT_ADP_3940U:
- case PCI_PRODUCT_ADP_3940:
- if (PCI_PRODUCT(pa->pa_id) == PCI_PRODUCT_ADP_3940U) {
- ahc->chip |= AHC_AIC7880;
- } else {
- ahc->chip |= AHC_AIC7870;
- }
- aic3940_count++;
- if (!(aic3940_count & 0x01))
- /* Even count implies second channel */
- ahc->channel = 'B';
- break;
- case PCI_PRODUCT_ADP_2940UWPro:
- ahc->flags |= AHC_INT50_SPEEDFLEX;
- /* fall through */
- case PCI_PRODUCT_ADP_AIC7880:
- case PCI_PRODUCT_ADP_398XU: /* XXX */
- case PCI_PRODUCT_ADP_2944U:
- case PCI_PRODUCT_ADP_2940U:
- ahc->chip |= AHC_AIC7880;
- break;
- case PCI_PRODUCT_ADP_AIC7870:
- case PCI_PRODUCT_ADP_2944:
- case PCI_PRODUCT_ADP_2940:
- ahc->chip |= AHC_AIC7870;
- break;
- case PCI_PRODUCT_ADP_AIC7860:
- case PCI_PRODUCT_ADP_2940AU:
- ahc->chip |= AHC_AIC7860;
- break;
- case PCI_PRODUCT_ADP_AIC7855:
- case PCI_PRODUCT_ADP_AIC7850:
- ahc->chip |= AHC_AIC7850;
- break;
- default:
- /* TTT */
- break;
- }
- break;
- case PCI_VENDOR_ADP2:
- switch (PCI_PRODUCT(pa->pa_id)) {
- case PCI_PRODUCT_ADP2_AIC7890:
- case PCI_PRODUCT_ADP2_2940U2:
- case PCI_PRODUCT_ADP2_2930U2:
- case PCI_PRODUCT_ADP2_AAA131U2:
- ahc->chip |= AHC_AIC7890;
- break;
- case PCI_PRODUCT_ADP2_AIC7892:
- case PCI_PRODUCT_ADP2_29160:
- case PCI_PRODUCT_ADP2_19160B:
- ahc->chip |= AHC_AIC7892;
- break;
- case PCI_PRODUCT_ADP2_3950U2B:
- case PCI_PRODUCT_ADP2_3950U2D:
- case PCI_PRODUCT_ADP2_AIC7896:
- ahc->chip |= AHC_AIC7896;
- ahc->channel = pa->pa_function == 1 ? 'B' : 'A';
- devconfig = ahc_pci_read_config(ahc->dev_softc,
- DEVCONFIG, 4);
- /* turn off 64 bit for now XXX smurph */
- devconfig &= ~PCI64BIT;
- ahc_pci_write_config(ahc->dev_softc,
- DEVCONFIG, devconfig, 4);
- break;
- case PCI_PRODUCT_ADP2_AIC7899:
- case PCI_PRODUCT_ADP2_3960D:
- ahc->chip |= AHC_AIC7899;
- ahc->channel = pa->pa_function == 1 ? 'B' : 'A';
- break;
- default:
- /* TTT */
- break;
- }
- }
-
- /* chip specific setup */
- switch(ahc->chip){
- case AHC_AIC7850:
- case AHC_AIC7855:
- case AHC_AIC7859:
- ahc->features = AHC_AIC7850_FE;
- ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
- if (PCI_REVISION(pa->pa_class) >= 1)
- ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
- break;
- case AHC_AIC7860:
- ahc->features = AHC_AIC7860_FE;
- ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
- if (PCI_REVISION(pa->pa_class) >= 1)
- ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
- break;
- case AHC_AIC7870:
- ahc->features = AHC_AIC7870_FE;
- ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
- break;
- case AHC_AIC7880:
- ahc->features = AHC_AIC7880_FE;
- ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
- if (PCI_REVISION(pa->pa_class) >= 1) {
- ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
- } else {
- ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
- }
- break;
- case AHC_AIC7895:
- ahc->features = AHC_AIC7895_FE;
- ahc->flags |= AHC_NEWEEPROM_FMT;
- /*
- * The BIOS disables the use of MWI transactions
- * since it does not have the MWI bug work around
- * we have. Disabling MWI reduces performance, so
- * turn it on again.
- */
- command = pci_conf_read(pa->pa_pc, pa->pa_tag,
- PCI_COMMAND_STATUS_REG);
- command |= PCI_COMMAND_INVALIDATE_ENABLE;
- pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG,
- command);
- ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG
- | AHC_CACHETHEN_BUG | AHC_PCI_MWI_BUG;
- break;
- case AHC_AIC7895C:
- ahc->features = AHC_AIC7895C_FE;
- ahc->flags |= AHC_NEWEEPROM_FMT;
- ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG
- | AHC_CACHETHEN_BUG;
- break;
- case AHC_AIC7890:
- ahc->features = AHC_AIC7890_FE;
- ahc->flags |= AHC_NEWEEPROM_FMT;
- if (PCI_REVISION(pa->pa_class) == 0)
- ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG;
- break;
- case AHC_AIC7892:
- ahc->features = AHC_AIC7892_FE;
- ahc->flags |= AHC_NEWEEPROM_FMT;
- ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
- break;
- case AHC_AIC7896:
- ahc->features = AHC_AIC7896_FE;
- ahc->flags |= AHC_NEWEEPROM_FMT;
- ahc->bugs |= AHC_CACHETHEN_DIS_BUG;
- break;
- case AHC_AIC7899:
- ahc->features = AHC_AIC7899_FE;
- ahc->flags |= AHC_NEWEEPROM_FMT;
- ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
- break;
- default:
- break;
- }
- /* setup the PCI interrupt */
- ahc->bus_intr = ahc_pci_intr;
- ahc->unsolicited_ints = 0;
+ command = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG);
+ subid = pci_conf_read(pa->pa_pc, pa->pa_tag, PCI_SUBSYS_ID_REG);
+ entry = ahc_find_pci_device(pa->pa_id, subid, pa->pa_function);
+ if (entry == NULL)
+ return;
- if(ahc_do_pci_config(ahc)){
- ahc_free(ahc);
+ /* Keep information about the PCI bus */
+ bd = malloc(sizeof (struct ahc_pci_busdata), M_DEVBUF, M_NOWAIT);
+ if (bd == NULL) {
+ printf("%s: unable to allocate bus-specific data\n", ahc_name(ahc));
return;
}
-
- ahc_attach(ahc);
-}
+ memset(bd, 0, sizeof(struct ahc_pci_busdata));
+
+ bd->pc = pa->pa_pc;
+ bd->tag = pa->pa_tag;
+ bd->func = pa->pa_function;
+ bd->dev = pa->pa_device;
+ bd->class = pa->pa_class;
+
+ ahc->bd = bd;
+
+ error = entry->setup(ahc);
+ if (error != 0)
+ return;
+
+ ioh_valid = memh_valid = 0;
-int
-ahc_pci_map_registers(ahc)
- struct ahc_softc *ahc;
-{
- pcireg_t command;
- int ioh_valid;
- bus_space_tag_t iot;
- bus_space_handle_t ioh;
- struct pci_attach_args *pa = ahc->dev_softc;
-
- command = ahc_pci_read_config(ahc->dev_softc,
- PCI_COMMAND_STATUS_REG, 4);
#ifdef AHC_ALLOW_MEMIO
- /*
- * attempt to use memory mapping on hardware that supports it.
- * e.g powerpc XXX - smurph
- *
- * Note: If this fails, IO mapping is used.
- */
- if ((command & PCI_COMMAND_MEM_ENABLE) != 0) {
- pcireg_t memtype;
- memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, AHC_PCI_MEMADDR);
- switch (memtype) {
- case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
- case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
- ioh_valid = (pci_mapreg_map(pa, AHC_PCI_MEMADDR,
- memtype, 0, &iot, &ioh, NULL, NULL, 0) == 0);
- break;
- default:
- ioh_valid = 0;
- }
- if (ioh_valid) {
- /*
- * Do a quick test to see if memory mapped
- * I/O is functioning correctly.
- */
- ahc->tag = iot;
- ahc->bsh = ioh;
- if (ahc_inb(ahc, HCNTRL) == 0xFF) {
- /* nope, use I/O mapping */
- ioh_valid = 0;
- } else {
- /* Using memory mapping, disable I/O mapping */
- command &= ~PCI_COMMAND_IO_ENABLE;
- ahc_pci_write_config(ahc->dev_softc,
- PCI_COMMAND_STATUS_REG,
- command, 4);
- }
- }
+ memtype = pci_mapreg_type(pa->pa_pc, pa->pa_tag, AHC_PCI_MEMADDR);
+ switch (memtype) {
+ case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_32BIT:
+ case PCI_MAPREG_TYPE_MEM | PCI_MAPREG_MEM_TYPE_64BIT:
+ memh_valid = (pci_mapreg_map(pa, AHC_PCI_MEMADDR,
+ memtype, 0, &memt, &memh, NULL, NULL, 0) == 0);
+ break;
+ default:
+ memh_valid = 0;
}
-
- if (!ioh_valid) /* try to drop back to IO mapping */
#endif
- {
- ioh_valid = (pci_mapreg_map(pa, AHC_PCI_IOADDR,
- PCI_MAPREG_TYPE_IO, 0, &iot, &ioh, NULL, NULL, 0) == 0);
-
- /* Using I/O mapping, disable memory mapping */
- command &= ~PCI_COMMAND_MEM_ENABLE;
- ahc_pci_write_config(ahc->dev_softc,
- PCI_COMMAND_STATUS_REG,
- command, 4);
- }
+ ioh_valid = (pci_mapreg_map(pa, AHC_PCI_IOADDR,
+ PCI_MAPREG_TYPE_IO, 0, &iot,
+ &ioh, NULL, NULL, 0) == 0);
+#if 0
+ printf("%s: mem mapping: memt 0x%x, memh 0x%x, iot 0x%x, ioh 0x%lx\n",
+ ahc_name(ahc), memt, (u_int32_t)memh, (u_int32_t)iot, ioh);
+#endif
- if (!ioh_valid) {
- /* Game Over. Insert coin... */
+ if (ioh_valid) {
+ st = iot;
+ sh = ioh;
+#ifdef AHC_ALLOW_MEMIO
+ } else if (memh_valid) {
+ st = memt;
+ sh = memh;
+#endif
+ } else {
printf(": unable to map registers\n");
- return (1);
+ return;
}
- ahc->tag = iot;
- ahc->bsh = ioh;
- return (0);
-}
-
-int
-ahc_do_pci_config(ahc)
- struct ahc_softc *ahc;
-{
- pcireg_t command;
- u_int our_id = 0;
- u_int sxfrctl1;
- u_int scsiseq;
- u_int dscommand0;
- int error;
- int opri;
- uint8_t sblkctl;
-
+ ahc->tag = st;
+ ahc->bsh = sh;
ahc->chip |= AHC_PCI;
-#if 0
- ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
-#endif
- error = ahc_pci_map_registers(ahc);
- if (error != 0)
- return (error);
- /*
- * Registers are mapped. Now it is safe to use
- * the ahc_inb and ahc_outb macros.
- */
-
- /*
+ /*
* Before we continue probing the card, ensure that
* its interrupts are *disabled*. We don't want
* a misstep to hang the machine in an interrupt
@@ -516,34 +802,53 @@ ahc_do_pci_config(ahc)
ahc_intr_enable(ahc, FALSE);
/*
+ * XXX somehow reading this once fails on some sparc64 systems.
+ * This may be a problem in the sparc64 PCI code. Doing it
+ * twice works around it.
+ */
+ devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
+ devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
+
+ /*
* If we need to support high memory, enable dual
* address cycles. This bit must be set to enable
* high address bit generation even if we are on a
* 64bit bus (PCI64BIT set in devconfig).
*/
if ((ahc->flags & AHC_39BIT_ADDRESSING) != 0) {
- pcireg_t devconfig;
- if (bootverbose)
+ if (1/*bootverbose*/)
printf("%s: Enabling 39Bit Addressing\n",
ahc_name(ahc));
- devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, 4);
devconfig |= DACEN;
- ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, 4);
}
+ /* Ensure that pci error generation, a test feature, is disabled. */
+ devconfig |= PCIERRGENDIS;
+
+ pci_conf_write(pa->pa_pc, pa->pa_tag, DEVCONFIG, devconfig);
+
/* Ensure busmastering is enabled */
- command = ahc_pci_read_config(ahc->dev_softc, PCI_COMMAND_STATUS_REG, 4);
- command |= PCI_COMMAND_MASTER_ENABLE;
+ command |= PCI_COMMAND_MASTER_ENABLE;;
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command);
+
+ /*
+ * Disable PCI parity error reporting. Users typically
+ * do this to work around broken PCI chipsets that get
+ * the parity timing wrong and thus generate lots of spurious
+ * errors.
+ */
+ if ((ahc->flags & AHC_DISABLE_PCI_PERR) != 0)
+ command &= ~PCI_COMMAND_PARITY_ENABLE;
+ pci_conf_write(pa->pa_pc, pa->pa_tag, PCI_COMMAND_STATUS_REG, command);
- ahc_pci_write_config(ahc->dev_softc, PCI_COMMAND_STATUS_REG, command, 4);
-
/* On all PCI adapters, we allow SCB paging */
ahc->flags |= AHC_PAGESCBS;
-
error = ahc_softc_init(ahc);
if (error != 0)
- return (error);
+ goto error_out;
+
+ ahc->bus_intr = ahc_pci_intr;
/* Remember how the card was setup in case there is no SEEPROM */
if ((ahc_inb(ahc, HCNTRL) & POWRDN) == 0) {
@@ -562,7 +867,7 @@ ahc_do_pci_config(ahc)
error = ahc_reset(ahc);
if (error != 0)
- return (ENXIO);
+ goto error_out;
if ((ahc->features & AHC_DT) != 0) {
u_int sfunct;
@@ -579,12 +884,27 @@ ahc_do_pci_config(ahc)
|TARGCRCENDEN);
}
- /*
- * Protect ourself from spurrious interrupts during
- * initialization.
- */
- opri = splbio();
-
+ if (pci_intr_map(pa, &ih)) {
+ printf("%s: couldn't map interrupt\n", ahc_name(ahc));
+ ahc_free(ahc);
+ return;
+ }
+ intrstr = pci_intr_string(pa->pa_pc, ih);
+ ahc->ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
+ ahc_platform_intr, ahc, ahc->sc_dev.dv_xname);
+ if (ahc->ih == NULL) {
+ printf("%s: couldn't establish interrupt",
+ ahc->sc_dev.dv_xname);
+ if (intrstr != NULL)
+ printf(" at %s", intrstr);
+ printf("\n");
+ ahc_free(ahc);
+ return;
+ }
+ printf("\n");
+ if (intrstr != NULL)
+ printf("%s: interrupting at %s\n", ahc_name(ahc), intrstr);
+
dscommand0 = ahc_inb(ahc, DSCOMMAND0);
dscommand0 |= MPARCKEN|CACHETHEN;
if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -607,34 +927,38 @@ ahc_do_pci_config(ahc)
dscommand0 &= ~CACHETHEN;
ahc_outb(ahc, DSCOMMAND0, dscommand0);
-
- ahc->pci_cachesize = ahc_pci_read_config(ahc->dev_softc,
- CSIZE_LATTIME, 4) & CACHESIZE;
+
+ ahc->pci_cachesize =
+ pci_conf_read(pa->pa_pc, pa->pa_tag, CSIZE_LATTIME) & CACHESIZE;
ahc->pci_cachesize *= 4;
if ((ahc->bugs & AHC_PCI_2_1_RETRY_BUG) != 0
- && ahc->pci_cachesize == 4) {
- u_int csl = ahc_pci_read_config(ahc->dev_softc,
- CSIZE_LATTIME, 4);
- csl &= ~CACHESIZE;
- ahc_pci_write_config(ahc->dev_softc, CSIZE_LATTIME, csl, 4);
+ && ahc->pci_cachesize == 4) {
+ pci_conf_write(pa->pa_pc, pa->pa_tag, CSIZE_LATTIME, 0);
ahc->pci_cachesize = 0;
}
/*
- * We cannot perform ULTRA speeds without the presense
+ * We cannot perform ULTRA speeds without the presence
* of the external precision resistor.
*/
if ((ahc->features & AHC_ULTRA) != 0) {
uint32_t devconfig;
- devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, 4);
+ devconfig = pci_conf_read(pa->pa_pc, pa->pa_tag, DEVCONFIG);
if ((devconfig & REXTVALID) == 0)
ahc->features &= ~AHC_ULTRA;
}
+ ahc->seep_config = malloc(sizeof(*ahc->seep_config),
+ M_DEVBUF, M_NOWAIT);
+ if (ahc->seep_config == NULL)
+ goto error_out;
+
+ memset(ahc->seep_config, 0, sizeof(*ahc->seep_config));
+
/* See if we have a SEEPROM and perform auto-term */
- check_extport(ahc, &sxfrctl1);
+ ahc_check_extport(ahc, &sxfrctl1);
/*
* Take the LED out of diagnostic mode
@@ -655,7 +979,8 @@ ahc_do_pci_config(ahc)
* a SEEPROM.
*/
/* See if someone else set us up already */
- if (scsiseq != 0) {
+ if ((ahc->flags & AHC_NO_BIOS_INIT) == 0
+ && scsiseq != 0) {
printf("%s: Using left over BIOS settings\n",
ahc_name(ahc));
ahc->flags &= ~AHC_USEDEFAULTS;
@@ -687,63 +1012,53 @@ ahc_do_pci_config(ahc)
if ((sxfrctl1 & STPWEN) != 0)
ahc->flags |= AHC_TERM_ENB_A;
- /* Core initialization */
- error = ahc_init(ahc);
- if (error != 0)
- return (error);
-
- /* Special func to force negotiation */
- ahc_force_neg(ahc);
-
- /*
- * Link this softc in with all other ahc instances.
- */
- ahc_softc_insert(ahc);
+ if (ahc_init(ahc))
+ goto error_out;
- /*
- * Allow interrupts now that we are completely setup.
- */
- error = ahc_pci_map_int(ahc);
- if (error != 0)
- return (error);
+ ahc_attach(ahc);
- ahc_intr_enable(ahc, TRUE);
- splx(opri);
+ return;
- return (0);
+ error_out:
+ ahc_free(ahc);
+ return;
}
-int
-ahc_pci_map_int(ahc)
- struct ahc_softc *ahc;
+static int
+ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
+ uint16_t subdevice, uint16_t subvendor)
{
- const char *intrstr = NULL;
- pci_intr_handle_t ih;
- struct pci_attach_args *pa = ahc->dev_softc;
-
- if (pci_intr_map(pa, &ih)) {
- printf(": couldn't map interrupt\n");
- return 1;
- }
- intrstr = pci_intr_string(pa->pa_pc, ih);
-
- ahc->platform_data->ih = pci_intr_establish(pa->pa_pc, ih, IPL_BIO,
- ahc_platform_intr, ahc,
- ahc->sc_dev.dv_xname);
-
- if (ahc->platform_data->ih == NULL) {
- printf(": couldn't establish interrupt");
- if (intrstr != NULL)
- printf(" at %s", intrstr);
- printf("\n");
- return 1;
+ int result;
+
+ /* Default to invalid. */
+ result = 0;
+ if (vendor == 0x9005
+ && subvendor == 0x9005
+ && subdevice != device
+ && SUBID_9005_TYPE_KNOWN(subdevice) != 0) {
+
+ switch (SUBID_9005_TYPE(subdevice)) {
+ case SUBID_9005_TYPE_MB:
+ break;
+ case SUBID_9005_TYPE_CARD:
+ case SUBID_9005_TYPE_LCCARD:
+ /*
+ * Currently only trust Adaptec cards to
+ * get the sub device info correct.
+ */
+ if (DEVID_9005_TYPE(device) == DEVID_9005_TYPE_HBA)
+ result = 1;
+ break;
+ case SUBID_9005_TYPE_RAID:
+ break;
+ default:
+ break;
+ }
}
-
- if (intrstr != NULL)
- printf(": %s\n", intrstr);
- return 0;
+ return (result);
}
+
/*
* Test for the presense of external sram in an
* "unshared" configuration.
@@ -755,15 +1070,21 @@ ahc_ext_scbram_present(struct ahc_softc *ahc)
int ramps;
int single_user;
uint32_t devconfig;
-
- chip = ahc->chip & AHC_CHIPID_MASK;
-
- devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, 4);
+ chip = ahc->chip & AHC_CHIPID_MASK;
+ devconfig = pci_conf_read(ahc->bd->pc, ahc->bd->tag, DEVCONFIG);
single_user = (devconfig & MPORTMODE) != 0;
if ((ahc->features & AHC_ULTRA2) != 0)
ramps = (ahc_inb(ahc, DSCOMMAND0) & RAMPS) != 0;
+ else if (chip == AHC_AIC7895 || chip == AHC_AIC7895C)
+ /*
+ * External SCBRAM arbitration is flakey
+ * on these chips. Unfortunately this means
+ * we don't use the extra SCB ram space on the
+ * 3940AUW.
+ */
+ ramps = 0;
else if (chip >= AHC_AIC7870)
ramps = (devconfig & RAMPSM) != 0;
else
@@ -778,24 +1099,23 @@ ahc_ext_scbram_present(struct ahc_softc *ahc)
* Enable external scbram.
*/
static void
-ahc_scbram_config(ahc, enable, pcheck, fast, large)
- struct ahc_softc *ahc;
- int enable;
- int pcheck;
- int fast;
- int large;
+ahc_scbram_config(struct ahc_softc *ahc, int enable, int pcheck,
+ int fast, int large)
{
- pcireg_t devconfig;
+ uint32_t devconfig;
if (ahc->features & AHC_MULTI_FUNC) {
/*
* Set the SCB Base addr (highest address bit)
* depending on which channel we are.
*/
- ahc_outb(ahc, SCBBADDR, ahc_get_pci_function(ahc->dev_softc));
+ ahc_outb(ahc, SCBBADDR, ahc->bd->func);
}
- devconfig = ahc_pci_read_config(ahc->dev_softc, DEVCONFIG, 4);
+ ahc->flags &= ~AHC_LSCBS_ENABLED;
+ if (large)
+ ahc->flags |= AHC_LSCBS_ENABLED;
+ devconfig = pci_conf_read(ahc->bd->pc, ahc->bd->tag, DEVCONFIG);
if ((ahc->features & AHC_ULTRA2) != 0) {
u_int dscommand0;
@@ -828,7 +1148,7 @@ ahc_scbram_config(ahc, enable, pcheck, fast, large)
else
devconfig &= ~EXTSCBPEN;
- ahc_pci_write_config(ahc->dev_softc, DEVCONFIG, devconfig, 4);
+ pci_conf_write(ahc->bd->pc, ahc->bd->tag, DEVCONFIG, devconfig);
}
/*
@@ -837,8 +1157,7 @@ ahc_scbram_config(ahc, enable, pcheck, fast, large)
* shared among multiple controllers.
*/
static void
-ahc_probe_ext_scbram(ahc)
- struct ahc_softc *ahc;
+ahc_probe_ext_scbram(struct ahc_softc *ahc)
{
int num_scbs;
int test_num_scbs;
@@ -925,7 +1244,7 @@ done:
/* Clear any latched parity error */
ahc_outb(ahc, CLRINT, CLRPARERR);
ahc_outb(ahc, CLRINT, CLRBRKADRINT);
- if (bootverbose && enable) {
+ if (1/*bootverbose*/ && enable) {
printf("%s: External SRAM, %s access%s, %dbytes/SCB\n",
ahc_name(ahc), fast ? "fast" : "slow",
pcheck ? ", parity checking enabled" : "",
@@ -934,759 +1253,449 @@ done:
ahc_scbram_config(ahc, enable, pcheck, fast, large);
}
+#if 0
/*
- * Check the external port logic for a serial eeprom
- * and termination/cable detection contrls.
+ * Perform some simple tests that should catch situations where
+ * our registers are invalidly mapped.
*/
-static void
-check_extport(ahc, sxfrctl1)
- struct ahc_softc *ahc;
- u_int *sxfrctl1;
+int
+ahc_pci_test_register_access(struct ahc_softc *ahc)
{
- struct seeprom_descriptor sd;
- struct seeprom_config sc;
- u_int scsi_conf;
- u_int adapter_control;
- int have_seeprom;
- int have_autoterm;
-
- sd.sd_tag = ahc->tag;
- sd.sd_bsh = ahc->bsh;
- sd.sd_regsize = 1;
- sd.sd_control_offset = SEECTL;
- sd.sd_status_offset = SEECTL;
- sd.sd_dataout_offset = SEECTL;
+ int error;
+ u_int status1;
+ uint32_t cmd;
+ uint8_t hcntrl;
+
+ error = EIO;
/*
- * For some multi-channel devices, the c46 is simply too
- * small to work. For the other controller types, we can
- * get our information from either SEEPROM type. Set the
- * type to start our probe with accordingly.
+ * Enable PCI error interrupt status, but suppress NMIs
+ * generated by SERR raised due to target aborts.
*/
- if (ahc->flags & AHC_LARGE_SEEPROM)
- sd.sd_chip = C56_66;
- else
- sd.sd_chip = C46;
-
- sd.sd_MS = SEEMS;
- sd.sd_RDY = SEERDY;
- sd.sd_CS = SEECS;
- sd.sd_CK = SEECK;
- sd.sd_DO = SEEDO;
- sd.sd_DI = SEEDI;
+ cmd = pci_conf_read(ahc->bd->pc, ahc->bd->tag, PCIR_COMMAND);
+ pci_conf_write(ahc->bd->pc, ahc->bd->tag, PCIR_COMMAND,
+ cmd & ~PCIM_CMD_SERRESPEN);
- have_seeprom = acquire_seeprom(ahc, &sd);
- if (have_seeprom) {
+ /*
+ * First a simple test to see if any
+ * registers can be read. Reading
+ * HCNTRL has no side effects and has
+ * at least one bit that is guaranteed to
+ * be zero so it is a good register to
+ * use for this test.
+ */
+ hcntrl = ahc_inb(ahc, HCNTRL);
+ if (hcntrl == 0xFF)
+ goto fail;
- if (bootverbose)
- printf("%s: Reading SEEPROM...", ahc_name(ahc));
+ /*
+ * Next create a situation where write combining
+ * or read prefetching could be initiated by the
+ * CPU or host bridge. Our device does not support
+ * either, so look for data corruption and/or flagged
+ * PCI errors.
+ */
+ ahc_outb(ahc, HCNTRL, hcntrl|PAUSE);
+ while (ahc_is_paused(ahc) == 0)
+ ;
+ ahc_outb(ahc, SEQCTL, PERRORDIS);
+ ahc_outb(ahc, SCBPTR, 0);
+ ahc_outl(ahc, SCB_BASE, 0x5aa555aa);
+ if (ahc_inl(ahc, SCB_BASE) != 0x5aa555aa)
+ goto fail;
+
+ status1 = pci_conf_read(ahc->bd->pc, ahc->bd->tag,
+ PCI_COMMAND_STATUS_REG + 1);
+ if ((status1 & STA) != 0)
+ goto fail;
+
+ error = 0;
+
+fail:
+ /* Silently clear any latched errors. */
+ status1 = pci_conf_read(ahc->bd->pc, ahc->bd->tag, PCI_COMMAND_STATUS_REG + 1);
+ ahc_pci_write_config(ahc->dev_softc, PCIR_STATUS + 1,
+ status1, /*bytes*/1);
+ ahc_outb(ahc, CLRINT, CLRPARERR);
+ ahc_outb(ahc, SEQCTL, PERRORDIS|FAILDIS);
+ ahc_pci_write_config(ahc->dev_softc, PCIR_COMMAND, cmd, /*bytes*/2);
+ return (error);
+}
+#endif
- for (;;) {
- u_int start_addr;
+void
+ahc_pci_intr(struct ahc_softc *ahc)
+{
+ u_int error;
+ u_int status1;
- start_addr = 32 * (ahc->channel - 'A');
+ error = ahc_inb(ahc, ERROR);
+ if ((error & PCIERRSTAT) == 0)
+ return;
- have_seeprom = read_seeprom(&sd, (uint16_t *)&sc,
- start_addr, sizeof(sc)/2);
+ status1 = pci_conf_read(ahc->bd->pc, ahc->bd->tag, PCI_COMMAND_STATUS_REG);
- if (have_seeprom)
- have_seeprom = verify_cksum(&sc);
+ printf("%s: PCI error Interrupt at seqaddr = 0x%x\n",
+ ahc_name(ahc),
+ ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8));
- if (have_seeprom != 0 || sd.sd_chip == C56_66) {
- if (bootverbose) {
- if (have_seeprom == 0)
- printf ("checksum error\n");
- else
- printf ("done.\n");
- }
- break;
- }
- sd.sd_chip = C56_66;
- }
- release_seeprom(&sd);
+ if (status1 & DPE) {
+ printf("%s: Data Parity Error Detected during address "
+ "or write data phase\n", ahc_name(ahc));
}
-
- if (!have_seeprom) {
- /*
- * Pull scratch ram settings and treat them as
- * if they are the contents of an seeprom if
- * the 'ADPT' signature is found in SCB2.
- * We manually compose the data as 16bit values
- * to avoid endian issues.
- */
- ahc_outb(ahc, SCBPTR, 2);
- if (ahc_inb(ahc, SCB_BASE) == 'A'
- && ahc_inb(ahc, SCB_BASE + 1) == 'D'
- && ahc_inb(ahc, SCB_BASE + 2) == 'P'
- && ahc_inb(ahc, SCB_BASE + 3) == 'T') {
- uint16_t *sc_data;
- int i;
-
- sc_data = (uint16_t *)&sc;
- for (i = 0; i < 32; i++) {
- uint16_t val;
- int j;
-
- j = i * 2;
- val = ahc_inb(ahc, SRAM_BASE + j)
- | ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
- }
- have_seeprom = verify_cksum(&sc);
- }
- /*
- * Clear any SCB parity errors in case this data and
- * its associated parity was not initialized by the BIOS
- */
- ahc_outb(ahc, CLRINT, CLRPARERR);
- ahc_outb(ahc, CLRINT, CLRBRKADRINT);
+ if (status1 & SSE) {
+ printf("%s: Signal System Error Detected\n", ahc_name(ahc));
+ }
+ if (status1 & RMA) {
+ printf("%s: Received a Master Abort\n", ahc_name(ahc));
+ }
+ if (status1 & RTA) {
+ printf("%s: Received a Target Abort\n", ahc_name(ahc));
+ }
+ if (status1 & STA) {
+ printf("%s: Signaled a Target Abort\n", ahc_name(ahc));
+ }
+ if (status1 & DPR) {
+ printf("%s: Data Parity Error has been reported via PERR#\n",
+ ahc_name(ahc));
}
- if (!have_seeprom) {
- if (bootverbose)
- printf("%s: No SEEPROM available.\n", ahc_name(ahc));
- ahc->flags |= AHC_USEDEFAULTS;
- } else {
- /*
- * Put the data we've collected down into SRAM
- * where ahc_init will find it.
- */
- int i;
- int max_targ = sc.max_targets & CFMAXTARG;
- uint16_t discenable;
- uint16_t ultraenb;
-
- discenable = 0;
- ultraenb = 0;
- if ((sc.adapter_control & CFULTRAEN) != 0) {
- /*
- * Determine if this adapter has a "newstyle"
- * SEEPROM format.
- */
- for (i = 0; i < max_targ; i++) {
- if ((sc.device_flags[i] & CFSYNCHISULTRA) != 0){
- ahc->flags |= AHC_NEWEEPROM_FMT;
- break;
- }
- }
- }
-
- for (i = 0; i < max_targ; i++) {
- u_int scsirate;
- uint16_t target_mask;
-
- target_mask = 0x01 << i;
- if (sc.device_flags[i] & CFDISC)
- discenable |= target_mask;
- if ((ahc->flags & AHC_NEWEEPROM_FMT) != 0) {
- if ((sc.device_flags[i] & CFSYNCHISULTRA) != 0)
- ultraenb |= target_mask;
- } else if ((sc.adapter_control & CFULTRAEN) != 0) {
- ultraenb |= target_mask;
- }
- if ((sc.device_flags[i] & CFXFER) == 0x04
- && (ultraenb & target_mask) != 0) {
- /* Treat 10MHz as a non-ultra speed */
- sc.device_flags[i] &= ~CFXFER;
- ultraenb &= ~target_mask;
- }
- if ((ahc->features & AHC_ULTRA2) != 0) {
- u_int offset;
-
- if (sc.device_flags[i] & CFSYNCH)
- offset = MAX_OFFSET_ULTRA2;
- else
- offset = 0;
- ahc_outb(ahc, TARG_OFFSET + i, offset);
-
- /*
- * The ultra enable bits contain the
- * high bit of the ultra2 sync rate
- * field.
- */
- scsirate = (sc.device_flags[i] & CFXFER)
- | ((ultraenb & target_mask)
- ? 0x8 : 0x0);
- if (sc.device_flags[i] & CFWIDEB)
- scsirate |= WIDEXFER;
- } else {
- scsirate = (sc.device_flags[i] & CFXFER) << 4;
- if (sc.device_flags[i] & CFSYNCH)
- scsirate |= SOFS;
- if (sc.device_flags[i] & CFWIDEB)
- scsirate |= WIDEXFER;
- }
- ahc_outb(ahc, TARG_SCSIRATE + i, scsirate);
- }
- ahc->our_id = sc.brtime_id & CFSCSIID;
+ /* Clear latched errors. */
+ pci_conf_write(ahc->bd->pc, ahc->bd->tag, PCI_COMMAND_STATUS_REG, status1);
- scsi_conf = (ahc->our_id & 0x7);
- if (sc.adapter_control & CFSPARITY)
- scsi_conf |= ENSPCHK;
- if (sc.adapter_control & CFRESETB)
- scsi_conf |= RESET_SCSI;
+ if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) {
+ printf("%s: Latched PCIERR interrupt with "
+ "no status bits set\n", ahc_name(ahc));
+ } else {
+ ahc_outb(ahc, CLRINT, CLRPARERR);
+ }
- ahc->flags |=
- (sc.adapter_control & CFBOOTCHAN) >> CFBOOTCHANSHIFT;
+ ahc_unpause(ahc);
+}
- if (sc.bios_control & CFEXTEND)
- ahc->flags |= AHC_EXTENDED_TRANS_A;
+static int
+ahc_aic785X_setup(struct ahc_softc *ahc)
+{
+ uint8_t rev;
+
+ ahc->channel = 'A';
+ ahc->chip = AHC_AIC7850;
+ ahc->features = AHC_AIC7850_FE;
+ ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
+ rev = PCI_REVISION(ahc->bd->class);
+ if (rev >= 1)
+ ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
+ return (0);
+}
- if (sc.bios_control & CFBIOSEN)
- ahc->flags |= AHC_BIOS_ENABLED;
- if (ahc->features & AHC_ULTRA
- && (ahc->flags & AHC_NEWEEPROM_FMT) == 0) {
- /* Should we enable Ultra mode? */
- if (!(sc.adapter_control & CFULTRAEN))
- /* Treat us as a non-ultra card */
- ultraenb = 0;
- }
+static int
+ahc_aic7860_setup(struct ahc_softc *ahc)
+{
+ uint8_t rev;
+
+ ahc->channel = 'A';
+ ahc->chip = AHC_AIC7860;
+ ahc->features = AHC_AIC7860_FE;
+ ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
+ rev = PCI_REVISION(ahc->bd->class);
+ if (rev >= 1)
+ ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
+ return (0);
+}
- if (sc.signature == CFSIGNATURE
- || sc.signature == CFSIGNATURE2) {
- pcireg_t devconfig;
-
- /* Honor the STPWLEVEL settings */
- devconfig = ahc_pci_read_config(ahc->dev_softc,
- DEVCONFIG, 4);
- devconfig &= ~STPWLEVEL;
- if ((sc.bios_control & CFSTPWLEVEL) != 0)
- devconfig |= STPWLEVEL;
- ahc_pci_write_config(ahc->dev_softc,
- DEVCONFIG, devconfig, 4);
- }
- /* Set SCSICONF info */
- ahc_outb(ahc, SCSICONF, scsi_conf);
- ahc_outb(ahc, DISC_DSB, ~(discenable & 0xff));
- ahc_outb(ahc, DISC_DSB + 1, ~((discenable >> 8) & 0xff));
- ahc_outb(ahc, ULTRA_ENB, ultraenb & 0xff);
- ahc_outb(ahc, ULTRA_ENB + 1, (ultraenb >> 8) & 0xff);
- }
+static int
+ahc_apa1480_setup(struct ahc_softc *ahc)
+{
+ int error;
- /*
- * Cards that have the external logic necessary to talk to
- * a SEEPROM, are almost certain to have the remaining logic
- * necessary for auto-termination control. This assumption
- * hasn't failed yet...
- */
- have_autoterm = have_seeprom;
- if (have_seeprom)
- adapter_control = sc.adapter_control;
- else
- adapter_control = CFAUTOTERM;
+ error = ahc_aic7860_setup(ahc);
+ if (error != 0)
+ return (error);
+ ahc->features |= AHC_REMOVABLE;
+ return (0);
+}
- /*
- * Some low-cost chips have SEEPROM and auto-term control built
- * in, instead of using a GAL. They can tell us directly
- * if the termination logic is enabled.
- */
- if ((ahc->features & AHC_SPIOCAP) != 0) {
- if ((ahc_inb(ahc, SPIOCAP) & SSPIOCPS) != 0)
- have_autoterm = TRUE;
- else
- have_autoterm = FALSE;
- }
+static int
+ahc_aic7870_setup(struct ahc_softc *ahc)
+{
- if (have_autoterm) {
- acquire_seeprom(ahc, &sd);
- configure_termination(ahc, &sd, adapter_control, sxfrctl1);
- release_seeprom(&sd);
- }
+ ahc->channel = 'A';
+ ahc->chip = AHC_AIC7870;
+ ahc->features = AHC_AIC7870_FE;
+ ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
+ return (0);
}
-static void
-configure_termination(struct ahc_softc *ahc,
- struct seeprom_descriptor *sd,
- u_int adapter_control,
- u_int *sxfrctl1)
+static int
+ahc_aha394X_setup(struct ahc_softc *ahc)
{
- uint8_t brddat;
-
- brddat = 0;
+ int error;
- /*
- * Update the settings in sxfrctl1 to match the
- * termination settings
- */
- *sxfrctl1 = 0;
-
- /*
- * SEECS must be on for the GALS to latch
- * the data properly. Be sure to leave MS
- * on or we will release the seeprom.
- */
- SEEPROM_OUTB(sd, sd->sd_MS | sd->sd_CS);
- if ((adapter_control & CFAUTOTERM) != 0
- || (ahc->features & AHC_NEW_TERMCTL) != 0) {
- int internal50_present;
- int internal68_present;
- int externalcable_present;
- int eeprom_present;
- int enableSEC_low;
- int enableSEC_high;
- int enablePRI_low;
- int enablePRI_high;
- int sum;
-
- enableSEC_low = 0;
- enableSEC_high = 0;
- enablePRI_low = 0;
- enablePRI_high = 0;
- if ((ahc->features & AHC_NEW_TERMCTL) != 0) {
- ahc_new_term_detect(ahc, &enableSEC_low,
- &enableSEC_high,
- &enablePRI_low,
- &enablePRI_high,
- &eeprom_present);
- if ((adapter_control & CFSEAUTOTERM) == 0) {
- if (bootverbose)
- printf("%s: Manual SE Termination\n",
- ahc_name(ahc));
- enableSEC_low = (adapter_control & CFSELOWTERM);
- enableSEC_high =
- (adapter_control & CFSEHIGHTERM);
- }
- if ((adapter_control & CFAUTOTERM) == 0) {
- if (bootverbose)
- printf("%s: Manual LVD Termination\n",
- ahc_name(ahc));
- enablePRI_low = (adapter_control & CFSTERM);
- enablePRI_high = (adapter_control & CFWSTERM);
- }
- /* Make the table calculations below happy */
- internal50_present = 0;
- internal68_present = 1;
- externalcable_present = 1;
- } else if ((ahc->features & AHC_SPIOCAP) != 0) {
- aic785X_cable_detect(ahc, &internal50_present,
- &externalcable_present,
- &eeprom_present);
- } else {
- aic787X_cable_detect(ahc, &internal50_present,
- &internal68_present,
- &externalcable_present,
- &eeprom_present);
- }
+ error = ahc_aic7870_setup(ahc);
+ if (error == 0)
+ error = ahc_aha394XX_setup(ahc);
+ return (error);
+}
- if ((ahc->features & AHC_WIDE) == 0)
- internal68_present = 0;
-
- if (bootverbose
- && (ahc->features & AHC_ULTRA2) == 0) {
- printf("%s: internal 50 cable %s present",
- ahc_name(ahc),
- internal50_present ? "is":"not");
-
- if ((ahc->features & AHC_WIDE) != 0)
- printf(", internal 68 cable %s present",
- internal68_present ? "is":"not");
- printf("\n%s: external cable %s present\n",
- ahc_name(ahc),
- externalcable_present ? "is":"not");
- }
- if (bootverbose)
- printf("%s: BIOS eeprom %s present\n",
- ahc_name(ahc), eeprom_present ? "is" : "not");
+static int
+ahc_aha398X_setup(struct ahc_softc *ahc)
+{
+ int error;
- if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0) {
- /*
- * The 50 pin connector is a separate bus,
- * so force it to always be terminated.
- * In the future, perform current sensing
- * to determine if we are in the middle of
- * a properly terminated bus.
- */
- internal50_present = 0;
- }
+ error = ahc_aic7870_setup(ahc);
+ if (error == 0)
+ error = ahc_aha398XX_setup(ahc);
+ return (error);
+}
- /*
- * Now set the termination based on what
- * we found.
- * Flash Enable = BRDDAT7
- * Secondary High Term Enable = BRDDAT6
- * Secondary Low Term Enable = BRDDAT5 (7890)
- * Primary High Term Enable = BRDDAT4 (7890)
- */
- if ((ahc->features & AHC_ULTRA2) == 0
- && (internal50_present != 0)
- && (internal68_present != 0)
- && (externalcable_present != 0)) {
- printf("%s: Illegal cable configuration!!. "
- "Only two connectors on the "
- "adapter may be used at a "
- "time!\n", ahc_name(ahc));
+static int
+ahc_aha494X_setup(struct ahc_softc *ahc)
+{
+ int error;
- /*
- * Pretend there are no cables in the hope
- * that having all of the termination on
- * gives us a more stable bus.
- */
- internal50_present = 0;
- internal68_present = 0;
- externalcable_present = 0;
- }
+ error = ahc_aic7870_setup(ahc);
+ if (error == 0)
+ error = ahc_aha494XX_setup(ahc);
+ return (error);
+}
- if ((ahc->features & AHC_WIDE) != 0
- && ((externalcable_present == 0)
- || (internal68_present == 0)
- || (enableSEC_high != 0))) {
- brddat |= BRDDAT6;
- if (bootverbose) {
- if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
- printf("%s: 68 pin termination "
- "Enabled\n", ahc_name(ahc));
- else
- printf("%s: %sHigh byte termination "
- "Enabled\n", ahc_name(ahc),
- enableSEC_high ? "Secondary "
- : "");
- }
- }
+static int
+ahc_aic7880_setup(struct ahc_softc *ahc)
+{
+ uint8_t rev;
+
+ ahc->channel = 'A';
+ ahc->chip = AHC_AIC7880;
+ ahc->features = AHC_AIC7880_FE;
+ ahc->bugs |= AHC_TMODE_WIDEODD_BUG;
+ rev = PCI_REVISION(ahc->bd->class);
+ if (rev >= 1) {
+ ahc->bugs |= AHC_PCI_2_1_RETRY_BUG;
+ } else {
+ ahc->bugs |= AHC_CACHETHEN_BUG|AHC_PCI_MWI_BUG;
+ }
+ return (0);
+}
- sum = internal50_present + internal68_present
- + externalcable_present;
- if (sum < 2 || (enableSEC_low != 0)) {
- if ((ahc->features & AHC_ULTRA2) != 0)
- brddat |= BRDDAT5;
- else
- *sxfrctl1 |= STPWEN;
- if (bootverbose) {
- if ((ahc->flags & AHC_INT50_SPEEDFLEX) != 0)
- printf("%s: 50 pin termination "
- "Enabled\n", ahc_name(ahc));
- else
- printf("%s: %sLow byte termination "
- "Enabled\n", ahc_name(ahc),
- enableSEC_low ? "Secondary "
- : "");
- }
- }
+static int
+ahc_aha2940Pro_setup(struct ahc_softc *ahc)
+{
- if (enablePRI_low != 0) {
- *sxfrctl1 |= STPWEN;
- if (bootverbose)
- printf("%s: Primary Low Byte termination "
- "Enabled\n", ahc_name(ahc));
- }
+ ahc->flags |= AHC_INT50_SPEEDFLEX;
+ return (ahc_aic7880_setup(ahc));
+}
- /*
- * Setup STPWEN before setting up the rest of
- * the termination per the tech note on the U160 cards.
- */
- ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
-
- if (enablePRI_high != 0) {
- brddat |= BRDDAT4;
- if (bootverbose)
- printf("%s: Primary High Byte "
- "termination Enabled\n",
- ahc_name(ahc));
- }
-
- write_brdctl(ahc, brddat);
+static int
+ahc_aha394XU_setup(struct ahc_softc *ahc)
+{
+ int error;
- } else {
- if ((adapter_control & CFSTERM) != 0) {
- *sxfrctl1 |= STPWEN;
-
- if (bootverbose)
- printf("%s: %sLow byte termination Enabled\n",
- ahc_name(ahc),
- (ahc->features & AHC_ULTRA2) ? "Primary "
- : "");
- }
+ error = ahc_aic7880_setup(ahc);
+ if (error == 0)
+ error = ahc_aha394XX_setup(ahc);
+ return (error);
+}
- if ((adapter_control & CFWSTERM) != 0
- && (ahc->features & AHC_WIDE) != 0) {
- brddat |= BRDDAT6;
- if (bootverbose)
- printf("%s: %sHigh byte termination Enabled\n",
- ahc_name(ahc),
- (ahc->features & AHC_ULTRA2)
- ? "Secondary " : "");
- }
+static int
+ahc_aha398XU_setup(struct ahc_softc *ahc)
+{
+ int error;
- /*
- * Setup STPWEN before setting up the rest of
- * the termination per the tech note on the U160 cards.
- */
- ahc_outb(ahc, SXFRCTL1, *sxfrctl1);
+ error = ahc_aic7880_setup(ahc);
+ if (error == 0)
+ error = ahc_aha398XX_setup(ahc);
+ return (error);
+}
- if ((ahc->features & AHC_WIDE) != 0)
- write_brdctl(ahc, brddat);
- }
- SEEPROM_OUTB(sd, sd->sd_MS); /* Clear CS */
+static int
+ahc_aic7890_setup(struct ahc_softc *ahc)
+{
+ uint8_t rev;
+
+ ahc->channel = 'A';
+ ahc->chip = AHC_AIC7890;
+ ahc->features = AHC_AIC7890_FE;
+ ahc->flags |= AHC_NEWEEPROM_FMT;
+ rev = PCI_REVISION(ahc->bd->class);
+ if (rev == 0)
+ ahc->bugs |= AHC_AUTOFLUSH_BUG|AHC_CACHETHEN_BUG;
+ return (0);
}
-static void
-ahc_new_term_detect(ahc, enableSEC_low, enableSEC_high, enablePRI_low,
- enablePRI_high, eeprom_present)
- struct ahc_softc *ahc;
- int *enableSEC_low;
- int *enableSEC_high;
- int *enablePRI_low;
- int *enablePRI_high;
- int *eeprom_present;
+static int
+ahc_aic7892_setup(struct ahc_softc *ahc)
{
- u_int8_t brdctl;
- /*
- * BRDDAT7 = Eeprom
- * BRDDAT6 = Enable Secondary High Byte termination
- * BRDDAT5 = Enable Secondary Low Byte termination
- * BRDDAT4 = Enable Primary high byte termination
- * BRDDAT3 = Enable Primary low byte termination
- */
- brdctl = read_brdctl(ahc);
- *eeprom_present = brdctl & BRDDAT7;
- *enableSEC_high = (brdctl & BRDDAT6);
- *enableSEC_low = (brdctl & BRDDAT5);
- *enablePRI_high = (brdctl & BRDDAT4);
- *enablePRI_low = (brdctl & BRDDAT3);
+ ahc->channel = 'A';
+ ahc->chip = AHC_AIC7892;
+ ahc->features = AHC_AIC7892_FE;
+ ahc->flags |= AHC_NEWEEPROM_FMT;
+ ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
+ return (0);
}
-static void
-aic787X_cable_detect(ahc, internal50_present, internal68_present,
- externalcable_present, eeprom_present)
- struct ahc_softc *ahc;
- int *internal50_present;
- int *internal68_present;
- int *externalcable_present;
- int *eeprom_present;
+static int
+ahc_aic7895_setup(struct ahc_softc *ahc)
{
- u_int8_t brdctl;
+ uint8_t rev;
+ ahc->channel = (ahc->bd->func == 1) ? 'B' : 'A';
/*
- * First read the status of our cables.
- * Set the rom bank to 0 since the
- * bank setting serves as a multiplexor
- * for the cable detection logic.
- * BRDDAT5 controls the bank switch.
+ * The 'C' revision of the aic7895 has a few additional features.
*/
- write_brdctl(ahc, 0);
+ rev = PCI_REVISION(ahc->bd->class);
+ if (rev >= 4) {
+ ahc->chip = AHC_AIC7895C;
+ ahc->features = AHC_AIC7895C_FE;
+ } else {
+ u_int command;
- /*
- * Now read the state of the internal
- * connectors. BRDDAT6 is INT50 and
- * BRDDAT7 is INT68.
- */
- brdctl = read_brdctl(ahc);
- *internal50_present = (brdctl & BRDDAT6) ? 0 : 1;
- *internal68_present = (brdctl & BRDDAT7) ? 0 : 1;
+ ahc->chip = AHC_AIC7895;
+ ahc->features = AHC_AIC7895_FE;
+ /*
+ * The BIOS disables the use of MWI transactions
+ * since it does not have the MWI bug work around
+ * we have. Disabling MWI reduces performance, so
+ * turn it on again.
+ */
+ command = pci_conf_read(ahc->bd->pc, ahc->bd->tag, PCI_COMMAND_STATUS_REG);
+ command |= PCI_COMMAND_INVALIDATE_ENABLE;
+ pci_conf_write(ahc->bd->pc, ahc->bd->tag, PCI_COMMAND_STATUS_REG, command);
+ ahc->bugs |= AHC_PCI_MWI_BUG;
+ }
/*
- * Set the rom bank to 1 and determine
- * the other signals.
+ * XXX Does CACHETHEN really not work??? What about PCI retry?
+ * on C level chips. Need to test, but for now, play it safe.
*/
- write_brdctl(ahc, BRDDAT5);
+ ahc->bugs |= AHC_TMODE_WIDEODD_BUG|AHC_PCI_2_1_RETRY_BUG
+ | AHC_CACHETHEN_BUG;
+
+#if 0
+ uint32_t devconfig;
/*
- * Now read the state of the external
- * connectors. BRDDAT6 is EXT68 and
- * BRDDAT7 is EPROMPS.
+ * Cachesize must also be zero due to stray DAC
+ * problem when sitting behind some bridges.
*/
- brdctl = read_brdctl(ahc);
- *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
- *eeprom_present = (brdctl & BRDDAT7) ? 1 : 0;
-}
-
-static void
-aic785X_cable_detect(ahc, internal50_present, externalcable_present,
- eeprom_present)
- struct ahc_softc *ahc;
- int *internal50_present;
- int *externalcable_present;
- int *eeprom_present;
-{
- u_int8_t brdctl;
-
- ahc_outb(ahc, BRDCTL, BRDRW|BRDCS);
- ahc_outb(ahc, BRDCTL, 0);
- brdctl = ahc_inb(ahc, BRDCTL);
- *internal50_present = (brdctl & BRDDAT5) ? 0 : 1;
- *externalcable_present = (brdctl & BRDDAT6) ? 0 : 1;
-
- *eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
+ pci_conf_write(ahc->bd->pc, ahc->bd->tag, CSIZE_LATTIME, 0);
+ devconfig = pci_conf_read(ahc->bd->pc, ahc->bd->tag, DEVCONFIG);
+ devconfig |= MRDCEN;
+ pci_conf_write(ahc->bd->pc, ahc->bd->tag, DEVCONFIG, devconfig);
+#endif
+ ahc->flags |= AHC_NEWEEPROM_FMT;
+ return (0);
}
-static void
-write_brdctl(ahc, value)
- struct ahc_softc *ahc;
- u_int8_t value;
+static int
+ahc_aic7896_setup(struct ahc_softc *ahc)
{
- u_int8_t brdctl;
-
- if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
- brdctl = BRDSTB;
- if (ahc->channel == 'B')
- brdctl |= BRDCS;
- } else if ((ahc->features & AHC_ULTRA2) != 0) {
- brdctl = 0;
- } else {
- brdctl = BRDSTB|BRDCS;
- }
- ahc_outb(ahc, BRDCTL, brdctl);
- ahc_flush_device_writes(ahc);
- brdctl |= value;
- ahc_outb(ahc, BRDCTL, brdctl);
- ahc_flush_device_writes(ahc);
- if ((ahc->features & AHC_ULTRA2) != 0)
- brdctl |= BRDSTB_ULTRA2;
- else
- brdctl &= ~BRDSTB;
- ahc_outb(ahc, BRDCTL, brdctl);
- ahc_flush_device_writes(ahc);
- if ((ahc->features & AHC_ULTRA2) != 0)
- brdctl = 0;
- else
- brdctl &= ~BRDCS;
- ahc_outb(ahc, BRDCTL, brdctl);
+ ahc->channel = (ahc->bd->func == 1) ? 'B' : 'A';
+ ahc->chip = AHC_AIC7896;
+ ahc->features = AHC_AIC7896_FE;
+ ahc->flags |= AHC_NEWEEPROM_FMT;
+ ahc->bugs |= AHC_CACHETHEN_DIS_BUG;
+ return (0);
}
-static u_int8_t
-read_brdctl(ahc)
- struct ahc_softc *ahc;
+static int
+ahc_aic7899_setup(struct ahc_softc *ahc)
{
- u_int8_t brdctl;
- u_int8_t value;
-
- if ((ahc->chip & AHC_CHIPID_MASK) == AHC_AIC7895) {
- brdctl = BRDRW;
- if (ahc->channel == 'B')
- brdctl |= BRDCS;
- } else if ((ahc->features & AHC_ULTRA2) != 0) {
- brdctl = BRDRW_ULTRA2;
- } else {
- brdctl = BRDRW|BRDCS;
- }
- ahc_outb(ahc, BRDCTL, brdctl);
- ahc_flush_device_writes(ahc);
- value = ahc_inb(ahc, BRDCTL);
- ahc_outb(ahc, BRDCTL, 0);
- return (value);
+ ahc->channel = (ahc->bd->func == 1) ? 'B' : 'A';
+ ahc->chip = AHC_AIC7899;
+ ahc->features = AHC_AIC7899_FE;
+ ahc->flags |= AHC_NEWEEPROM_FMT;
+ ahc->bugs |= AHC_SCBCHAN_UPLOAD_BUG;
+ return (0);
}
static int
-acquire_seeprom(ahc, sd)
- struct ahc_softc *ahc;
- struct seeprom_descriptor *sd;
+ahc_aha29160C_setup(struct ahc_softc *ahc)
{
- int wait;
-
- if ((ahc->features & AHC_SPIOCAP) != 0
- && (ahc_inb(ahc, SPIOCAP) & SEEPROM) == 0)
- return (0);
+ int error;
- /*
- * Request access of the memory port. When access is
- * granted, SEERDY will go high. We use a 1 second
- * timeout which should be near 1 second more than
- * is needed. Reason: after the chip reset, there
- * should be no contention.
- */
- SEEPROM_OUTB(sd, sd->sd_MS);
- wait = 1000; /* 1 second timeout in msec */
- while (--wait && ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0)) {
- DELAY(1000); /* delay 1 msec */
- }
- if ((SEEPROM_STATUS_INB(sd) & sd->sd_RDY) == 0) {
- SEEPROM_OUTB(sd, 0);
- return (0);
- }
- return (1);
+ error = ahc_aic7899_setup(ahc);
+ if (error != 0)
+ return (error);
+ ahc->features |= AHC_REMOVABLE;
+ return (0);
}
-static void
-release_seeprom(sd)
- struct seeprom_descriptor *sd;
+static int
+ahc_raid_setup(struct ahc_softc *ahc)
{
- /* Release access to the memory port and the serial EEPROM. */
- SEEPROM_OUTB(sd, 0);
+ printf("RAID functionality unsupported\n");
+ return (ENXIO);
}
-#define DPE PCI_STATUS_PARITY_DETECT
-#define SSE PCI_STATUS_SPECIAL_ERROR
-#define RMA PCI_STATUS_MASTER_ABORT
-#define RTA PCI_STATUS_MASTER_TARGET_ABORT
-#define STA PCI_STATUS_TARGET_TARGET_ABORT
-#define DPR PCI_STATUS_PARITY_ERROR
-
-#define PCIDEBUG
-#ifdef PCIDEBUG
-#define PCI_PRINT(Printstuff) printf Printstuff
-#else
-#define PCI_PRINT(Printstuff)
-#endif
-
-void
-ahc_pci_intr(ahc)
- struct ahc_softc *ahc;
+static int
+ahc_aha394XX_setup(struct ahc_softc *ahc)
{
- pcireg_t status1;
- if ((ahc_inb(ahc, ERROR) & PCIERRSTAT) == 0)
- return;
- PCI_PRINT(("%s: PCI error Interrupt at seqaddr = 0x%x\n",
- ahc_name(ahc),
- ahc_inb(ahc, SEQADDR0) | (ahc_inb(ahc, SEQADDR1) << 8)));
-
- status1 = ahc_pci_read_config(ahc->dev_softc, PCI_COMMAND_STATUS_REG, 4);
-
-/* define AHC_SHOW_PCI_ERRORS to get painful errors on your i386 console */
-#ifdef AHC_SHOW_PCI_ERRORS
- if (status1 & DPE) {
- PCI_PRINT(("%s: Data Parity Error Detected during address "
- "or write data phase\n", ahc_name(ahc)));
- }
-#endif
- if (status1 & SSE) {
- PCI_PRINT(("%s: Signal System Error Detected\n", ahc_name(ahc)));
- }
- if (status1 & RMA) {
- PCI_PRINT(("%s: Received a Master Abort\n", ahc_name(ahc)));
- }
- if (status1 & RTA) {
- PCI_PRINT(("%s: Received a Target Abort\n", ahc_name(ahc)));
- }
- if (status1 & STA) {
- PCI_PRINT(("%s: Signaled a Target Abort\n", ahc_name(ahc)));
- }
- if (status1 & DPR) {
- PCI_PRINT(("%s: Data Parity Error has been reported via PERR#\n",
- ahc_name(ahc)));
+ switch (ahc->bd->dev) {
+ case AHC_394X_SLOT_CHANNEL_A:
+ ahc->channel = 'A';
+ break;
+ case AHC_394X_SLOT_CHANNEL_B:
+ ahc->channel = 'B';
+ break;
+ default:
+ printf("adapter at unexpected slot %d\n"
+ "unable to map to a channel\n",
+ ahc->bd->dev);
+ ahc->channel = 'A';
}
-
- ahc_pci_write_config(ahc->dev_softc, PCI_COMMAND_STATUS_REG, status1, 4);
+ return (0);
+}
- if ((status1 & (DPE|SSE|RMA|RTA|STA|DPR)) == 0) {
- printf("%s: Latched PCIERR interrupt with "
- "no status bits set\n", ahc_name(ahc));
- } else {
- ahc_outb(ahc, CLRINT, CLRPARERR);
- }
-
- ahc_unpause(ahc);
+static int
+ahc_aha398XX_setup(struct ahc_softc *ahc)
+{
- return;
+ switch (ahc->bd->dev) {
+ case AHC_398X_SLOT_CHANNEL_A:
+ ahc->channel = 'A';
+ break;
+ case AHC_398X_SLOT_CHANNEL_B:
+ ahc->channel = 'B';
+ break;
+ case AHC_398X_SLOT_CHANNEL_C:
+ ahc->channel = 'C';
+ break;
+ default:
+ printf("adapter at unexpected slot %d\n"
+ "unable to map to a channel\n",
+ ahc->bd->dev);
+ ahc->channel = 'A';
+ break;
+ }
+ ahc->flags |= AHC_LARGE_SEEPROM;
+ return (0);
}
static int
-verify_cksum(struct seeprom_config *sc)
+ahc_aha494XX_setup(struct ahc_softc *ahc)
{
- int i;
- int maxaddr;
- u_int32_t checksum;
- u_int16_t *scarray;
-
- maxaddr = (sizeof(*sc)/2) - 1;
- checksum = 0;
- scarray = (uint16_t *)sc;
-
- for (i = 0; i < maxaddr; i++)
- checksum = checksum + scarray[i];
- if (checksum == 0 ||
- (checksum & 0xFFFF) != sc->checksum) {
- return (0);
- } else {
- return (1);
+
+ switch (ahc->bd->dev) {
+ case AHC_494X_SLOT_CHANNEL_A:
+ ahc->channel = 'A';
+ break;
+ case AHC_494X_SLOT_CHANNEL_B:
+ ahc->channel = 'B';
+ break;
+ case AHC_494X_SLOT_CHANNEL_C:
+ ahc->channel = 'C';
+ break;
+ case AHC_494X_SLOT_CHANNEL_D:
+ ahc->channel = 'D';
+ break;
+ default:
+ printf("adapter at unexpected slot %d\n"
+ "unable to map to a channel\n",
+ ahc->bd->dev);
+ ahc->channel = 'A';
}
+ ahc->flags |= AHC_LARGE_SEEPROM;
+ return (0);
}