summaryrefslogtreecommitdiffstats
path: root/sys/dev/aac
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2005-10-08 15:55:09 +0000
committerscottl <scottl@FreeBSD.org>2005-10-08 15:55:09 +0000
commit5374999d013200def723741dd18b40500a1c0f37 (patch)
tree864aa6aa2577b9ca68a5238dfea048a8d474b969 /sys/dev/aac
parent105781c4880e48a6ff6444f77d5e1c631cb97e8e (diff)
downloadFreeBSD-src-5374999d013200def723741dd18b40500a1c0f37.zip
FreeBSD-src-5374999d013200def723741dd18b40500a1c0f37.tar.gz
Mega Update to the aac driver to support a whole new family of cards and
the modified interface that they use. Changes include: - Register a different interrupt handler for the new interface. This one is INTR_MPSAFE, not INTR_FAST, and directly processes completions and AIFs. - Add an event registration and callback mechanism for the ioctl and CAM modules can know when a resource shortage clears. This condition was previously fatal in CAM due to programming oversights. - Fix locking to play better with newbus. - Provide access methods for talking to cards with the NEWCOMM interface. - Fix up the CAM module to be better suited for dealing with newer firmware on the PERC Si/Di series that requires talking to plain SCSI via aac. - Add a whole slew of new PCI Id's. Thanks to Adaptec for providing an initial version of this work and for answering countless questions about it. There are still some rough edges in this, but it works well enough to commit and test for now. Obtained from: Adaptec, Inc.
Diffstat (limited to 'sys/dev/aac')
-rw-r--r--sys/dev/aac/aac.c579
-rw-r--r--sys/dev/aac/aac_cam.c107
-rw-r--r--sys/dev/aac/aac_pci.c83
-rw-r--r--sys/dev/aac/aac_tables.h16
-rw-r--r--sys/dev/aac/aacreg.h125
-rw-r--r--sys/dev/aac/aacvar.h60
6 files changed, 799 insertions, 171 deletions
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
index e8d3607..e9f3e23 100644
--- a/sys/dev/aac/aac.c
+++ b/sys/dev/aac/aac.c
@@ -33,6 +33,9 @@ __FBSDID("$FreeBSD$");
/*
* Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
*/
+#define AAC_DRIVER_VERSION 0x02000000
+#define AAC_DRIVER_BUILD_DATE __DATE__ " " __TIME__
+#define AAC_DRIVERNAME "aac"
#include "opt_aac.h"
@@ -51,11 +54,15 @@ __FBSDID("$FreeBSD$");
#include <sys/signalvar.h>
#include <sys/time.h>
#include <sys/eventhandler.h>
+#include <sys/rman.h>
#include <machine/bus.h>
#include <sys/bus_dma.h>
#include <machine/resource.h>
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
#include <dev/aac/aacreg.h>
#include <sys/aac_ioctl.h>
#include <dev/aac/aacvar.h>
@@ -116,7 +123,8 @@ struct aac_interface aac_fa_interface = {
aac_fa_clear_istatus,
aac_fa_set_mailbox,
aac_fa_get_mailbox,
- aac_fa_set_interrupts
+ aac_fa_set_interrupts,
+ NULL, NULL, NULL
};
/* StrongARM interface */
@@ -137,7 +145,8 @@ struct aac_interface aac_sa_interface = {
aac_sa_clear_istatus,
aac_sa_set_mailbox,
aac_sa_get_mailbox,
- aac_sa_set_interrupts
+ aac_sa_set_interrupts,
+ NULL, NULL, NULL
};
/* i960Rx interface */
@@ -150,6 +159,9 @@ static void aac_rx_set_mailbox(struct aac_softc *sc, u_int32_t command,
u_int32_t arg2, u_int32_t arg3);
static int aac_rx_get_mailbox(struct aac_softc *sc, int mb);
static void aac_rx_set_interrupts(struct aac_softc *sc, int enable);
+static int aac_rx_send_command(struct aac_softc *sc, struct aac_command *cm);
+static int aac_rx_get_outb_queue(struct aac_softc *sc);
+static void aac_rx_set_outb_queue(struct aac_softc *sc, int index);
struct aac_interface aac_rx_interface = {
aac_rx_get_fwstatus,
@@ -158,7 +170,10 @@ struct aac_interface aac_rx_interface = {
aac_rx_clear_istatus,
aac_rx_set_mailbox,
aac_rx_get_mailbox,
- aac_rx_set_interrupts
+ aac_rx_set_interrupts,
+ aac_rx_send_command,
+ aac_rx_get_outb_queue,
+ aac_rx_set_outb_queue
};
/* Rocket/MIPS interface */
@@ -171,6 +186,9 @@ static void aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command,
u_int32_t arg2, u_int32_t arg3);
static int aac_rkt_get_mailbox(struct aac_softc *sc, int mb);
static void aac_rkt_set_interrupts(struct aac_softc *sc, int enable);
+static int aac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm);
+static int aac_rkt_get_outb_queue(struct aac_softc *sc);
+static void aac_rkt_set_outb_queue(struct aac_softc *sc, int index);
struct aac_interface aac_rkt_interface = {
aac_rkt_get_fwstatus,
@@ -179,7 +197,10 @@ struct aac_interface aac_rkt_interface = {
aac_rkt_clear_istatus,
aac_rkt_set_mailbox,
aac_rkt_get_mailbox,
- aac_rkt_set_interrupts
+ aac_rkt_set_interrupts,
+ aac_rkt_send_command,
+ aac_rkt_get_outb_queue,
+ aac_rkt_set_outb_queue
};
/* Debugging and Diagnostics */
@@ -199,6 +220,9 @@ static int aac_rev_check(struct aac_softc *sc, caddr_t udata);
static int aac_getnext_aif(struct aac_softc *sc, caddr_t arg);
static int aac_return_aif(struct aac_softc *sc, caddr_t uptr);
static int aac_query_disk(struct aac_softc *sc, caddr_t uptr);
+static int aac_get_pci_info(struct aac_softc *sc, caddr_t uptr);
+static void aac_ioctl_event(struct aac_softc *sc,
+ struct aac_event *event, void *arg);
static struct cdevsw aac_cdevsw = {
.d_version = D_VERSION,
@@ -242,9 +266,6 @@ aac_attach(struct aac_softc *sc)
*/
TASK_INIT(&sc->aac_task_complete, 0, aac_complete, sc);
- /* disable interrupts before we enable anything */
- AAC_MASK_INTERRUPTS(sc);
-
/* mark controller as suspended until we get ourselves organised */
sc->aac_state |= AAC_STATE_SUSPEND;
@@ -272,6 +293,40 @@ aac_attach(struct aac_softc *sc)
return(error);
/*
+ * Allocate and connect our interrupt.
+ */
+ sc->aac_irq_rid = 0;
+ if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ,
+ &sc->aac_irq_rid,
+ RF_SHAREABLE |
+ RF_ACTIVE)) == NULL) {
+ device_printf(sc->aac_dev, "can't allocate interrupt\n");
+ return (EINVAL);
+ }
+ if (sc->flags & AAC_FLAGS_NEW_COMM) {
+ if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
+ INTR_MPSAFE|INTR_TYPE_BIO, aac_new_intr,
+ sc, &sc->aac_intr)) {
+ device_printf(sc->aac_dev, "can't set up interrupt\n");
+ return (EINVAL);
+ }
+ } else {
+ if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
+ INTR_FAST|INTR_TYPE_BIO, aac_fast_intr,
+ sc, &sc->aac_intr)) {
+ device_printf(sc->aac_dev,
+ "can't set up FAST interrupt\n");
+ if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
+ INTR_MPSAFE|INTR_TYPE_BIO,
+ aac_fast_intr, sc, &sc->aac_intr)) {
+ device_printf(sc->aac_dev,
+ "can't set up MPSAFE interrupt\n");
+ return (EINVAL);
+ }
+ }
+ }
+
+ /*
* Print a little information about the controller.
*/
aac_describe_controller(sc);
@@ -299,7 +354,7 @@ aac_attach(struct aac_softc *sc)
/* Create the AIF thread */
if (kthread_create((void(*)(void *))aac_command_thread, sc,
- &sc->aifthread, 0, 0, "aac%daif", unit))
+ &sc->aifthread, 0, 0, "aac%daif", unit))
panic("Could not create AIF thread\n");
/* Register the shutdown method to only be called post-dump */
@@ -317,6 +372,23 @@ aac_attach(struct aac_softc *sc)
return(0);
}
+void
+aac_add_event(struct aac_softc *sc, struct aac_event *event)
+{
+
+ switch (event->ev_type & AAC_EVENT_MASK) {
+ case AAC_EVENT_CMFREE:
+ TAILQ_INSERT_TAIL(&sc->aac_ev_cmfree, event, ev_links);
+ break;
+ default:
+ device_printf(sc->aac_dev, "aac_add event: unknown event %d\n",
+ event->ev_type);
+ break;
+ }
+
+ return;
+}
+
/*
* Probe for containers, create disks.
*/
@@ -336,6 +408,7 @@ aac_startup(void *arg)
/* disconnect ourselves from the intrhook chain */
config_intrhook_disestablish(&sc->aac_ich);
+ mtx_lock(&sc->aac_io_lock);
aac_alloc_sync_fib(sc, &fib);
mi = (struct aac_mntinfo *)&fib->data[0];
@@ -360,6 +433,7 @@ aac_startup(void *arg)
} while ((i < count) && (i < AAC_MAX_CONTAINERS));
aac_release_sync_fib(sc);
+ mtx_unlock(&sc->aac_io_lock);
/* poke the bus to actually attach the child devices */
if (bus_generic_attach(sc->aac_dev))
@@ -550,6 +624,7 @@ aac_shutdown(device_t dev)
*/
device_printf(sc->aac_dev, "shutting down controller...");
+ mtx_lock(&sc->aac_io_lock);
aac_alloc_sync_fib(sc, &fib);
cc = (struct aac_close_command *)&fib->data[0];
@@ -581,6 +656,7 @@ aac_shutdown(device_t dev)
AAC_MASK_INTERRUPTS(sc);
aac_release_sync_fib(sc);
+ mtx_unlock(&sc->aac_io_lock);
return(0);
}
@@ -621,10 +697,91 @@ aac_resume(device_t dev)
}
/*
- * Take an interrupt.
+ * Interrupt handler for NEW_COMM interface.
*/
void
-aac_intr(void *arg)
+aac_new_intr(void *arg)
+{
+ struct aac_softc *sc;
+ u_int32_t index, fast;
+ struct aac_command *cm;
+ struct aac_fib *fib;
+ int i;
+
+ debug_called(2);
+
+ sc = (struct aac_softc *)arg;
+
+ mtx_lock(&sc->aac_io_lock);
+ while (1) {
+ index = AAC_GET_OUTB_QUEUE(sc);
+ if (index == 0xffffffff)
+ index = AAC_GET_OUTB_QUEUE(sc);
+ if (index == 0xffffffff)
+ break;
+ if (index & 2) {
+ if (index == 0xfffffffe) {
+ /* XXX This means that the controller wants
+ * more work. Ignore it for now.
+ */
+ continue;
+ }
+ /* AIF */
+ fib = (struct aac_fib *)malloc(sizeof *fib, M_AACBUF,
+ M_NOWAIT | M_ZERO);
+ if (fib == NULL) {
+ /* If we're really this short on memory,
+ * hopefully breaking out of the handler will
+ * allow something to get freed. This
+ * actually sucks a whole lot.
+ */
+ break;
+ }
+ index &= ~2;
+ for (i = 0; i < sizeof(struct aac_fib)/4; ++i)
+ ((u_int32_t *)fib)[i] = AAC_GETREG4(sc, index + i*4);
+ aac_handle_aif(sc, fib);
+ free(fib, M_AACBUF);
+
+ /*
+ * AIF memory is owned by the adapter, so let it
+ * know that we are done with it.
+ */
+ AAC_SET_OUTB_QUEUE(sc, index);
+ AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
+ } else {
+ fast = index & 1;
+ cm = sc->aac_commands + (index >> 2);
+ fib = cm->cm_fib;
+ if (fast) {
+ fib->Header.XferState |= AAC_FIBSTATE_DONEADAP;
+ *((u_int32_t *)(fib->data)) = AAC_ERROR_NORMAL;
+ }
+ aac_remove_busy(cm);
+ aac_unmap_command(cm);
+ cm->cm_flags |= AAC_CMD_COMPLETED;
+
+ /* is there a completion handler? */
+ if (cm->cm_complete != NULL) {
+ cm->cm_complete(cm);
+ } else {
+ /* assume that someone is sleeping on this
+ * command
+ */
+ wakeup(cm);
+ }
+ sc->flags &= ~AAC_QUEUE_FRZN;
+ }
+ }
+ /* see if we can start some more I/O */
+ if ((sc->flags & AAC_QUEUE_FRZN) == 0)
+ aac_startio(sc);
+
+ mtx_unlock(&sc->aac_io_lock);
+}
+
+void
+aac_fast_intr(void *arg)
{
struct aac_softc *sc;
u_int16_t reason;
@@ -653,7 +810,7 @@ aac_intr(void *arg)
* that start with a NULL.
*/
if ((reason & AAC_DB_PRINTF) &&
- (sc->aac_common->ac_printf[0] == 0))
+ (sc->aac_common->ac_printf[0] == 0))
sc->aac_common->ac_printf[0] = 32;
/*
@@ -781,8 +938,12 @@ aac_command_thread(struct aac_softc *sc)
aac_print_printf(sc);
/* Also check to see if the adapter has a command for us. */
- while (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE,
- &fib_size, &fib) == 0) {
+ if (sc->flags & AAC_FLAGS_NEW_COMM)
+ continue;
+ for (;;) {
+ if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE,
+ &fib_size, &fib))
+ break;
AAC_PRINT_FIB(sc, fib);
@@ -797,8 +958,9 @@ aac_command_thread(struct aac_softc *sc)
}
if ((fib->Header.XferState == 0) ||
- (fib->Header.StructType != AAC_FIBTYPE_TFIB))
+ (fib->Header.StructType != AAC_FIBTYPE_TFIB)) {
break;
+ }
/* Return the AIF to the controller. */
if (fib->Header.XferState & AAC_FIBSTATE_FROMADAP) {
@@ -817,8 +979,8 @@ aac_command_thread(struct aac_softc *sc)
* enqueue->startio chain.
*/
aac_enqueue_response(sc,
- AAC_ADAP_NORM_RESP_QUEUE,
- fib);
+ AAC_ADAP_NORM_RESP_QUEUE,
+ fib);
}
}
}
@@ -850,7 +1012,7 @@ aac_complete(void *context, int pending)
for (;;) {
/* look for completed FIBs on our queue */
if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE, &fib_size,
- &fib))
+ &fib))
break; /* nothing to do */
/* get the command, unmap and hand off for processing */
@@ -859,9 +1021,9 @@ aac_complete(void *context, int pending)
AAC_PRINT_FIB(sc, fib);
break;
}
-
aac_remove_busy(cm);
- aac_unmap_command(cm);
+
+ aac_unmap_command(cm);
cm->cm_flags |= AAC_CMD_COMPLETED;
/* is there a completion handler? */
@@ -944,7 +1106,25 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
/* build the read/write request */
ad = (struct aac_disk *)bp->bio_disk->d_drv1;
- if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
+ if (sc->flags & AAC_FLAGS_RAW_IO) {
+ struct aac_raw_io *raw;
+ raw = (struct aac_raw_io *)&fib->data[0];
+ fib->Header.Command = RawIo;
+ raw->BlockNumber = (u_int64_t)bp->bio_pblkno;
+ raw->ByteCount = bp->bio_bcount;
+ raw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
+ raw->BpTotal = 0;
+ raw->BpComplete = 0;
+ fib->Header.Size += sizeof(struct aac_raw_io);
+ cm->cm_sgtable = (struct aac_sg_table *)&raw->SgMapRaw;
+ if (bp->bio_cmd == BIO_READ) {
+ raw->Flags = 1;
+ cm->cm_flags |= AAC_CMD_DATAIN;
+ } else {
+ raw->Flags = 0;
+ cm->cm_flags |= AAC_CMD_DATAOUT;
+ }
+ } else if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
fib->Header.Command = ContainerCommand;
if (bp->bio_cmd == BIO_READ) {
struct aac_blockread *br;
@@ -1001,6 +1181,8 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
return(0);
fail:
+ if (bp != NULL)
+ aac_enqueue_bio(sc, bp);
if (cm != NULL)
aac_release_command(cm);
return(ENOMEM);
@@ -1101,6 +1283,9 @@ aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp)
void
aac_release_command(struct aac_command *cm)
{
+ struct aac_event *event;
+ struct aac_softc *sc;
+
debug_called(3);
/* (re)initialise the command/FIB */
@@ -1111,7 +1296,7 @@ aac_release_command(struct aac_command *cm)
cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY;
cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB;
cm->cm_fib->Header.Flags = 0;
- cm->cm_fib->Header.SenderSize = sizeof(struct aac_fib);
+ cm->cm_fib->Header.SenderSize = cm->cm_sc->aac_max_fib_size;
/*
* These are duplicated in aac_start to cover the case where an
@@ -1122,6 +1307,13 @@ aac_release_command(struct aac_command *cm)
cm->cm_fib->Header.SenderData = 0;
aac_enqueue_free(cm);
+
+ sc = cm->cm_sc;
+ event = TAILQ_FIRST(&sc->aac_ev_cmfree);
+ if (event != NULL) {
+ TAILQ_REMOVE(&sc->aac_ev_cmfree, event, ev_links);
+ event->ev_callback(sc, event, event->ev_arg);
+ }
}
/*
@@ -1130,9 +1322,9 @@ aac_release_command(struct aac_command *cm)
static void
aac_map_command_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
- uint32_t *fibphys;
+ uint64_t *fibphys;
- fibphys = (uint32_t *)arg;
+ fibphys = (uint64_t *)arg;
debug_called(3);
@@ -1147,12 +1339,12 @@ aac_alloc_commands(struct aac_softc *sc)
{
struct aac_command *cm;
struct aac_fibmap *fm;
- uint32_t fibphys;
+ uint64_t fibphys;
int i, error;
debug_called(2);
- if (sc->total_fibs + AAC_FIB_COUNT > sc->aac_max_fibs)
+ if (sc->total_fibs + sc->aac_max_fibs_alloc > sc->aac_max_fibs)
return (ENOMEM);
fm = malloc(sizeof(struct aac_fibmap), M_AACBUF, M_NOWAIT|M_ZERO);
@@ -1170,18 +1362,19 @@ aac_alloc_commands(struct aac_softc *sc)
/* Ignore errors since this doesn't bounce */
(void)bus_dmamap_load(sc->aac_fib_dmat, fm->aac_fibmap, fm->aac_fibs,
- AAC_FIB_COUNT * sizeof(struct aac_fib),
+ sc->aac_max_fibs_alloc * sc->aac_max_fib_size,
aac_map_command_helper, &fibphys, 0);
/* initialise constant fields in the command structure */
mtx_lock(&sc->aac_io_lock);
- bzero(fm->aac_fibs, AAC_FIB_COUNT * sizeof(struct aac_fib));
- for (i = 0; i < AAC_FIB_COUNT; i++) {
+ bzero(fm->aac_fibs, sc->aac_max_fibs_alloc * sc->aac_max_fib_size);
+ for (i = 0; i < sc->aac_max_fibs_alloc; i++) {
cm = sc->aac_commands + sc->total_fibs;
fm->aac_commands = cm;
cm->cm_sc = sc;
- cm->cm_fib = fm->aac_fibs + i;
- cm->cm_fibphys = fibphys + (i * sizeof(struct aac_fib));
+ cm->cm_fib = (struct aac_fib *)
+ ((u_int8_t *)fm->aac_fibs + i*sc->aac_max_fib_size);
+ cm->cm_fibphys = fibphys + i*sc->aac_max_fib_size;
cm->cm_index = sc->total_fibs;
if ((error = bus_dmamap_create(sc->aac_buffer_dmat, 0,
@@ -1225,7 +1418,7 @@ aac_free_commands(struct aac_softc *sc)
* We check against total_fibs to handle partially
* allocated blocks.
*/
- for (i = 0; i < AAC_FIB_COUNT && sc->total_fibs--; i++) {
+ for (i = 0; i < sc->aac_max_fibs_alloc && sc->total_fibs--; i++) {
cm = fm->aac_commands + i;
bus_dmamap_destroy(sc->aac_buffer_dmat, cm->cm_datamap);
}
@@ -1254,7 +1447,20 @@ aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
/* copy into the FIB */
if (cm->cm_sgtable != NULL) {
- if ((cm->cm_sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
+ if (fib->Header.Command == RawIo) {
+ struct aac_sg_tableraw *sg;
+ sg = (struct aac_sg_tableraw *)cm->cm_sgtable;
+ sg->SgCount = nseg;
+ for (i = 0; i < nseg; i++) {
+ sg->SgEntryRaw[i].SgAddress = segs[i].ds_addr;
+ sg->SgEntryRaw[i].SgByteCount = segs[i].ds_len;
+ sg->SgEntryRaw[i].Next = 0;
+ sg->SgEntryRaw[i].Prev = 0;
+ sg->SgEntryRaw[i].Flags = 0;
+ }
+ /* update the FIB size for the s/g count */
+ fib->Header.Size += nseg*sizeof(struct aac_sg_entryraw);
+ } else if ((cm->cm_sc->flags & AAC_FLAGS_SG_64BIT) == 0) {
struct aac_sg_table *sg;
sg = cm->cm_sgtable;
sg->SgCount = nseg;
@@ -1263,7 +1469,7 @@ aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
sg->SgEntry[i].SgByteCount = segs[i].ds_len;
}
/* update the FIB size for the s/g count */
- fib->Header.Size += nseg * sizeof(struct aac_sg_entry);
+ fib->Header.Size += nseg*sizeof(struct aac_sg_entry);
} else {
struct aac_sg_table64 *sg;
sg = (struct aac_sg_table64 *)cm->cm_sgtable;
@@ -1279,10 +1485,11 @@ aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
/* Fix up the address values in the FIB. Use the command array index
* instead of a pointer since these fields are only 32 bits. Shift
- * the SenderFibAddress over to make room for the fast response bit.
+ * the SenderFibAddress over to make room for the fast response bit
+ * and for the AIF bit
*/
- cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 1);
- cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys;
+ cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 2);
+ cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys;
/* save a pointer to the command for speedy reverse-lookup */
cm->cm_fib->Header.SenderData = cm->cm_index;
@@ -1295,11 +1502,23 @@ aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
BUS_DMASYNC_PREWRITE);
cm->cm_flags |= AAC_CMD_MAPPED;
- /* Put the FIB on the outbound queue */
- if (aac_enqueue_fib(sc, cm->cm_queue, cm) == EBUSY) {
- aac_unmap_command(cm);
- sc->flags |= AAC_QUEUE_FRZN;
- aac_requeue_ready(cm);
+ if (sc->flags & AAC_FLAGS_NEW_COMM) {
+ int count = 10000000L;
+ while (AAC_SEND_COMMAND(sc, cm) != 0) {
+ if (--count == 0) {
+ aac_unmap_command(cm);
+ sc->flags |= AAC_QUEUE_FRZN;
+ aac_requeue_ready(cm);
+ }
+ DELAY(5); /* wait 5 usec. */
+ }
+ } else {
+ /* Put the FIB on the outbound queue */
+ if (aac_enqueue_fib(sc, cm->cm_queue, cm) == EBUSY) {
+ aac_unmap_command(cm);
+ sc->flags |= AAC_QUEUE_FRZN;
+ aac_requeue_ready(cm);
+ }
}
return;
@@ -1355,7 +1574,7 @@ aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error)
static int
aac_check_firmware(struct aac_softc *sc)
{
- u_int32_t major, minor, options;
+ u_int32_t major, minor, options, atu_size;
debug_called(1);
@@ -1391,6 +1610,7 @@ aac_check_firmware(struct aac_softc *sc)
return (EIO);
}
options = AAC_GET_MAILBOX(sc, 1);
+ atu_size = AAC_GET_MAILBOX(sc, 2);
sc->supported_options = options;
if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 &&
@@ -1403,13 +1623,60 @@ aac_check_firmware(struct aac_softc *sc)
device_printf(sc->aac_dev, "Enabling 64-bit address support\n");
sc->flags |= AAC_FLAGS_SG_64BIT;
}
+ if ((options & AAC_SUPPORTED_NEW_COMM) && sc->aac_if.aif_send_command)
+ sc->flags |= AAC_FLAGS_NEW_COMM;
+ if (options & AAC_SUPPORTED_64BIT_ARRAYSIZE)
+ sc->flags |= AAC_FLAGS_ARRAY_64BIT;
/* Check for broken hardware that does a lower number of commands */
- if ((sc->flags & AAC_FLAGS_256FIBS) == 0)
- sc->aac_max_fibs = AAC_MAX_FIBS;
- else
- sc->aac_max_fibs = 256;
+ sc->aac_max_fibs = (sc->flags & AAC_FLAGS_256FIBS ? 256:512);
+
+ /* Remap mem. resource, if required */
+ if ((sc->flags & AAC_FLAGS_NEW_COMM) &&
+ atu_size > rman_get_size(sc->aac_regs_resource)) {
+ bus_release_resource(
+ sc->aac_dev, SYS_RES_MEMORY,
+ sc->aac_regs_rid, sc->aac_regs_resource);
+ sc->aac_regs_resource = bus_alloc_resource(
+ sc->aac_dev, SYS_RES_MEMORY, &sc->aac_regs_rid,
+ 0ul, ~0ul, atu_size, RF_ACTIVE);
+ if (sc->aac_regs_resource == NULL) {
+ sc->aac_regs_resource = bus_alloc_resource_any(
+ sc->aac_dev, SYS_RES_MEMORY,
+ &sc->aac_regs_rid, RF_ACTIVE);
+ if (sc->aac_regs_resource == NULL) {
+ device_printf(sc->aac_dev,
+ "couldn't allocate register window\n");
+ return (ENXIO);
+ }
+ sc->flags &= ~AAC_FLAGS_NEW_COMM;
+ }
+ sc->aac_btag = rman_get_bustag(sc->aac_regs_resource);
+ sc->aac_bhandle = rman_get_bushandle(sc->aac_regs_resource);
+ }
+ /* Read preferred settings */
+ sc->aac_max_fib_size = sizeof(struct aac_fib);
+ sc->aac_max_sectors = 128; /* 64KB */
+ if (sc->flags & AAC_FLAGS_SG_64BIT)
+ sc->aac_sg_tablesize = (AAC_FIB_DATASIZE - sizeof(struct aac_blockwrite64)
+ + sizeof(struct aac_sg_table64)) / sizeof(struct aac_sg_table64);
+ else
+ sc->aac_sg_tablesize = (AAC_FIB_DATASIZE - sizeof(struct aac_blockwrite)
+ + sizeof(struct aac_sg_table)) / sizeof(struct aac_sg_table);
+ if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) {
+ options = AAC_GET_MAILBOX(sc, 1);
+ sc->aac_max_fib_size = (options & 0xFFFF);
+ sc->aac_max_sectors = (options >> 16) << 1;
+ options = AAC_GET_MAILBOX(sc, 2);
+ sc->aac_sg_tablesize = (options >> 16);
+ options = AAC_GET_MAILBOX(sc, 3);
+ sc->aac_max_fibs = (options & 0xFFFF);
+ }
+ if (sc->aac_max_fib_size > PAGE_SIZE)
+ sc->aac_max_fib_size = PAGE_SIZE;
+ sc->aac_max_fibs_alloc = PAGE_SIZE / sc->aac_max_fib_size;
+
return (0);
}
@@ -1458,7 +1725,7 @@ aac_init(struct aac_softc *sc)
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
MAXBSIZE, /* maxsize */
- AAC_MAXSGENTRIES, /* nsegments */
+ sc->aac_sg_tablesize, /* nsegments */
MAXBSIZE, /* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
busdma_lock_mutex, /* lockfunc */
@@ -1478,11 +1745,11 @@ aac_init(struct aac_softc *sc)
0x7fffffff, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
- AAC_FIB_COUNT *
- sizeof(struct aac_fib), /* maxsize */
+ sc->aac_max_fibs_alloc *
+ sc->aac_max_fib_size, /* maxsize */
1, /* nsegments */
- AAC_FIB_COUNT *
- sizeof(struct aac_fib), /* maxsegsize */
+ sc->aac_max_fibs_alloc *
+ sc->aac_max_fib_size, /* maxsegsize */
0, /* flags */
NULL, NULL, /* No locking needed */
&sc->aac_fib_dmat)) {
@@ -1535,7 +1802,7 @@ aac_init(struct aac_softc *sc)
/* Allocate some FIBs and associated command structs */
TAILQ_INIT(&sc->aac_fibmap_tqh);
- sc->aac_commands = malloc(AAC_MAX_FIBS * sizeof(struct aac_command),
+ sc->aac_commands = malloc(sc->aac_max_fibs * sizeof(struct aac_command),
M_AACBUF, M_WAITOK|M_ZERO);
while (sc->total_fibs < AAC_PREALLOCATE_FIBS) {
if (aac_alloc_commands(sc) != 0)
@@ -1550,6 +1817,10 @@ aac_init(struct aac_softc *sc)
*/
ip = &sc->aac_common->ac_init;
ip->InitStructRevision = AAC_INIT_STRUCT_REVISION;
+ if (sc->aac_max_fib_size > sizeof(struct aac_fib)) {
+ ip->InitStructRevision = AAC_INIT_STRUCT_REVISION_4;
+ sc->flags |= AAC_FLAGS_RAW_IO;
+ }
ip->MiniPortRevision = AAC_INIT_STRUCT_MINIPORT_REVISION;
ip->AdapterFibsPhysicalAddress = sc->aac_common_busaddr +
@@ -1575,6 +1846,16 @@ aac_init(struct aac_softc *sc)
}
ip->HostElapsedSeconds = time_uptime; /* reset later if invalid */
+ ip->InitFlags = 0;
+ if (sc->flags & AAC_FLAGS_NEW_COMM) {
+ ip->InitFlags = INITFLAGS_NEW_COMM_SUPPORTED;
+ device_printf(sc->aac_dev, "New comm. interface enabled\n");
+ }
+
+ ip->MaxIoCommands = sc->aac_max_fibs;
+ ip->MaxIoSize = sc->aac_max_sectors << 9;
+ ip->MaxFibSize = sc->aac_max_fib_size;
+
/*
* Initialise FIB queues. Note that it appears that the layout of the
* indexes and the segmentation of the entries may be mandated by the
@@ -1680,6 +1961,7 @@ out:
/*
* Send a synchronous command to the controller and wait for a result.
+ * Indicate if the controller completed the command with an error status.
*/
static int
aac_sync_command(struct aac_softc *sc, u_int32_t command,
@@ -1716,6 +1998,9 @@ aac_sync_command(struct aac_softc *sc, u_int32_t command,
status = AAC_GET_MAILBOX(sc, 0);
if (sp != NULL)
*sp = status;
+
+ if (status != 0x01)
+ return (-1);
return(0);
}
@@ -1724,6 +2009,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
struct aac_fib *fib, u_int16_t datasize)
{
debug_called(3);
+ mtx_assert(&sc->aac_io_lock, MA_OWNED);
if (datasize > AAC_FIB_DATASIZE)
return(EINVAL);
@@ -1902,7 +2188,7 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
* field.
*/
fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr;
- cm = sc->aac_commands + (fib_index >> 1);
+ cm = sc->aac_commands + (fib_index >> 2);
*fib_addr = cm->cm_fib;
/*
@@ -2292,7 +2578,10 @@ aac_rx_set_interrupts(struct aac_softc *sc, int enable)
debug(2, "%sable interrupts", enable ? "en" : "dis");
if (enable) {
- AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
+ if (sc->flags & AAC_FLAGS_NEW_COMM)
+ AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INT_NEW_COMM);
+ else
+ AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS);
} else {
AAC_SETREG4(sc, AAC_RX_OIMR, ~0);
}
@@ -2318,13 +2607,100 @@ aac_rkt_set_interrupts(struct aac_softc *sc, int enable)
debug(2, "%sable interrupts", enable ? "en" : "dis");
if (enable) {
- AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS);
+ if (sc->flags & AAC_FLAGS_NEW_COMM)
+ AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INT_NEW_COMM);
+ else
+ AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS);
} else {
AAC_SETREG4(sc, AAC_RKT_OIMR, ~0);
}
}
/*
+ * New comm. interface: Send command functions
+ */
+static int
+aac_rx_send_command(struct aac_softc *sc, struct aac_command *cm)
+{
+ u_int32_t index, device;
+
+ debug(2, "send command (new comm.)");
+
+ index = AAC_GETREG4(sc, AAC_RX_IQUE);
+ if (index == 0xffffffffL)
+ index = AAC_GETREG4(sc, AAC_RX_IQUE);
+ if (index == 0xffffffffL)
+ return index;
+ aac_enqueue_busy(cm);
+ device = index;
+ AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys & 0xffffffffUL));
+ device += 4;
+ AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys >> 32));
+ device += 4;
+ AAC_SETREG4(sc, device, cm->cm_fib->Header.Size);
+ AAC_SETREG4(sc, AAC_RX_IQUE, index);
+ return 0;
+}
+
+static int
+aac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm)
+{
+ u_int32_t index, device;
+
+ debug(2, "send command (new comm.)");
+
+ index = AAC_GETREG4(sc, AAC_RKT_IQUE);
+ if (index == 0xffffffffL)
+ index = AAC_GETREG4(sc, AAC_RKT_IQUE);
+ if (index == 0xffffffffL)
+ return index;
+ aac_enqueue_busy(cm);
+ device = index;
+ AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys & 0xffffffffUL));
+ device += 4;
+ AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys >> 32));
+ device += 4;
+ AAC_SETREG4(sc, device, cm->cm_fib->Header.Size);
+ AAC_SETREG4(sc, AAC_RKT_IQUE, index);
+ return 0;
+}
+
+/*
+ * New comm. interface: get, set outbound queue index
+ */
+static int
+aac_rx_get_outb_queue(struct aac_softc *sc)
+{
+ debug_called(3);
+
+ return(AAC_GETREG4(sc, AAC_RX_OQUE));
+}
+
+static int
+aac_rkt_get_outb_queue(struct aac_softc *sc)
+{
+ debug_called(3);
+
+ return(AAC_GETREG4(sc, AAC_RKT_OQUE));
+}
+
+static void
+aac_rx_set_outb_queue(struct aac_softc *sc, int index)
+{
+ debug_called(3);
+
+ AAC_SETREG4(sc, AAC_RX_OQUE, index);
+}
+
+static void
+aac_rkt_set_outb_queue(struct aac_softc *sc, int index)
+{
+ debug_called(3);
+
+ AAC_SETREG4(sc, AAC_RKT_OQUE, index);
+}
+
+/*
* Debugging and Diagnostics
*/
@@ -2352,6 +2728,12 @@ aac_describe_controller(struct aac_softc *sc)
info = (struct aac_adapter_info *)&fib->data[0];
sc->aac_revision = info->KernelRevision;
+ device_printf(sc->aac_dev, "Adaptec Raid Controller %d.%d.%d-%d\n",
+ AAC_DRIVER_VERSION >> 24,
+ (AAC_DRIVER_VERSION >> 16) & 0xFF,
+ AAC_DRIVER_VERSION & 0xFF,
+ AAC_DRIVER_BUILD);
+
if (bootverbose) {
device_printf(sc->aac_dev, "%s %dMHz, %dMB memory "
"(%dMB cache, %dMB execution), %s\n",
@@ -2385,7 +2767,13 @@ aac_describe_controller(struct aac_softc *sc)
"\12NORECOND"
"\13SGMAP64"
"\14ALARM"
- "\15NONDASD");
+ "\15NONDASD"
+ "\16SCSIMGT"
+ "\17RAIDSCSI"
+ "\21ADPTINFO"
+ "\22NEWCOMM"
+ "\23ARRAY64BIT"
+ "\24HEATSENSOR");
}
aac_release_sync_fib(sc);
}
@@ -2523,7 +2911,7 @@ aac_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
case FSACTL_LNX_QUERY_DISK:
debug(1, "FSACTL_QUERY_DISK");
error = aac_query_disk(sc, arg);
- break;
+ break;
case FSACTL_DELETE_DISK:
case FSACTL_LNX_DELETE_DISK:
/*
@@ -2533,6 +2921,12 @@ aac_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int flag, d_thread_t *td)
*/
error = 0;
break;
+ case FSACTL_GET_PCI_INFO:
+ arg = *(caddr_t*)arg;
+ case FSACTL_LNX_GET_PCI_INFO:
+ debug(1, "FSACTL_GET_PCI_INFO");
+ error = aac_get_pci_info(sc, arg);
+ break;
default:
debug(1, "unsupported cmd 0x%lx\n", cmd);
error = EINVAL;
@@ -2565,6 +2959,27 @@ aac_poll(struct cdev *dev, int poll_events, d_thread_t *td)
return (revents);
}
+static void
+aac_ioctl_event(struct aac_softc *sc, struct aac_event *event, void *arg)
+{
+
+ switch (event->ev_type) {
+ case AAC_EVENT_CMFREE:
+ mtx_lock(&sc->aac_io_lock);
+ if (aac_alloc_command(sc, (struct aac_command **)arg) == 0) {
+ aac_add_event(sc, event);
+ mtx_unlock(&sc->aac_io_lock);
+ return;
+ }
+ free(event, M_AACBUF);
+ wakeup(aac_ioctl_sendfib);
+ mtx_unlock(&sc->aac_io_lock);
+ break;
+ default:
+ break;
+ }
+}
+
/*
* Send a FIB supplied from userspace
*/
@@ -2583,8 +2998,19 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib)
*/
mtx_lock(&sc->aac_io_lock);
if (aac_alloc_command(sc, &cm)) {
- error = EBUSY;
- goto out;
+ struct aac_event *event;
+
+ event = malloc(sizeof(struct aac_event), M_AACBUF,
+ M_NOWAIT | M_ZERO);
+ if (event == NULL) {
+ error = EBUSY;
+ goto out;
+ }
+ event->ev_type = AAC_EVENT_CMFREE;
+ event->ev_callback = aac_ioctl_event;
+ event->ev_arg = &cm;
+ aac_add_event(sc, event);
+ msleep(aac_ioctl_sendfib, &sc->aac_io_lock, 0, "sendfib", 0);
}
/*
@@ -2736,8 +3162,12 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
co = TAILQ_FIRST(&sc->aac_container_tqh);
while (co != NULL) {
if (co->co_found == 0) {
+ mtx_unlock(&sc->aac_io_lock);
+ mtx_lock(&Giant);
device_delete_child(sc->aac_dev,
co->co_disk);
+ mtx_unlock(&Giant);
+ mtx_lock(&sc->aac_io_lock);
co_next = TAILQ_NEXT(co, co_link);
mtx_lock(&sc->aac_container_lock);
TAILQ_REMOVE(&sc->aac_container_tqh, co,
@@ -2752,8 +3182,13 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
}
/* Attach the newly created containers */
- if (added)
+ if (added) {
+ mtx_unlock(&sc->aac_io_lock);
+ mtx_lock(&Giant);
bus_generic_attach(sc->aac_dev);
+ mtx_unlock(&Giant);
+ mtx_lock(&sc->aac_io_lock);
+ }
break;
@@ -2887,6 +3322,26 @@ aac_return_aif(struct aac_softc *sc, caddr_t uptr)
return(error);
}
+static int
+aac_get_pci_info(struct aac_softc *sc, caddr_t uptr)
+{
+ struct aac_pci_info {
+ u_int32_t bus;
+ u_int32_t slot;
+ } pciinf;
+ int error;
+
+ debug_called(2);
+
+ pciinf.bus = pci_get_bus(sc->aac_dev);
+ pciinf.slot = pci_get_slot(sc->aac_dev);
+
+ error = copyout((caddr_t)&pciinf, uptr,
+ sizeof(struct aac_pci_info));
+
+ return (error);
+}
+
/*
* Give the userland some information about the container. The AAC arch
* expects the driver to be a SCSI passthrough type driver, so it expects
@@ -3024,7 +3479,7 @@ aac_get_bus_info(struct aac_softc *sc)
device_printf(sc->aac_dev,
"No memory to add passthrough bus %d\n", i);
break;
- }
+ };
child = device_add_child(sc->aac_dev, "aacp", -1);
if (child == NULL) {
@@ -3032,7 +3487,7 @@ aac_get_bus_info(struct aac_softc *sc)
"device_add_child failed for passthrough bus %d\n",
i);
free(caminf, M_AACBUF);
- break;
+ break;
}
caminf->TargetsPerBus = businfo.TargetsPerBus;
diff --git a/sys/dev/aac/aac_cam.c b/sys/dev/aac/aac_cam.c
index 978b2e2..aaca0d1 100644
--- a/sys/dev/aac/aac_cam.c
+++ b/sys/dev/aac/aac_cam.c
@@ -79,7 +79,6 @@ static void aac_cam_complete(struct aac_command *);
static u_int32_t aac_cam_reset_bus(struct cam_sim *, union ccb *);
static u_int32_t aac_cam_abort_ccb(struct cam_sim *, union ccb *);
static u_int32_t aac_cam_term_io(struct cam_sim *, union ccb *);
-static int aac_cam_get_tran_settings(struct aac_softc *, struct ccb_trans_settings *, u_int32_t);
static devclass_t aac_pass_devclass;
@@ -101,6 +100,26 @@ MODULE_DEPEND(aacp, cam, 1, 1, 1);
MALLOC_DEFINE(M_AACCAM, "aaccam", "AAC CAM info");
+static void
+aac_cam_event(struct aac_softc *sc, struct aac_event *event, void *arg)
+{
+ struct aac_cam *camsc;
+
+ switch (event->ev_type) {
+ case AAC_EVENT_CMFREE:
+ camsc = arg;
+ free(event, M_AACCAM);
+ xpt_release_simq(camsc->sim, 1);
+ break;
+ default:
+ device_printf(sc->aac_dev, "unknown event %d in aac_cam\n",
+ event->ev_type);
+ break;
+ }
+
+ return;
+}
+
static int
aac_cam_probe(device_t dev)
{
@@ -251,12 +270,9 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb)
}
case XPT_GET_TRAN_SETTINGS:
{
- u_int32_t handle;
-
- handle = AAC_BTL_TO_HANDLE(camsc->inf->BusNumber,
- ccb->ccb_h.target_id, ccb->ccb_h.target_lun);
- ccb->ccb_h.status = aac_cam_get_tran_settings(sc, &ccb->cts,
- handle);
+ ccb->cts.flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
+ ccb->cts.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
+ ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
return;
}
@@ -292,10 +308,25 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb)
mtx_lock(&sc->aac_io_lock);
if (aac_alloc_command(sc, &cm)) {
- mtx_unlock(&sc->aac_io_lock);
+ struct aac_event *event;
+
xpt_freeze_simq(sim, 1);
ccb->ccb_h.status = CAM_REQUEUE_REQ;
xpt_done(ccb);
+ event = malloc(sizeof(struct aac_event), M_AACCAM,
+ M_NOWAIT | M_ZERO);
+ if (event == NULL) {
+ device_printf(sc->aac_dev,
+ "Warning, out of memory for event\n");
+ /* XXX Yuck, what to do here? */
+ mtx_unlock(&sc->aac_io_lock);
+ return;
+ }
+ event->ev_callback = aac_cam_event;
+ event->ev_arg = camsc;
+ event->ev_type = AAC_EVENT_CMFREE;
+ aac_add_event(sc, event);
+ mtx_unlock(&sc->aac_io_lock);
return;
}
@@ -469,7 +500,7 @@ aac_cam_complete(struct aac_command *cm)
srbr->sense_len);
ccb->csio.sense_len = sense_len;
ccb->ccb_h.status |= CAM_AUTOSNS_VALID;
- scsi_sense_print(&ccb->csio);
+ // scsi_sense_print(&ccb->csio);
}
/* If this is an inquiry command, fake things out */
@@ -518,6 +549,7 @@ aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb)
return (CAM_REQ_ABORTED);
}
+ mtx_lock(&sc->aac_io_lock);
aac_alloc_sync_fib(sc, &fib);
vmi = (struct aac_vmioctl *)&fib->data[0];
@@ -542,6 +574,7 @@ aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb)
}
aac_release_sync_fib(sc);
+ mtx_unlock(&sc->aac_io_lock);
return (CAM_REQ_CMP);
}
@@ -557,59 +590,3 @@ aac_cam_term_io(struct cam_sim *sim, union ccb *ccb)
return (CAM_UA_TERMIO);
}
-static int
-aac_cam_get_tran_settings(struct aac_softc *sc, struct ccb_trans_settings *cts, u_int32_t handle)
-{
- struct aac_fib *fib;
- struct aac_vmioctl *vmi;
- struct aac_vmi_devinfo_resp *vmi_resp;
- int error;
-
- aac_alloc_sync_fib(sc, &fib);
- vmi = (struct aac_vmioctl *)&fib->data[0];
- bzero(vmi, sizeof(struct aac_vmioctl));
-
- vmi->Command = VM_Ioctl;
- vmi->ObjType = FT_DRIVE;
- vmi->MethId = sc->scsi_method_id;
- vmi->ObjId = handle;
- vmi->IoctlCmd = GetDeviceProbeInfo;
-
- error = aac_sync_fib(sc, ContainerCommand, 0, fib,
- sizeof(struct aac_vmioctl));
- if (error) {
- device_printf(sc->aac_dev, "Error %d sending GetDeviceProbeInfo"
- " command\n", error);
- aac_release_sync_fib(sc);
- return (CAM_REQ_INVALID);
- }
-
- vmi_resp = (struct aac_vmi_devinfo_resp *)&fib->data[0];
- if (vmi_resp->Status != ST_OK) {
- /*
- * The only reason why this command will return an error is
- * if the requested device doesn't exist.
- */
- debug(1, "GetDeviceProbeInfo returned %d\n", vmi_resp->Status);
- aac_release_sync_fib(sc);
- return (CAM_DEV_NOT_THERE);
- }
-
- cts->bus_width = ((vmi_resp->Inquiry7 & 0x60) >> 5);
- cts->valid = CCB_TRANS_BUS_WIDTH_VALID;
-
- if (vmi_resp->ScsiRate) {
- cts->sync_period =
- scsi_calc_syncparam((10000 / vmi_resp->ScsiRate));
- cts->sync_offset = vmi_resp->ScsiOffset;
- cts->valid |= CCB_TRANS_SYNC_RATE_VALID |
- CCB_TRANS_SYNC_OFFSET_VALID;
- }
-
- cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
- cts->valid |= CCB_TRANS_DISC_VALID |
- CCB_TRANS_TQ_VALID;
-
- aac_release_sync_fib(sc);
- return (CAM_REQ_CMP);
-}
diff --git a/sys/dev/aac/aac_pci.c b/sys/dev/aac/aac_pci.c
index f97c85c..de0f739 100644
--- a/sys/dev/aac/aac_pci.c
+++ b/sys/dev/aac/aac_pci.c
@@ -139,6 +139,59 @@ struct aac_ident
"Adaptec SCSI RAID 2230S"},
{0x9005, 0x0286, 0x9005, 0x028d, AAC_HWIF_RKT, 0,
"Adaptec SCSI RAID 2130S"},
+
+ {0x9005, 0x0285, 0x9005, 0x0287, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB |
+ AAC_FLAGS_256FIBS, "Adaptec SCSI RAID 2200S"},
+ {0x9005, 0x0285, 0x17aa, 0x0286, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB |
+ AAC_FLAGS_256FIBS, "Legend S220"},
+ {0x9005, 0x0285, 0x17aa, 0x0287, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB |
+ AAC_FLAGS_256FIBS, "Legend S230"},
+ {0x9005, 0x0285, 0x9005, 0x0288, AAC_HWIF_I960RX, 0,
+ "Adaptec SCSI RAID 3230S"},
+ {0x9005, 0x0285, 0x9005, 0x0289, AAC_HWIF_I960RX, 0,
+ "Adaptec SCSI RAID 3240S"},
+ {0x9005, 0x0285, 0x9005, 0x028a, AAC_HWIF_I960RX, 0,
+ "Adaptec SCSI RAID 2020ZCR"},
+ {0x9005, 0x0285, 0x9005, 0x028b, AAC_HWIF_I960RX, 0,
+ "Adaptec SCSI RAID 2025ZCR"},
+ {0x9005, 0x0286, 0x9005, 0x029b, AAC_HWIF_RKT, 0,
+ "Adaptec SATA RAID 2820SA"},
+ {0x9005, 0x0286, 0x9005, 0x029c, AAC_HWIF_RKT, 0,
+ "Adaptec SATA RAID 2620SA"},
+ {0x9005, 0x0286, 0x9005, 0x029d, AAC_HWIF_RKT, 0,
+ "Adaptec SATA RAID 2420SA"},
+ {0x9005, 0x0286, 0x9005, 0x029e, AAC_HWIF_RKT, 0,
+ "ICP9024RO SATA RAID"},
+ {0x9005, 0x0286, 0x9005, 0x029f, AAC_HWIF_RKT, 0,
+ "ICP9014RO SATA RAID"},
+ {0x9005, 0x0285, 0x9005, 0x0294, AAC_HWIF_I960RX, 0,
+ "Adaptec SATA RAID 2026ZCR"},
+ {0x9005, 0x0285, 0x103c, 0x3227, AAC_HWIF_I960RX, 0,
+ "Adaptec SATA RAID 2610SA"},
+ {0x9005, 0x0285, 0x9005, 0x0296, AAC_HWIF_I960RX, 0,
+ "Adaptec SCSI RAID 2240S"},
+ {0x9005, 0x0285, 0x9005, 0x0297, AAC_HWIF_I960RX, 0,
+ "Adaptec SAS RAID 4005SAS"},
+ {0x9005, 0x0285, 0x1014, 0x02f2, AAC_HWIF_I960RX, 0,
+ "IBM ServeRAID 8i"},
+ {0x9005, 0x0285, 0x9005, 0x0298, AAC_HWIF_I960RX, 0,
+ "Adaptec SAS RAID 4000SAS"},
+ {0x9005, 0x0285, 0x9005, 0x0299, AAC_HWIF_I960RX, 0,
+ "Adaptec SAS RAID 4800SAS"},
+ {0x9005, 0x0285, 0x9005, 0x029a, AAC_HWIF_I960RX, 0,
+ "Adaptec SAS RAID 4805SAS"},
+ {0x9005, 0x0285, 0x9005, 0x028e, AAC_HWIF_I960RX, 0,
+ "Adaptec SATA RAID 2020SA ZCR"},
+ {0x9005, 0x0285, 0x9005, 0x028f, AAC_HWIF_I960RX, 0,
+ "Adaptec SATA RAID 2025SA ZCR"},
+ {0x9005, 0x0285, 0x9005, 0x02a4, AAC_HWIF_I960RX, 0,
+ "ICP 9085LI SAS RAID"},
+ {0x9005, 0x0285, 0x9005, 0x02a5, AAC_HWIF_I960RX, 0,
+ "ICP 5085BR SAS RAID"},
+ {0x9005, 0x0286, 0x9005, 0x02a0, AAC_HWIF_RKT, 0,
+ "ICP9047MA SATA RAID"},
+ {0x9005, 0x0286, 0x9005, 0x02a1, AAC_HWIF_RKT, 0,
+ "ICP9087MA SATA RAID"},
{0, 0, 0, 0, 0, 0, 0}
};
@@ -221,30 +274,6 @@ aac_pci_attach(device_t dev)
sc->aac_btag = rman_get_bustag(sc->aac_regs_resource);
sc->aac_bhandle = rman_get_bushandle(sc->aac_regs_resource);
- /*
- * Allocate and connect our interrupt.
- */
- sc->aac_irq_rid = 0;
- if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ,
- &sc->aac_irq_rid,
- RF_SHAREABLE |
- RF_ACTIVE)) == NULL) {
- device_printf(sc->aac_dev, "can't allocate interrupt\n");
- goto out;
- }
- if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
- INTR_FAST|INTR_TYPE_BIO, aac_intr,
- sc, &sc->aac_intr)) {
- device_printf(sc->aac_dev, "can't set up FAST interrupt\n");
- if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
- INTR_MPSAFE|INTR_ENTROPY|INTR_TYPE_BIO,
- aac_intr, sc, &sc->aac_intr)) {
- device_printf(sc->aac_dev,
- "can't set up MPSAFE interrupt\n");
- goto out;
- }
- }
-
/* assume failure is 'out of memory' */
error = ENOMEM;
@@ -259,7 +288,7 @@ aac_pci_attach(device_t dev)
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
BUS_SPACE_MAXSIZE_32BIT, /* maxsize */
- AAC_MAXSGENTRIES, /* nsegments */
+ BUS_SPACE_UNRESTRICTED, /* nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
0, /* flags */
NULL, NULL, /* No locking needed */
@@ -292,7 +321,7 @@ aac_pci_attach(device_t dev)
sc->aac_if = aac_fa_interface;
break;
case AAC_HWIF_RKT:
- debug(2, "setu hardware up for Rocket/MIPS");
+ debug(2, "set hardware up for Rocket/MIPS");
sc->aac_if = aac_rkt_interface;
break;
default:
@@ -317,7 +346,7 @@ aac_pci_attach(device_t dev)
* Do bus-independent initialisation.
*/
error = aac_attach(sc);
-
+
out:
if (error)
aac_free(sc);
diff --git a/sys/dev/aac/aac_tables.h b/sys/dev/aac/aac_tables.h
index 4ce82ac..4a0d0e3 100644
--- a/sys/dev/aac/aac_tables.h
+++ b/sys/dev/aac/aac_tables.h
@@ -40,7 +40,7 @@ static struct aac_code_lookup aac_command_status_table[] = {
{"I/O error", 5},
{"device not configured", 6},
{"too big", 7},
- {"permission denoed", 13},
+ {"permission denied", 13},
{"file exists", 17},
{"cross-device link", 18},
{"operation not supported by device", 19},
@@ -66,7 +66,7 @@ static struct aac_code_lookup aac_command_status_table[] = {
{"bad type", 10007},
{"jukebox", 10008},
{"not mounted", 10009},
- {"in maintenace mode", 10010},
+ {"in maintenance mode", 10010},
{"stale ACL", 10011},
{NULL, 0},
{"unknown command status", 0}
@@ -79,11 +79,14 @@ static struct aac_code_lookup aac_cpu_variant[] = {
{"i960CX", CPUI960_CX},
{"i960HX", CPUI960_HX},
{"i960RX", CPUI960_RX},
+ {"i960 80303", CPUI960_80303},
{"StrongARM SA110", CPUARM_SA110},
- {"MPC824x", CPUMPC_824x},
+ {"PPC603e", CPUPPC_603e},
+ {"XScale 80321", CPU_XSCALE_80321},
+ {"MIPS 4KC", CPU_MIPS_4KC},
+ {"MIPS 5KC", CPU_MIPS_5KC},
{"Unknown StrongARM", CPUARM_xxx},
{"Unknown PowerPC", CPUPPC_xxx},
- {"IOP302/303", CPUI960_30X},
{NULL, 0},
{"Unknown processor", 0}
};
@@ -113,6 +116,11 @@ static struct aac_code_lookup aac_container_types[] = {
{"Volume of Mirrors", CT_VOLUME_OF_MIRRORS},
{"Pseudo RAID 3", CT_PSEUDO_RAID3},
{"RAID 0/5", CT_RAID50},
+ {"RAID 5D", CT_RAID5D},
+ {"RAID 0/5D", CT_RAID5D0},
+ {"RAID 1E", CT_RAID1E},
+ {"RAID 6", CT_RAID6},
+ {"RAID 0/6", CT_RAID60},
{NULL, 0},
{"unknown", 0}
};
diff --git a/sys/dev/aac/aacreg.h b/sys/dev/aac/aacreg.h
index 11357e3..efa14a1 100644
--- a/sys/dev/aac/aacreg.h
+++ b/sys/dev/aac/aacreg.h
@@ -200,12 +200,17 @@ typedef enum {
/* Container Commands */
ContainerCommand = 500,
ContainerCommand64 = 501,
+ RawIo = 502,
/* Cluster Commands */
ClusterCommand = 550,
/* Scsi Port commands (scsi passthrough) */
ScsiPortCommand = 600,
+ ScsiPortCommandU64 = 601,
+ SataPortCommandU64 = 602,
+ SasSmpPassThrough = 603,
+ SasRequestPhyInfo = 612,
/* misc house keeping and generic adapter initiated commands */
AifRequest = 700,
@@ -214,7 +219,21 @@ typedef enum {
RequestAdapterInfo = 703,
IsAdapterPaused = 704,
SendHostTime = 705,
- LastMiscCommand = 706
+ RequestSupplementAdapterInfo = 706, /* Supp. Info for set in UCC
+ * use only if supported
+ * (RequestAdapterInfo first) */
+ LastMiscCommand = 707,
+
+ OnLineDiagnostic = 800,
+ FduAdapterTest = 801,
+ RequestCompatibilityId = 802,
+ AdapterEnvironmentInfo = 803, /* temp. sensors */
+ NvsramEventLog = 900,
+ ResetNvsramEventLogPointers = 901,
+ EnableEventLog = 902,
+ DisableEventLog = 903,
+ EncryptedKeyTransportFIB= 904,
+ KeyableFeaturesFIB= 905
} AAC_FibCommands;
/*
@@ -270,6 +289,7 @@ typedef enum {
struct aac_adapter_init {
u_int32_t InitStructRevision;
#define AAC_INIT_STRUCT_REVISION 3
+#define AAC_INIT_STRUCT_REVISION_4 4
u_int32_t MiniPortRevision;
#define AAC_INIT_STRUCT_MINIPORT_REVISION 1
u_int32_t FilesystemRevision;
@@ -284,6 +304,12 @@ struct aac_adapter_init {
#define AAC_PAGE_SIZE 4096
u_int32_t HostPhysMemPages;
u_int32_t HostElapsedSeconds;
+ /* ADAPTER_INIT_STRUCT_REVISION_4 begins here */
+ u_int32_t InitFlags; /* flags for supported features */
+#define INITFLAGS_NEW_COMM_SUPPORTED 1
+ u_int32_t MaxIoCommands; /* max outstanding commands */
+ u_int32_t MaxIoSize; /* largest I/O command */
+ u_int32_t MaxFibSize; /* largest FIB to adapter */
} __packed;
/*
@@ -308,6 +334,11 @@ typedef enum {
CT_VOLUME_OF_MIRRORS, /* volume of mirror */
CT_PSEUDO_RAID3, /* really raid4 */
CT_RAID50, /* stripe of raid5 */
+ CT_RAID5D, /* raid5 distributed hot-sparing */
+ CT_RAID5D0,
+ CT_RAID1E, /* extended raid1 mirroring */
+ CT_RAID6,
+ CT_RAID60,
} AAC_FSAVolType;
/*
@@ -346,6 +377,14 @@ struct aac_sg_entry64 {
u_int32_t SgByteCount;
} __packed;
+struct aac_sg_entryraw {
+ u_int32_t Next; /* reserved for FW use */
+ u_int32_t Prev; /* reserved for FW use */
+ u_int64_t SgAddress;
+ u_int32_t SgByteCount;
+ u_int32_t Flags; /* reserved for FW use */
+} __packed;
+
struct aac_sg_table {
u_int32_t SgCount;
struct aac_sg_entry SgEntry[0];
@@ -360,6 +399,14 @@ struct aac_sg_table64 {
} __packed;
/*
+ * s/g list for raw commands
+ */
+struct aac_sg_tableraw {
+ u_int32_t SgCount;
+ struct aac_sg_entryraw SgEntryRaw[0];
+} __packed;
+
+/*
* Container creation data
*/
struct aac_container_creation {
@@ -417,6 +464,8 @@ typedef enum {
CPU_ALPHA,
CPU_P7,
CPU_I960_RX,
+ CPU_MIPS,
+ CPU_XSCALE,
CPU__last
} AAC_CpuType;
@@ -427,9 +476,12 @@ typedef enum {
CPUI960_RX,
CPUARM_SA110,
CPUARM_xxx,
- CPUMPC_824x,
+ CPUPPC_603e,
CPUPPC_xxx,
- CPUI960_30X,
+ CPUI960_80303,
+ CPU_XSCALE_80321,
+ CPU_MIPS_4KC,
+ CPU_MIPS_5KC,
CPUSUBTYPE__last
} AAC_CpuSubType;
@@ -454,6 +506,20 @@ typedef enum {
PLAT_POBLANO_XXX,
PLAT_JALAPENO_P2,
PLAT_HABANERO,
+ PLAT_VULCAN,
+ PLAT_CRUSADER,
+ PLAT_LANCER,
+ PLAT_HARRIER,
+ PLAT_TERMINATOR,
+ PLAT_SKYHAWK,
+ PLAT_CORSAIR,
+ PLAT_JAGUAR,
+ PLAT_SATAHAWK,
+ PLAT_SATANATOR,
+ PLAT_PROWLER,
+ PLAT_BLACKBIRD,
+ PLAT_SABREEXPRESS,
+ PLAT_INTRUDER,
PLAT__last
} AAC_Platform;
@@ -463,9 +529,14 @@ typedef enum {
OEM_FLAVOR_HP,
OEM_FLAVOR_IBM,
OEM_FLAVOR_CPQ,
- OEM_FLAVOR_BRAND_X,
- OEM_FLAVOR_BRAND_Y,
+ OEM_FLAVOR_FSC,
+ OEM_FLAVOR_DWS,
OEM_FLAVOR_BRAND_Z,
+ OEM_FLAVOR_LEGEND,
+ OEM_FLAVOR_HITACHI,
+ OEM_FLAVOR_ESG,
+ OEM_FLAVOR_ICP,
+ OEM_FLAVOR_SCM,
OEM_FLAVOR__last
} AAC_OemFlavor;
@@ -499,6 +570,12 @@ typedef enum
#define AAC_SUPPORTED_SGMAP_HOST64 0x400
#define AAC_SUPPORTED_ALARM 0x800
#define AAC_SUPPORTED_NONDASD 0x1000
+#define AAC_SUPPORTED_SCSI_MANAGED 0x2000
+#define AAC_SUPPORTED_RAID_SCSI_MODE 0x4000
+#define AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO 0x10000
+#define AAC_SUPPORTED_NEW_COMM 0x20000
+#define AAC_SUPPORTED_64BIT_ARRAYSIZE 0x40000
+#define AAC_SUPPORTED_HEAT_SENSOR 0x80000
/*
* Structure used to respond to a RequestAdapterInfo fib.
@@ -534,10 +611,16 @@ struct aac_adapter_info {
/*
* Synchronous commands to the monitor/kernel.
*/
+#define AAC_MONKER_BREAKPOINT 0x04
#define AAC_MONKER_INITSTRUCT 0x05
#define AAC_MONKER_SYNCFIB 0x0c
#define AAC_MONKER_GETKERNVER 0x11
+#define AAC_MONKER_POSTRESULTS 0x14
#define AAC_MONKER_GETINFO 0x19
+#define AAC_MONKER_GETDRVPROP 0x23
+#define AAC_MONKER_RCVTEMP 0x25
+#define AAC_MONKER_GETCOMMPREF 0x26
+#define AAC_MONKER_REINIT 0xee
/*
* Adapter Status Register
@@ -658,6 +741,7 @@ typedef enum {
AifJobScsiExercise, /* SCSI device Exercise operation */
AifJobScsiVerifyRepair, /* SCSI device Verify operation WITH
* repair */
+ AifJobScsiWritePattern, /* write pattern */
AifJobScsiMax = 99, /* Max Scsi value */
AifJobCtrMin, /* Min Ctr op value */
AifJobCtrZero, /* Container clear operation */
@@ -671,6 +755,12 @@ typedef enum {
AifJobCtrPartCopy, /* Container Partition copy operation */
AifJobCtrRebuildMirror, /* Container Rebuild Mirror operation */
AifJobCtrCrazyCache, /* crazy cache */
+ AifJobCtrCopyback, /* Container Copyback operation */
+ AifJobCtrCompactRaid5D, /* Container Compaction operation */
+ AifJobCtrExpandRaid5D, /* Container Expansion operation */
+ AifJobCtrRebuildRaid6, /* Container Rebuild Raid6 operation */
+ AifJobCtrScrubRaid6, /* Container Scrub Raid6 operation */
+ AifJobCtrSSBackup, /* Container snapshot backup task */
AifJobCtrMax = 199, /* Max Ctr type operation */
AifJobFsMin, /* Min Fs type operation */
AifJobFsCreate, /* File System Create operation */
@@ -977,6 +1067,8 @@ typedef enum _VM_COMMANDS {
VM_CtBlockVerify64,
VM_CtHostRead64,
VM_CtHostWrite64,
+ VM_DrvErrTblLog, /* drive error table/log type of command */
+ VM_NameServe64
} AAC_VMCommand;
/*
@@ -1071,8 +1163,15 @@ struct aac_vmi_businf_resp {
struct aac_getbusinf BusInf;
} __packed;
+#if 0
#define AAC_BTL_TO_HANDLE(b, t, l) \
(((b & 0x3f) << 7) | ((l & 0x7) << 4) | (t & 0xf))
+#else
+#define AAC_BTL_TO_HANDLE(b, t, l) \
+ ((((u_int32_t)b & 0x0f) << 24) | \
+ (((u_int32_t)l & 0xff) << 16) | \
+ ((u_int32_t)t & 0xffff))
+#endif
#define GetDeviceProbeInfo 0x5
struct aac_vmi_devinfo_resp {
@@ -1190,6 +1289,16 @@ struct aac_blockwrite_response {
u_int32_t Committed;
} __packed;
+struct aac_raw_io {
+ u_int64_t BlockNumber;
+ u_int32_t ByteCount;
+ u_int16_t ContainerId;
+ u_int16_t Flags; /* 0: W, 1: R */
+ u_int16_t BpTotal; /* reserved for FW use */
+ u_int16_t BpComplete; /* reserved for FW use */
+ struct aac_sg_tableraw SgMapRaw; /* variable size */
+} __packed;
+
/*
* Container shutdown command.
*/
@@ -1334,6 +1443,8 @@ enum {
#define AAC_RX_ODBR 0x2c /* outbound doorbell register */
#define AAC_RX_OISR 0x30 /* outbound interrupt status register */
#define AAC_RX_OIMR 0x34 /* outbound interrupt mask register */
+#define AAC_RX_IQUE 0x40 /* inbound queue */
+#define AAC_RX_OQUE 0x44 /* outbound queue */
#define AAC_RX_MAILBOX 0x50 /* mailbox (20 bytes) */
#define AAC_RX_FWSTATUS 0x6c
@@ -1349,6 +1460,8 @@ enum {
#define AAC_RKT_ODBR 0x2c /* outbound doorbell register */
#define AAC_RKT_OISR 0x30 /* outbound interrupt status register */
#define AAC_RKT_OIMR 0x34 /* outbound interrupt mask register */
+#define AAC_RKT_IQUE 0x40 /* inbound queue */
+#define AAC_RKT_OQUE 0x44 /* outbound queue */
#define AAC_RKT_MAILBOX 0x1000 /* mailbox */
#define AAC_RKT_FWSTATUS 0x101c /* Firmware Status (mailbox 7) */
@@ -1383,3 +1496,5 @@ enum {
#define AAC_DB_INTERRUPTS (AAC_DB_COMMAND_READY | \
AAC_DB_RESPONSE_READY | \
AAC_DB_PRINTF)
+#define AAC_DB_INT_NEW_COMM 0x08
+
diff --git a/sys/dev/aac/aacvar.h b/sys/dev/aac/aacvar.h
index 87e3c9c..a5ae32b 100644
--- a/sys/dev/aac/aacvar.h
+++ b/sys/dev/aac/aacvar.h
@@ -36,6 +36,9 @@
#include <sys/selinfo.h>
#include <geom/geom_disk.h>
+#ifndef AAC_DRIVER_BUILD
+# define AAC_DRIVER_BUILD 1
+#endif
/*
* Driver Parameter Definitions
@@ -56,9 +59,8 @@
* FIBs are allocated in page-size chunks and can grow up to the 512
* limit imposed by the hardware.
*/
-#define AAC_FIB_COUNT (PAGE_SIZE/sizeof(struct aac_fib))
#define AAC_PREALLOCATE_FIBS 128
-#define AAC_MAX_FIBS 504
+#define AAC_NUM_MGT_FIB 8
/*
* The controller reports status events in AIFs. We hang on to a number of
@@ -146,7 +148,7 @@ struct aac_command
struct aac_fib *cm_fib; /* FIB associated with this
* command */
- u_int32_t cm_fibphys; /* bus address of the FIB */
+ u_int64_t cm_fibphys; /* bus address of the FIB */
struct bio *cm_data; /* pointer to data in kernel
* space */
u_int32_t cm_datalen; /* data length */
@@ -165,7 +167,9 @@ struct aac_command
#define AAC_ON_AACQ_FREE (1<<5)
#define AAC_ON_AACQ_READY (1<<6)
#define AAC_ON_AACQ_BUSY (1<<7)
-#define AAC_ON_AACQ_MASK ((1<<5)|(1<<6)|(1<<7))
+#define AAC_ON_AACQ_AIF (1<<8)
+#define AAC_ON_AACQ_NORM (1<<10)
+#define AAC_ON_AACQ_MASK ((1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<10))
#define AAC_QUEUE_FRZN (1<<9) /* Freeze the processing of
* commands on the queue. */
@@ -228,6 +232,9 @@ struct aac_interface
u_int32_t arg2, u_int32_t arg3);
int (*aif_get_mailbox)(struct aac_softc *sc, int mb);
void (*aif_set_interrupts)(struct aac_softc *sc, int enable);
+ int (*aif_send_command)(struct aac_softc *sc, struct aac_command *cm);
+ int (*aif_get_outb_queue)(struct aac_softc *sc);
+ void (*aif_set_outb_queue)(struct aac_softc *sc, int index);
};
extern struct aac_interface aac_rx_interface;
extern struct aac_interface aac_sa_interface;
@@ -248,6 +255,9 @@ extern struct aac_interface aac_rkt_interface;
0))
#define AAC_UNMASK_INTERRUPTS(sc) ((sc)->aac_if.aif_set_interrupts((sc), \
1))
+#define AAC_SEND_COMMAND(sc, cm) ((sc)->aac_if.aif_send_command((sc), (cm)))
+#define AAC_GET_OUTB_QUEUE(sc) ((sc)->aac_if.aif_get_outb_queue((sc)))
+#define AAC_SET_OUTB_QUEUE(sc, idx) ((sc)->aac_if.aif_set_outb_queue((sc), (idx)))
#define AAC_SETREG4(sc, reg, val) bus_space_write_4(sc->aac_btag, \
sc->aac_bhandle, reg, val)
@@ -317,6 +327,11 @@ struct aac_softc
TAILQ_HEAD(,aac_command) aac_ready; /* commands on hold for
* controller resources */
TAILQ_HEAD(,aac_command) aac_busy;
+ TAILQ_HEAD(,aac_command) aac_aif;
+#if 0
+ TAILQ_HEAD(,aac_command) aac_norm;
+#endif
+ TAILQ_HEAD(,aac_event) aac_ev_cmfree;
struct bio_queue_head aac_bioq;
struct aac_queue_table *aac_queues;
struct aac_queue_entry *aac_qentries[AAC_QUEUE_COUNT];
@@ -366,13 +381,39 @@ struct aac_softc
#define AAC_FLAGS_NO4GB (1 << 6) /* Can't access host mem >2GB */
#define AAC_FLAGS_256FIBS (1 << 7) /* Can only do 256 commands */
#define AAC_FLAGS_BROKEN_MEMMAP (1 << 8) /* Broken HostPhysMemPages */
+#define AAC_FLAGS_SLAVE (1 << 9)
+#define AAC_FLAGS_MASTER (1 << 10)
+#define AAC_FLAGS_NEW_COMM (1 << 11) /* New comm. interface supported */
+#define AAC_FLAGS_RAW_IO (1 << 12) /* Raw I/O interface */
+#define AAC_FLAGS_ARRAY_64BIT (1 << 13) /* 64-bit array size */
u_int32_t supported_options;
- int aac_max_fibs;
u_int32_t scsi_method_id;
TAILQ_HEAD(,aac_sim) aac_sim_tqh;
+
+ u_int32_t aac_max_fibs; /* max. FIB count */
+ u_int32_t aac_max_fibs_alloc; /* max. alloc. per alloc_commands() */
+ u_int32_t aac_max_fib_size; /* max. FIB size */
+ u_int32_t aac_sg_tablesize; /* max. sg count from host */
+ u_int32_t aac_max_sectors; /* max. I/O size from host (blocks) */
};
+/*
+ * Event callback mechanism for the driver
+ */
+#define AAC_EVENT_NONE 0x00
+#define AAC_EVENT_CMFREE 0x01
+#define AAC_EVENT_MASK 0xff
+#define AAC_EVENT_REPEAT 0x100
+
+typedef void aac_event_cb_t(struct aac_softc *sc, struct aac_event *event,
+ void *arg);
+struct aac_event {
+ TAILQ_ENTRY(aac_event) ev_links;
+ int ev_type;
+ aac_event_cb_t *ev_callback;
+ void *ev_arg;
+};
/*
* Public functions
@@ -383,7 +424,8 @@ extern int aac_detach(device_t dev);
extern int aac_shutdown(device_t dev);
extern int aac_suspend(device_t dev);
extern int aac_resume(device_t dev);
-extern void aac_intr(void *arg);
+extern void aac_new_intr(void *arg);
+extern void aac_fast_intr(void *arg);
extern void aac_submit_bio(struct bio *bp);
extern void aac_biodone(struct bio *bp);
extern void aac_startio(struct aac_softc *sc);
@@ -393,6 +435,8 @@ extern void aac_release_command(struct aac_command *cm);
extern int aac_sync_fib(struct aac_softc *sc, u_int32_t command,
u_int32_t xferstate, struct aac_fib *fib,
u_int16_t datasize);
+extern void aac_add_event(struct aac_softc *sc, struct aac_event
+ *event);
/*
* Debugging levels:
@@ -571,7 +615,7 @@ static __inline int
aac_alloc_sync_fib(struct aac_softc *sc, struct aac_fib **fib)
{
- mtx_lock(&sc->aac_io_lock);
+ mtx_assert(&sc->aac_io_lock, MA_OWNED);
*fib = &sc->aac_common->ac_sync_fib;
return (0);
}
@@ -580,6 +624,6 @@ static __inline void
aac_release_sync_fib(struct aac_softc *sc)
{
- mtx_unlock(&sc->aac_io_lock);
+ mtx_assert(&sc->aac_io_lock, MA_OWNED);
}
OpenPOWER on IntegriCloud