summaryrefslogtreecommitdiff
path: root/sys/dev/pci/ahc_pci.c
diff options
context:
space:
mode:
authorKenneth R Westerback <krw@cvs.openbsd.org>2003-12-24 22:45:46 +0000
committerKenneth R Westerback <krw@cvs.openbsd.org>2003-12-24 22:45:46 +0000
commit5b156d44dd8236cd26c977490c958658eafcdca6 (patch)
tree7ef4dfa6c4f8fb64f9f910339f02ab668f271d85 /sys/dev/pci/ahc_pci.c
parent5b78bc9ec37dd0ce858345ede4e4690aec39bdb6 (diff)
Sync ahc with NetBSD, which was in turn updated from FreeBSD by Pascal
Renauld of Network Storage Solutions, Inc. Many fixes, wider device support. In particular, the notorious 'Target 0' problem seems to be fixed. Does *not* include any updates to isa or eisa code beyond what was necessary to compile. Known issues: 1) Tagged Queuing is probably not optimal. 2) PPR negotiation may not be fully functional. 3) No support yet for freezing devices or channels. 4) The mechanism for preventing 'A' and 'B' channel confusion during probe can fail if scsibus > 254 found. 5) Requeuing I/O's not working. A workaround will be committed almost immediately. At the moment timeouts, SCSI message rejects, aborting SCB's and trying to freeze a device may cause incomplete i/o's to be reported as complete. 6) Verbosity and probe messages need work. 7) Last disk on bus seems to go through an extra re-negotiation. 8) >16 devices on an adapter will trigger the usual problems of total openings exceeding available SCB's under heavy load. Tested by deraadt@, beck@, miod@, naddy@, drahn@, marc@ amoung others. ok deraadt@.
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);
}