summaryrefslogtreecommitdiffstats
path: root/sys/dev
diff options
context:
space:
mode:
authorgibbs <gibbs@FreeBSD.org>2002-04-24 16:58:51 +0000
committergibbs <gibbs@FreeBSD.org>2002-04-24 16:58:51 +0000
commit27ca4db2579f6e74861db16299eeb52e158fa7a7 (patch)
tree7c875c3432e564099ae4c00ea9ad834cb36534d0 /sys/dev
parent06842004edacee7beec6cb72239ded59709506a2 (diff)
downloadFreeBSD-src-27ca4db2579f6e74861db16299eeb52e158fa7a7.zip
FreeBSD-src-27ca4db2579f6e74861db16299eeb52e158fa7a7.tar.gz
Major update to the aic7xxx driver:
ahc_eisa.c: ahc_pci.c: Conform to new aic7xxx IRQ API. Adapt to aic7xxx_freebsd -> aic7xxx_osm changes. aic7770.c: Disable card generated interrupt early in our probe for "extra safety" Commonize some seeprom code with the PCI side of the driver. aic7xxx.c: Correctly initialize a few scratch ram locations during a sequencer restart. This avoids spurious sequencer ram parity errors in some configurations. Include the softc in ahc_update_residual calls. We need it for some diagnostics in this code path. Flag a data overrun on an auto-request sense failure as a CAM_AUTOSENSE_FAIL rather than a CAM_DATA_RUN_ERR. Force a renegotiation after noticing a parity error. This covers targets that lose our negotiation settings but don't bother to give us a unit attention condition. This can happen if a target fails during a reselection of us during a cable pull. Convert some code to using constants. Fix some typos. Correct target mode message loop handling. ahc_clear_msg_state was not clearing the "need to go to message out phase" bit once our loop was over. Simplify some abort handling code. Include tag information in target mode immediate notify events. When shutting down EISA controllers, don't EISA BIOS settings in the high portions of scratch ram. This fixes warm boot issues on some systems. Save a bit of space by only allocating the SCBs that we can use. Avoid some code paths in ahc_abort_scbs() if we are currently acting as a target. Correctly cleanup stranded SCBs in the card's SCB array. These are SCBs who's mapping has already been torn down by code that aborted the SCB by seeing it in another list first. Add a comment about some potential bus reset issues for target mode on Twin (EISA only) controllers. aic7xxx.h: Cleanup the hardware scb definitions a bit. Allocate a ful 256 byte scb mapping index. This simplifies the lookup code since the table covers all possible (and potentially bogus) values. Make AHC_DEBUG work again. aic7xxx.reg: Updates to hardware SCB definition. New definitions for target mode fixes. aic7xxx.seq: In target mode, initialize SAVED_LUN just after we receive the identify message. It may be required in the error recovery path when a normal cdb packet (includes lun) is not sent up to the host for processing. Respond to irregular messages during a selection in target mode. Defer looking for space for a cdb packet until we are about to enter command phase. We want to be able to handle irregular messages even if we would otherwise return QUEUE_FULL or BUSY. Add support for sending Ignore Wide Residue messages as a target. In the disable disconnect case in target mode, set our transfer rate correctly once data are availble. aic7xxx_93cx6.c: aic7xxx_93cx6.h: Add the ability to write and erase the seeprom. aic7xxx_inline.h: Correct Big Endian handling of large cdb sizes (> 12 bytes). Adaptec to changes in the calc_residual API. Correct a target mode bug where we always attempted to service the input queue even if no progress could be made due to lack of ATIOs. aic7xxx_osm.c: Adaptec to new IRQ mapping API. The new API allows the core to only enable our IRQ mapping once it is safe (sufficient initialization) to do so. Slap bootverbose protection around some diagnostics. Only attempt DT phases if we are wide. aic7xxx_osm.h: Enable big endian support. Adjust for IRQ API change. aic7xxx_pci.c: Be more careful about relying on subvendor 9005 information. We now only trust it for HBAs. This should allow the driver to attach to some MBs where the subvendor/device information does not follow the Adaptec spec. Only enable interrupts on the card once we are fully setup. Disable external SCB ram usage on the aic7895. I have not been able to make it 100% reliable. Adjust to seeprom routines being properly prefixed with "ahc". Fix a few bugs in the external SCB ram probing routine. We need to clear any parity errors we've triggered during the probe to avoid future, fatal, interrupts. If we detect an invalid cable combination, pretent there are no cable at all. This will enable all of the terminators which is probably the safest configuration we can "guess". MFC after: 4 days
Diffstat (limited to 'sys/dev')
-rw-r--r--sys/dev/aic7xxx/ahc_eisa.c12
-rw-r--r--sys/dev/aic7xxx/ahc_pci.c10
-rw-r--r--sys/dev/aic7xxx/aic7770.c73
-rw-r--r--sys/dev/aic7xxx/aic7xxx.c323
-rw-r--r--sys/dev/aic7xxx/aic7xxx.h90
-rw-r--r--sys/dev/aic7xxx/aic7xxx.reg78
-rw-r--r--sys/dev/aic7xxx/aic7xxx.seq166
-rw-r--r--sys/dev/aic7xxx/aic7xxx_93cx6.c165
-rw-r--r--sys/dev/aic7xxx/aic7xxx_93cx6.h42
-rw-r--r--sys/dev/aic7xxx/aic7xxx_freebsd.c1953
-rw-r--r--sys/dev/aic7xxx/aic7xxx_freebsd.h516
-rw-r--r--sys/dev/aic7xxx/aic7xxx_inline.h64
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.c69
-rw-r--r--sys/dev/aic7xxx/aic7xxx_osm.h34
-rw-r--r--sys/dev/aic7xxx/aic7xxx_pci.c152
15 files changed, 858 insertions, 2889 deletions
diff --git a/sys/dev/aic7xxx/ahc_eisa.c b/sys/dev/aic7xxx/ahc_eisa.c
index f7552d4..eddfc9c 100644
--- a/sys/dev/aic7xxx/ahc_eisa.c
+++ b/sys/dev/aic7xxx/ahc_eisa.c
@@ -31,7 +31,7 @@
* $FreeBSD$
*/
-#include <dev/aic7xxx/aic7xxx_freebsd.h>
+#include <dev/aic7xxx/aic7xxx_osm.h>
#include <dev/eisa/eisaconf.h>
@@ -148,7 +148,7 @@ aic7770_attach(device_t dev)
return (ENOMEM);
}
ahc->dev_softc = dev;
- error = aic7770_config(ahc, entry);
+ error = aic7770_config(ahc, entry, /*unused ioport arg*/0);
if (error != 0) {
ahc_free(ahc);
return (error);
@@ -159,7 +159,7 @@ aic7770_attach(device_t dev)
}
int
-aic7770_map_registers(struct ahc_softc *ahc)
+aic7770_map_registers(struct ahc_softc *ahc, u_int unused_ioport_arg)
{
struct resource *regs;
int rid;
@@ -191,10 +191,10 @@ aic7770_map_int(struct ahc_softc *ahc, int irq)
if (ahc->platform_data->irq == NULL)
return (ENOMEM);
ahc->platform_data->irq_res_type = SYS_RES_IRQ;
- return (0);
+ return (ahc_map_int(ahc));
}
-static device_method_t ahc_eisa_methods[] = {
+static device_method_t ahc_eisa_device_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, aic7770_probe),
DEVMETHOD(device_attach, aic7770_attach),
@@ -204,7 +204,7 @@ static device_method_t ahc_eisa_methods[] = {
static driver_t ahc_eisa_driver = {
"ahc",
- ahc_eisa_methods,
+ ahc_eisa_device_methods,
sizeof(struct ahc_softc)
};
diff --git a/sys/dev/aic7xxx/ahc_pci.c b/sys/dev/aic7xxx/ahc_pci.c
index b76d232..6060810 100644
--- a/sys/dev/aic7xxx/ahc_pci.c
+++ b/sys/dev/aic7xxx/ahc_pci.c
@@ -33,7 +33,7 @@
* $FreeBSD$
*/
-#include <dev/aic7xxx/aic7xxx_freebsd.h>
+#include <dev/aic7xxx/aic7xxx_osm.h>
#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */
#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */
@@ -41,7 +41,7 @@
static int ahc_pci_probe(device_t dev);
static int ahc_pci_attach(device_t dev);
-static device_method_t ahc_pci_methods[] = {
+static device_method_t ahc_pci_device_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, ahc_pci_probe),
DEVMETHOD(device_attach, ahc_pci_attach),
@@ -51,7 +51,7 @@ static device_method_t ahc_pci_methods[] = {
static driver_t ahc_pci_driver = {
"ahc",
- ahc_pci_methods,
+ ahc_pci_device_methods,
sizeof(struct ahc_softc)
};
@@ -222,7 +222,7 @@ ahc_pci_map_int(struct ahc_softc *ahc)
if (ahc->platform_data->irq == NULL)
return (ENOMEM);
ahc->platform_data->irq_res_type = SYS_RES_IRQ;
- return (0);
+ return (ahc_map_int(ahc));
}
void
@@ -248,7 +248,7 @@ ahc_power_state_change(struct ahc_softc *ahc, ahc_power_state new_state)
pm_control = ahc_pci_read_config(ahc->dev_softc,
cap_offset + 4,
- /*bytes*/4);
+ /*bytes*/2);
pm_control &= ~0x3;
pm_control |= new_state;
ahc_pci_write_config(ahc->dev_softc,
diff --git a/sys/dev/aic7xxx/aic7770.c b/sys/dev/aic7xxx/aic7770.c
index 8383762..92239f5 100644
--- a/sys/dev/aic7xxx/aic7770.c
+++ b/sys/dev/aic7xxx/aic7770.c
@@ -9,34 +9,48 @@
* 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. 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 Public License ("GPL").
+ * 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: //depot/src/aic7xxx/aic7770.c#12 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7770.c#16 $
*
* $FreeBSD$
*/
-#include <dev/aic7xxx/aic7xxx_freebsd.h>
+#ifdef __linux__
+#include "aic7xxx_osm.h"
+#include "aic7xxx_inline.h"
+#include "aic7xxx_93cx6.h"
+#else
+#include <dev/aic7xxx/aic7xxx_osm.h>
#include <dev/aic7xxx/aic7xxx_inline.h>
#include <dev/aic7xxx/aic7xxx_93cx6.h>
+#endif
#define ID_AIC7770 0x04907770
#define ID_AHA_274x 0x04907771
@@ -88,7 +102,7 @@ aic7770_find_device(uint32_t id)
}
int
-aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry)
+aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry, u_int io)
{
int error;
u_int hostconf;
@@ -99,10 +113,18 @@ aic7770_config(struct ahc_softc *ahc, struct aic7770_identity *entry)
if (error != 0)
return (error);
- error = aic7770_map_registers(ahc);
+ error = aic7770_map_registers(ahc, io);
if (error != 0)
return (error);
+ /*
+ * 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
+ * storm.
+ */
+ ahc_intr_enable(ahc, FALSE);
+
ahc->description = entry->name;
error = ahc_softc_init(ahc);
@@ -223,7 +245,6 @@ aha2840_load_seeprom(struct ahc_softc *ahc)
{
struct seeprom_descriptor sd;
struct seeprom_config sc;
- uint16_t checksum = 0;
uint8_t scsi_conf;
int have_seeprom;
@@ -241,20 +262,12 @@ aha2840_load_seeprom(struct ahc_softc *ahc)
if (bootverbose)
printf("%s: Reading SEEPROM...", ahc_name(ahc));
- have_seeprom = read_seeprom(&sd,
- (uint16_t *)&sc,
- /*start_addr*/0,
- sizeof(sc)/2);
+ have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)&sc,
+ /*start_addr*/0, sizeof(sc)/2);
if (have_seeprom) {
- /* Check checksum */
- int i;
- int maxaddr = (sizeof(sc)/2) - 1;
- uint16_t *scarray = (uint16_t *)&sc;
- for (i = 0; i < maxaddr; i++)
- checksum = checksum + scarray[i];
- if (checksum != sc.checksum) {
+ if (ahc_verify_cksum(&sc) == 0) {
if(bootverbose)
printf ("checksum error\n");
have_seeprom = 0;
diff --git a/sys/dev/aic7xxx/aic7xxx.c b/sys/dev/aic7xxx/aic7xxx.c
index 8b6c634..654c4f9 100644
--- a/sys/dev/aic7xxx/aic7xxx.c
+++ b/sys/dev/aic7xxx/aic7xxx.c
@@ -2,6 +2,7 @@
* Core routines and tables shareable across OS platforms.
*
* 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
@@ -10,32 +11,46 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 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 Public License ("GPL").
+ * 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: //depot/src/aic7xxx/aic7xxx.c#43 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.c#59 $
*
* $FreeBSD$
*/
-#include <dev/aic7xxx/aic7xxx_freebsd.h>
+#ifdef __linux__
+#include "aic7xxx_osm.h"
+#include "aic7xxx_inline.h"
+#include "aicasm/aicasm_insformat.h"
+#else
+#include <dev/aic7xxx/aic7xxx_osm.h>
#include <dev/aic7xxx/aic7xxx_inline.h>
#include <dev/aic7xxx/aicasm/aicasm_insformat.h>
+#endif
/****************************** Softc Data ************************************/
struct ahc_softc_tailq ahc_tailq = TAILQ_HEAD_INITIALIZER(ahc_tailq);
@@ -129,6 +144,7 @@ static struct ahc_syncrate ahc_syncrates[] =
#include "aic7xxx_seq.h"
/**************************** Function Declarations ***************************/
+static void ahc_force_renegotiation(struct ahc_softc *ahc);
static struct ahc_tmode_tstate*
ahc_alloc_tstate(struct ahc_softc *ahc,
u_int scsi_id, char channel);
@@ -203,9 +219,6 @@ static u_int ahc_rem_scb_from_disc_list(struct ahc_softc *ahc,
static void ahc_add_curscb_to_free_list(struct ahc_softc *ahc);
static u_int ahc_rem_wscb(struct ahc_softc *ahc,
u_int scbpos, u_int prev);
-static int ahc_abort_scbs(struct ahc_softc *ahc, int target,
- char channel, int lun, u_int tag,
- role_t role, uint32_t status);
static void ahc_reset_current_bus(struct ahc_softc *ahc);
#ifdef AHC_DUMP_SEQ
static void ahc_dumpseq(struct ahc_softc *ahc);
@@ -237,9 +250,15 @@ ahc_restart(struct ahc_softc *ahc)
ahc_pause(ahc);
+ /* No more pending messages. */
+ ahc_clear_msg_state(ahc);
+
ahc_outb(ahc, SCSISIGO, 0); /* De-assert BSY */
ahc_outb(ahc, MSG_OUT, MSG_NOOP); /* No message to send */
ahc_outb(ahc, SXFRCTL1, ahc_inb(ahc, SXFRCTL1) & ~BITBUCKET);
+ ahc_outb(ahc, LASTPHASE, P_BUSFREE);
+ ahc_outb(ahc, SAVED_SCSIID, 0xFF);
+ ahc_outb(ahc, SAVED_LUN, 0xFF);
/*
* Ensure that the sequencer's idea of TQINPOS
@@ -319,7 +338,7 @@ ahc_run_qoutfifo(struct ahc_softc *ahc)
* Save off the residual
* if there is one.
*/
- ahc_update_residual(scb);
+ ahc_update_residual(ahc, scb);
ahc_done(ahc, scb);
}
}
@@ -480,7 +499,7 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
/*
* Save off the residual if there is one.
*/
- ahc_update_residual(scb);
+ ahc_update_residual(ahc, scb);
#ifdef AHC_DEBUG
if (ahc_debug & AHC_SHOWSENSE) {
ahc_print_path(ahc, scb);
@@ -705,19 +724,20 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
MSG_TYPE_INITIATOR_MSGIN;
ahc->msgin_index = 0;
}
- } else {
+ }
+#if AHC_TARGET_MODE
+ else {
if (bus_phase == P_MESGOUT) {
ahc->msg_type =
MSG_TYPE_TARGET_MSGOUT;
ahc->msgin_index = 0;
}
-#if AHC_TARGET_MODE
else
ahc_setup_target_msgin(ahc,
&devinfo,
scb);
-#endif
}
+#endif
}
ahc_handle_message_phase(ahc);
@@ -801,7 +821,12 @@ ahc_handle_seqint(struct ahc_softc *ahc, u_int intstat)
* target does a command complete.
*/
ahc_freeze_devq(ahc, scb);
- ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+ if ((scb->flags & SCB_SENSE) == 0) {
+ ahc_set_transaction_status(scb, CAM_DATA_RUN_ERR);
+ } else {
+ scb->flags &= ~SCB_SENSE;
+ ahc_set_transaction_status(scb, CAM_AUTOSENSE_FAIL);
+ }
ahc_freeze_scb(scb);
if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -1063,10 +1088,16 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
else
ahc_outb(ahc, MSG_OUT, mesg_out);
}
+ /*
+ * Force a renegotiation with this target just in
+ * case we are out of sync for some external reason
+ * unknown (or unreported) by the target.
+ */
+ ahc_force_renegotiation(ahc);
ahc_outb(ahc, CLRINT, CLRSCSIINT);
ahc_unpause(ahc);
} else if ((status & SELTO) != 0) {
- u_int scbptr;
+ u_int scbptr;
/* Stop the selection */
ahc_outb(ahc, SCSISEQ, 0);
@@ -1102,6 +1133,16 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
ahc_freeze_devq(ahc, scb);
}
ahc_outb(ahc, CLRINT, CLRSCSIINT);
+ /*
+ * Force a renegotiation with this target just in
+ * case the cable was pulled and will later be
+ * re-attached. The target may forget its negotiation
+ * settings with us should it attempt to reselect
+ * during the interruption. The target will not issue
+ * a unit attention in this case, so we must always
+ * renegotiate.
+ */
+ ahc_force_renegotiation(ahc);
ahc_restart(ahc);
} else if ((status & BUSFREE) != 0
&& (ahc_inb(ahc, SIMODE1) & ENBUSFREE) != 0) {
@@ -1167,7 +1208,6 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
printerror = 0;
} else if (ahc_sent_msg(ahc, AHCMSG_1B,
MSG_BUS_DEV_RESET, TRUE)) {
- struct ahc_devinfo devinfo;
#ifdef __FreeBSD__
/*
* Don't mark the user's request for this BDR
@@ -1267,7 +1307,6 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
ahc_inb(ahc, SEQADDR0)
| (ahc_inb(ahc, SEQADDR1) << 8));
}
- ahc_clear_msg_state(ahc);
ahc_outb(ahc, CLRINT, CLRSCSIINT);
ahc_restart(ahc);
} else {
@@ -1277,6 +1316,27 @@ ahc_handle_scsiint(struct ahc_softc *ahc, u_int intstat)
}
}
+/*
+ * Force renegotiation to occur the next time we initiate
+ * a command to the current device.
+ */
+static void
+ahc_force_renegotiation(struct ahc_softc *ahc)
+{
+ struct ahc_devinfo devinfo;
+ struct ahc_initiator_tinfo *targ_info;
+ struct ahc_tmode_tstate *tstate;
+
+ ahc_fetch_devinfo(ahc, &devinfo);
+ targ_info = ahc_fetch_transinfo(ahc,
+ devinfo.channel,
+ devinfo.our_scsiid,
+ devinfo.target,
+ &tstate);
+ ahc_update_neg_request(ahc, &devinfo, tstate,
+ targ_info, /*force*/TRUE);
+}
+
#define AHC_MAX_STEPS 2000
void
ahc_clear_critical_section(struct ahc_softc *ahc)
@@ -1343,9 +1403,8 @@ ahc_clear_critical_section(struct ahc_softc *ahc)
stepping = TRUE;
}
ahc_outb(ahc, HCNTRL, ahc->unpause);
- do {
+ while (!ahc_is_paused(ahc))
ahc_delay(200);
- } while (!ahc_is_paused(ahc));
}
if (stepping) {
ahc_outb(ahc, SIMODE0, simode0);
@@ -1364,11 +1423,18 @@ ahc_clear_intstat(struct ahc_softc *ahc)
ahc_outb(ahc, CLRSINT1, CLRSELTIMEO|CLRATNO|CLRSCSIRSTI
|CLRBUSFREE|CLRSCSIPERR|CLRPHASECHG|
CLRREQINIT);
+ ahc_flush_device_writes(ahc);
ahc_outb(ahc, CLRSINT0, CLRSELDO|CLRSELDI|CLRSELINGO);
+ ahc_flush_device_writes(ahc);
ahc_outb(ahc, CLRINT, CLRSCSIINT);
+ ahc_flush_device_writes(ahc);
}
/**************************** Debugging Routines ******************************/
+#ifdef AHC_DEBUG
+int ahc_debug = AHC_DEBUG;
+#endif
+
void
ahc_print_scb(struct scb *scb)
{
@@ -1437,7 +1503,7 @@ ahc_alloc_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel)
memcpy(tstate, master_tstate, sizeof(*tstate));
memset(tstate->enabled_luns, 0, sizeof(tstate->enabled_luns));
tstate->ultraenb = 0;
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < AHC_NUM_TARGETS; i++) {
memset(&tstate->transinfo[i].curr, 0,
sizeof(tstate->transinfo[i].curr));
memset(&tstate->transinfo[i].goal, 0,
@@ -1486,7 +1552,8 @@ ahc_free_tstate(struct ahc_softc *ahc, u_int scsi_id, char channel, int force)
struct ahc_syncrate *
ahc_devlimited_syncrate(struct ahc_softc *ahc,
struct ahc_initiator_tinfo *tinfo,
- u_int *period, u_int *ppr_options, role_t role) {
+ u_int *period, u_int *ppr_options, role_t role)
+{
struct ahc_transinfo *transinfo;
u_int maxsync;
@@ -2284,7 +2351,7 @@ ahc_construct_sdtr(struct ahc_softc *ahc, struct ahc_devinfo *devinfo,
}
/*
- * Build a wide negotiateion message in our message
+ * Build a wide negotiation message in our message
* buffer based on the input parameters.
*/
static void
@@ -2346,6 +2413,8 @@ ahc_clear_msg_state(struct ahc_softc *ahc)
ahc_outb(ahc, CLRSINT1, CLRATNO);
}
ahc_outb(ahc, MSG_OUT, MSG_NOOP);
+ ahc_outb(ahc, SEQ_FLAGS2,
+ ahc_inb(ahc, SEQ_FLAGS2) & ~TARGET_MSG_PENDING);
}
/*
@@ -2537,7 +2606,7 @@ reswitch:
/*
* Read the latched byte, but turn off SPIOEN first
- * so that we don't inadvertantly cause a REQ for the
+ * so that we don't inadvertently cause a REQ for the
* next byte.
*/
ahc_outb(ahc, SXFRCTL0, ahc_inb(ahc, SXFRCTL0) & ~SPIOEN);
@@ -2982,6 +3051,7 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
}
break;
}
+#ifdef AHC_TARGET_MODE
case MSG_BUS_DEV_RESET:
ahc_handle_devreset(ahc, devinfo,
CAM_BDR_SENT,
@@ -2993,18 +3063,20 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
case MSG_ABORT_TAG:
case MSG_ABORT:
case MSG_CLEAR_QUEUE:
-#ifdef AHC_TARGET_MODE
+ {
+ int tag;
+
/* Target mode messages */
if (devinfo->role != ROLE_TARGET) {
reject = TRUE;
break;
}
+ tag = SCB_LIST_NULL;
+ if (ahc->msgin_buf[0] == MSG_ABORT_TAG)
+ tag = ahc_inb(ahc, INITIATOR_TAG);
ahc_abort_scbs(ahc, devinfo->target, devinfo->channel,
- devinfo->lun,
- ahc->msgin_buf[0] == MSG_ABORT_TAG
- ? SCB_LIST_NULL
- : ahc_inb(ahc, INITIATOR_TAG),
- ROLE_TARGET, CAM_REQ_ABORTED);
+ devinfo->lun, tag, ROLE_TARGET,
+ CAM_REQ_ABORTED);
tstate = ahc->enabled_targets[devinfo->our_scsiid];
if (tstate != NULL) {
@@ -3015,12 +3087,14 @@ ahc_parse_msg(struct ahc_softc *ahc, struct ahc_devinfo *devinfo)
ahc_queue_lstate_event(ahc, lstate,
devinfo->our_scsiid,
ahc->msgin_buf[0],
- /*arg*/0);
+ /*arg*/tag);
ahc_send_lstate_events(ahc, lstate);
}
}
- done = MSGLOOP_MSGCOMPLETE;
+ ahc_restart(ahc);
+ done = MSGLOOP_TERMINATED;
break;
+ }
#endif
case MSG_TERM_IO_PROC:
default:
@@ -3475,7 +3549,7 @@ ahc_alloc(void *platform_arg, char *name)
ahc->bugs = AHC_BUGNONE;
ahc->flags = AHC_FNONE;
- for (i = 0; i < 16; i++)
+ for (i = 0; i < AHC_NUM_TARGETS; i++)
TAILQ_INIT(&ahc->untagged_queues[i]);
if (ahc_platform_alloc(ahc, platform_arg) != 0) {
ahc_free(ahc);
@@ -3562,6 +3636,22 @@ ahc_softc_insert(struct ahc_softc *ahc)
ahc->init_level++;
}
+/*
+ * Verify that the passed in softc pointer is for a
+ * controller that is still configured.
+ */
+struct ahc_softc *
+ahc_find_softc(struct ahc_softc *ahc)
+{
+ struct ahc_softc *list_ahc;
+
+ TAILQ_FOREACH(list_ahc, &ahc_tailq, links) {
+ if (list_ahc == ahc)
+ return (ahc);
+ }
+ return (NULL);
+}
+
void
ahc_set_unit(struct ahc_softc *ahc, int unit)
{
@@ -3662,7 +3752,7 @@ ahc_shutdown(void *arg)
ahc_outb(ahc, SXFRCTL0, 0);
ahc_outb(ahc, DSPCISTATUS, 0);
- for (i = TARG_SCSIRATE; i < HA_274_BIOSCTRL; i++)
+ for (i = TARG_SCSIRATE; i < SCSICONF; i++)
ahc_outb(ahc, i, 0);
}
@@ -3701,7 +3791,10 @@ ahc_reset(struct ahc_softc *ahc)
ahc_outb(ahc, HCNTRL, CHIPRST | ahc->pause);
/*
- * Ensure that the reset has finished
+ * Ensure that the reset has finished. We delay 1000us
+ * prior to reading the register to make sure the chip
+ * has sufficiently completed its reset to handle register
+ * accesses.
*/
wait = 1000;
do {
@@ -3815,10 +3908,6 @@ ahc_build_free_scb_list(struct ahc_softc *ahc)
/* Make sure that the last SCB terminates the free list */
ahc_outb(ahc, SCBPTR, i-1);
ahc_outb(ahc, SCB_NEXT, SCB_LIST_NULL);
-
- /* Ensure we clear the 0 SCB's control byte. */
- ahc_outb(ahc, SCBPTR, 0);
- ahc_outb(ahc, SCB_CONTROL, 0);
}
static int
@@ -3832,11 +3921,11 @@ ahc_init_scbdata(struct ahc_softc *ahc)
/* Allocate SCB resources */
scb_data->scbarray =
- (struct scb *)malloc(sizeof(struct scb) * AHC_SCB_MAX,
+ (struct scb *)malloc(sizeof(struct scb) * AHC_SCB_MAX_ALLOC,
M_DEVBUF, M_NOWAIT);
if (scb_data->scbarray == NULL)
return (ENOMEM);
- memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX);
+ memset(scb_data->scbarray, 0, sizeof(struct scb) * AHC_SCB_MAX_ALLOC);
/* Determine the number of hardware SCBs and initialize them */
@@ -3871,7 +3960,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
/*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL, /*filterarg*/NULL,
- AHC_SCB_MAX * sizeof(struct hardware_scb),
+ AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb),
/*nsegments*/1,
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
/*flags*/0, &scb_data->hscb_dmat) != 0) {
@@ -3892,7 +3981,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
/* And permanently map them */
ahc_dmamap_load(ahc, scb_data->hscb_dmat, scb_data->hscb_dmamap,
scb_data->hscbs,
- AHC_SCB_MAX * sizeof(struct hardware_scb),
+ AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb),
ahc_dmamap_cb, &scb_data->hscb_busaddr, /*flags*/0);
scb_data->init_level++;
@@ -3903,7 +3992,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
/*lowaddr*/BUS_SPACE_MAXADDR_32BIT,
/*highaddr*/BUS_SPACE_MAXADDR,
/*filter*/NULL, /*filterarg*/NULL,
- AHC_SCB_MAX * sizeof(struct scsi_sense_data),
+ AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data),
/*nsegments*/1,
/*maxsegsz*/BUS_SPACE_MAXSIZE_32BIT,
/*flags*/0, &scb_data->sense_dmat) != 0) {
@@ -3924,7 +4013,7 @@ ahc_init_scbdata(struct ahc_softc *ahc)
/* And permanently map them */
ahc_dmamap_load(ahc, scb_data->sense_dmat, scb_data->sense_dmamap,
scb_data->sense,
- AHC_SCB_MAX * sizeof(struct scsi_sense_data),
+ AHC_SCB_MAX_ALLOC * sizeof(struct scsi_sense_data),
ahc_dmamap_cb, &scb_data->sense_busaddr, /*flags*/0);
scb_data->init_level++;
@@ -3944,7 +4033,8 @@ ahc_init_scbdata(struct ahc_softc *ahc)
scb_data->init_level++;
/* Perform initial CCB allocation */
- memset(scb_data->hscbs, 0, AHC_SCB_MAX * sizeof(struct hardware_scb));
+ memset(scb_data->hscbs, 0,
+ AHC_SCB_MAX_ALLOC * sizeof(struct hardware_scb));
ahc_alloc_scbs(ahc);
if (scb_data->numscbs == 0) {
@@ -4036,7 +4126,7 @@ ahc_alloc_scbs(struct ahc_softc *ahc)
int i;
scb_data = ahc->scb_data;
- if (scb_data->numscbs >= AHC_SCB_MAX)
+ if (scb_data->numscbs >= AHC_SCB_MAX_ALLOC)
/* Can't allocate any more */
return;
@@ -4065,7 +4155,8 @@ ahc_alloc_scbs(struct ahc_softc *ahc)
physaddr = sg_map->sg_physaddr;
newcount = (PAGE_SIZE / (AHC_NSEG * sizeof(struct ahc_dma_seg)));
- for (i = 0; scb_data->numscbs < AHC_SCB_MAX && i < newcount; i++) {
+ newcount = MIN(newcount, (AHC_SCB_MAX_ALLOC - scb_data->numscbs));
+ for (i = 0; i < newcount; i++) {
struct scb_platform_data *pdata;
#ifndef __linux__
int error;
@@ -4137,7 +4228,7 @@ ahc_controller_info(struct ahc_softc *ahc, char *buf)
if ((ahc->flags & AHC_PAGESCBS) != 0)
sprintf(buf, "%d/%d SCBs",
- ahc->scb_data->maxhscbs, AHC_SCB_MAX);
+ ahc->scb_data->maxhscbs, AHC_MAX_QUEUE);
else
sprintf(buf, "%d SCBs", ahc->scb_data->maxhscbs);
}
@@ -4180,6 +4271,12 @@ ahc_init(struct ahc_softc *ahc)
}
}
printf ("\n");
+ /*
+ * Reading uninitialized scratch ram may
+ * generate parity errors.
+ */
+ ahc_outb(ahc, CLRINT, CLRPARERR);
+ ahc_outb(ahc, CLRINT, CLRBRKADRINT);
#endif
max_targ = 15;
@@ -4303,7 +4400,7 @@ ahc_init(struct ahc_softc *ahc)
ahc_outb(ahc, SEQ_FLAGS, 0);
ahc_outb(ahc, SEQ_FLAGS2, 0);
- if (ahc->scb_data->maxhscbs < AHC_SCB_MAX) {
+ if (ahc->scb_data->maxhscbs < AHC_SCB_MAX_ALLOC) {
ahc->flags |= AHC_PAGESCBS;
} else {
ahc->flags &= ~AHC_PAGESCBS;
@@ -4371,7 +4468,7 @@ ahc_init(struct ahc_softc *ahc)
tagenable = ALL_TARGETS_MASK;
/* Grab the disconnection disable table and invert it for our needs */
- if (ahc->flags & AHC_USEDEFAULTS) {
+ if ((ahc->flags & AHC_USEDEFAULTS) != 0) {
printf("%s: Host Adapter Bios disabled. Using default SCSI "
"device parameters\n", ahc_name(ahc));
ahc->flags |= AHC_EXTENDED_TRANS_A|AHC_EXTENDED_TRANS_B|
@@ -5014,7 +5111,8 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
uint8_t qinstart;
uint8_t qinpos;
uint8_t qintail;
- uint8_t next, prev;
+ uint8_t next;
+ uint8_t prev;
uint8_t curscbptr;
int found;
int maxtarget;
@@ -5029,7 +5127,6 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
} else
qinstart = ahc_inb(ahc, QINPOS);
qinpos = qinstart;
- next = ahc_inb(ahc, NEXT_QUEUED_SCB);
found = 0;
prev_scb = NULL;
@@ -5079,9 +5176,9 @@ ahc_search_qinfifo(struct ahc_softc *ahc, int target, char channel,
ahc_done(ahc, scb);
/* FALLTHROUGH */
+ }
case SEARCH_REMOVE:
break;
- }
case SEARCH_COUNT:
ahc_qinfifo_requeue(ahc, prev_scb, scb);
prev_scb = scb;
@@ -5507,24 +5604,40 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
maxlun = lun + 1;
}
- for (;i < maxtarget; i++) {
- for (j = minlun;j < maxlun; j++)
- ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, j));
- }
+ if (role != ROLE_TARGET) {
+ for (;i < maxtarget; i++) {
+ for (j = minlun;j < maxlun; j++) {
+ u_int scbid;
+ u_int tcl;
- /*
- * Go through the disconnected list and remove any entries we
- * have queued for completion, 0'ing their control byte too.
- * We save the active SCB and restore it ourselves, so there
- * is no reason for this search to restore it too.
- */
- ahc_search_disc_list(ahc, target, channel, lun, tag,
- /*stop_on_first*/FALSE, /*remove*/TRUE,
- /*save_state*/FALSE);
+ tcl = BUILD_TCL(i << 4, j);
+ scbid = ahc_index_busy_tcl(ahc, tcl);
+ scbp = ahc_lookup_scb(ahc, scbid);
+ if (scbp == NULL
+ || ahc_match_scb(ahc, scbp, target, channel,
+ lun, tag, role) == 0)
+ continue;
+ ahc_unbusy_tcl(ahc, BUILD_TCL(i << 4, j));
+ }
+ }
+
+ /*
+ * Go through the disconnected list and remove any entries we
+ * have queued for completion, 0'ing their control byte too.
+ * We save the active SCB and restore it ourselves, so there
+ * is no reason for this search to restore it too.
+ */
+ ahc_search_disc_list(ahc, target, channel, lun, tag,
+ /*stop_on_first*/FALSE, /*remove*/TRUE,
+ /*save_state*/FALSE);
+ }
/*
* Go through the hardware SCB array looking for commands that
- * were active but not on any list.
+ * were active but not on any list. In some cases, these remnants
+ * might not still have mappings in the scbindex array (e.g. unexpected
+ * bus free with the same scb queued for an abort). Don't hold this
+ * against them.
*/
for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
u_int scbid;
@@ -5532,8 +5645,9 @@ ahc_abort_scbs(struct ahc_softc *ahc, int target, char channel,
ahc_outb(ahc, SCBPTR, i);
scbid = ahc_inb(ahc, SCB_TAG);
scbp = ahc_lookup_scb(ahc, scbid);
- if (scbp != NULL
- && ahc_match_scb(ahc, scbp, target, channel, lun, tag, role))
+ if ((scbp == NULL && scbid != SCB_LIST_NULL)
+ || (scbp != NULL
+ && ahc_match_scb(ahc, scbp, target, channel, lun, tag, role)))
ahc_add_curscb_to_free_list(ahc);
}
@@ -5575,6 +5689,7 @@ ahc_reset_current_bus(struct ahc_softc *ahc)
ahc_outb(ahc, SIMODE1, ahc_inb(ahc, SIMODE1) & ~ENSCSIRST);
scsiseq = ahc_inb(ahc, SCSISEQ);
ahc_outb(ahc, SCSISEQ, scsiseq | SCSIRSTO);
+ ahc_flush_device_writes(ahc);
ahc_delay(AHC_BUSRESET_DELAY);
/* Turn off the bus reset */
ahc_outb(ahc, SCSISEQ, scsiseq & ~SCSIRSTO);
@@ -5616,6 +5731,16 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
*/
ahc_run_qoutfifo(ahc);
#if AHC_TARGET_MODE
+ /*
+ * XXX - In Twin mode, the tqinfifo may have commands
+ * for an unaffected channel in it. However, if
+ * we have run out of ATIO resources to drain that
+ * queue, we may not get them all out here. Further,
+ * the blocked transactions for the reset channel
+ * should just be killed off, irrespecitve of whether
+ * we are blocked on ATIO resources. Write a routine
+ * to compact the tqinfifo appropriately.
+ */
if ((ahc->flags & AHC_TARGETROLE) != 0) {
ahc_run_tqinfifo(ahc, /*paused*/TRUE);
}
@@ -5637,10 +5762,6 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
*/
ahc_outb(ahc, SBLKCTL, sblkctl ^ SELBUSB);
simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST);
- ahc_outb(ahc, SIMODE1, simode1);
- if (initiate_reset)
- ahc_reset_current_bus(ahc);
- ahc_clear_intstat(ahc);
#if AHC_TARGET_MODE
/*
* Bus resets clear ENSELI, so we cannot
@@ -5648,19 +5769,18 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
* if we are in target mode.
*/
if ((ahc->flags & AHC_TARGETROLE) != 0)
- ahc_outb(ahc, SIMODE1, simode1 | ENSCSIRST);
+ simode1 |= ENSCSIRST;
#endif
+ ahc_outb(ahc, SIMODE1, simode1);
+ if (initiate_reset)
+ ahc_reset_current_bus(ahc);
+ ahc_clear_intstat(ahc);
ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP));
ahc_outb(ahc, SBLKCTL, sblkctl);
restart_needed = FALSE;
} else {
/* Case 2: A command from this bus is active or we're idle */
- ahc_clear_msg_state(ahc);
simode1 = ahc_inb(ahc, SIMODE1) & ~(ENBUSFREE|ENSCSIRST);
- ahc_outb(ahc, SIMODE1, simode1);
- if (initiate_reset)
- ahc_reset_current_bus(ahc);
- ahc_clear_intstat(ahc);
#if AHC_TARGET_MODE
/*
* Bus resets clear ENSELI, so we cannot
@@ -5668,8 +5788,12 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
* if we are in target mode.
*/
if ((ahc->flags & AHC_TARGETROLE) != 0)
- ahc_outb(ahc, SIMODE1, simode1 | ENSCSIRST);
+ simode1 |= ENSCSIRST;
#endif
+ ahc_outb(ahc, SIMODE1, simode1);
+ if (initiate_reset)
+ ahc_reset_current_bus(ahc);
+ ahc_clear_intstat(ahc);
ahc_outb(ahc, SCSISEQ, scsiseq & (ENSELI|ENRSELI|ENAUTOATNP));
restart_needed = TRUE;
}
@@ -5748,7 +5872,7 @@ ahc_reset_channel(struct ahc_softc *ahc, char channel, int initiate_reset)
* Calculate the residual for a just completed SCB.
*/
void
-ahc_calc_residual(struct scb *scb)
+ahc_calc_residual(struct ahc_softc *ahc, struct scb *scb)
{
struct hardware_scb *hscb;
struct status_pkt *spkt;
@@ -6228,7 +6352,8 @@ ahc_dump_card_state(struct ahc_softc *ahc)
printf("ACCUM = 0x%x, SINDEX = 0x%x, DINDEX = 0x%x, ARG_2 = 0x%x\n",
ahc_inb(ahc, ACCUM), ahc_inb(ahc, SINDEX), ahc_inb(ahc, DINDEX),
ahc_inb(ahc, ARG_2));
- printf("HCNT = 0x%x\n", ahc_inb(ahc, HCNT));
+ printf("HCNT = 0x%x SCBPTR = 0x%x\n", ahc_inb(ahc, HCNT),
+ ahc_inb(ahc, SCBPTR));
printf("SCSISEQ = 0x%x, SBLKCTL = 0x%x\n",
ahc_inb(ahc, SCSISEQ), ahc_inb(ahc, SBLKCTL));
printf(" DFCNTRL = 0x%x, DFSTATUS = 0x%x\n",
@@ -6301,6 +6426,17 @@ ahc_dump_card_state(struct ahc_softc *ahc)
}
printf("\n");
+ printf("Sequencer SCB Info: ");
+ for (i = 0; i < ahc->scb_data->maxhscbs; i++) {
+ ahc_outb(ahc, SCBPTR, i);
+ printf("%d(c 0x%x, s 0x%x, l %d, t 0x%x) ",
+ i, ahc_inb(ahc, SCB_CONTROL),
+ ahc_inb(ahc, SCB_SCSIID),
+ ahc_inb(ahc, SCB_LUN),
+ ahc_inb(ahc, SCB_TAG));
+ }
+ printf("\n");
+
printf("Pending list: ");
i = 0;
LIST_FOREACH(scb, &ahc->pending_scbs, pending_links) {
@@ -6308,7 +6444,8 @@ ahc_dump_card_state(struct ahc_softc *ahc)
break;
if (scb != LIST_FIRST(&ahc->pending_scbs))
printf(", ");
- printf("%d", scb->hscb->tag);
+ printf("%d(c 0x%x, s 0x%x, l %d)", scb->hscb->tag,
+ scb->hscb->control, scb->hscb->scsiid, scb->hscb->lun);
if ((ahc->flags & AHC_PAGESCBS) == 0) {
ahc_outb(ahc, SCBPTR, scb->hscb->tag);
printf("(0x%x, 0x%x)", ahc_inb(ahc, SCB_CONTROL),
@@ -6836,6 +6973,8 @@ ahc_handle_target_cmd(struct ahc_softc *ahc, struct target_cmd *cmd)
/*
* Wait for more ATIOs from the peripheral driver for this lun.
*/
+ if (bootverbose)
+ printf("%s: ATIOs exhausted\n", ahc_name(ahc));
return (1);
} else
ahc->flags &= ~AHC_TQINFIFO_BLOCKED;
diff --git a/sys/dev/aic7xxx/aic7xxx.h b/sys/dev/aic7xxx/aic7xxx.h
index cc5bf76..6de2450 100644
--- a/sys/dev/aic7xxx/aic7xxx.h
+++ b/sys/dev/aic7xxx/aic7xxx.h
@@ -2,6 +2,7 @@
* Core definitions and data structures shareable across OS platforms.
*
* 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
@@ -10,25 +11,33 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 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 Public License ("GPL").
+ * 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: //depot/src/aic7xxx/aic7xxx.h#29 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx.h#40 $
*
* $FreeBSD$
*/
@@ -42,6 +51,7 @@
/************************* Forward Declarations *******************************/
struct ahc_platform_data;
struct scb_platform_data;
+struct seeprom_descriptor;
/****************************** Useful Macros *********************************/
#ifndef MAX
@@ -147,6 +157,13 @@ struct scb_platform_data;
#define AHC_MAX_QUEUE 253
/*
+ * The maximum amount of SCB storage we allocate in host memory. This
+ * number should reflect the 1 additional SCB we require to handle our
+ * qinfifo mechanism.
+ */
+#define AHC_SCB_MAX_ALLOC (AHC_MAX_QUEUE+1)
+
+/*
* Ring Buffer of incoming target commands.
* We allocate 256 to simplify the logic in the sequencer
* by using the natural wrap point of an 8bit counter.
@@ -373,10 +390,12 @@ struct status_pkt {
* Target mode version of the shared data SCB segment.
*/
struct target_data {
- uint8_t target_phases; /* Bitmap of phases to execute */
- uint8_t data_phase; /* Data-In or Data-Out */
- uint8_t scsi_status; /* SCSI status to give to initiator */
- uint8_t initiator_tag; /* Initiator's transaction tag */
+ uint32_t residual_datacnt; /* Residual in the current S/G seg */
+ uint32_t residual_sg_ptr; /* The next S/G for this transfer */
+ uint8_t scsi_status; /* SCSI status to give to initiator */
+ uint8_t target_phases; /* Bitmap of phases to execute */
+ uint8_t data_phase; /* Data-In or Data-Out */
+ uint8_t initiator_tag; /* Initiator's transaction tag */
};
struct hardware_scb {
@@ -387,10 +406,10 @@ struct hardware_scb {
* of the cdb payload as seen by the chip and a DMA
* is used to pull it in.
*/
- uint8_t cdb[12];
- uint32_t cdb_ptr;
- struct status_pkt status;
- struct target_data tdata;
+ uint8_t cdb[12];
+ uint32_t cdb_ptr;
+ struct status_pkt status;
+ struct target_data tdata;
} shared_data;
/*
* A word about residuals.
@@ -544,7 +563,15 @@ struct scb_data {
* Pool of SCBs ready to be assigned
* commands to execute.
*/
- struct scb *scbindex[AHC_SCB_MAX + 1];/* Mapping from tag to SCB */
+ struct scb *scbindex[256]; /*
+ * Mapping from tag to SCB.
+ * As tag identifiers are an
+ * 8bit value, we provide space
+ * for all possible tag values.
+ * Any lookups to entries at or
+ * above AHC_SCB_MAX_ALLOC will
+ * always fail.
+ */
struct hardware_scb *hscbs; /* Array of hardware SCBs */
struct scb *scbarray; /* Array of kernel SCBs */
struct scsi_sense_data *sense; /* Per SCB sense data */
@@ -1067,7 +1094,8 @@ int ahc_pci_config(struct ahc_softc *,
/*************************** EISA/VL Front End ********************************/
struct aic7770_identity *aic7770_find_device(uint32_t);
int aic7770_config(struct ahc_softc *ahc,
- struct aic7770_identity *);
+ struct aic7770_identity *,
+ u_int port);
/************************** SCB and SCB queue management **********************/
int ahc_probe_scbs(struct ahc_softc *);
@@ -1090,6 +1118,7 @@ void ahc_pause_and_flushwork(struct ahc_softc *ahc);
int ahc_suspend(struct ahc_softc *ahc);
int ahc_resume(struct ahc_softc *ahc);
void ahc_softc_insert(struct ahc_softc *);
+struct ahc_softc *ahc_find_softc(struct ahc_softc *ahc);
void ahc_set_unit(struct ahc_softc *, int);
void ahc_set_name(struct ahc_softc *, char *);
void ahc_alloc_scbs(struct ahc_softc *ahc);
@@ -1127,8 +1156,12 @@ int ahc_search_disc_list(struct ahc_softc *ahc, int target,
void ahc_freeze_devq(struct ahc_softc *ahc, struct scb *scb);
int ahc_reset_channel(struct ahc_softc *ahc, char channel,
int initiate_reset);
+int ahc_abort_scbs(struct ahc_softc *ahc, int target,
+ char channel, int lun, u_int tag,
+ role_t role, uint32_t status);
void ahc_restart(struct ahc_softc *ahc);
-void ahc_calc_residual(struct scb *scb);
+void ahc_calc_residual(struct ahc_softc *ahc,
+ struct scb *scb);
/*************************** Utility Functions ********************************/
struct ahc_phase_table_entry*
ahc_lookup_phase_entry(int phase);
@@ -1190,6 +1223,15 @@ cam_status ahc_find_tmode_devs(struct ahc_softc *ahc,
#endif
#endif
/******************************* Debug ***************************************/
+#ifdef AHC_DEBUG
+extern int ahc_debug;
+#define AHC_SHOWMISC 0x1
+#define AHC_SHOWSENSE 0x2
+#endif
void ahc_print_scb(struct scb *scb);
void ahc_dump_card_state(struct ahc_softc *ahc);
+/******************************* SEEPROM *************************************/
+int ahc_acquire_seeprom(struct ahc_softc *ahc,
+ struct seeprom_descriptor *sd);
+void ahc_release_seeprom(struct seeprom_descriptor *sd);
#endif /* _AIC7XXX_H_ */
diff --git a/sys/dev/aic7xxx/aic7xxx.reg b/sys/dev/aic7xxx/aic7xxx.reg
index 6d44293..c12e2b2 100644
--- a/sys/dev/aic7xxx/aic7xxx.reg
+++ b/sys/dev/aic7xxx/aic7xxx.reg
@@ -1,7 +1,8 @@
/*
* Aic7xxx register and scratch ram definitions.
*
- * Copyright (c) 1994-2001 Justin 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
@@ -10,27 +11,35 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 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 Public License ("GPL").
+ * 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.
*
* $FreeBSD$
*/
-VERSION = "$Id: //depot/src/aic7xxx/aic7xxx.reg#19 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.reg#27 $"
/*
* This file is processed by the aic7xxx_asm utility for use in assembling
@@ -328,6 +337,7 @@ register SSTAT3 {
access_mode RO
mask SCSICNT 0xf0
mask OFFCNT 0x0f
+ mask U2OFFCNT 0x7f
}
/*
@@ -999,12 +1009,13 @@ register SFUNCT {
* SCB Definition (p. 5-4)
*/
scb {
- address 0x0a0
+ address 0x0a0
+ size 64
+
SCB_CDB_PTR {
size 4
alias SCB_RESIDUAL_DATACNT
alias SCB_CDB_STORE
- alias SCB_TARGET_INFO
}
SCB_RESIDUAL_SGPTR {
size 4
@@ -1012,8 +1023,14 @@ scb {
SCB_SCSI_STATUS {
size 1
}
- SCB_CDB_STORE_PAD {
- size 3
+ SCB_TARGET_PHASES {
+ size 1
+ }
+ SCB_TARGET_DATA_DIR {
+ size 1
+ }
+ SCB_TARGET_ITAG {
+ size 1
}
SCB_DATAPTR {
size 4
@@ -1239,7 +1256,8 @@ register SG_CACHE_SHADOW {
*/
scratch_ram {
- address 0x020
+ address 0x020
+ size 58
/*
* 1 byte per target starting at this address for configuration values
@@ -1301,7 +1319,7 @@ scratch_ram {
bit SDMAENACK 0x10
bit HDMAEN 0x08
bit HDMAENACK 0x08
- bit DIRECTION 0x04
+ bit DIRECTION 0x04 /* Set indicates PCI->SCSI */
bit FIFOFLUSH 0x02
bit FIFORESET 0x01
}
@@ -1464,15 +1482,20 @@ scratch_ram {
SEQ_FLAGS2 {
size 1
- bit SCB_DMA 0x01
+ bit SCB_DMA 0x01
+ bit TARGET_MSG_PENDING 0x02
}
+}
+
+scratch_ram {
+ address 0x05a
+ size 6
/*
* These are reserved registers in the card's scratch ram. Some of
* the values are specified in the AHA2742 technical reference manual
* and are initialized by the BIOS at boot time.
*/
SCSICONF {
- address 0x05a
size 1
bit TERM_ENB 0x80
bit RESET_SCSI 0x40
@@ -1497,11 +1520,16 @@ scratch_ram {
mask BIOSDISABLED 0x30
bit CHANNEL_B_PRIMARY 0x08
}
+}
+
+scratch_ram {
+ address 0x070
+ size 16
+
/*
* Per target SCSI offset values for Ultra2 controllers.
*/
TARG_OFFSET {
- address 0x070
size 16
}
}
@@ -1529,10 +1557,6 @@ const CMD_GROUP_CODE_SHIFT 0x05
const STATUS_BUSY 0x08
const STATUS_QUEUE_FULL 0x28
-const SCB_TARGET_PHASES 0
-const SCB_TARGET_DATA_DIR 1
-const SCB_TARGET_STATUS 2
-const SCB_INITIATOR_TAG 3
const TARGET_DATA_IN 1
/*
diff --git a/sys/dev/aic7xxx/aic7xxx.seq b/sys/dev/aic7xxx/aic7xxx.seq
index fa42362..543c2d6 100644
--- a/sys/dev/aic7xxx/aic7xxx.seq
+++ b/sys/dev/aic7xxx/aic7xxx.seq
@@ -1,7 +1,8 @@
/*
* Adaptec 274x/284x/294x device driver firmware for Linux and FreeBSD.
*
- * Copyright (c) 1994-2001 Justin 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
@@ -10,28 +11,37 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 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 Public License ("GPL").
+ * 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.
*
* $FreeBSD$
*/
-VERSION = "$Id: //depot/src/aic7xxx/aic7xxx.seq#32 $"
+VERSION = "$Id: //depot/aic7xxx/aic7xxx/aic7xxx.seq#40 $"
+PATCH_ARG_LIST = "struct ahc_softc *ahc"
#include "aic7xxx.reg"
#include "scsi_message.h"
@@ -80,7 +90,7 @@ poll_for_work_loop:
test SSTAT0, SELDO|SELDI jnz selection;
test_queue:
/* Has the driver posted any work for us? */
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
if ((ahc->features & AHC_QUEUE_REGS) != 0) {
test QOFF_CTLSTA, SCB_AVAIL jz poll_for_work_loop;
} else {
@@ -101,7 +111,7 @@ BEGIN_CRITICAL
mov SCBPTR, ARG_1;
}
or SEQ_FLAGS2, SCB_DMA;
-END_CRITICAL
+END_CRITICAL;
dma_queued_scb:
/*
* DMA the SCB from host ram into the current SCB location.
@@ -115,7 +125,7 @@ dma_queued_scb:
* value.
*/
mov A, ARG_1;
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
cmp NEXT_QUEUED_SCB, A jne abort_qinscb;
if ((ahc->flags & AHC_SEQUENCER_DEBUG) != 0) {
cmp SCB_TAG, A je . + 2;
@@ -130,7 +140,7 @@ BEGIN_CRITICAL
inc QINPOS;
}
and SEQ_FLAGS2, ~SCB_DMA;
-END_CRITICAL
+END_CRITICAL;
start_waiting:
/*
* Start the first entry on the waiting SCB list.
@@ -242,6 +252,7 @@ select_in:
} else {
mov DFDAT, DINDEX;
}
+ and SAVED_LUN, MSG_IDENTIFY_LUNMASK, DINDEX;
/* Remember for disconnection decision */
test DINDEX, MSG_IDENTIFY_DISCFLAG jnz . + 2;
@@ -257,9 +268,10 @@ select_in:
* < MSG_IGN_WIDE_RESIDUE.
*/
add A, -MSG_SIMPLE_Q_TAG, DINDEX;
- jnc ident_messages_done;
+ jnc ident_messages_done_msg_pending;
add A, -MSG_IGN_WIDE_RESIDUE, DINDEX;
- jc ident_messages_done;
+ jc ident_messages_done_msg_pending;
+
/* Store for host */
if ((ahc->features & AHC_CMD_CHAN) != 0) {
mov CCSCBRAM, DINDEX;
@@ -285,9 +297,23 @@ select_in:
}
mov INITIATOR_TAG, DINDEX;
or SEQ_FLAGS, TARGET_CMD_IS_TAGGED;
- test SCSISIGI, ATNI jz . + 2;
- /* Initiator still wants to give us messages */
- call target_inb;
+
+ident_messages_done:
+ /* Terminate the ident list */
+ if ((ahc->features & AHC_CMD_CHAN) != 0) {
+ mvi CCSCBRAM, SCB_LIST_NULL;
+ } else {
+ mvi DFDAT, SCB_LIST_NULL;
+ }
+ or SEQ_FLAGS, TARG_CMD_PENDING|IDENTIFY_SEEN;
+ test SEQ_FLAGS2, TARGET_MSG_PENDING
+ jnz target_mesgout_pending;
+ test SCSISIGI, ATNI jnz target_mesgout_continue;
+ jmp target_ITloop;
+
+
+ident_messages_done_msg_pending:
+ or SEQ_FLAGS2, TARGET_MSG_PENDING;
jmp ident_messages_done;
/*
@@ -299,31 +325,6 @@ host_target_message_loop:
cmp RETURN_1, EXIT_MSG_LOOP je target_ITloop;
test SSTAT0, SPIORDY jz .;
jmp host_target_message_loop;
-
-ident_messages_done:
- /* If ring buffer is full, return busy or queue full */
- if ((ahc->features & AHC_HS_MAILBOX) != 0) {
- and A, HOST_TQINPOS, HS_MAILBOX;
- } else {
- mov A, KERNEL_TQINPOS;
- }
- cmp TQINPOS, A jne tqinfifo_has_space;
- mvi P_STATUS|BSYO call change_phase;
- test SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3;
- mvi STATUS_QUEUE_FULL call target_outb;
- jmp target_busfree_wait;
- mvi STATUS_BUSY call target_outb;
- jmp target_busfree_wait;
-tqinfifo_has_space:
- /* Terminate the ident list */
- if ((ahc->features & AHC_CMD_CHAN) != 0) {
- mvi CCSCBRAM, SCB_LIST_NULL;
- } else {
- mvi DFDAT, SCB_LIST_NULL;
- }
- or SEQ_FLAGS, TARG_CMD_PENDING|IDENTIFY_SEEN;
- test SCSISIGI, ATNI jnz target_mesgout_pending;
- jmp target_ITloop;
}
if ((ahc->flags & AHC_INITIATORROLE) != 0) {
@@ -464,13 +465,13 @@ select_out:
*/
test SCB_CONTROL, TAG_ENB jz . + 3;
mvi MSG_SIMPLE_Q_TAG call target_outb;
- mov SCB_TARGET_INFO[SCB_INITIATOR_TAG] call target_outb;
+ mov SCB_TARGET_ITAG call target_outb;
target_synccmd:
/*
* Now determine what phases the host wants us
* to go through.
*/
- mov SEQ_FLAGS, SCB_TARGET_INFO[SCB_TARGET_PHASES];
+ mov SEQ_FLAGS, SCB_TARGET_PHASES;
test SCB_CONTROL, MK_MESSAGE jz target_ITloop;
mvi P_MESGIN|BSYO call change_phase;
@@ -498,6 +499,7 @@ target_ITloop:
}
mvi DMAPARAMS, HDMAEN|DIRECTION|FIFORESET;
mov SCB_TAG call dma_scb;
+ call set_transfer_settings;
jmp target_synccmd;
target_mesgout:
@@ -528,6 +530,24 @@ target_busfree:
jmp poll_for_work;
target_cmdphase:
+ /*
+ * The target has dropped ATN (doesn't want to abort or BDR)
+ * and we believe this selection to be valid. If the ring
+ * buffer for new commands is full, return busy or queue full.
+ */
+ if ((ahc->features & AHC_HS_MAILBOX) != 0) {
+ and A, HOST_TQINPOS, HS_MAILBOX;
+ } else {
+ mov A, KERNEL_TQINPOS;
+ }
+ cmp TQINPOS, A jne tqinfifo_has_space;
+ mvi P_STATUS|BSYO call change_phase;
+ test SEQ_FLAGS, TARGET_CMD_IS_TAGGED jz . + 3;
+ mvi STATUS_QUEUE_FULL call target_outb;
+ jmp target_busfree_wait;
+ mvi STATUS_BUSY call target_outb;
+ jmp target_busfree_wait;
+tqinfifo_has_space:
mvi P_COMMAND|BSYO call change_phase;
call target_inb;
mov A, DINDEX;
@@ -576,15 +596,14 @@ target_dphase:
* data direction of the DMA. Toggle it for
* target transfers.
*/
- xor LASTPHASE, IOI, SCB_TARGET_INFO[SCB_TARGET_DATA_DIR];
- or SCB_TARGET_INFO[SCB_TARGET_DATA_DIR], BSYO
- call change_phase;
+ xor LASTPHASE, IOI, SCB_TARGET_DATA_DIR;
+ or SCB_TARGET_DATA_DIR, BSYO call change_phase;
jmp p_data;
target_sphase:
mvi P_STATUS|BSYO call change_phase;
mvi LASTPHASE, P_STATUS;
- mov SCB_TARGET_INFO[SCB_TARGET_STATUS] call target_outb;
+ mov SCB_SCSI_STATUS call target_outb;
/* XXX Watch for ATN or parity errors??? */
mvi SCSISIGO, P_MESGIN|BSYO;
/* MSG_CMDCMPLT is 0, but we can't do an immediate of 0 */
@@ -951,12 +970,12 @@ ultra2_dmafinish:
ultra2_ensure_sg:
test SG_CACHE_SHADOW, LAST_SEG jz ultra2_shvalid;
/* Record if we've consumed all S/G entries */
- test SSTAT2, SHVALID jnz residuals_correct;
+ test SSTAT2, SHVALID jnz residuals_correct;
or SCB_RESIDUAL_SGPTR[0], SG_LIST_NULL;
jmp residuals_correct;
ultra2_shvalid:
- test SSTAT2, SHVALID jnz sgptr_fixup;
+ test SSTAT2, SHVALID jnz sgptr_fixup;
call idle_loop;
jmp ultra2_ensure_sg;
@@ -1318,10 +1337,19 @@ residual_update_done:
and SEQ_FLAGS, ~DPHASE_PENDING;
/*
* For data-in phases, wait for any pending acks from the
- * initiator before changing phase.
+ * initiator before changing phase. We only need to
+ * send Ignore Wide Residue messages for data-in phases.
*/
test DFCNTRL, DIRECTION jz target_ITloop;
test SSTAT1, REQINIT jnz .;
+ test DATA_COUNT_ODD, 0x1 jz target_ITloop;
+ test SCSIRATE, WIDEXFER jz target_ITloop;
+ /*
+ * Issue an Ignore Wide Residue Message.
+ */
+ mvi P_MESGIN|BSYO call change_phase;
+ mvi MSG_IGN_WIDE_RESIDUE call target_outb;
+ mvi 1 call target_outb;
jmp target_ITloop;
} else {
jmp ITloop;
@@ -1371,7 +1399,7 @@ p_command_embedded:
* The data fifo seems to require 4 byte aligned
* transfers from the sequencer. Force this to
* be the case by clearing HADDR[0] even though
- * we aren't going to touch host memeory.
+ * we aren't going to touch host memory.
*/
clr HADDR[0];
if ((ahc->features & AHC_ULTRA2) != 0) {
@@ -1977,7 +2005,7 @@ target_outb:
* removal of the found SCB from the disconnected list.
*/
if ((ahc->flags & AHC_PAGESCBS) != 0) {
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
findSCB:
mov A, SINDEX; /* Tag passed in SINDEX */
cmp DISCONNECTED_SCBH, SCB_LIST_NULL je findSCB_notFound;
@@ -1999,7 +2027,7 @@ rem_scb_from_disc_list:
mov SCBPTR, SINDEX ret;
rHead:
mov DISCONNECTED_SCBH,SCB_NEXT ret;
-END_CRITICAL
+END_CRITICAL;
findSCB_notFound:
/*
* We didn't find it. Page in the SCB.
@@ -2124,7 +2152,7 @@ set_1byte_addr:
adc DINDIR, A, SINDIR ret;
/*
- * Either post or fetch and SCB from host memory based on the
+ * Either post or fetch an SCB from host memory based on the
* DIRECTION bit in DMAPARAMS. The host SCB index is in SINDEX.
*/
dma_scb:
@@ -2282,11 +2310,11 @@ cleanup_scb:
}
add_scb_to_free_list:
if ((ahc->flags & AHC_PAGESCBS) != 0) {
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
mov SCB_NEXT, FREE_SCBH;
mvi SCB_TAG, SCB_LIST_NULL;
mov FREE_SCBH, SCBPTR ret;
-END_CRITICAL
+END_CRITICAL;
} else {
mvi SCB_TAG, SCB_LIST_NULL ret;
}
@@ -2300,7 +2328,7 @@ set_hhaddr:
if ((ahc->flags & AHC_PAGESCBS) != 0) {
get_free_or_disc_scb:
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
cmp FREE_SCBH, SCB_LIST_NULL jne dequeue_free_scb;
cmp DISCONNECTED_SCBH, SCB_LIST_NULL jne dequeue_disc_scb;
return_error:
@@ -2309,14 +2337,14 @@ return_error:
dequeue_disc_scb:
mov SCBPTR, DISCONNECTED_SCBH;
mov DISCONNECTED_SCBH, SCB_NEXT;
-END_CRITICAL
+END_CRITICAL;
mvi DMAPARAMS, FIFORESET;
mov SCB_TAG jmp dma_scb;
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
dequeue_free_scb:
mov SCBPTR, FREE_SCBH;
mov FREE_SCBH, SCB_NEXT ret;
-END_CRITICAL
+END_CRITICAL;
add_scb_to_disc_list:
/*
@@ -2324,10 +2352,10 @@ add_scb_to_disc_list:
* candidates for paging out an SCB if one is needed for a new command.
* Modifying the disconnected list is a critical(pause dissabled) section.
*/
-BEGIN_CRITICAL
+BEGIN_CRITICAL;
mov SCB_NEXT, DISCONNECTED_SCBH;
mov DISCONNECTED_SCBH, SCBPTR ret;
-END_CRITICAL
+END_CRITICAL;
}
set_seqint:
mov INTSTAT, SINDEX;
diff --git a/sys/dev/aic7xxx/aic7xxx_93cx6.c b/sys/dev/aic7xxx/aic7xxx_93cx6.c
index c2a216d..18fd5d2 100644
--- a/sys/dev/aic7xxx/aic7xxx_93cx6.c
+++ b/sys/dev/aic7xxx/aic7xxx_93cx6.c
@@ -14,7 +14,7 @@
* derived from this software without specific prior written permission.
*
* Alternatively, this software may be distributed under the terms of the
- * GNU Public License ("GPL").
+ * GNU General Public License ("GPL").
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
@@ -28,7 +28,7 @@
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * $Id: //depot/src/aic7xxx/aic7xxx_93cx6.c#8 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.c#14 $
*
* $FreeBSD$
*/
@@ -67,9 +67,15 @@
*
*/
-#include <dev/aic7xxx/aic7xxx_freebsd.h>
+#ifdef __linux__
+#include "aic7xxx_osm.h"
+#include "aic7xxx_inline.h"
+#include "aic7xxx_93cx6.h"
+#else
+#include <dev/aic7xxx/aic7xxx_osm.h>
#include <dev/aic7xxx/aic7xxx_inline.h>
#include <dev/aic7xxx/aic7xxx_93cx6.h>
+#endif
/*
* Right now, we only have to read the SEEPROM. But we make it easier to
@@ -77,9 +83,13 @@
*/
static struct seeprom_cmd {
uint8_t len;
- uint8_t bits[3];
+ uint8_t bits[9];
} seeprom_read = {3, {1, 1, 0}};
+static struct seeprom_cmd seeprom_ewen = {9, {1, 0, 0, 1, 1, 0, 0, 0, 0}};
+static struct seeprom_cmd seeprom_ewds = {9, {1, 0, 0, 0, 0, 0, 0, 0, 0}};
+static struct seeprom_cmd seeprom_write = {3, {1, 0, 1}};
+
/*
* Wait for the SEERDY to go high; about 800 ns.
*/
@@ -90,15 +100,55 @@ static struct seeprom_cmd {
(void)SEEPROM_INB(sd); /* Clear clock */
/*
+ * Send a START condition and the given command
+ */
+static void
+send_seeprom_cmd(struct seeprom_descriptor *sd, struct seeprom_cmd *cmd)
+{
+ uint8_t temp;
+ int i = 0;
+
+ /* Send chip select for one clock cycle. */
+ temp = sd->sd_MS ^ sd->sd_CS;
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+
+ for (i = 0; i < cmd->len; i++) {
+ if (cmd->bits[i] != 0)
+ temp ^= sd->sd_DO;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ if (cmd->bits[i] != 0)
+ temp ^= sd->sd_DO;
+ }
+}
+
+/*
+ * Clear CS put the chip in the reset state, where it can wait for new commands.
+ */
+static void
+reset_seeprom(struct seeprom_descriptor *sd)
+{
+ uint8_t temp;
+
+ temp = sd->sd_MS;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+}
+
+/*
* Read the serial EEPROM and returns 1 if successful and 0 if
* not successful.
*/
int
-read_seeprom(sd, buf, start_addr, count)
- struct seeprom_descriptor *sd;
- uint16_t *buf;
- u_int start_addr;
- u_int count;
+ahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
+ u_int start_addr, u_int count)
{
int i = 0;
u_int k = 0;
@@ -110,26 +160,14 @@ read_seeprom(sd, buf, start_addr, count)
* will range from 0 to count-1.
*/
for (k = start_addr; k < count + start_addr; k++) {
- /* Send chip select for one clock cycle. */
- temp = sd->sd_MS ^ sd->sd_CS;
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
-
/*
* Now we're ready to send the read command followed by the
* address of the 16-bit register we want to read.
*/
- for (i = 0; i < seeprom_read.len; i++) {
- if (seeprom_read.bits[i] != 0)
- temp ^= sd->sd_DO;
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
- if (seeprom_read.bits[i] != 0)
- temp ^= sd->sd_DO;
- }
+ send_seeprom_cmd(sd, &seeprom_read);
+
/* Send the 6 or 8 bit address (MSB first, LSB last). */
+ temp = sd->sd_MS ^ sd->sd_CS;
for (i = (sd->sd_chip - 1); i >= 0; i--) {
if ((k & (1 << i)) != 0)
temp ^= sd->sd_DO;
@@ -161,13 +199,7 @@ read_seeprom(sd, buf, start_addr, count)
buf[k - start_addr] = v;
/* Reset the chip select for the next command cycle. */
- temp = sd->sd_MS;
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
- SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
- CLOCK_PULSE(sd, sd->sd_RDY);
- SEEPROM_OUTB(sd, temp);
- CLOCK_PULSE(sd, sd->sd_RDY);
+ reset_seeprom(sd);
}
#ifdef AHC_DUMP_EEPROM
printf("\nSerial EEPROM:\n\t");
@@ -182,8 +214,77 @@ read_seeprom(sd, buf, start_addr, count)
return (1);
}
+/*
+ * Write the serial EEPROM and return 1 if successful and 0 if
+ * not successful.
+ */
+int
+ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
+ u_int start_addr, u_int count)
+{
+ uint16_t v;
+ uint8_t temp;
+ int i, k;
+
+ /* Place the chip into write-enable mode */
+ send_seeprom_cmd(sd, &seeprom_ewen);
+ reset_seeprom(sd);
+
+ /* Write all requested data out to the seeprom. */
+ temp = sd->sd_MS ^ sd->sd_CS;
+ for (k = start_addr; k < count + start_addr; k++) {
+ /* Send the write command */
+ send_seeprom_cmd(sd, &seeprom_write);
+
+ /* Send the 6 or 8 bit address (MSB first). */
+ for (i = (sd->sd_chip - 1); i >= 0; i--) {
+ if ((k & (1 << i)) != 0)
+ temp ^= sd->sd_DO;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ if ((k & (1 << i)) != 0)
+ temp ^= sd->sd_DO;
+ }
+
+ /* Write the 16 bit value, MSB first */
+ v = buf[k - start_addr];
+ for (i = 15; i >= 0; i--) {
+ if ((v & (1 << i)) != 0)
+ temp ^= sd->sd_DO;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ if ((v & (1 << i)) != 0)
+ temp ^= sd->sd_DO;
+ }
+
+ /* Wait for the chip to complete the write */
+ temp = sd->sd_MS;
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ temp = sd->sd_MS ^ sd->sd_CS;
+ do {
+ SEEPROM_OUTB(sd, temp);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ SEEPROM_OUTB(sd, temp ^ sd->sd_CK);
+ CLOCK_PULSE(sd, sd->sd_RDY);
+ } while ((SEEPROM_DATA_INB(sd) & sd->sd_DI) == 0);
+
+ reset_seeprom(sd);
+ }
+
+ /* Put the chip back into write-protect mode */
+ send_seeprom_cmd(sd, &seeprom_ewds);
+ reset_seeprom(sd);
+
+ return (1);
+}
+
int
-verify_cksum(struct seeprom_config *sc)
+ahc_verify_cksum(struct seeprom_config *sc)
{
int i;
int maxaddr;
diff --git a/sys/dev/aic7xxx/aic7xxx_93cx6.h b/sys/dev/aic7xxx/aic7xxx_93cx6.h
index 6e003ef..c5b5dcb 100644
--- a/sys/dev/aic7xxx/aic7xxx_93cx6.h
+++ b/sys/dev/aic7xxx/aic7xxx_93cx6.h
@@ -12,25 +12,33 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 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 Public License ("GPL").
+ * 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: //depot/src/aic7xxx/aic7xxx_93cx6.h#5 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_93cx6.h#9 $
*
* $FreeBSD$
*/
@@ -85,8 +93,10 @@ do { \
#define SEEPROM_DATA_INB(sd) \
ahc_inb(sd->sd_ahc, sd->sd_dataout_offset)
-int read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
- u_int start_addr, u_int count);
-int verify_cksum(struct seeprom_config *sc);
+int ahc_read_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
+ u_int start_addr, u_int count);
+int ahc_write_seeprom(struct seeprom_descriptor *sd, uint16_t *buf,
+ u_int start_addr, u_int count);
+int ahc_verify_cksum(struct seeprom_config *sc);
#endif /* _AIC7XXX_93CX6_H_ */
diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.c b/sys/dev/aic7xxx/aic7xxx_freebsd.c
deleted file mode 100644
index 6582f8c..0000000
--- a/sys/dev/aic7xxx/aic7xxx_freebsd.c
+++ /dev/null
@@ -1,1953 +0,0 @@
-/*
- * Bus independent FreeBSD shim for the aic7xxx based adaptec SCSI controllers
- *
- * Copyright (c) 1994-2001 Justin T. Gibbs.
- * 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, this list of conditions, and the following disclaimer,
- * without modification.
- * 2. The name of the author may not 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 Public License ("GPL").
- *
- * 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
- * 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.
- *
- * $Id$
- *
- * $FreeBSD$
- */
-
-#include <dev/aic7xxx/aic7xxx_freebsd.h>
-#include <dev/aic7xxx/aic7xxx_inline.h>
-
-#ifndef AHC_TMODE_ENABLE
-#define AHC_TMODE_ENABLE 0
-#endif
-
-#define ccb_scb_ptr spriv_ptr0
-
-#ifdef AHC_DEBUG
-static int ahc_debug = AHC_DEBUG;
-#endif
-
-#if UNUSED
-static void ahc_dump_targcmd(struct target_cmd *cmd);
-#endif
-static int ahc_modevent(module_t mod, int type, void *data);
-static void ahc_action(struct cam_sim *sim, union ccb *ccb);
-static void ahc_get_tran_settings(struct ahc_softc *ahc,
- int our_id, char channel,
- struct ccb_trans_settings *cts);
-static void ahc_async(void *callback_arg, uint32_t code,
- struct cam_path *path, void *arg);
-static void ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs,
- int nsegments, int error);
-static void ahc_poll(struct cam_sim *sim);
-static void ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim,
- struct ccb_scsiio *csio, struct scb *scb);
-static void ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim,
- union ccb *ccb);
-static int ahc_create_path(struct ahc_softc *ahc,
- char channel, u_int target, u_int lun,
- struct cam_path **path);
-
-static void ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb);
-
-static int
-ahc_create_path(struct ahc_softc *ahc, char channel, u_int target,
- u_int lun, struct cam_path **path)
-{
- path_id_t path_id;
-
- if (channel == 'B')
- path_id = cam_sim_path(ahc->platform_data->sim_b);
- else
- path_id = cam_sim_path(ahc->platform_data->sim);
-
- return (xpt_create_path(path, /*periph*/NULL,
- path_id, target, lun));
-}
-
-/*
- * Attach all the sub-devices we can find
- */
-int
-ahc_attach(struct ahc_softc *ahc)
-{
- char ahc_info[256];
- struct ccb_setasync csa;
- struct cam_devq *devq;
- int bus_id;
- int bus_id2;
- struct cam_sim *sim;
- struct cam_sim *sim2;
- struct cam_path *path;
- struct cam_path *path2;
- long s;
- int count;
- int error;
-
- count = 0;
- sim = NULL;
- sim2 = NULL;
-
- ahc_controller_info(ahc, ahc_info);
- printf("%s\n", ahc_info);
- ahc_lock(ahc, &s);
- /* Hook up our interrupt handler */
- if ((error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq,
- INTR_TYPE_CAM|INTR_ENTROPY, ahc_platform_intr, ahc,
- &ahc->platform_data->ih)) != 0) {
- device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n",
- error);
- goto fail;
- }
-
- /*
- * Attach secondary channel first if the user has
- * declared it the primary channel.
- */
- if ((ahc->features & AHC_TWIN) != 0
- && (ahc->flags & AHC_PRIMARY_CHANNEL) != 0) {
- bus_id = 1;
- bus_id2 = 0;
- } else {
- bus_id = 0;
- bus_id2 = 1;
- }
-
- /*
- * Create the device queue for our SIM(s).
- */
- devq = cam_simq_alloc(AHC_MAX_QUEUE);
- if (devq == NULL)
- goto fail;
-
- /*
- * Construct our first channel SIM entry
- */
- sim = cam_sim_alloc(ahc_action, ahc_poll, "ahc", ahc,
- device_get_unit(ahc->dev_softc),
- 1, AHC_MAX_QUEUE, devq);
- if (sim == NULL) {
- cam_simq_free(devq);
- goto fail;
- }
-
- if (xpt_bus_register(sim, bus_id) != CAM_SUCCESS) {
- cam_sim_free(sim, /*free_devq*/TRUE);
- sim = NULL;
- goto fail;
- }
-
- if (xpt_create_path(&path, /*periph*/NULL,
- cam_sim_path(sim), CAM_TARGET_WILDCARD,
- CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- xpt_bus_deregister(cam_sim_path(sim));
- cam_sim_free(sim, /*free_devq*/TRUE);
- sim = NULL;
- goto fail;
- }
-
- xpt_setup_ccb(&csa.ccb_h, path, /*priority*/5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_LOST_DEVICE;
- csa.callback = ahc_async;
- csa.callback_arg = sim;
- xpt_action((union ccb *)&csa);
- count++;
-
- if (ahc->features & AHC_TWIN) {
- sim2 = cam_sim_alloc(ahc_action, ahc_poll, "ahc",
- ahc, device_get_unit(ahc->dev_softc), 1,
- AHC_MAX_QUEUE, devq);
-
- if (sim2 == NULL) {
- printf("ahc_attach: Unable to attach second "
- "bus due to resource shortage");
- goto fail;
- }
-
- if (xpt_bus_register(sim2, bus_id2) != CAM_SUCCESS) {
- printf("ahc_attach: Unable to attach second "
- "bus due to resource shortage");
- /*
- * We do not want to destroy the device queue
- * because the first bus is using it.
- */
- cam_sim_free(sim2, /*free_devq*/FALSE);
- goto fail;
- }
-
- if (xpt_create_path(&path2, /*periph*/NULL,
- cam_sim_path(sim2),
- CAM_TARGET_WILDCARD,
- CAM_LUN_WILDCARD) != CAM_REQ_CMP) {
- xpt_bus_deregister(cam_sim_path(sim2));
- cam_sim_free(sim2, /*free_devq*/FALSE);
- sim2 = NULL;
- goto fail;
- }
- xpt_setup_ccb(&csa.ccb_h, path2, /*priority*/5);
- csa.ccb_h.func_code = XPT_SASYNC_CB;
- csa.event_enable = AC_LOST_DEVICE;
- csa.callback = ahc_async;
- csa.callback_arg = sim2;
- xpt_action((union ccb *)&csa);
- count++;
- }
-
-fail:
- if ((ahc->features & AHC_TWIN) != 0
- && (ahc->flags & AHC_PRIMARY_CHANNEL) != 0) {
- ahc->platform_data->sim_b = sim;
- ahc->platform_data->path_b = path;
- ahc->platform_data->sim = sim2;
- ahc->platform_data->path = path2;
- } else {
- ahc->platform_data->sim = sim;
- ahc->platform_data->path = path;
- ahc->platform_data->sim_b = sim2;
- ahc->platform_data->path_b = path2;
- }
- ahc_unlock(ahc, &s);
-
- if (count != 0)
- /* We have to wait until after any system dumps... */
- ahc->platform_data->eh =
- EVENTHANDLER_REGISTER(shutdown_final, ahc_shutdown,
- ahc, SHUTDOWN_PRI_DEFAULT);
-
- return (count);
-}
-
-/*
- * Catch an interrupt from the adapter
- */
-void
-ahc_platform_intr(void *arg)
-{
- struct ahc_softc *ahc;
-
- ahc = (struct ahc_softc *)arg;
- ahc_intr(ahc);
-}
-
-/*
- * We have an scb which has been processed by the
- * adaptor, now we look to see how the operation
- * went.
- */
-void
-ahc_done(struct ahc_softc *ahc, struct scb *scb)
-{
- union ccb *ccb;
-
- CAM_DEBUG(scb->io_ctx->ccb_h.path, CAM_DEBUG_TRACE,
- ("ahc_done - scb %d\n", scb->hscb->tag));
-
- ccb = scb->io_ctx;
- LIST_REMOVE(scb, pending_links);
- if ((scb->flags & SCB_UNTAGGEDQ) != 0) {
- struct scb_tailq *untagged_q;
- int target_offset;
-
- target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
- untagged_q = &ahc->untagged_queues[target_offset];
- TAILQ_REMOVE(untagged_q, scb, links.tqe);
- scb->flags &= ~SCB_UNTAGGEDQ;
- ahc_run_untagged_queue(ahc, untagged_q);
- }
-
- untimeout(ahc_timeout, (caddr_t)scb, ccb->ccb_h.timeout_ch);
-
- if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
- bus_dmasync_op_t op;
-
- if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
- op = BUS_DMASYNC_POSTREAD;
- else
- op = BUS_DMASYNC_POSTWRITE;
- bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op);
- bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
- }
-
- if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
- struct cam_path *ccb_path;
-
- /*
- * If we have finally disconnected, clean up our
- * pending device state.
- * XXX - There may be error states that cause where
- * we will remain connected.
- */
- ccb_path = ccb->ccb_h.path;
- if (ahc->pending_device != NULL
- && xpt_path_comp(ahc->pending_device->path, ccb_path) == 0) {
-
- if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
- ahc->pending_device = NULL;
- } else {
- xpt_print_path(ccb->ccb_h.path);
- printf("Still disconnected\n");
- ahc_freeze_ccb(ccb);
- }
- }
-
- if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG)
- ccb->ccb_h.status |= CAM_REQ_CMP;
- ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
- ahc_free_scb(ahc, scb);
- xpt_done(ccb);
- return;
- }
-
- /*
- * If the recovery SCB completes, we have to be
- * out of our timeout.
- */
- if ((scb->flags & SCB_RECOVERY_SCB) != 0) {
- struct scb *list_scb;
-
- /*
- * We were able to complete the command successfully,
- * so reinstate the timeouts for all other pending
- * commands.
- */
- LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) {
- union ccb *ccb;
- uint64_t time;
-
- ccb = list_scb->io_ctx;
- if (ccb->ccb_h.timeout == CAM_TIME_INFINITY)
- continue;
-
- time = ccb->ccb_h.timeout;
- time *= hz;
- time /= 1000;
- ccb->ccb_h.timeout_ch =
- timeout(ahc_timeout, list_scb, time);
- }
-
- if (ahc_get_transaction_status(scb) == CAM_BDR_SENT
- || ahc_get_transaction_status(scb) == CAM_REQ_ABORTED)
- ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
- ahc_print_path(ahc, scb);
- printf("no longer in timeout, status = %x\n",
- ccb->ccb_h.status);
- }
-
- /* Don't clobber any existing error state */
- if (ahc_get_transaction_status(scb) == CAM_REQ_INPROG) {
- ccb->ccb_h.status |= CAM_REQ_CMP;
- } else if ((scb->flags & SCB_SENSE) != 0) {
- /*
- * We performed autosense retrieval.
- *
- * Zero any sense not transferred by the
- * device. The SCSI spec mandates that any
- * untransfered data should be assumed to be
- * zero. Complete the 'bounce' of sense information
- * through buffers accessible via bus-space by
- * copying it into the clients csio.
- */
- memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
- memcpy(&ccb->csio.sense_data,
- ahc_get_sense_buf(ahc, scb),
- (scb->sg_list->len & AHC_SG_LEN_MASK)
- - ccb->csio.sense_resid);
- scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID;
- }
- ccb->ccb_h.status &= ~CAM_SIM_QUEUED;
- ahc_free_scb(ahc, scb);
- xpt_done(ccb);
-}
-
-static void
-ahc_action(struct cam_sim *sim, union ccb *ccb)
-{
- struct ahc_softc *ahc;
- struct ahc_tmode_lstate *lstate;
- u_int target_id;
- u_int our_id;
- long s;
-
- CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_TRACE, ("ahc_action\n"));
-
- ahc = (struct ahc_softc *)cam_sim_softc(sim);
-
- target_id = ccb->ccb_h.target_id;
- our_id = SIM_SCSI_ID(ahc, sim);
-
- switch (ccb->ccb_h.func_code) {
- /* Common cases first */
- case XPT_ACCEPT_TARGET_IO: /* Accept Host Target Mode CDB */
- case XPT_CONT_TARGET_IO:/* Continue Host Target I/O Connection*/
- {
- struct ahc_tmode_tstate *tstate;
- cam_status status;
-
- status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate,
- &lstate, TRUE);
-
- if (status != CAM_REQ_CMP) {
- if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
- /* Response from the black hole device */
- tstate = NULL;
- lstate = ahc->black_hole;
- } else {
- ccb->ccb_h.status = status;
- xpt_done(ccb);
- break;
- }
- }
- if (ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO) {
-
- ahc_lock(ahc, &s);
- SLIST_INSERT_HEAD(&lstate->accept_tios, &ccb->ccb_h,
- sim_links.sle);
- ccb->ccb_h.status = CAM_REQ_INPROG;
- if ((ahc->flags & AHC_TQINFIFO_BLOCKED) != 0)
- ahc_run_tqinfifo(ahc, /*paused*/FALSE);
- ahc_unlock(ahc, &s);
- break;
- }
-
- /*
- * The target_id represents the target we attempt to
- * select. In target mode, this is the initiator of
- * the original command.
- */
- our_id = target_id;
- target_id = ccb->csio.init_id;
- /* FALLTHROUGH */
- }
- case XPT_SCSI_IO: /* Execute the requested I/O operation */
- case XPT_RESET_DEV: /* Bus Device Reset the specified SCSI device */
- {
- struct scb *scb;
- struct hardware_scb *hscb;
-
- if ((ahc->flags & AHC_INITIATORROLE) == 0
- && (ccb->ccb_h.func_code == XPT_SCSI_IO
- || ccb->ccb_h.func_code == XPT_RESET_DEV)) {
- ccb->ccb_h.status = CAM_PROVIDE_FAIL;
- xpt_done(ccb);
- return;
- }
-
- /*
- * get an scb to use.
- */
- ahc_lock(ahc, &s);
- if ((scb = ahc_get_scb(ahc)) == NULL) {
-
- xpt_freeze_simq(sim, /*count*/1);
- ahc->flags |= AHC_RESOURCE_SHORTAGE;
- ahc_unlock(ahc, &s);
- ccb->ccb_h.status = CAM_REQUEUE_REQ;
- xpt_done(ccb);
- return;
- }
- ahc_unlock(ahc, &s);
-
- hscb = scb->hscb;
-
- CAM_DEBUG(ccb->ccb_h.path, CAM_DEBUG_SUBTRACE,
- ("start scb(%p)\n", scb));
- scb->io_ctx = ccb;
- /*
- * So we can find the SCB when an abort is requested
- */
- ccb->ccb_h.ccb_scb_ptr = scb;
-
- /*
- * Put all the arguments for the xfer in the scb
- */
- hscb->control = 0;
- hscb->scsiid = BUILD_SCSIID(ahc, sim, target_id, our_id);
- hscb->lun = ccb->ccb_h.target_lun;
- if (ccb->ccb_h.func_code == XPT_RESET_DEV) {
- hscb->cdb_len = 0;
- scb->flags |= SCB_DEVICE_RESET;
- hscb->control |= MK_MESSAGE;
- ahc_execute_scb(scb, NULL, 0, 0);
- } else {
- if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
- struct target_data *tdata;
-
- tdata = &hscb->shared_data.tdata;
- if (ahc->pending_device == lstate)
- scb->flags |= SCB_TARGET_IMMEDIATE;
- hscb->control |= TARGET_SCB;
- tdata->target_phases = IDENTIFY_SEEN;
- if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
- tdata->target_phases |= SPHASE_PENDING;
- tdata->scsi_status =
- ccb->csio.scsi_status;
- }
- if (ccb->ccb_h.flags & CAM_DIS_DISCONNECT)
- tdata->target_phases |= NO_DISCONNECT;
-
- tdata->initiator_tag = ccb->csio.tag_id;
- }
- if (ccb->ccb_h.flags & CAM_TAG_ACTION_VALID)
- hscb->control |= ccb->csio.tag_action;
-
- ahc_setup_data(ahc, sim, &ccb->csio, scb);
- }
- break;
- }
- case XPT_NOTIFY_ACK:
- case XPT_IMMED_NOTIFY:
- {
- struct ahc_tmode_tstate *tstate;
- struct ahc_tmode_lstate *lstate;
- cam_status status;
-
- status = ahc_find_tmode_devs(ahc, sim, ccb, &tstate,
- &lstate, TRUE);
-
- if (status != CAM_REQ_CMP) {
- ccb->ccb_h.status = status;
- xpt_done(ccb);
- break;
- }
- SLIST_INSERT_HEAD(&lstate->immed_notifies, &ccb->ccb_h,
- sim_links.sle);
- ccb->ccb_h.status = CAM_REQ_INPROG;
- ahc_send_lstate_events(ahc, lstate);
- break;
- }
- case XPT_EN_LUN: /* Enable LUN as a target */
- ahc_handle_en_lun(ahc, sim, ccb);
- xpt_done(ccb);
- break;
- case XPT_ABORT: /* Abort the specified CCB */
- {
- ahc_abort_ccb(ahc, sim, ccb);
- break;
- }
- case XPT_SET_TRAN_SETTINGS:
- {
-#ifdef AHC_NEW_TRAN_SETTINGS
- struct ahc_devinfo devinfo;
- struct ccb_trans_settings *cts;
- struct ccb_trans_settings_scsi *scsi;
- struct ccb_trans_settings_spi *spi;
- struct ahc_initiator_tinfo *tinfo;
- struct ahc_tmode_tstate *tstate;
- uint16_t *discenable;
- uint16_t *tagenable;
- u_int update_type;
-
- cts = &ccb->cts;
- scsi = &cts->proto_specific.scsi;
- spi = &cts->xport_specific.spi;
- ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim),
- cts->ccb_h.target_id,
- cts->ccb_h.target_lun,
- SIM_CHANNEL(ahc, sim),
- ROLE_UNKNOWN);
- tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
- devinfo.our_scsiid,
- devinfo.target, &tstate);
- update_type = 0;
- if (cts->type == CTS_TYPE_CURRENT_SETTINGS) {
- update_type |= AHC_TRANS_GOAL;
- discenable = &tstate->discenable;
- tagenable = &tstate->tagenable;
- tinfo->curr.protocol_version =
- cts->protocol_version;
- tinfo->curr.transport_version =
- cts->transport_version;
- tinfo->goal.protocol_version =
- cts->protocol_version;
- tinfo->goal.transport_version =
- cts->transport_version;
- } else if (cts->type == CTS_TYPE_USER_SETTINGS) {
- update_type |= AHC_TRANS_USER;
- discenable = &ahc->user_discenable;
- tagenable = &ahc->user_tagenable;
- tinfo->user.protocol_version =
- cts->protocol_version;
- tinfo->user.transport_version =
- cts->transport_version;
- } else {
- ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
- break;
- }
-
- ahc_lock(ahc, &s);
-
- if ((spi->valid & CTS_SPI_VALID_DISC) != 0) {
- if ((spi->flags & CTS_SPI_FLAGS_DISC_ENB) != 0)
- *discenable |= devinfo.target_mask;
- else
- *discenable &= ~devinfo.target_mask;
- }
-
- if ((scsi->valid & CTS_SCSI_VALID_TQ) != 0) {
- if ((scsi->flags & CTS_SCSI_FLAGS_TAG_ENB) != 0)
- *tagenable |= devinfo.target_mask;
- else
- *tagenable &= ~devinfo.target_mask;
- }
-
- if ((spi->valid & CTS_SPI_VALID_BUS_WIDTH) != 0) {
- ahc_validate_width(ahc, /*tinfo limit*/NULL,
- &spi->bus_width, ROLE_UNKNOWN);
- ahc_set_width(ahc, &devinfo, spi->bus_width,
- update_type, /*paused*/FALSE);
- }
-
- if ((spi->valid & CTS_SPI_VALID_PPR_OPTIONS) == 0) {
- if (update_type == AHC_TRANS_USER)
- spi->ppr_options = tinfo->user.ppr_options;
- else
- spi->ppr_options = tinfo->goal.ppr_options;
- }
-
- if ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) == 0) {
- if (update_type == AHC_TRANS_USER)
- spi->sync_offset = tinfo->user.offset;
- else
- spi->sync_offset = tinfo->goal.offset;
- }
-
- if ((spi->valid & CTS_SPI_VALID_SYNC_RATE) == 0) {
- if (update_type == AHC_TRANS_USER)
- spi->sync_period = tinfo->user.period;
- else
- spi->sync_period = tinfo->goal.period;
- }
-
- if (((spi->valid & CTS_SPI_VALID_SYNC_RATE) != 0)
- || ((spi->valid & CTS_SPI_VALID_SYNC_OFFSET) != 0)) {
- struct ahc_syncrate *syncrate;
- u_int maxsync;
-
- if ((ahc->features & AHC_ULTRA2) != 0)
- maxsync = AHC_SYNCRATE_DT;
- else if ((ahc->features & AHC_ULTRA) != 0)
- maxsync = AHC_SYNCRATE_ULTRA;
- else
- maxsync = AHC_SYNCRATE_FAST;
-
- syncrate = ahc_find_syncrate(ahc, &spi->sync_period,
- &spi->ppr_options,
- maxsync);
- ahc_validate_offset(ahc, /*tinfo limit*/NULL,
- syncrate, &spi->sync_offset,
- spi->bus_width, ROLE_UNKNOWN);
-
- /* We use a period of 0 to represent async */
- if (spi->sync_offset == 0) {
- spi->sync_period = 0;
- spi->ppr_options = 0;
- }
-
- ahc_set_syncrate(ahc, &devinfo, syncrate,
- spi->sync_period, spi->sync_offset,
- spi->ppr_options, update_type,
- /*paused*/FALSE);
- }
- ahc_unlock(ahc, &s);
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
-#else
- struct ahc_devinfo devinfo;
- struct ccb_trans_settings *cts;
- struct ahc_initiator_tinfo *tinfo;
- struct ahc_tmode_tstate *tstate;
- uint16_t *discenable;
- uint16_t *tagenable;
- u_int update_type;
- long s;
-
- cts = &ccb->cts;
- ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim),
- cts->ccb_h.target_id,
- cts->ccb_h.target_lun,
- SIM_CHANNEL(ahc, sim),
- ROLE_UNKNOWN);
- tinfo = ahc_fetch_transinfo(ahc, devinfo.channel,
- devinfo.our_scsiid,
- devinfo.target, &tstate);
- update_type = 0;
- if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0) {
- update_type |= AHC_TRANS_GOAL;
- discenable = &tstate->discenable;
- tagenable = &tstate->tagenable;
- } else if ((cts->flags & CCB_TRANS_USER_SETTINGS) != 0) {
- update_type |= AHC_TRANS_USER;
- discenable = &ahc->user_discenable;
- tagenable = &ahc->user_tagenable;
- } else {
- ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
- break;
- }
-
- ahc_lock(ahc, &s);
-
- if ((cts->valid & CCB_TRANS_DISC_VALID) != 0) {
- if ((cts->flags & CCB_TRANS_DISC_ENB) != 0)
- *discenable |= devinfo.target_mask;
- else
- *discenable &= ~devinfo.target_mask;
- }
-
- if ((cts->valid & CCB_TRANS_TQ_VALID) != 0) {
- if ((cts->flags & CCB_TRANS_TAG_ENB) != 0)
- *tagenable |= devinfo.target_mask;
- else
- *tagenable &= ~devinfo.target_mask;
- }
-
- if ((cts->valid & CCB_TRANS_BUS_WIDTH_VALID) != 0) {
- ahc_validate_width(ahc, /*tinfo limit*/NULL,
- &cts->bus_width, ROLE_UNKNOWN);
- ahc_set_width(ahc, &devinfo, cts->bus_width,
- update_type, /*paused*/FALSE);
- }
-
- if ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) == 0) {
- if (update_type == AHC_TRANS_USER)
- cts->sync_offset = tinfo->user.offset;
- else
- cts->sync_offset = tinfo->goal.offset;
- }
-
- if ((cts->valid & CCB_TRANS_SYNC_RATE_VALID) == 0) {
- if (update_type == AHC_TRANS_USER)
- cts->sync_period = tinfo->user.period;
- else
- cts->sync_period = tinfo->goal.period;
- }
-
- if (((cts->valid & CCB_TRANS_SYNC_RATE_VALID) != 0)
- || ((cts->valid & CCB_TRANS_SYNC_OFFSET_VALID) != 0)) {
- struct ahc_syncrate *syncrate;
- u_int ppr_options;
- u_int maxsync;
-
- if ((ahc->features & AHC_ULTRA2) != 0)
- maxsync = AHC_SYNCRATE_DT;
- else if ((ahc->features & AHC_ULTRA) != 0)
- maxsync = AHC_SYNCRATE_ULTRA;
- else
- maxsync = AHC_SYNCRATE_FAST;
-
- ppr_options = 0;
- if (cts->sync_period <= 9)
- ppr_options = MSG_EXT_PPR_DT_REQ;
-
- syncrate = ahc_find_syncrate(ahc, &cts->sync_period,
- &ppr_options,
- maxsync);
- ahc_validate_offset(ahc, /*tinfo limit*/NULL,
- syncrate, &cts->sync_offset,
- MSG_EXT_WDTR_BUS_8_BIT,
- ROLE_UNKNOWN);
-
- /* We use a period of 0 to represent async */
- if (cts->sync_offset == 0) {
- cts->sync_period = 0;
- ppr_options = 0;
- }
-
- if (ppr_options == MSG_EXT_PPR_DT_REQ
- && tinfo->user.transport_version >= 3) {
- tinfo->goal.transport_version =
- tinfo->user.transport_version;
- tinfo->curr.transport_version =
- tinfo->user.transport_version;
- }
-
- ahc_set_syncrate(ahc, &devinfo, syncrate,
- cts->sync_period, cts->sync_offset,
- ppr_options, update_type,
- /*paused*/FALSE);
- }
- ahc_unlock(ahc, &s);
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
-#endif
- break;
- }
- case XPT_GET_TRAN_SETTINGS:
- /* Get default/user set transfer settings for the target */
- {
-
- ahc_lock(ahc, &s);
- ahc_get_tran_settings(ahc, SIM_SCSI_ID(ahc, sim),
- SIM_CHANNEL(ahc, sim), &ccb->cts);
- ahc_unlock(ahc, &s);
- xpt_done(ccb);
- break;
- }
- case XPT_CALC_GEOMETRY:
- {
- struct ccb_calc_geometry *ccg;
- uint32_t size_mb;
- uint32_t secs_per_cylinder;
- int extended;
-
- ccg = &ccb->ccg;
- size_mb = ccg->volume_size
- / ((1024L * 1024L) / ccg->block_size);
- extended = SIM_IS_SCSIBUS_B(ahc, sim)
- ? ahc->flags & AHC_EXTENDED_TRANS_B
- : ahc->flags & AHC_EXTENDED_TRANS_A;
-
- if (size_mb > 1024 && extended) {
- ccg->heads = 255;
- ccg->secs_per_track = 63;
- } else {
- ccg->heads = 64;
- ccg->secs_per_track = 32;
- }
- secs_per_cylinder = ccg->heads * ccg->secs_per_track;
- ccg->cylinders = ccg->volume_size / secs_per_cylinder;
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
- case XPT_RESET_BUS: /* Reset the specified SCSI bus */
- {
- int found;
-
- ahc_lock(ahc, &s);
- found = ahc_reset_channel(ahc, SIM_CHANNEL(ahc, sim),
- /*initiate reset*/TRUE);
- ahc_unlock(ahc, &s);
- if (bootverbose) {
- xpt_print_path(SIM_PATH(ahc, sim));
- printf("SCSI bus reset delivered. "
- "%d SCBs aborted.\n", found);
- }
- ccb->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
- case XPT_TERM_IO: /* Terminate the I/O process */
- /* XXX Implement */
- ccb->ccb_h.status = CAM_REQ_INVALID;
- xpt_done(ccb);
- break;
- case XPT_PATH_INQ: /* Path routing inquiry */
- {
- struct ccb_pathinq *cpi = &ccb->cpi;
-
- cpi->version_num = 1; /* XXX??? */
- cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE;
- if ((ahc->features & AHC_WIDE) != 0)
- cpi->hba_inquiry |= PI_WIDE_16;
- if ((ahc->features & AHC_TARGETMODE) != 0) {
- cpi->target_sprt = PIT_PROCESSOR
- | PIT_DISCONNECT
- | PIT_TERM_IO;
- } else {
- cpi->target_sprt = 0;
- }
- cpi->hba_misc = 0;
- cpi->hba_eng_cnt = 0;
- cpi->max_target = (ahc->features & AHC_WIDE) ? 15 : 7;
- cpi->max_lun = AHC_NUM_LUNS - 1;
- if (SIM_IS_SCSIBUS_B(ahc, sim)) {
- cpi->initiator_id = ahc->our_id_b;
- if ((ahc->flags & AHC_RESET_BUS_B) == 0)
- cpi->hba_misc |= PIM_NOBUSRESET;
- } else {
- cpi->initiator_id = ahc->our_id;
- if ((ahc->flags & AHC_RESET_BUS_A) == 0)
- cpi->hba_misc |= PIM_NOBUSRESET;
- }
- cpi->bus_id = cam_sim_bus(sim);
- cpi->base_transfer_speed = 3300;
- strncpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN);
- strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN);
- strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN);
- cpi->unit_number = cam_sim_unit(sim);
-#ifdef AHC_NEW_TRAN_SETTINGS
- cpi->protocol = PROTO_SCSI;
- cpi->protocol_version = SCSI_REV_2;
- cpi->transport = XPORT_SPI;
- cpi->transport_version = 2;
- cpi->xport_specific.spi.ppr_options = SID_SPI_CLOCK_ST;
- if ((ahc->features & AHC_DT) != 0) {
- cpi->transport_version = 3;
- cpi->xport_specific.spi.ppr_options =
- SID_SPI_CLOCK_DT_ST;
- }
-#endif
- cpi->ccb_h.status = CAM_REQ_CMP;
- xpt_done(ccb);
- break;
- }
- default:
- ccb->ccb_h.status = CAM_PROVIDE_FAIL;
- xpt_done(ccb);
- break;
- }
-}
-
-static void
-ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
- struct ccb_trans_settings *cts)
-{
-#ifdef AHC_NEW_TRAN_SETTINGS
- struct ahc_devinfo devinfo;
- struct ccb_trans_settings_scsi *scsi;
- struct ccb_trans_settings_spi *spi;
- struct ahc_initiator_tinfo *targ_info;
- struct ahc_tmode_tstate *tstate;
- struct ahc_transinfo *tinfo;
-
- scsi = &cts->proto_specific.scsi;
- spi = &cts->xport_specific.spi;
- ahc_compile_devinfo(&devinfo, our_id,
- cts->ccb_h.target_id,
- cts->ccb_h.target_lun,
- channel, ROLE_UNKNOWN);
- targ_info = ahc_fetch_transinfo(ahc, devinfo.channel,
- devinfo.our_scsiid,
- devinfo.target, &tstate);
-
- if (cts->type == CTS_TYPE_CURRENT_SETTINGS)
- tinfo = &targ_info->curr;
- else
- tinfo = &targ_info->user;
-
- scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
- spi->flags &= ~CTS_SPI_FLAGS_DISC_ENB;
- if (cts->type == CTS_TYPE_USER_SETTINGS) {
- if ((ahc->user_discenable & devinfo.target_mask) != 0)
- spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
-
- if ((ahc->user_tagenable & devinfo.target_mask) != 0)
- scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
- } else {
- if ((tstate->discenable & devinfo.target_mask) != 0)
- spi->flags |= CTS_SPI_FLAGS_DISC_ENB;
-
- if ((tstate->tagenable & devinfo.target_mask) != 0)
- scsi->flags |= CTS_SCSI_FLAGS_TAG_ENB;
- }
- cts->protocol_version = tinfo->protocol_version;
- cts->transport_version = tinfo->transport_version;
-
- spi->sync_period = tinfo->period;
- spi->sync_offset = tinfo->offset;
- spi->bus_width = tinfo->width;
- spi->ppr_options = tinfo->ppr_options;
-
- cts->protocol = PROTO_SCSI;
- cts->transport = XPORT_SPI;
- spi->valid = CTS_SPI_VALID_SYNC_RATE
- | CTS_SPI_VALID_SYNC_OFFSET
- | CTS_SPI_VALID_BUS_WIDTH
- | CTS_SPI_VALID_PPR_OPTIONS;
-
- if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD) {
- scsi->valid = CTS_SCSI_VALID_TQ;
- spi->valid |= CTS_SPI_VALID_DISC;
- } else {
- scsi->valid = 0;
- }
-
- cts->ccb_h.status = CAM_REQ_CMP;
-#else
- struct ahc_devinfo devinfo;
- struct ahc_initiator_tinfo *targ_info;
- struct ahc_tmode_tstate *tstate;
- struct ahc_transinfo *tinfo;
- long s;
-
- ahc_compile_devinfo(&devinfo, our_id,
- cts->ccb_h.target_id,
- cts->ccb_h.target_lun,
- channel, ROLE_UNKNOWN);
- targ_info = ahc_fetch_transinfo(ahc, devinfo.channel,
- devinfo.our_scsiid,
- devinfo.target, &tstate);
-
- if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) != 0)
- tinfo = &targ_info->curr;
- else
- tinfo = &targ_info->user;
-
- ahc_lock(ahc, &s);
-
- cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
- if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) == 0) {
- if ((ahc->user_discenable & devinfo.target_mask) != 0)
- cts->flags |= CCB_TRANS_DISC_ENB;
-
- if ((ahc->user_tagenable & devinfo.target_mask) != 0)
- cts->flags |= CCB_TRANS_TAG_ENB;
- } else {
- if ((tstate->discenable & devinfo.target_mask) != 0)
- cts->flags |= CCB_TRANS_DISC_ENB;
-
- if ((tstate->tagenable & devinfo.target_mask) != 0)
- cts->flags |= CCB_TRANS_TAG_ENB;
- }
- cts->sync_period = tinfo->period;
- cts->sync_offset = tinfo->offset;
- cts->bus_width = tinfo->width;
-
- ahc_unlock(ahc, &s);
-
- cts->valid = CCB_TRANS_SYNC_RATE_VALID
- | CCB_TRANS_SYNC_OFFSET_VALID
- | CCB_TRANS_BUS_WIDTH_VALID;
-
- if (cts->ccb_h.target_lun != CAM_LUN_WILDCARD)
- cts->valid |= CCB_TRANS_DISC_VALID|CCB_TRANS_TQ_VALID;
-
- cts->ccb_h.status = CAM_REQ_CMP;
-#endif
-}
-
-static void
-ahc_async(void *callback_arg, uint32_t code, struct cam_path *path, void *arg)
-{
- struct ahc_softc *ahc;
- struct cam_sim *sim;
-
- sim = (struct cam_sim *)callback_arg;
- ahc = (struct ahc_softc *)cam_sim_softc(sim);
- switch (code) {
- case AC_LOST_DEVICE:
- {
- struct ahc_devinfo devinfo;
- long s;
-
- ahc_compile_devinfo(&devinfo, SIM_SCSI_ID(ahc, sim),
- xpt_path_target_id(path),
- xpt_path_lun_id(path),
- SIM_CHANNEL(ahc, sim),
- ROLE_UNKNOWN);
-
- /*
- * Revert to async/narrow transfers
- * for the next device.
- */
- ahc_lock(ahc, &s);
- ahc_set_width(ahc, &devinfo, MSG_EXT_WDTR_BUS_8_BIT,
- AHC_TRANS_GOAL|AHC_TRANS_CUR, /*paused*/FALSE);
- ahc_set_syncrate(ahc, &devinfo, /*syncrate*/NULL,
- /*period*/0, /*offset*/0, /*ppr_options*/0,
- AHC_TRANS_GOAL|AHC_TRANS_CUR,
- /*paused*/FALSE);
- ahc_unlock(ahc, &s);
- break;
- }
- default:
- break;
- }
-}
-
-static void
-ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
- int error)
-{
- struct scb *scb;
- union ccb *ccb;
- struct ahc_softc *ahc;
- struct ahc_initiator_tinfo *tinfo;
- struct ahc_tmode_tstate *tstate;
- u_int mask;
- long s;
-
- scb = (struct scb *)arg;
- ccb = scb->io_ctx;
- ahc = scb->ahc_softc;
-
- if (error != 0) {
- if (error == EFBIG)
- ahc_set_transaction_status(scb, CAM_REQ_TOO_BIG);
- else
- ahc_set_transaction_status(scb, CAM_REQ_CMP_ERR);
- if (nsegments != 0)
- bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
- ahc_lock(ahc, &s);
- ahc_free_scb(ahc, scb);
- ahc_unlock(ahc, &s);
- xpt_done(ccb);
- return;
- }
- if (nsegments != 0) {
- struct ahc_dma_seg *sg;
- bus_dma_segment_t *end_seg;
- bus_dmasync_op_t op;
-
- end_seg = dm_segs + nsegments;
-
- /* Copy the segments into our SG list */
- sg = scb->sg_list;
- while (dm_segs < end_seg) {
- uint32_t len;
-
- sg->addr = ahc_htole32(dm_segs->ds_addr);
- len = dm_segs->ds_len
- | ((dm_segs->ds_addr >> 8) & 0x7F000000);
- sg->len = ahc_htole32(len);
- sg++;
- dm_segs++;
- }
-
- /*
- * Note where to find the SG entries in bus space.
- * We also set the full residual flag which the
- * sequencer will clear as soon as a data transfer
- * occurs.
- */
- scb->hscb->sgptr = ahc_htole32(scb->sg_list_phys|SG_FULL_RESID);
-
- if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN)
- op = BUS_DMASYNC_PREREAD;
- else
- op = BUS_DMASYNC_PREWRITE;
-
- bus_dmamap_sync(ahc->buffer_dmat, scb->dmamap, op);
-
- if (ccb->ccb_h.func_code == XPT_CONT_TARGET_IO) {
- struct target_data *tdata;
-
- tdata = &scb->hscb->shared_data.tdata;
- tdata->target_phases |= DPHASE_PENDING;
- if ((ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT)
- tdata->data_phase = P_DATAOUT;
- else
- tdata->data_phase = P_DATAIN;
-
- /*
- * If the transfer is of an odd length and in the
- * "in" direction (scsi->HostBus), then it may
- * trigger a bug in the 'WideODD' feature of
- * non-Ultra2 chips. Force the total data-length
- * to be even by adding an extra, 1 byte, SG,
- * element. We do this even if we are not currently
- * negotiated wide as negotiation could occur before
- * this command is executed.
- */
- if ((ahc->bugs & AHC_TMODE_WIDEODD_BUG) != 0
- && (ccb->csio.dxfer_len & 0x1) != 0
- && (ccb->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) {
-
- nsegments++;
- if (nsegments > AHC_NSEG) {
-
- ahc_set_transaction_status(scb,
- CAM_REQ_TOO_BIG);
- bus_dmamap_unload(ahc->buffer_dmat,
- scb->dmamap);
- ahc_lock(ahc, &s);
- ahc_free_scb(ahc, scb);
- ahc_unlock(ahc, &s);
- xpt_done(ccb);
- return;
- }
- sg->addr = ahc_htole32(ahc->dma_bug_buf);
- sg->len = ahc_htole32(1);
- sg++;
- }
- }
- sg--;
- sg->len |= ahc_htole32(AHC_DMA_LAST_SEG);
-
- /* Copy the first SG into the "current" data pointer area */
- scb->hscb->dataptr = scb->sg_list->addr;
- scb->hscb->datacnt = scb->sg_list->len;
- } else {
- scb->hscb->sgptr = SG_LIST_NULL;
- scb->hscb->dataptr = 0;
- scb->hscb->datacnt = 0;
- }
-
- scb->sg_count = nsegments;
-
- ahc_lock(ahc, &s);
-
- /*
- * Last time we need to check if this SCB needs to
- * be aborted.
- */
- if (ahc_get_transaction_status(scb) != CAM_REQ_INPROG) {
- if (nsegments != 0)
- bus_dmamap_unload(ahc->buffer_dmat,
- scb->dmamap);
- ahc_free_scb(ahc, scb);
- ahc_unlock(ahc, &s);
- xpt_done(ccb);
- return;
- }
-
- tinfo = ahc_fetch_transinfo(ahc, SCSIID_CHANNEL(ahc, scb->hscb->scsiid),
- SCSIID_OUR_ID(scb->hscb->scsiid),
- SCSIID_TARGET(ahc, scb->hscb->scsiid),
- &tstate);
-
- mask = SCB_GET_TARGET_MASK(ahc, scb);
- scb->hscb->scsirate = tinfo->scsirate;
- scb->hscb->scsioffset = tinfo->curr.offset;
- if ((tstate->ultraenb & mask) != 0)
- scb->hscb->control |= ULTRAENB;
-
- if ((tstate->discenable & mask) != 0
- && (ccb->ccb_h.flags & CAM_DIS_DISCONNECT) == 0)
- scb->hscb->control |= DISCENB;
-
- if ((ccb->ccb_h.flags & CAM_NEGOTIATE) != 0
- && (tinfo->goal.width != 0
- || tinfo->goal.period != 0
- || tinfo->goal.ppr_options != 0)) {
- scb->flags |= SCB_NEGOTIATE;
- scb->hscb->control |= MK_MESSAGE;
- } else if ((tstate->auto_negotiate & mask) != 0) {
- scb->flags |= SCB_AUTO_NEGOTIATE;
- scb->hscb->control |= MK_MESSAGE;
- }
-
- LIST_INSERT_HEAD(&ahc->pending_scbs, scb, pending_links);
-
- ccb->ccb_h.status |= CAM_SIM_QUEUED;
-
- if (ccb->ccb_h.timeout != CAM_TIME_INFINITY) {
- uint64_t time;
-
- if (ccb->ccb_h.timeout == CAM_TIME_DEFAULT)
- ccb->ccb_h.timeout = 5 * 1000;
-
- time = ccb->ccb_h.timeout;
- time *= hz;
- time /= 1000;
- ccb->ccb_h.timeout_ch =
- timeout(ahc_timeout, (caddr_t)scb, time);
- }
-
- /*
- * We only allow one untagged transaction
- * per target in the initiator role unless
- * we are storing a full busy target *lun*
- * table in SCB space.
- */
- if ((scb->hscb->control & (TARGET_SCB|TAG_ENB)) == 0
- && (ahc->flags & AHC_SCB_BTT) == 0) {
- struct scb_tailq *untagged_q;
- int target_offset;
-
- target_offset = SCB_GET_TARGET_OFFSET(ahc, scb);
- untagged_q = &(ahc->untagged_queues[target_offset]);
- TAILQ_INSERT_TAIL(untagged_q, scb, links.tqe);
- scb->flags |= SCB_UNTAGGEDQ;
- if (TAILQ_FIRST(untagged_q) != scb) {
- ahc_unlock(ahc, &s);
- return;
- }
- }
- scb->flags |= SCB_ACTIVE;
-
- if ((scb->flags & SCB_TARGET_IMMEDIATE) != 0) {
- /* Define a mapping from our tag to the SCB. */
- ahc->scb_data->scbindex[scb->hscb->tag] = scb;
- ahc_pause(ahc);
- if ((ahc->flags & AHC_PAGESCBS) == 0)
- ahc_outb(ahc, SCBPTR, scb->hscb->tag);
- ahc_outb(ahc, SCB_TAG, scb->hscb->tag);
- ahc_outb(ahc, RETURN_1, CONT_MSG_LOOP);
- ahc_unpause(ahc);
- } else {
- ahc_queue_scb(ahc, scb);
- }
-
- ahc_unlock(ahc, &s);
-}
-
-static void
-ahc_poll(struct cam_sim *sim)
-{
- ahc_intr(cam_sim_softc(sim));
-}
-
-static void
-ahc_setup_data(struct ahc_softc *ahc, struct cam_sim *sim,
- struct ccb_scsiio *csio, struct scb *scb)
-{
- struct hardware_scb *hscb;
- struct ccb_hdr *ccb_h;
-
- hscb = scb->hscb;
- ccb_h = &csio->ccb_h;
-
- csio->resid = 0;
- csio->sense_resid = 0;
- if (ccb_h->func_code == XPT_SCSI_IO) {
- hscb->cdb_len = csio->cdb_len;
- if ((ccb_h->flags & CAM_CDB_POINTER) != 0) {
-
- if (hscb->cdb_len > sizeof(hscb->cdb32)
- || (ccb_h->flags & CAM_CDB_PHYS) != 0) {
- u_long s;
-
- ahc_set_transaction_status(scb,
- CAM_REQ_INVALID);
- ahc_lock(ahc, &s);
- ahc_free_scb(ahc, scb);
- ahc_unlock(ahc, &s);
- xpt_done((union ccb *)csio);
- return;
- }
- if (hscb->cdb_len > 12) {
- memcpy(hscb->cdb32,
- csio->cdb_io.cdb_ptr,
- hscb->cdb_len);
- scb->flags |= SCB_CDB32_PTR;
- } else {
- memcpy(hscb->shared_data.cdb,
- csio->cdb_io.cdb_ptr,
- hscb->cdb_len);
- }
- } else {
- if (hscb->cdb_len > 12) {
- memcpy(hscb->cdb32, csio->cdb_io.cdb_bytes,
- hscb->cdb_len);
- scb->flags |= SCB_CDB32_PTR;
- } else {
- memcpy(hscb->shared_data.cdb,
- csio->cdb_io.cdb_bytes,
- hscb->cdb_len);
- }
- }
- }
-
- /* Only use S/G if there is a transfer */
- if ((ccb_h->flags & CAM_DIR_MASK) != CAM_DIR_NONE) {
- if ((ccb_h->flags & CAM_SCATTER_VALID) == 0) {
- /* We've been given a pointer to a single buffer */
- if ((ccb_h->flags & CAM_DATA_PHYS) == 0) {
- int s;
- int error;
-
- s = splsoftvm();
- error = bus_dmamap_load(ahc->buffer_dmat,
- scb->dmamap,
- csio->data_ptr,
- csio->dxfer_len,
- ahc_execute_scb,
- scb, /*flags*/0);
- if (error == EINPROGRESS) {
- /*
- * So as to maintain ordering,
- * freeze the controller queue
- * until our mapping is
- * returned.
- */
- xpt_freeze_simq(sim,
- /*count*/1);
- scb->io_ctx->ccb_h.status |=
- CAM_RELEASE_SIMQ;
- }
- splx(s);
- } else {
- struct bus_dma_segment seg;
-
- /* Pointer to physical buffer */
- if (csio->dxfer_len > AHC_MAXTRANSFER_SIZE)
- panic("ahc_setup_data - Transfer size "
- "larger than can device max");
-
- seg.ds_addr = (bus_addr_t)csio->data_ptr;
- seg.ds_len = csio->dxfer_len;
- ahc_execute_scb(scb, &seg, 1, 0);
- }
- } else {
- struct bus_dma_segment *segs;
-
- if ((ccb_h->flags & CAM_DATA_PHYS) != 0)
- panic("ahc_setup_data - Physical segment "
- "pointers unsupported");
-
- if ((ccb_h->flags & CAM_SG_LIST_PHYS) == 0)
- panic("ahc_setup_data - Virtual segment "
- "addresses unsupported");
-
- /* Just use the segments provided */
- segs = (struct bus_dma_segment *)csio->data_ptr;
- ahc_execute_scb(scb, segs, csio->sglist_cnt, 0);
- }
- } else {
- ahc_execute_scb(scb, NULL, 0, 0);
- }
-}
-
-static void
-ahc_set_recoveryscb(struct ahc_softc *ahc, struct scb *scb) {
-
- if ((scb->flags & SCB_RECOVERY_SCB) == 0) {
- struct scb *list_scb;
-
- scb->flags |= SCB_RECOVERY_SCB;
-
- /*
- * Take all queued, but not sent SCBs out of the equation.
- * Also ensure that no new CCBs are queued to us while we
- * try to fix this problem.
- */
- if ((scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
- xpt_freeze_simq(SCB_GET_SIM(ahc, scb), /*count*/1);
- scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ;
- }
-
- /*
- * Go through all of our pending SCBs and remove
- * any scheduled timeouts for them. We will reschedule
- * them after we've successfully fixed this problem.
- */
- LIST_FOREACH(list_scb, &ahc->pending_scbs, pending_links) {
- union ccb *ccb;
-
- ccb = list_scb->io_ctx;
- untimeout(ahc_timeout, list_scb, ccb->ccb_h.timeout_ch);
- }
- }
-}
-
-void
-ahc_timeout(void *arg)
-{
- struct scb *scb;
- struct ahc_softc *ahc;
- long s;
- int found;
- u_int last_phase;
- int target;
- int lun;
- int i;
- char channel;
-
- scb = (struct scb *)arg;
- ahc = (struct ahc_softc *)scb->ahc_softc;
-
- ahc_lock(ahc, &s);
-
- ahc_pause_and_flushwork(ahc);
-
- if ((scb->flags & SCB_ACTIVE) == 0) {
- /* Previous timeout took care of me already */
- printf("%s: Timedout SCB already complete. "
- "Interrupts may not be functioning.\n", ahc_name(ahc));
- ahc_unpause(ahc);
- ahc_unlock(ahc, &s);
- return;
- }
-
- target = SCB_GET_TARGET(ahc, scb);
- channel = SCB_GET_CHANNEL(ahc, scb);
- lun = SCB_GET_LUN(scb);
-
- ahc_print_path(ahc, scb);
- printf("SCB 0x%x - timed out\n", scb->hscb->tag);
- ahc_dump_card_state(ahc);
- last_phase = ahc_inb(ahc, LASTPHASE);
- if (scb->sg_count > 0) {
- for (i = 0; i < scb->sg_count; i++) {
- printf("sg[%d] - Addr 0x%x : Length %d\n",
- i,
- scb->sg_list[i].addr,
- scb->sg_list[i].len & AHC_SG_LEN_MASK);
- }
- }
- if (scb->flags & (SCB_DEVICE_RESET|SCB_ABORT)) {
- /*
- * Been down this road before.
- * Do a full bus reset.
- */
-bus_reset:
- ahc_set_transaction_status(scb, CAM_CMD_TIMEOUT);
- found = ahc_reset_channel(ahc, channel, /*Initiate Reset*/TRUE);
- printf("%s: Issued Channel %c Bus Reset. "
- "%d SCBs aborted\n", ahc_name(ahc), channel, found);
- } else {
- /*
- * If we are a target, transition to bus free and report
- * the timeout.
- *
- * The target/initiator that is holding up the bus may not
- * be the same as the one that triggered this timeout
- * (different commands have different timeout lengths).
- * If the bus is idle and we are actiing as the initiator
- * for this request, queue a BDR message to the timed out
- * target. Otherwise, if the timed out transaction is
- * active:
- * Initiator transaction:
- * Stuff the message buffer with a BDR message and assert
- * ATN in the hopes that the target will let go of the bus
- * and go to the mesgout phase. If this fails, we'll
- * get another timeout 2 seconds later which will attempt
- * a bus reset.
- *
- * Target transaction:
- * Transition to BUS FREE and report the error.
- * It's good to be the target!
- */
- u_int active_scb_index;
- u_int saved_scbptr;
-
- saved_scbptr = ahc_inb(ahc, SCBPTR);
- active_scb_index = ahc_inb(ahc, SCB_TAG);
-
- if (last_phase != P_BUSFREE
- && (ahc_inb(ahc, SEQ_FLAGS) & IDENTIFY_SEEN) != 0
- && (active_scb_index < ahc->scb_data->numscbs)) {
- struct scb *active_scb;
-
- /*
- * If the active SCB is not us, assume that
- * the active SCB has a longer timeout than
- * the timedout SCB, and wait for the active
- * SCB to timeout.
- */
- active_scb = ahc_lookup_scb(ahc, active_scb_index);
- if (active_scb != scb) {
- struct ccb_hdr *ccbh;
- uint64_t newtimeout;
-
- ahc_print_path(ahc, scb);
- printf("Other SCB Timeout%s",
- (scb->flags & SCB_OTHERTCL_TIMEOUT) != 0
- ? " again\n" : "\n");
- scb->flags |= SCB_OTHERTCL_TIMEOUT;
- newtimeout =
- MAX(active_scb->io_ctx->ccb_h.timeout,
- scb->io_ctx->ccb_h.timeout);
- newtimeout *= hz;
- newtimeout /= 1000;
- ccbh = &scb->io_ctx->ccb_h;
- scb->io_ctx->ccb_h.timeout_ch =
- timeout(ahc_timeout, scb, newtimeout);
- ahc_unpause(ahc);
- ahc_unlock(ahc, &s);
- return;
- }
-
- /* It's us */
- if ((scb->hscb->control & TARGET_SCB) != 0) {
-
- /*
- * Send back any queued up transactions
- * and properly record the error condition.
- */
- ahc_freeze_devq(ahc, scb);
- ahc_set_transaction_status(scb,
- CAM_CMD_TIMEOUT);
- ahc_freeze_scb(scb);
- ahc_done(ahc, scb);
-
- /* Will clear us from the bus */
- ahc_restart(ahc);
- ahc_unlock(ahc, &s);
- return;
- }
-
- ahc_set_recoveryscb(ahc, active_scb);
- ahc_outb(ahc, MSG_OUT, HOST_MSG);
- ahc_outb(ahc, SCSISIGO, last_phase|ATNO);
- ahc_print_path(ahc, active_scb);
- printf("BDR message in message buffer\n");
- active_scb->flags |= SCB_DEVICE_RESET;
- active_scb->io_ctx->ccb_h.timeout_ch =
- timeout(ahc_timeout, (caddr_t)active_scb, 2 * hz);
- ahc_unpause(ahc);
- } else {
- int disconnected;
-
- /* XXX Shouldn't panic. Just punt instead */
- if ((scb->hscb->control & TARGET_SCB) != 0)
- panic("Timed-out target SCB but bus idle");
-
- if (last_phase != P_BUSFREE
- && (ahc_inb(ahc, SSTAT0) & TARGET) != 0) {
- /* XXX What happened to the SCB? */
- /* Hung target selection. Goto busfree */
- printf("%s: Hung target selection\n",
- ahc_name(ahc));
- ahc_restart(ahc);
- ahc_unlock(ahc, &s);
- return;
- }
-
- if (ahc_search_qinfifo(ahc, target, channel, lun,
- scb->hscb->tag, ROLE_INITIATOR,
- /*status*/0, SEARCH_COUNT) > 0) {
- disconnected = FALSE;
- } else {
- disconnected = TRUE;
- }
-
- if (disconnected) {
-
- ahc_set_recoveryscb(ahc, scb);
- /*
- * Actually re-queue this SCB in an attempt
- * to select the device before it reconnects.
- * In either case (selection or reselection),
- * we will now issue a target reset to the
- * timed-out device.
- *
- * Set the MK_MESSAGE control bit indicating
- * that we desire to send a message. We
- * also set the disconnected flag since
- * in the paging case there is no guarantee
- * that our SCB control byte matches the
- * version on the card. We don't want the
- * sequencer to abort the command thinking
- * an unsolicited reselection occurred.
- */
- scb->hscb->control |= MK_MESSAGE|DISCONNECTED;
- scb->flags |= SCB_DEVICE_RESET;
-
- /*
- * Remove any cached copy of this SCB in the
- * disconnected list in preparation for the
- * queuing of our abort SCB. We use the
- * same element in the SCB, SCB_NEXT, for
- * both the qinfifo and the disconnected list.
- */
- ahc_search_disc_list(ahc, target, channel,
- lun, scb->hscb->tag,
- /*stop_on_first*/TRUE,
- /*remove*/TRUE,
- /*save_state*/FALSE);
-
- /*
- * In the non-paging case, the sequencer will
- * never re-reference the in-core SCB.
- * To make sure we are notified during
- * reslection, set the MK_MESSAGE flag in
- * the card's copy of the SCB.
- */
- if ((ahc->flags & AHC_PAGESCBS) == 0) {
- ahc_outb(ahc, SCBPTR, scb->hscb->tag);
- ahc_outb(ahc, SCB_CONTROL,
- ahc_inb(ahc, SCB_CONTROL)
- | MK_MESSAGE);
- }
-
- /*
- * Clear out any entries in the QINFIFO first
- * so we are the next SCB for this target
- * to run.
- */
- ahc_search_qinfifo(ahc,
- SCB_GET_TARGET(ahc, scb),
- channel, SCB_GET_LUN(scb),
- SCB_LIST_NULL,
- ROLE_INITIATOR,
- CAM_REQUEUE_REQ,
- SEARCH_COMPLETE);
- ahc_print_path(ahc, scb);
- printf("Queuing a BDR SCB\n");
- ahc_qinfifo_requeue_tail(ahc, scb);
- ahc_outb(ahc, SCBPTR, saved_scbptr);
- scb->io_ctx->ccb_h.timeout_ch =
- timeout(ahc_timeout, (caddr_t)scb, 2 * hz);
- ahc_unpause(ahc);
- } else {
- /* Go "immediatly" to the bus reset */
- /* This shouldn't happen */
- ahc_set_recoveryscb(ahc, scb);
- ahc_print_path(ahc, scb);
- printf("SCB %d: Immediate reset. "
- "Flags = 0x%x\n", scb->hscb->tag,
- scb->flags);
- goto bus_reset;
- }
- }
- }
- ahc_unlock(ahc, &s);
-}
-
-static void
-ahc_abort_ccb(struct ahc_softc *ahc, struct cam_sim *sim, union ccb *ccb)
-{
- union ccb *abort_ccb;
-
- abort_ccb = ccb->cab.abort_ccb;
- switch (abort_ccb->ccb_h.func_code) {
- case XPT_ACCEPT_TARGET_IO:
- case XPT_IMMED_NOTIFY:
- case XPT_CONT_TARGET_IO:
- {
- struct ahc_tmode_tstate *tstate;
- struct ahc_tmode_lstate *lstate;
- struct ccb_hdr_slist *list;
- cam_status status;
-
- status = ahc_find_tmode_devs(ahc, sim, abort_ccb, &tstate,
- &lstate, TRUE);
-
- if (status != CAM_REQ_CMP) {
- ccb->ccb_h.status = status;
- break;
- }
-
- if (abort_ccb->ccb_h.func_code == XPT_ACCEPT_TARGET_IO)
- list = &lstate->accept_tios;
- else if (abort_ccb->ccb_h.func_code == XPT_IMMED_NOTIFY)
- list = &lstate->immed_notifies;
- else
- list = NULL;
-
- if (list != NULL) {
- struct ccb_hdr *curelm;
- int found;
-
- curelm = SLIST_FIRST(list);
- found = 0;
- if (curelm == &abort_ccb->ccb_h) {
- found = 1;
- SLIST_REMOVE_HEAD(list, sim_links.sle);
- } else {
- while(curelm != NULL) {
- struct ccb_hdr *nextelm;
-
- nextelm =
- SLIST_NEXT(curelm, sim_links.sle);
-
- if (nextelm == &abort_ccb->ccb_h) {
- found = 1;
- SLIST_NEXT(curelm,
- sim_links.sle) =
- SLIST_NEXT(nextelm,
- sim_links.sle);
- break;
- }
- curelm = nextelm;
- }
- }
-
- if (found) {
- abort_ccb->ccb_h.status = CAM_REQ_ABORTED;
- xpt_done(abort_ccb);
- ccb->ccb_h.status = CAM_REQ_CMP;
- } else {
- xpt_print_path(abort_ccb->ccb_h.path);
- printf("Not found\n");
- ccb->ccb_h.status = CAM_PATH_INVALID;
- }
- break;
- }
- /* FALLTHROUGH */
- }
- case XPT_SCSI_IO:
- /* XXX Fully implement the hard ones */
- ccb->ccb_h.status = CAM_UA_ABORT;
- break;
- default:
- ccb->ccb_h.status = CAM_REQ_INVALID;
- break;
- }
- xpt_done(ccb);
-}
-
-void
-ahc_send_async(struct ahc_softc *ahc, char channel, u_int target,
- u_int lun, ac_code code, void *opt_arg)
-{
- struct ccb_trans_settings cts;
- struct cam_path *path;
- void *arg;
- int error;
-
- arg = NULL;
- error = ahc_create_path(ahc, channel, target, lun, &path);
-
- if (error != CAM_REQ_CMP)
- return;
-
- switch (code) {
- case AC_TRANSFER_NEG:
- {
-#ifdef AHC_NEW_TRAN_SETTINGS
- struct ccb_trans_settings_scsi *scsi;
-
- cts.type = CTS_TYPE_CURRENT_SETTINGS;
- scsi = &cts.proto_specific.scsi;
-#else
- cts.flags = CCB_TRANS_CURRENT_SETTINGS;
-#endif
- cts.ccb_h.path = path;
- cts.ccb_h.target_id = target;
- cts.ccb_h.target_lun = lun;
- ahc_get_tran_settings(ahc, channel == 'A' ? ahc->our_id
- : ahc->our_id_b,
- channel, &cts);
- arg = &cts;
-#ifdef AHC_NEW_TRAN_SETTINGS
- scsi->valid &= ~CTS_SCSI_VALID_TQ;
- scsi->flags &= ~CTS_SCSI_FLAGS_TAG_ENB;
-#else
- cts.valid &= ~CCB_TRANS_TQ_VALID;
- cts.flags &= ~CCB_TRANS_TAG_ENB;
-#endif
- if (opt_arg == NULL)
- break;
- if (*((ahc_queue_alg *)opt_arg) == AHC_QUEUE_TAGGED)
-#ifdef AHC_NEW_TRAN_SETTINGS
- scsi->flags |= ~CTS_SCSI_FLAGS_TAG_ENB;
- scsi->valid |= CTS_SCSI_VALID_TQ;
-#else
- cts.flags |= CCB_TRANS_TAG_ENB;
- cts.valid |= CCB_TRANS_TQ_VALID;
-#endif
- break;
- }
- case AC_SENT_BDR:
- case AC_BUS_RESET:
- break;
- default:
- panic("ahc_send_async: Unexpected async event");
- }
- xpt_async(code, path, arg);
- xpt_free_path(path);
-}
-
-void
-ahc_platform_set_tags(struct ahc_softc *ahc,
- struct ahc_devinfo *devinfo, int enable)
-{
-}
-
-int
-ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg)
-{
- ahc->platform_data = malloc(sizeof(struct ahc_platform_data), M_DEVBUF,
- M_NOWAIT | M_ZERO);
- if (ahc->platform_data == NULL)
- return (ENOMEM);
- return (0);
-}
-
-void
-ahc_platform_free(struct ahc_softc *ahc)
-{
- struct ahc_platform_data *pdata;
-
- pdata = ahc->platform_data;
- if (pdata != NULL) {
- if (pdata->regs != NULL)
- bus_release_resource(ahc->dev_softc,
- pdata->regs_res_type,
- pdata->regs_res_id,
- pdata->regs);
-
- if (pdata->irq != NULL)
- bus_release_resource(ahc->dev_softc,
- pdata->irq_res_type,
- 0, pdata->irq);
-
- if (pdata->sim_b != NULL) {
- xpt_async(AC_LOST_DEVICE, pdata->path_b, NULL);
- xpt_free_path(pdata->path_b);
- xpt_bus_deregister(cam_sim_path(pdata->sim_b));
- cam_sim_free(pdata->sim_b, /*free_devq*/TRUE);
- }
- if (pdata->sim != NULL) {
- xpt_async(AC_LOST_DEVICE, pdata->path, NULL);
- xpt_free_path(pdata->path);
- xpt_bus_deregister(cam_sim_path(pdata->sim));
- cam_sim_free(pdata->sim, /*free_devq*/TRUE);
- }
- if (pdata->eh != NULL)
- EVENTHANDLER_DEREGISTER(shutdown_final, pdata->eh);
- free(ahc->platform_data, M_DEVBUF);
- }
-}
-
-int
-ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc)
-{
- /* We don't sort softcs under FreeBSD so report equal always */
- return (0);
-}
-
-int
-ahc_detach(device_t dev)
-{
- struct ahc_softc *ahc;
- u_long s;
-
- device_printf(dev, "detaching device\n");
- ahc = device_get_softc(dev);
- ahc_lock(ahc, &s);
- bus_teardown_intr(dev, ahc->platform_data->irq, ahc->platform_data->ih);
- ahc_unlock(ahc, &s);
- ahc_free(ahc);
- return (0);
-}
-
-#if UNUSED
-static void
-ahc_dump_targcmd(struct target_cmd *cmd)
-{
- uint8_t *byte;
- uint8_t *last_byte;
- int i;
-
- byte = &cmd->initiator_channel;
- /* Debugging info for received commands */
- last_byte = &cmd[1].initiator_channel;
-
- i = 0;
- while (byte < last_byte) {
- if (i == 0)
- printf("\t");
- printf("%#x", *byte++);
- i++;
- if (i == 8) {
- printf("\n");
- i = 0;
- } else {
- printf(", ");
- }
- }
-}
-#endif
-
-static int
-ahc_modevent(module_t mod, int type, void *data)
-{
- /* XXX Deal with busy status on unload. */
- return 0;
-}
-
-static moduledata_t ahc_mod = {
- "ahc",
- ahc_modevent,
- NULL
-};
-
-DECLARE_MODULE(ahc, ahc_mod, SI_SUB_DRIVERS, SI_ORDER_MIDDLE);
-MODULE_DEPEND(ahc, cam, 1, 1, 1);
-MODULE_VERSION(ahc, 1);
diff --git a/sys/dev/aic7xxx/aic7xxx_freebsd.h b/sys/dev/aic7xxx/aic7xxx_freebsd.h
deleted file mode 100644
index b12a2d6..0000000
--- a/sys/dev/aic7xxx/aic7xxx_freebsd.h
+++ /dev/null
@@ -1,516 +0,0 @@
-/*
- * FreeBSD platform specific driver option settings, data structures,
- * function declarations and includes.
- *
- * Copyright (c) 1994-2001 Justin T. Gibbs.
- * 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, this list of conditions, and the following disclaimer,
- * without modification.
- * 2. The name of the author may not 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 Public License ("GPL").
- *
- * 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
- * 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.
- *
- * $Id$
- *
- * $FreeBSD$
- */
-
-#ifndef _AIC7XXX_FREEBSD_H_
-#define _AIC7XXX_FREEBSD_H_
-
-#include <opt_aic7xxx.h> /* for config options */
-#ifndef NPCI
-#include <pci.h>
-#endif
-
-#include <sys/param.h>
-#include <sys/systm.h>
-#include <sys/bus.h> /* For device_t */
-#include <sys/eventhandler.h>
-#include <sys/kernel.h>
-#include <sys/malloc.h>
-#include <sys/queue.h>
-
-#if NPCI > 0
-#define AHC_PCI_CONFIG 1
-#ifdef AHC_ALLOW_MEMIO
-#include <machine/bus_memio.h>
-#endif
-#endif
-#include <machine/bus_pio.h>
-#include <machine/bus.h>
-#include <machine/clock.h>
-#include <machine/resource.h>
-
-#include <sys/rman.h>
-
-#if NPCI > 0
-#include <pci/pcireg.h>
-#include <pci/pcivar.h>
-#endif
-
-#include <cam/cam.h>
-#include <cam/cam_ccb.h>
-#include <cam/cam_debug.h>
-#include <cam/cam_sim.h>
-#include <cam/cam_xpt_sim.h>
-
-#include <cam/scsi/scsi_all.h>
-#include <cam/scsi/scsi_message.h>
-
-#ifdef CAM_NEW_TRAN_CODE
-#define AHC_NEW_TRAN_SETTINGS
-#endif /* CAM_NEW_TRAN_CODE */
-
-/****************************** Platform Macros *******************************/
-#define SIM_IS_SCSIBUS_B(ahc, sim) \
- ((sim) == ahc->platform_data->sim_b)
-#define SIM_CHANNEL(ahc, sim) \
- (((sim) == ahc->platform_data->sim_b) ? 'B' : 'A')
-#define SIM_SCSI_ID(ahc, sim) \
- (((sim) == ahc->platform_data->sim_b) ? ahc->our_id_b : ahc->our_id)
-#define SIM_PATH(ahc, sim) \
- (((sim) == ahc->platform_data->sim_b) ? ahc->platform_data->path_b \
- : ahc->platform_data->path)
-#define BUILD_SCSIID(ahc, sim, target_id, our_id) \
- ((((target_id) << TID_SHIFT) & TID) | (our_id) \
- | (SIM_IS_SCSIBUS_B(ahc, sim) ? TWIN_CHNLB : 0))
-
-#define SCB_GET_SIM(ahc, scb) \
- (SCB_GET_CHANNEL(ahc, scb) == 'A' ? (ahc)->platform_data->sim \
- : (ahc)->platform_data->sim_b)
-
-#ifndef offsetof
-#define offsetof(type, member) ((size_t)(&((type *)0)->member))
-#endif
-/************************* Forward Declarations *******************************/
-typedef device_t ahc_dev_softc_t;
-typedef union ccb *ahc_io_ctx_t;
-
-/***************************** Bus Space/DMA **********************************/
-#define ahc_dma_tag_create(ahc, parent_tag, alignment, boundary, \
- lowaddr, highaddr, filter, filterarg, \
- maxsize, nsegments, maxsegsz, flags, \
- dma_tagp) \
- bus_dma_tag_create(parent_tag, alignment, boundary, \
- lowaddr, highaddr, filter, filterarg, \
- maxsize, nsegments, maxsegsz, flags, \
- dma_tagp)
-
-#define ahc_dma_tag_destroy(ahc, tag) \
- bus_dma_tag_destroy(tag)
-
-#define ahc_dmamem_alloc(ahc, dmat, vaddr, flags, mapp) \
- bus_dmamem_alloc(dmat, vaddr, flags, mapp)
-
-#define ahc_dmamem_free(ahc, dmat, vaddr, map) \
- bus_dmamem_free(dmat, vaddr, map)
-
-#define ahc_dmamap_create(ahc, tag, flags, mapp) \
- bus_dmamap_create(tag, flags, mapp)
-
-#define ahc_dmamap_destroy(ahc, tag, map) \
- bus_dmamap_destroy(tag, map)
-
-#define ahc_dmamap_load(ahc, dmat, map, addr, buflen, callback, \
- callback_arg, flags) \
- bus_dmamap_load(dmat, map, addr, buflen, callback, callback_arg, flags)
-
-#define ahc_dmamap_unload(ahc, tag, map) \
- bus_dmamap_unload(tag, map)
-
-/* XXX Need to update Bus DMA for partial map syncs */
-#define ahc_dmamap_sync(ahc, dma_tag, dmamap, offset, len, op) \
- bus_dmamap_sync(dma_tag, dmamap, op)
-
-/************************ Tunable Driver Parameters **************************/
-/*
- * The number of dma segments supported. The sequencer can handle any number
- * of physically contiguous S/G entrys. To reduce the driver's memory
- * consumption, we limit the number supported to be sufficient to handle
- * the largest mapping supported by the kernel, MAXPHYS. Assuming the
- * transfer is as fragmented as possible and unaligned, this turns out to
- * be the number of paged sized transfers in MAXPHYS plus an extra element
- * to handle any unaligned residual. The sequencer fetches SG elements
- * in cacheline sized chucks, so make the number per-transaction an even
- * multiple of 16 which should align us on even the largest of cacheline
- * boundaries.
- */
-#define AHC_NSEG (roundup(btoc(MAXPHYS) + 1, 16))
-
-/* This driver supports target mode */
-#define AHC_TARGET_MODE 1
-
-/************************** Softc/SCB Platform Data ***************************/
-struct ahc_platform_data {
- /*
- * Hooks into the XPT.
- */
- struct cam_sim *sim;
- struct cam_sim *sim_b;
- struct cam_path *path;
- struct cam_path *path_b;
-
- int regs_res_type;
- int regs_res_id;
- int irq_res_type;
- struct resource *regs;
- struct resource *irq;
- void *ih;
- eventhandler_tag eh;
-};
-
-struct scb_platform_data {
-};
-
-/********************************* Byte Order *********************************/
-/*
- * XXX Waiting for FreeBSD byte swapping functions.
- * For now assume host is Little Endian.
- */
-#define ahc_htobe16(x) x
-#define ahc_htobe32(x) x
-#define ahc_htobe64(x) x
-#define ahc_htole16(x) x
-#define ahc_htole32(x) x
-#define ahc_htole64(x) x
-
-#define ahc_be16toh(x) x
-#define ahc_be32toh(x) x
-#define ahc_be64toh(x) x
-#define ahc_le16toh(x) x
-#define ahc_le32toh(x) x
-#define ahc_le64toh(x) x
-
-/***************************** Core Includes **********************************/
-#include <dev/aic7xxx/aic7xxx.h>
-
-/*************************** Device Access ************************************/
-#define ahc_inb(ahc, port) \
- bus_space_read_1((ahc)->tag, (ahc)->bsh, port)
-
-#define ahc_outb(ahc, port, value) \
- bus_space_write_1((ahc)->tag, (ahc)->bsh, port, value)
-
-#define ahc_outsb(ahc, port, valp, count) \
- bus_space_write_multi_1((ahc)->tag, (ahc)->bsh, port, valp, count)
-
-#define ahc_insb(ahc, port, valp, count) \
- bus_space_read_multi_1((ahc)->tag, (ahc)->bsh, port, valp, count)
-
-static __inline void ahc_flush_device_writes(struct ahc_softc *);
-
-static __inline void
-ahc_flush_device_writes(struct ahc_softc *ahc)
-{
- /* XXX Is this sufficient for all architectures??? */
- ahc_inb(ahc, INTSTAT);
-}
-
-/**************************** Locking Primitives ******************************/
-/* Lock protecting internal data structures */
-static __inline void ahc_lockinit(struct ahc_softc *);
-static __inline void ahc_lock(struct ahc_softc *, unsigned long *flags);
-static __inline void ahc_unlock(struct ahc_softc *, unsigned long *flags);
-
-/* Lock held during command compeletion to the upper layer */
-static __inline void ahc_done_lockinit(struct ahc_softc *);
-static __inline void ahc_done_lock(struct ahc_softc *, unsigned long *flags);
-static __inline void ahc_done_unlock(struct ahc_softc *, unsigned long *flags);
-
-static __inline void
-ahc_lockinit(struct ahc_softc *ahc)
-{
-}
-
-static __inline void
-ahc_lock(struct ahc_softc *ahc, unsigned long *flags)
-{
- *flags = splcam();
-}
-
-static __inline void
-ahc_unlock(struct ahc_softc *ahc, unsigned long *flags)
-{
- splx(*flags);
-}
-
-/* Lock held during command compeletion to the upper layer */
-static __inline void
-ahc_done_lockinit(struct ahc_softc *ahc)
-{
-}
-
-static __inline void
-ahc_done_lock(struct ahc_softc *ahc, unsigned long *flags)
-{
-}
-
-static __inline void
-ahc_done_unlock(struct ahc_softc *ahc, unsigned long *flags)
-{
-}
-
-/****************************** OS Primitives *********************************/
-#define ahc_delay DELAY
-
-/************************** Transaction Operations ****************************/
-static __inline void ahc_set_transaction_status(struct scb *, uint32_t);
-static __inline void ahc_set_scsi_status(struct scb *, uint32_t);
-static __inline uint32_t ahc_get_transaction_status(struct scb *);
-static __inline uint32_t ahc_get_scsi_status(struct scb *);
-static __inline void ahc_set_transaction_tag(struct scb *, int, u_int);
-static __inline u_long ahc_get_transfer_length(struct scb *);
-static __inline int ahc_get_transfer_dir(struct scb *);
-static __inline void ahc_set_residual(struct scb *, u_long);
-static __inline void ahc_set_sense_residual(struct scb *, u_long);
-static __inline u_long ahc_get_residual(struct scb *);
-static __inline int ahc_perform_autosense(struct scb *);
-static __inline uint32_t ahc_get_sense_bufsize(struct ahc_softc*, struct scb*);
-static __inline void ahc_freeze_ccb(union ccb *ccb);
-static __inline void ahc_freeze_scb(struct scb *scb);
-static __inline void ahc_platform_freeze_devq(struct ahc_softc *, struct scb *);
-static __inline int ahc_platform_abort_scbs(struct ahc_softc *ahc, int target,
- char channel, int lun, u_int tag,
- role_t role, uint32_t status);
-
-static __inline
-void ahc_set_transaction_status(struct scb *scb, uint32_t status)
-{
- scb->io_ctx->ccb_h.status &= ~CAM_STATUS_MASK;
- scb->io_ctx->ccb_h.status |= status;
-}
-
-static __inline
-void ahc_set_scsi_status(struct scb *scb, uint32_t status)
-{
- scb->io_ctx->csio.scsi_status = status;
-}
-
-static __inline
-uint32_t ahc_get_transaction_status(struct scb *scb)
-{
- return (scb->io_ctx->ccb_h.status & CAM_STATUS_MASK);
-}
-
-static __inline
-uint32_t ahc_get_scsi_status(struct scb *scb)
-{
- return (scb->io_ctx->csio.scsi_status);
-}
-
-static __inline
-void ahc_set_transaction_tag(struct scb *scb, int enabled, u_int type)
-{
- scb->io_ctx->csio.tag_action = type;
- if (enabled)
- scb->io_ctx->ccb_h.flags |= CAM_TAG_ACTION_VALID;
- else
- scb->io_ctx->ccb_h.flags &= ~CAM_TAG_ACTION_VALID;
-}
-
-static __inline
-u_long ahc_get_transfer_length(struct scb *scb)
-{
- return (scb->io_ctx->csio.dxfer_len);
-}
-
-static __inline
-int ahc_get_transfer_dir(struct scb *scb)
-{
- return (scb->io_ctx->ccb_h.flags & CAM_DIR_MASK);
-}
-
-static __inline
-void ahc_set_residual(struct scb *scb, u_long resid)
-{
- scb->io_ctx->csio.resid = resid;
-}
-
-static __inline
-void ahc_set_sense_residual(struct scb *scb, u_long resid)
-{
- scb->io_ctx->csio.sense_resid = resid;
-}
-
-static __inline
-u_long ahc_get_residual(struct scb *scb)
-{
- return (scb->io_ctx->csio.resid);
-}
-
-static __inline
-int ahc_perform_autosense(struct scb *scb)
-{
- return (!(scb->io_ctx->ccb_h.flags & CAM_DIS_AUTOSENSE));
-}
-
-static __inline uint32_t
-ahc_get_sense_bufsize(struct ahc_softc *ahc, struct scb *scb)
-{
- return (sizeof(struct scsi_sense_data));
-}
-
-static __inline void
-ahc_freeze_ccb(union ccb *ccb)
-{
- if ((ccb->ccb_h.status & CAM_DEV_QFRZN) == 0) {
- ccb->ccb_h.status |= CAM_DEV_QFRZN;
- xpt_freeze_devq(ccb->ccb_h.path, /*count*/1);
- }
-}
-
-static __inline void
-ahc_freeze_scb(struct scb *scb)
-{
- ahc_freeze_ccb(scb->io_ctx);
-}
-
-static __inline void
-ahc_platform_freeze_devq(struct ahc_softc *ahc, struct scb *scb)
-{
- /* Nothing to do here for FreeBSD */
-}
-
-static __inline int
-ahc_platform_abort_scbs(struct ahc_softc *ahc, int target,
- char channel, int lun, u_int tag,
- role_t role, uint32_t status)
-{
- /* Nothing to do here for FreeBSD */
- return (0);
-}
-
-static __inline void
-ahc_platform_scb_free(struct ahc_softc *ahc, struct scb *scb)
-{
- /* What do we do to generically handle driver resource shortages??? */
- if ((ahc->flags & AHC_RESOURCE_SHORTAGE) != 0
- && scb->io_ctx != NULL
- && (scb->io_ctx->ccb_h.status & CAM_RELEASE_SIMQ) == 0) {
- scb->io_ctx->ccb_h.status |= CAM_RELEASE_SIMQ;
- ahc->flags &= ~AHC_RESOURCE_SHORTAGE;
- }
- scb->io_ctx = NULL;
-}
-
-/********************************** PCI ***************************************/
-#ifdef AHC_PCI_CONFIG
-static __inline uint32_t ahc_pci_read_config(ahc_dev_softc_t pci,
- int reg, int width);
-static __inline void ahc_pci_write_config(ahc_dev_softc_t pci,
- int reg, uint32_t value,
- int width);
-static __inline int ahc_get_pci_function(ahc_dev_softc_t);
-static __inline int ahc_get_pci_slot(ahc_dev_softc_t);
-static __inline int ahc_get_pci_bus(ahc_dev_softc_t);
-
-int ahc_pci_map_registers(struct ahc_softc *ahc);
-int ahc_pci_map_int(struct ahc_softc *ahc);
-
-static __inline uint32_t
-ahc_pci_read_config(ahc_dev_softc_t pci, int reg, int width)
-{
- return (pci_read_config(pci, reg, width));
-}
-
-static __inline void
-ahc_pci_write_config(ahc_dev_softc_t pci, int reg, uint32_t value, int width)
-{
- pci_write_config(pci, reg, value, width);
-}
-
-static __inline int
-ahc_get_pci_function(ahc_dev_softc_t pci)
-{
- return (pci_get_function(pci));
-}
-
-static __inline int
-ahc_get_pci_slot(ahc_dev_softc_t pci)
-{
- return (pci_get_slot(pci));
-}
-
-static __inline int
-ahc_get_pci_bus(ahc_dev_softc_t pci)
-{
- return (pci_get_bus(pci));
-}
-
-typedef enum
-{
- AHC_POWER_STATE_D0,
- AHC_POWER_STATE_D1,
- AHC_POWER_STATE_D2,
- AHC_POWER_STATE_D3
-} ahc_power_state;
-
-void ahc_power_state_change(struct ahc_softc *ahc,
- ahc_power_state new_state);
-#endif
-/******************************** VL/EISA *************************************/
-int aic7770_map_registers(struct ahc_softc *ahc);
-int aic7770_map_int(struct ahc_softc *ahc, int irq);
-
-/********************************* Debug **************************************/
-static __inline void ahc_print_path(struct ahc_softc *, struct scb *);
-static __inline void ahc_platform_dump_card_state(struct ahc_softc *ahc);
-
-static __inline void
-ahc_print_path(struct ahc_softc *ahc, struct scb *scb)
-{
- xpt_print_path(scb->io_ctx->ccb_h.path);
-}
-
-static __inline void
-ahc_platform_dump_card_state(struct ahc_softc *ahc)
-{
- /* Nothing to do here for FreeBSD */
-}
-/**************************** Transfer Settings *******************************/
-void ahc_notify_xfer_settings_change(struct ahc_softc *,
- struct ahc_devinfo *);
-void ahc_platform_set_tags(struct ahc_softc *, struct ahc_devinfo *,
- int /*enable*/);
-
-/************************* Initialization/Teardown ****************************/
-int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg);
-void ahc_platform_free(struct ahc_softc *ahc);
-int ahc_attach(struct ahc_softc *);
-int ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc);
-int ahc_detach(device_t);
-
-/****************************** Interrupts ************************************/
-void ahc_platform_intr(void *);
-static __inline void ahc_platform_flushwork(struct ahc_softc *ahc);
-static __inline void
-ahc_platform_flushwork(struct ahc_softc *ahc)
-{
-}
-
-/************************ Misc Function Declarations **************************/
-timeout_t ahc_timeout;
-void ahc_done(struct ahc_softc *ahc, struct scb *scb);
-void ahc_send_async(struct ahc_softc *, char /*channel*/,
- u_int /*target*/, u_int /*lun*/, ac_code, void *arg);
-#endif /* _AIC7XXX_FREEBSD_H_ */
diff --git a/sys/dev/aic7xxx/aic7xxx_inline.h b/sys/dev/aic7xxx/aic7xxx_inline.h
index c5db614..ca7d932 100644
--- a/sys/dev/aic7xxx/aic7xxx_inline.h
+++ b/sys/dev/aic7xxx/aic7xxx_inline.h
@@ -2,6 +2,7 @@
* Inline routines shareable across OS platforms.
*
* 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
@@ -10,25 +11,33 @@
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
* without modification.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 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 Public License ("GPL").
+ * 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: //depot/src/aic7xxx/aic7xxx_inline.h#27 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_inline.h#33 $
*
* $FreeBSD$
*/
@@ -222,7 +231,8 @@ ahc_name(struct ahc_softc *ahc)
/*********************** Miscelaneous Support Functions ***********************/
-static __inline void ahc_update_residual(struct scb *scb);
+static __inline void ahc_update_residual(struct ahc_softc *ahc,
+ struct scb *scb);
static __inline struct ahc_initiator_tinfo *
ahc_fetch_transinfo(struct ahc_softc *ahc,
char channel, u_int our_id,
@@ -246,13 +256,13 @@ static __inline uint32_t
* for this SCB/transaction.
*/
static __inline void
-ahc_update_residual(struct scb *scb)
+ahc_update_residual(struct ahc_softc *ahc, struct scb *scb)
{
uint32_t sgptr;
sgptr = ahc_le32toh(scb->hscb->sgptr);
if ((sgptr & SG_RESID_VALID) != 0)
- ahc_calc_residual(scb);
+ ahc_calc_residual(ahc, scb);
}
/*
@@ -348,8 +358,8 @@ ahc_swap_with_next_hscb(struct ahc_softc *ahc, struct scb *scb)
memcpy(q_hscb, scb->hscb, sizeof(*scb->hscb));
if ((scb->flags & SCB_CDB32_PTR) != 0) {
q_hscb->shared_data.cdb_ptr =
- ahc_hscb_busaddr(ahc, q_hscb->tag)
- + offsetof(struct hardware_scb, cdb32);
+ ahc_htole32(ahc_hscb_busaddr(ahc, q_hscb->tag)
+ + offsetof(struct hardware_scb, cdb32));
}
q_hscb->tag = saved_tag;
q_hscb->next = scb->hscb->tag;
@@ -462,7 +472,8 @@ ahc_check_cmdcmpltqueues(struct ahc_softc *ahc)
if (ahc->qoutfifo[ahc->qoutfifonext] != SCB_LIST_NULL)
retval |= AHC_RUN_QOUTFIFO;
#ifdef AHC_TARGET_MODE
- if ((ahc->flags & AHC_TARGETROLE) != 0) {
+ if ((ahc->flags & AHC_TARGETROLE) != 0
+ && (ahc->flags & AHC_TQINFIFO_BLOCKED) == 0) {
ahc_dmamap_sync(ahc, ahc->shared_data_dmat,
ahc->shared_data_dmamap,
ahc_targetcmd_offset(ahc, ahc->tqinfifofnext),
@@ -482,7 +493,6 @@ static __inline void
ahc_intr(struct ahc_softc *ahc)
{
u_int intstat;
- u_int queuestat;
/*
* Instead of directly reading the interrupt status register,
@@ -491,15 +501,10 @@ ahc_intr(struct ahc_softc *ahc)
* most cases.
*/
if ((ahc->flags & (AHC_ALL_INTERRUPTS|AHC_EDGE_INTERRUPT)) == 0
- && (queuestat = ahc_check_cmdcmpltqueues(ahc)) != 0)
+ && (ahc_check_cmdcmpltqueues(ahc) != 0))
intstat = CMDCMPLT;
else {
intstat = ahc_inb(ahc, INTSTAT);
- queuestat = AHC_RUN_QOUTFIFO;
-#ifdef AHC_TARGET_MODE
- if ((ahc->flags & AHC_TARGETROLE) != 0)
- queuestat |= AHC_RUN_TQINFIFO;
-#endif
}
if (intstat & CMDCMPLT) {
@@ -514,12 +519,9 @@ ahc_intr(struct ahc_softc *ahc)
* and asserted the interrupt again.
*/
ahc_flush_device_writes(ahc);
+ ahc_run_qoutfifo(ahc);
#ifdef AHC_TARGET_MODE
- if ((queuestat & AHC_RUN_QOUTFIFO) != 0)
-#endif
- ahc_run_qoutfifo(ahc);
-#ifdef AHC_TARGET_MODE
- if ((queuestat & AHC_RUN_TQINFIFO) != 0)
+ if ((ahc->flags & AHC_TARGETROLE) != 0)
ahc_run_tqinfifo(ahc, /*paused*/FALSE);
#endif
}
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.c b/sys/dev/aic7xxx/aic7xxx_osm.c
index 6582f8c..1c990c2 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.c
+++ b/sys/dev/aic7xxx/aic7xxx_osm.c
@@ -33,7 +33,7 @@
* $FreeBSD$
*/
-#include <dev/aic7xxx/aic7xxx_freebsd.h>
+#include <dev/aic7xxx/aic7xxx_osm.h>
#include <dev/aic7xxx/aic7xxx_inline.h>
#ifndef AHC_TMODE_ENABLE
@@ -42,10 +42,6 @@
#define ccb_scb_ptr spriv_ptr0
-#ifdef AHC_DEBUG
-static int ahc_debug = AHC_DEBUG;
-#endif
-
#if UNUSED
static void ahc_dump_targcmd(struct target_cmd *cmd);
#endif
@@ -84,6 +80,22 @@ ahc_create_path(struct ahc_softc *ahc, char channel, u_int target,
path_id, target, lun));
}
+int
+ahc_map_int(struct ahc_softc *ahc)
+{
+ int error;
+
+ /* Hook up our interrupt handler */
+ error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq,
+ INTR_TYPE_CAM, ahc_platform_intr, ahc,
+ &ahc->platform_data->ih);
+
+ if (error != 0)
+ device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n",
+ error);
+ return (error);
+}
+
/*
* Attach all the sub-devices we can find
*/
@@ -101,7 +113,6 @@ ahc_attach(struct ahc_softc *ahc)
struct cam_path *path2;
long s;
int count;
- int error;
count = 0;
sim = NULL;
@@ -110,15 +121,6 @@ ahc_attach(struct ahc_softc *ahc)
ahc_controller_info(ahc, ahc_info);
printf("%s\n", ahc_info);
ahc_lock(ahc, &s);
- /* Hook up our interrupt handler */
- if ((error = bus_setup_intr(ahc->dev_softc, ahc->platform_data->irq,
- INTR_TYPE_CAM|INTR_ENTROPY, ahc_platform_intr, ahc,
- &ahc->platform_data->ih)) != 0) {
- device_printf(ahc->dev_softc, "bus_setup_intr() failed: %d\n",
- error);
- goto fail;
- }
-
/*
* Attach secondary channel first if the user has
* declared it the primary channel.
@@ -304,8 +306,10 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
if ((ccb->ccb_h.flags & CAM_SEND_STATUS) != 0) {
ahc->pending_device = NULL;
} else {
- xpt_print_path(ccb->ccb_h.path);
- printf("Still disconnected\n");
+ if (bootverbose) {
+ xpt_print_path(ccb->ccb_h.path);
+ printf("Still connected\n");
+ }
ahc_freeze_ccb(ccb);
}
}
@@ -370,7 +374,7 @@ ahc_done(struct ahc_softc *ahc, struct scb *scb)
memset(&ccb->csio.sense_data, 0, sizeof(ccb->csio.sense_data));
memcpy(&ccb->csio.sense_data,
ahc_get_sense_buf(ahc, scb),
- (scb->sg_list->len & AHC_SG_LEN_MASK)
+ (ahc_le32toh(scb->sg_list->len) & AHC_SG_LEN_MASK)
- ccb->csio.sense_resid);
scb->io_ctx->ccb_h.status |= CAM_AUTOSNS_VALID;
}
@@ -651,6 +655,9 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
else
maxsync = AHC_SYNCRATE_FAST;
+ if (spi->bus_width != MSG_EXT_WDTR_BUS_16_BIT)
+ spi->ppr_options &= ~MSG_EXT_PPR_DT_REQ;
+
syncrate = ahc_find_syncrate(ahc, &spi->sync_period,
&spi->ppr_options,
maxsync);
@@ -757,7 +764,8 @@ ahc_action(struct cam_sim *sim, union ccb *ccb)
maxsync = AHC_SYNCRATE_FAST;
ppr_options = 0;
- if (cts->sync_period <= 9)
+ if (cts->sync_period <= 9
+ && cts->bus_width == MSG_EXT_WDTR_BUS_16_BIT)
ppr_options = MSG_EXT_PPR_DT_REQ;
syncrate = ahc_find_syncrate(ahc, &cts->sync_period,
@@ -980,7 +988,6 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
struct ahc_initiator_tinfo *targ_info;
struct ahc_tmode_tstate *tstate;
struct ahc_transinfo *tinfo;
- long s;
ahc_compile_devinfo(&devinfo, our_id,
cts->ccb_h.target_id,
@@ -995,8 +1002,6 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
else
tinfo = &targ_info->user;
- ahc_lock(ahc, &s);
-
cts->flags &= ~(CCB_TRANS_DISC_ENB|CCB_TRANS_TAG_ENB);
if ((cts->flags & CCB_TRANS_CURRENT_SETTINGS) == 0) {
if ((ahc->user_discenable & devinfo.target_mask) != 0)
@@ -1015,8 +1020,6 @@ ahc_get_tran_settings(struct ahc_softc *ahc, int our_id, char channel,
cts->sync_offset = tinfo->offset;
cts->bus_width = tinfo->width;
- ahc_unlock(ahc, &s);
-
cts->valid = CCB_TRANS_SYNC_RATE_VALID
| CCB_TRANS_SYNC_OFFSET_VALID
| CCB_TRANS_BUS_WIDTH_VALID;
@@ -1180,7 +1183,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
scb->hscb->dataptr = scb->sg_list->addr;
scb->hscb->datacnt = scb->sg_list->len;
} else {
- scb->hscb->sgptr = SG_LIST_NULL;
+ scb->hscb->sgptr = ahc_htole32(SG_LIST_NULL);
scb->hscb->dataptr = 0;
scb->hscb->datacnt = 0;
}
@@ -1195,8 +1198,7 @@ ahc_execute_scb(void *arg, bus_dma_segment_t *dm_segs, int nsegments,
*/
if (ahc_get_transaction_status(scb) != CAM_REQ_INPROG) {
if (nsegments != 0)
- bus_dmamap_unload(ahc->buffer_dmat,
- scb->dmamap);
+ bus_dmamap_unload(ahc->buffer_dmat, scb->dmamap);
ahc_free_scb(ahc, scb);
ahc_unlock(ahc, &s);
xpt_done(ccb);
@@ -1558,11 +1560,12 @@ bus_reset:
* Send back any queued up transactions
* and properly record the error condition.
*/
- ahc_freeze_devq(ahc, scb);
- ahc_set_transaction_status(scb,
- CAM_CMD_TIMEOUT);
- ahc_freeze_scb(scb);
- ahc_done(ahc, scb);
+ ahc_abort_scbs(ahc, SCB_GET_TARGET(ahc, scb),
+ SCB_GET_CHANNEL(ahc, scb),
+ SCB_GET_LUN(scb),
+ scb->hscb->tag,
+ ROLE_TARGET,
+ CAM_CMD_TIMEOUT);
/* Will clear us from the bus */
ahc_restart(ahc);
@@ -1582,7 +1585,7 @@ bus_reset:
} else {
int disconnected;
- /* XXX Shouldn't panic. Just punt instead */
+ /* XXX Shouldn't panic. Just punt instead? */
if ((scb->hscb->control & TARGET_SCB) != 0)
panic("Timed-out target SCB but bus idle");
diff --git a/sys/dev/aic7xxx/aic7xxx_osm.h b/sys/dev/aic7xxx/aic7xxx_osm.h
index b12a2d6..c3ce610 100644
--- a/sys/dev/aic7xxx/aic7xxx_osm.h
+++ b/sys/dev/aic7xxx/aic7xxx_osm.h
@@ -58,6 +58,7 @@
#endif
#include <machine/bus_pio.h>
#include <machine/bus.h>
+#include <machine/endian.h>
#include <machine/clock.h>
#include <machine/resource.h>
@@ -183,23 +184,19 @@ struct scb_platform_data {
};
/********************************* Byte Order *********************************/
-/*
- * XXX Waiting for FreeBSD byte swapping functions.
- * For now assume host is Little Endian.
- */
-#define ahc_htobe16(x) x
-#define ahc_htobe32(x) x
-#define ahc_htobe64(x) x
-#define ahc_htole16(x) x
-#define ahc_htole32(x) x
-#define ahc_htole64(x) x
-
-#define ahc_be16toh(x) x
-#define ahc_be32toh(x) x
-#define ahc_be64toh(x) x
-#define ahc_le16toh(x) x
-#define ahc_le32toh(x) x
-#define ahc_le64toh(x) x
+#define ahc_htobe16(x) htobe16(x)
+#define ahc_htobe32(x) htobe32(x)
+#define ahc_htobe64(x) htobe64(x)
+#define ahc_htole16(x) htole16(x)
+#define ahc_htole32(x) htole32(x)
+#define ahc_htole64(x) htole64(x)
+
+#define ahc_be16toh(x) be16toh(x)
+#define ahc_be32toh(x) be32toh(x)
+#define ahc_be64toh(x) be64toh(x)
+#define ahc_le16toh(x) le16toh(x)
+#define ahc_le32toh(x) le32toh(x)
+#define ahc_le64toh(x) le64toh(x)
/***************************** Core Includes **********************************/
#include <dev/aic7xxx/aic7xxx.h>
@@ -469,7 +466,7 @@ void ahc_power_state_change(struct ahc_softc *ahc,
ahc_power_state new_state);
#endif
/******************************** VL/EISA *************************************/
-int aic7770_map_registers(struct ahc_softc *ahc);
+int aic7770_map_registers(struct ahc_softc *ahc, u_int port);
int aic7770_map_int(struct ahc_softc *ahc, int irq);
/********************************* Debug **************************************/
@@ -496,6 +493,7 @@ void ahc_platform_set_tags(struct ahc_softc *, struct ahc_devinfo *,
/************************* Initialization/Teardown ****************************/
int ahc_platform_alloc(struct ahc_softc *ahc, void *platform_arg);
void ahc_platform_free(struct ahc_softc *ahc);
+int ahc_map_int(struct ahc_softc *ahc);
int ahc_attach(struct ahc_softc *);
int ahc_softc_comp(struct ahc_softc *lahc, struct ahc_softc *rahc);
int ahc_detach(device_t);
diff --git a/sys/dev/aic7xxx/aic7xxx_pci.c b/sys/dev/aic7xxx/aic7xxx_pci.c
index a4c0f46..42dcdcc 100644
--- a/sys/dev/aic7xxx/aic7xxx_pci.c
+++ b/sys/dev/aic7xxx/aic7xxx_pci.c
@@ -3,7 +3,8 @@
* 3940, 2940, aic7895, aic7890, aic7880,
* aic7870, aic7860 and aic7850 SCSI controllers
*
- * Copyright (c) 1995-2000 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
@@ -11,33 +12,47 @@
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions, and the following disclaimer,
- * without modification, immediately at the beginning of the file.
- * 2. The name of the author may not be used to endorse or promote products
- * derived from this software without specific prior written permission.
+ * 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 Public License ("GPL").
+ * 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: //depot/src/aic7xxx/aic7xxx_pci.c#28 $
+ * $Id: //depot/aic7xxx/aic7xxx/aic7xxx_pci.c#37 $
*
* $FreeBSD$
*/
-#include <dev/aic7xxx/aic7xxx_freebsd.h>
+#ifdef __linux__
+#include "aic7xxx_osm.h"
+#include "aic7xxx_inline.h"
+#include "aic7xxx_93cx6.h"
+#else
+#include <dev/aic7xxx/aic7xxx_osm.h>
#include <dev/aic7xxx/aic7xxx_inline.h>
#include <dev/aic7xxx/aic7xxx_93cx6.h>
+#endif
#define AHC_PCI_IOADDR PCIR_MAPS /* I/O Address */
#define AHC_PCI_MEMADDR (PCIR_MAPS + 4) /* Mem I/O Address */
@@ -137,7 +152,7 @@ ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
#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 /* Low Cost 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)
@@ -198,7 +213,7 @@ ahc_compose_id(u_int device, u_int vendor, u_int subdevice, u_int subvendor)
: ((id) & 0x1000) >> 12)
/*
* Informational only. Should use chip register to be
- * ceratian, but may be use in identification strings.
+ * certain, but may be use in identification strings.
*/
#define SUBID_9005_CARD_SCSIWIDTH_MASK 0x2000
#define SUBID_9005_CARD_PCIWIDTH_MASK 0x4000
@@ -645,6 +660,8 @@ const u_int ahc_num_pci_devs = NUM_ELEMENTS(ahc_pci_ident_table);
#define CACHESIZE 0x0000003ful /* only 5 bits */
#define LATTIME 0x0000ff00ul
+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);
@@ -668,12 +685,43 @@ static void aic787X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
static void aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
int *externalcable_present,
int *eeprom_present);
-static int acquire_seeprom(struct ahc_softc *ahc,
- struct seeprom_descriptor *sd);
-static void release_seeprom(struct seeprom_descriptor *sd);
static void write_brdctl(struct ahc_softc *ahc, uint8_t value);
static uint8_t read_brdctl(struct ahc_softc *ahc);
+static int
+ahc_9005_subdevinfo_valid(uint16_t device, uint16_t vendor,
+ uint16_t subdevice, uint16_t subvendor)
+{
+ 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;
+ }
+ }
+ return (result);
+}
+
struct ahc_pci_identity *
ahc_find_pci_device(ahc_dev_softc_t pci)
{
@@ -702,9 +750,7 @@ ahc_find_pci_device(ahc_dev_softc_t pci)
* ID as valid.
*/
if (ahc_get_pci_function(pci) > 0
- && subvendor == 0x9005
- && subdevice != device
- && SUBID_9005_TYPE_KNOWN(subdevice) != 0
+ && ahc_9005_subdevinfo_valid(vendor, device, subvendor, subdevice)
&& SUBID_9005_MFUNCENB(subdevice) == 0)
return (NULL);
@@ -739,11 +785,19 @@ ahc_pci_config(struct ahc_softc *ahc, struct ahc_pci_identity *entry)
ahc->chip |= AHC_PCI;
ahc->description = entry->name;
+ ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
+
error = ahc_pci_map_registers(ahc);
if (error != 0)
return (error);
- ahc_power_state_change(ahc, AHC_POWER_STATE_D0);
+ /*
+ * 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
+ * storm.
+ */
+ ahc_intr_enable(ahc, FALSE);
/*
* If we need to support high memory, enable dual
@@ -956,6 +1010,14 @@ ahc_ext_scbram_present(struct ahc_softc *ahc)
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
@@ -1158,7 +1220,7 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
sd.sd_DO = SEEDO;
sd.sd_DI = SEEDI;
- have_seeprom = acquire_seeprom(ahc, &sd);
+ have_seeprom = ahc_acquire_seeprom(ahc, &sd);
if (have_seeprom) {
if (bootverbose)
@@ -1169,11 +1231,12 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
start_addr = 32 * (ahc->channel - 'A');
- have_seeprom = read_seeprom(&sd, (uint16_t *)&sc,
- start_addr, sizeof(sc)/2);
+ have_seeprom = ahc_read_seeprom(&sd, (uint16_t *)&sc,
+ start_addr,
+ sizeof(sc)/2);
if (have_seeprom)
- have_seeprom = verify_cksum(&sc);
+ have_seeprom = ahc_verify_cksum(&sc);
if (have_seeprom != 0 || sd.sd_chip == C56_66) {
if (bootverbose) {
@@ -1186,7 +1249,7 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
}
sd.sd_chip = C56_66;
}
- release_seeprom(&sd);
+ ahc_release_seeprom(&sd);
}
if (!have_seeprom) {
@@ -1214,8 +1277,14 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
val = ahc_inb(ahc, SRAM_BASE + j)
| ahc_inb(ahc, SRAM_BASE + j + 1) << 8;
}
- have_seeprom = verify_cksum(&sc);
+ have_seeprom = ahc_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 (!have_seeprom) {
@@ -1364,9 +1433,9 @@ check_extport(struct ahc_softc *ahc, u_int *sxfrctl1)
}
if (have_autoterm) {
- acquire_seeprom(ahc, &sd);
+ ahc_acquire_seeprom(ahc, &sd);
configure_termination(ahc, &sd, adapter_control, sxfrctl1);
- release_seeprom(&sd);
+ ahc_release_seeprom(&sd);
}
}
@@ -1491,6 +1560,15 @@ configure_termination(struct ahc_softc *ahc,
"Only two connectors on the "
"adapter may be used at a "
"time!\n", ahc_name(ahc));
+
+ /*
+ * 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;
}
if ((ahc->features & AHC_WIDE) != 0
@@ -1663,8 +1741,8 @@ aic785X_cable_detect(struct ahc_softc *ahc, int *internal50_present,
*eeprom_present = (ahc_inb(ahc, SPIOCAP) & EEPROM) ? 1 : 0;
}
-static int
-acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
+int
+ahc_acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
{
int wait;
@@ -1691,8 +1769,8 @@ acquire_seeprom(struct ahc_softc *ahc, struct seeprom_descriptor *sd)
return(1);
}
-static void
-release_seeprom(struct seeprom_descriptor *sd)
+void
+ahc_release_seeprom(struct seeprom_descriptor *sd)
{
/* Release access to the memory port and the serial EEPROM. */
SEEPROM_OUTB(sd, 0);
OpenPOWER on IntegriCloud