summaryrefslogtreecommitdiffstats
path: root/sys/dev/aac
diff options
context:
space:
mode:
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