summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorscottl <scottl@FreeBSD.org>2001-08-29 23:34:05 +0000
committerscottl <scottl@FreeBSD.org>2001-08-29 23:34:05 +0000
commitca93e132a40987f527cf6023647c4a067283a0f5 (patch)
tree9664aff7481b95b2f50a88ff50e381ca89fc4235
parentd118ae3895cbb757e23c8a19dfe269d7e5348b2f (diff)
downloadFreeBSD-src-ca93e132a40987f527cf6023647c4a067283a0f5.zip
FreeBSD-src-ca93e132a40987f527cf6023647c4a067283a0f5.tar.gz
Mega update to the aac driver.
1. Correctly handle commands initiated by the adapter. These commands are defered to a kthread responsible for their processing, then are properly returned to the controller. 2. Add/remove disk devices when notified by the card that a container was created/deleted/offline. 3. Implement crashdump functionality. 4. Support all ioctls needed for the management CLI to work. The linux version of this app can be found at the Dell or HP website. A native version will be forthcoming. MFC-after: 4.4-RELEASE
-rw-r--r--share/man/man4/aac.416
-rw-r--r--sys/dev/aac/aac.c592
-rw-r--r--sys/dev/aac/aac_debug.c2
-rw-r--r--sys/dev/aac/aac_disk.c116
-rw-r--r--sys/dev/aac/aac_ioctl.h28
-rw-r--r--sys/dev/aac/aac_pci.c8
-rw-r--r--sys/dev/aac/aacreg.h2
-rw-r--r--sys/dev/aac/aacvar.h54
-rw-r--r--sys/sys/aac_ioctl.h28
9 files changed, 718 insertions, 128 deletions
diff --git a/share/man/man4/aac.4 b/share/man/man4/aac.4
index 4857721..630b2df 100644
--- a/share/man/man4/aac.4
+++ b/share/man/man4/aac.4
@@ -48,7 +48,7 @@ Supported controllers include:
.It
AAC-364
.It
-AAC-3642
+Adaptec SCSI RAID 5400S
.It
HP NetRAID 4M
.It
@@ -86,12 +86,6 @@ Compiling the driver with the
option enables the Linux-compatible
.Xr ioctl 2
interface for the management device.
-The
-.Xr ioctl 2
-command set is heavily tailored to existing Linux applications.
-Native
-.Xr ioctl 2
-support is not present at this time.
.Ss Tuning
The read-only sysctl
.Va hw.aac.iosize_max
@@ -148,13 +142,9 @@ and is
.An Scott Long
.Aq scottl@FreeBSD.org
.Sh BUGS
-This driver has not been tested on Alpha, though it should work.
+This driver will not work on systems with more than 4GB of memory.
.Pp
The controller is not actually paused on suspend/resume.
.Pp
-Adapter-initiated messages are not returned back to the controller,
-possibly causing a resource leak on the controller.
-.Pp
-Unloading and reloading the driver as a kernel loadable module
-without rebooting the system is strongly discouraged.
+Unloading driver is not supported at this time.
.Pp
diff --git a/sys/dev/aac/aac.c b/sys/dev/aac/aac.c
index d679bc8..aedd939 100644
--- a/sys/dev/aac/aac.c
+++ b/sys/dev/aac/aac.c
@@ -35,11 +35,12 @@
#include "opt_aac.h"
-/* include <stddef.h> */
+/* #include <stddef.h> */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
+#include <sys/kthread.h>
#include <sys/sysctl.h>
#include <dev/aac/aac_compat.h>
@@ -51,6 +52,7 @@
#include <sys/file.h>
#include <sys/signalvar.h>
#include <sys/time.h>
+#include <sys/eventhandler.h>
#include <machine/bus_memio.h>
#include <machine/bus.h>
@@ -101,7 +103,10 @@ static int aac_sync_fib(struct aac_softc *sc, u_int32_t command,
static int aac_enqueue_fib(struct aac_softc *sc, int queue,
struct aac_command *cm);
static int aac_dequeue_fib(struct aac_softc *sc, int queue,
- u_int32_t *fib_size, struct aac_fib **fib_addr);
+ u_int32_t *fib_size,
+ struct aac_fib **fib_addr);
+static int aac_enqueue_response(struct aac_softc *sc, int queue,
+ struct aac_fib *fib);
/* StrongARM interface */
static int aac_sa_get_fwstatus(struct aac_softc *sc);
@@ -147,7 +152,7 @@ struct aac_interface aac_rx_interface = {
/* Debugging and Diagnostics */
static void aac_describe_controller(struct aac_softc *sc);
-static char *aac_describe_code(struct aac_code_lookup *table,
+static char *aac_describe_code(struct aac_code_lookup *table
u_int32_t code);
/* Management Interface */
@@ -156,10 +161,11 @@ static d_close_t aac_close;
static d_ioctl_t aac_ioctl;
static int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib);
static void aac_handle_aif(struct aac_softc *sc,
- struct aac_aif_command *aif);
+ struct aac_fib *fib);
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);
#define AAC_CDEV_MAJOR 150
@@ -177,8 +183,13 @@ static struct cdevsw aac_cdevsw = {
nodump, /* dump */
nopsize, /* psize */
0, /* flags */
+#if __FreeBSD_version < 500005
+ -1, /* bmaj */
+#endif
};
+MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for the AAC driver");
+
/* sysctl node */
SYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters");
@@ -240,6 +251,9 @@ aac_attach(struct aac_softc *sc)
/*
* Register to probe our containers later.
*/
+ TAILQ_INIT(&sc->aac_container_tqh);
+ AAC_LOCK_INIT(&sc->aac_container_lock);
+
sc->aac_ich.ich_func = aac_startup;
sc->aac_ich.ich_arg = sc;
if (config_intrhook_establish(&sc->aac_ich) != 0) {
@@ -253,11 +267,27 @@ aac_attach(struct aac_softc *sc)
unit = device_get_unit(sc->aac_dev);
sc->aac_dev_t = make_dev(&aac_cdevsw, unit, UID_ROOT, GID_WHEEL, 0644,
"aac%d", unit);
+#if __FreeBSD_version > 500005
(void)make_dev_alias(sc->aac_dev_t, "afa%d", unit);
(void)make_dev_alias(sc->aac_dev_t, "hpn%d", unit);
-
+#endif
sc->aac_dev_t->si_drv1 = sc;
+ /* Create the AIF thread */
+#if __FreeBSD_version > 500005
+ if (kthread_create((void(*)(void *))aac_host_command, sc, &sc->aifthread,
+ 0, "aac%daif", unit))
+#else
+ if (kthread_create((void(*)(void *))aac_host_command, sc, &sc->aifthread,
+ "aac%daif", unit))
+#endif
+ panic("Could not create AIF thread\n");
+
+ /* Register the shutdown method to only be called post-dump */
+ if ((EVENTHANDLER_REGISTER(shutdown_final, aac_shutdown, sc->aac_dev,
+ SHUTDOWN_PRI_DEFAULT)) == NULL)
+ device_printf(sc->aac_dev, "shutdown event registration failed\n");
+
return(0);
}
@@ -270,9 +300,10 @@ aac_startup(void *arg)
struct aac_softc *sc = (struct aac_softc *)arg;
struct aac_mntinfo mi;
struct aac_mntinforesponse mir;
+ struct aac_container *co;
device_t child;
u_int16_t rsize;
- int i;
+ int i = 0;
debug_called(1);
@@ -282,7 +313,7 @@ aac_startup(void *arg)
/* loop over possible containers */
mi.Command = VM_NameServe;
mi.MntType = FT_FILESYS;
- for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
+ do {
/* request information on this container */
mi.MntCount = i;
rsize = sizeof(mir);
@@ -302,6 +333,9 @@ aac_startup(void *arg)
* possible types may never show up.
*/
if ((mir.Status == ST_OK) && (mir.MntTable[0].VolType != CT_NONE)) {
+ MALLOC(co, struct aac_container *, sizeof *co, M_AACBUF, M_NOWAIT);
+ if (co == NULL)
+ panic("Out of memory?!\n");
debug(1, "%d: id %x name '%.16s' size %u type %d",
i, mir.MntTable[0].ObjectId,
mir.MntTable[0].FileSystemName, mir.MntTable[0].Capacity,
@@ -310,14 +344,17 @@ aac_startup(void *arg)
if ((child = device_add_child(sc->aac_dev, NULL, -1)) == NULL) {
device_printf(sc->aac_dev, "device_add_child failed\n");
} else {
- device_set_ivars(child, &sc->aac_container[i]);
+ device_set_ivars(child, co);
}
device_set_desc(child, aac_describe_code(aac_container_types,
mir.MntTable[0].VolType));
- sc->aac_container[i].co_disk = child;
- sc->aac_container[i].co_mntobj = mir.MntTable[0];
+ co->co_disk = child;
+ co->co_found = 0;
+ bcopy(&mir.MntTable[0], &co->co_mntobj, sizeof(struct aac_mntobj));
+ TAILQ_INSERT_TAIL(&sc->aac_container_tqh, co, co_link);
}
- }
+ i++;
+ } while ((i < mir.MntRespCount) && (i < AAC_MAX_CONTAINERS));
/* poke the bus to actually attach the child devices */
if (bus_generic_attach(sc->aac_dev))
@@ -390,19 +427,34 @@ int
aac_detach(device_t dev)
{
struct aac_softc *sc = device_get_softc(dev);
+#if AAC_BROKEN
int error;
+#endif
debug_called(1);
if (sc->aac_state & AAC_STATE_OPEN)
return(EBUSY);
+#if AAC_BROKEN
+ if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
+ sc->aifflags |= AAC_AIFFLAGS_EXIT;
+ wakeup(sc->aifthread);
+ tsleep(sc->aac_dev, PUSER | PCATCH, "aacdch", 30 * hz);
+ }
+
+ if (sc->aifflags & AAC_AIFFLAGS_RUNNING)
+ panic("Cannot shutdown AIF thread\n");
+
if ((error = aac_shutdown(dev)))
return(error);
aac_free(sc);
return(0);
+#else
+ return (EBUSY);
+#endif
}
/******************************************************************************
@@ -439,6 +491,12 @@ aac_shutdown(device_t dev)
printf("FAILED.\n");
} else {
i = 0;
+ /*
+ * XXX Issuing this command to the controller makes it shut down,
+ * but also keeps it from coming back up without a reset of the
+ * PCI bus. This is not desirable if you are just unloading the
+ * driver module with the intent to reload it later.
+ */
if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, &i,
sizeof(i), NULL, NULL)) {
printf("FAILED.\n");
@@ -486,7 +544,7 @@ aac_resume(device_t dev)
return(0);
}
-/******************************************************************************
+/*******************************************************************************
* Take an interrupt.
*/
void
@@ -499,21 +557,24 @@ aac_intr(void *arg)
reason = AAC_GET_ISTATUS(sc);
- /* controller wants to talk to the log? XXX should we defer this? */
+ /* controller wants to talk to the log? Defer it to the AIF thread */
if (reason & AAC_DB_PRINTF) {
- if (sc->aac_common->ac_printf[0]) {
- device_printf(sc->aac_dev, "** %.*s", AAC_PRINTF_BUFSIZE,
- sc->aac_common->ac_printf);
- sc->aac_common->ac_printf[0] = 0;
- }
AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
- AAC_QNOTIFY(sc, AAC_DB_PRINTF);
+ if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
+ sc->aifflags |= AAC_AIFFLAGS_PENDING;
+ wakeup(sc->aifthread);
+ } else
+ aac_print_printf(sc);
}
/* controller has a message for us? */
if (reason & AAC_DB_COMMAND_READY) {
AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
- aac_host_command(sc);
+ /* XXX What happens if the thread is already awake? */
+ if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
+ sc->aifflags |= AAC_AIFFLAGS_PENDING;
+ wakeup(sc->aifthread);
+ }
}
/* controller has a response for us? */
@@ -594,7 +655,7 @@ aac_start(struct aac_command *cm)
* address issue */
/* put the FIB on the outbound queue */
- error = aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, cm);
+ error = aac_enqueue_fib(sc, cm->cm_queue, cm);
return(error);
}
@@ -606,26 +667,74 @@ aac_host_command(struct aac_softc *sc)
{
struct aac_fib *fib;
u_int32_t fib_size;
+ int size;
- debug_called(1);
+ debug_called(2);
- for (;;) {
- if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, &fib))
- break; /* nothing to do */
+ sc->aifflags |= AAC_AIFFLAGS_RUNNING;
+
+ while(!(sc->aifflags & AAC_AIFFLAGS_EXIT)) {
+ if (!(sc->aifflags & AAC_AIFFLAGS_PENDING))
+ tsleep(sc->aifthread, PRIBIO, "aifthd", 15 * hz);
+
+ sc->aifflags &= ~AAC_AIFFLAGS_PENDING;
+ for (;;) {
+ if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, &fib))
+ break; /* nothing to do */
- switch(fib->Header.Command) {
- case AifRequest:
- aac_handle_aif(sc, (struct aac_aif_command *)&fib->data[0]);
- break;
- default:
- device_printf(sc->aac_dev, "unknown command from controller\n");
AAC_PRINT_FIB(sc, fib);
- break;
+
+ switch(fib->Header.Command) {
+ case AifRequest:
+ aac_handle_aif(sc, fib);
+ break;
+ default:
+ device_printf(sc->aac_dev, "unknown command from controller\n");
+ break;
+ }
+
+ /* Return the AIF to the controller. */
+ if ((fib->Header.XferState == 0) ||
+ (fib->Header.StructType != AAC_FIBTYPE_TFIB))
+ break;
+
+ if (fib->Header.XferState & AAC_FIBSTATE_FROMADAP) {
+ if (!(fib->Header.XferState & AAC_FIBSTATE_NORM)) {
+ /*
+ * XXX How to recover from this? If anything goes on
+ * the high priority queue, the controller will panic.
+ * Since it came on the normal priority queue, just
+ * punt and return it there.
+ */
+ device_printf(sc->aac_dev, "Error: Attempted to return "
+ "an AIF not at normal priority\n");
+ }
+ fib->Header.XferState |= AAC_FIBSTATE_DONEHOST;
+ *(AAC_FSAStatus*)fib->data = ST_OK;
+
+ /* XXX Compute the Size field? */
+ size = fib->Header.Size;
+ if (size > sizeof(struct aac_fib)) {
+ size = sizeof(struct aac_fib);
+ fib->Header.Size = size;
+ }
+ /*
+ * Since we did not generate this command, it cannot go
+ * through the normal enqueue->startio chain.
+ */
+ aac_enqueue_response(sc, AAC_ADAP_NORM_RESP_QUEUE, fib);
+ }
}
+ aac_print_printf(sc);
- /* XXX reply to FIBs requesting responses ?? */
- /* XXX how do we return these FIBs to the controller? */
}
+ sc->aifflags &= ~AAC_AIFFLAGS_RUNNING;
+ wakeup(sc->aac_dev);
+
+#if __FreeBSD_version > 500005
+ mtx_lock(&Giant);
+#endif
+ kthread_exit(0);
}
/******************************************************************************
@@ -739,6 +848,7 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
cm->cm_complete = aac_bio_complete;
cm->cm_private = bp;
cm->cm_timestamp = time_second;
+ cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
/* build the FIB */
fib = cm->cm_fib;
@@ -820,6 +930,95 @@ aac_bio_complete(struct aac_command *cm)
}
/******************************************************************************
+ * Dump a block of data to the controller. If the queue is full, tell the
+ * caller to hold off and wait for the queue to drain
+ */
+int
+aac_dump_enqueue(struct aac_disk *ad, u_int32_t lba, void *data, int dumppages)
+{
+ struct aac_softc *sc = ad->ad_controller;
+ struct aac_command *cm = NULL;
+ struct aac_fib *fib;
+ struct aac_blockwrite *bw;
+
+ if (aac_alloc_command(sc, &cm))
+ return (EBUSY);
+
+ /* fill out the command */
+ cm->cm_data = data;
+ cm->cm_datalen = dumppages * PAGE_SIZE;
+ cm->cm_complete = NULL;
+ cm->cm_private = NULL;
+ cm->cm_timestamp = time_second;
+ cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
+
+ /* build the FIB */
+ fib = cm->cm_fib;
+ fib->Header.XferState =
+ AAC_FIBSTATE_HOSTOWNED |
+ AAC_FIBSTATE_INITIALISED |
+ AAC_FIBSTATE_FROMHOST |
+ AAC_FIBSTATE_REXPECTED |
+ AAC_FIBSTATE_NORM;
+ fib->Header.Command = ContainerCommand;
+ fib->Header.Size = sizeof(struct aac_fib_header);
+
+ bw = (struct aac_blockwrite *)&fib->data[0];
+ bw->Command = VM_CtBlockWrite;
+ bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
+ bw->BlockNumber = lba;
+ bw->ByteCount = dumppages * PAGE_SIZE;
+ bw->Stable = CUNSTABLE; /* XXX what's appropriate here? */
+ fib->Header.Size += sizeof(struct aac_blockwrite);
+ cm->cm_flags |= AAC_CMD_DATAOUT;
+ cm->cm_sgtable = &bw->SgMap;
+
+ return (aac_start(cm));
+}
+
+/******************************************************************************
+ * Wait for the card's queue to drain when dumping. Also check for monitor
+ * printf's
+ */
+void
+aac_dump_complete(struct aac_softc *sc)
+{
+ struct aac_fib *fib;
+ struct aac_command *cm;
+ u_int16_t reason;
+ u_int32_t pi, ci, fib_size;
+
+ do {
+ reason = AAC_GET_ISTATUS(sc);
+ if (reason & AAC_DB_RESPONSE_READY) {
+ AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
+ for (;;) {
+ if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE,
+ &fib_size, &fib))
+ break;
+ cm = (struct aac_command *)fib->Header.SenderData;
+ if (cm == NULL) {
+ AAC_PRINT_FIB(sc, fib);
+ } else {
+ aac_remove_busy(cm);
+ aac_unmap_command(cm);
+ aac_enqueue_complete(cm);
+ aac_release_command(cm);
+ }
+ }
+ }
+ if (reason & AAC_DB_PRINTF) {
+ AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
+ aac_print_printf(sc);
+ }
+ pi = sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX];
+ ci = sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX];
+ } while (ci != pi);
+
+ return;
+}
+
+/******************************************************************************
* Submit a command to the controller, return when it completes.
*/
static int
@@ -830,11 +1029,14 @@ aac_wait_command(struct aac_command *cm, int timeout)
debug_called(2);
/* Put the command on the ready queue and get things going */
+ cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
aac_enqueue_ready(cm);
aac_startio(cm->cm_sc);
s = splbio();
while(!(cm->cm_flags & AAC_CMD_COMPLETED) && (error != EWOULDBLOCK)) {
- error = tsleep(cm, PRIBIO, "aacwait", 0);
+ error = tsleep(cm, PRIBIO | PCATCH, "aacwait", 0);
+ if ((error == ERESTART) || (error == EINTR))
+ break;
}
splx(s);
return(error);
@@ -1082,7 +1284,7 @@ aac_init(struct aac_softc *sc)
}
if (time_second > (then + AAC_BOOT_TIMEOUT)) {
device_printf(sc->aac_dev, "FATAL: controller not coming ready, "
- "status %x\n", code);
+ "status %x\n", code);
return(ENXIO);
}
} while (!(code & AAC_UP_AND_RUNNING));
@@ -1328,7 +1530,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
return(0);
}
-/********************************************************************************
+/******************************************************************************
* Adapter-space FIB queue manipulation
*
* Note that the queue implementation here is a little funky; neither the PI or
@@ -1353,8 +1555,7 @@ static struct {
* EBUSY if the queue is full.
*
* Note: it would be more efficient to defer notifying the controller in
- * the case where we may be inserting several entries in rapid succession,
- * but implementing this usefully may be difficult (it would involve a
+ * the case where we may be inserting several entries in rapid succession, * but implementing this usefully may be difficult (it would involve a
* separate queue/notify interface).
*/
static int
@@ -1365,11 +1566,11 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
u_int32_t fib_size;
u_int32_t fib_addr;
- fib_size = cm->cm_fib->Header.Size;
- fib_addr = cm->cm_fib->Header.ReceiverFibAddress;
-
debug_called(3);
+ fib_size = cm->cm_fib->Header.Size;
+ fib_addr = cm->cm_fib->Header.ReceiverFibAddress;
+
s = splbio();
/* get the producer/consumer indices */
@@ -1411,8 +1612,8 @@ out:
}
/*
- * Atomically remove one entry from the nominated queue, returns 0 on success or
- * ENOENT if the queue is empty.
+ * Atomically remove one entry from the nominated queue, returns 0 on
+ * success or ENOENT if the queue is empty.
*/
static int
aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
@@ -1462,6 +1663,58 @@ out:
}
/******************************************************************************
+ * Put our response to an Adapter Initialed Fib on the response queue
+ */
+static int
+aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
+{
+ u_int32_t pi, ci;
+ int s, error;
+ u_int32_t fib_size;
+ u_int32_t fib_addr;
+
+ debug_called(1);
+
+ /* Tell the adapter where the FIB is */
+ fib_size = fib->Header.Size;
+ fib_addr = fib->Header.SenderFibAddress;
+ fib->Header.ReceiverFibAddress = fib_addr;
+
+ s = splbio();
+
+ /* get the producer/consumer indices */
+ pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
+ ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
+
+ /* wrap the queue? */
+ if (pi >= aac_qinfo[queue].size)
+ pi = 0;
+
+ /* check for queue full */
+ if ((pi + 1) == ci) {
+ error = EBUSY;
+ goto out;
+ }
+
+ /* populate queue entry */
+ (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
+ (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
+
+ /* update producer index */
+ sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
+
+ /* notify the adapter if we know how */
+ if (aac_qinfo[queue].notify != 0)
+ AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
+
+ error = 0;
+
+out:
+ splx(s);
+ return(error);
+}
+
+/******************************************************************************
* Check for commands that have been outstanding for a suspiciously long time,
* and complain about them.
*/
@@ -1483,19 +1736,19 @@ aac_timeout(struct aac_softc *sc)
s = splbio();
aac_intr(sc);
splx(s);
-#endif
/* kick the I/O queue to restart it in the case of deadlock */
aac_startio(sc);
+#endif
/* traverse the busy command list, bitch about late commands once only */
deadline = time_second - AAC_CMD_TIMEOUT;
s = splbio();
TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) {
- if ((cm->cm_timestamp < deadline)
- /* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) {
+ if ((cm->cm_timestamp < deadline)
+ /* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) {
cm->cm_flags |= AAC_CMD_TIMEDOUT;
- device_printf(sc->aac_dev, "COMMAND %p TIMEOUT AFTER %d SECONDS\n",
+ device_printf(sc->aac_dev, "COMMAND %p TIMEOUT AFTER %d SECONDS\n",
cm, (int)(time_second - cm->cm_timestamp));
AAC_PRINT_FIB(sc, cm->cm_fib);
}
@@ -1699,19 +1952,19 @@ aac_describe_controller(struct aac_softc *sc)
}
info = (struct aac_adapter_info *)&buf[0];
- device_printf(sc->aac_dev, "%s %dMHz, %dMB total memory, %s (%d)\n",
+ device_printf(sc->aac_dev, "%s %dMHz, %dMB cache memory, %s\n",
aac_describe_code(aac_cpu_variant, info->CpuVariant),
- info->ClockSpeed, info->TotalMem / (1024 * 1024),
- aac_describe_code(aac_battery_platform,
- info->batteryPlatform), info->batteryPlatform);
+ info->ClockSpeed, info->BufferMem / (1024 * 1024),
+ aac_describe_code(aac_battery_platform, info->batteryPlatform));
/* save the kernel revision structure for later use */
sc->aac_revision = info->KernelRevision;
- device_printf(sc->aac_dev, "Kernel %d.%d-%d, S/N %llx\n",
+ device_printf(sc->aac_dev, "Kernel %d.%d-%d, Build %d, S/N %6X\n",
info->KernelRevision.external.comp.major,
info->KernelRevision.external.comp.minor,
info->KernelRevision.external.comp.dash,
- info->SerialNumber); /* XXX format? */
+ info->KernelRevision.buildNumber,
+ (u_int32_t)(info->SerialNumber & 0xffffff));
}
/******************************************************************************
@@ -1792,7 +2045,7 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
break;
case FSACTL_SENDFIB:
- arg = *(caddr_t *)arg;
+ arg = *(caddr_t*)arg;
case FSACTL_LNX_SENDFIB:
debug(1, "FSACTL_SENDFIB");
error = aac_ioctl_sendfib(sc, arg);
@@ -1803,7 +2056,7 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
error = EINVAL;
break;
case FSACTL_OPEN_GET_ADAPTER_FIB:
- arg = *(caddr_t *)arg;
+ arg = *(caddr_t*)arg;
case FSACTL_LNX_OPEN_GET_ADAPTER_FIB:
debug(1, "FSACTL_OPEN_GET_ADAPTER_FIB");
/*
@@ -1815,12 +2068,14 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
*
* The Linux code hands the driver a pointer into kernel space,
* and then trusts it when the caller hands it back. Aiee!
+ * Here, we give it the proc pointer of the per-adapter aif thread.
+ * It's only used as a sanity check in other calls.
*/
- i = AAC_AIF_SILLYMAGIC;
+ i = (int)sc->aifthread;
error = copyout(&i, arg, sizeof(i));
break;
case FSACTL_GET_NEXT_ADAPTER_FIB:
- arg = *(caddr_t *)arg;
+ arg = *(caddr_t*)arg;
case FSACTL_LNX_GET_NEXT_ADAPTER_FIB:
debug(1, "FSACTL_GET_NEXT_ADAPTER_FIB");
error = aac_getnext_aif(sc, arg);
@@ -1831,11 +2086,21 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
/* don't do anything here */
break;
case FSACTL_MINIPORT_REV_CHECK:
- arg = *(caddr_t *)arg;
+ arg = *(caddr_t*)arg;
case FSACTL_LNX_MINIPORT_REV_CHECK:
debug(1, "FSACTL_MINIPORT_REV_CHECK");
error = aac_rev_check(sc, arg);
break;
+ case FSACTL_QUERY_DISK:
+ arg = *(caddr_t*)arg;
+ case FSACTL_LNX_QUERY_DISK:
+ debug(1, "FSACTL_QUERY_DISK");
+ error = aac_query_disk(sc, arg);
+ break;
+ case FSACTL_DELETE_DISK:
+ case FSACTL_LNX_DELETE_DISK:
+ error = 0;
+ break;
default:
device_printf(sc->aac_dev, "unsupported cmd 0x%lx\n", cmd);
error = EINVAL;
@@ -1907,17 +2172,140 @@ out:
/******************************************************************************
* Handle an AIF sent to us by the controller; queue it for later reference.
- *
- * XXX what's the right thing to do here when the queue is full? Drop the older
- * or newer entries?
+ * If the queue fills up, then drop the older entries.
*/
static void
-aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif)
+aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
{
- int next, s;
+ device_t child;
+ struct aac_aif_command *aif;
+ struct aac_container *co, *co_next;
+ struct aac_mntinfo mi;
+ struct aac_mntinforesponse mir;
+ u_int16_t rsize;
+ int next, s, found;
+ int added = 0, i = 0;
debug_called(2);
+ aif = (struct aac_aif_command*)&fib->data[0];
+ aac_print_aif(sc, aif);
+
+ /* Is it an event that we should care about? */
+ switch (aif->command) {
+ case AifCmdEventNotify:
+ switch (aif->data.EN.type) {
+ case AifEnAddContainer:
+ case AifEnDeleteContainer:
+ /*
+ * A container was added or deleted, but the message doesn't tell us
+ * anything else! Re-enumerate the containers and sort things out.
+ */
+ mi.Command = VM_NameServe;
+ mi.MntType = FT_FILESYS;
+ do {
+ /*
+ * Ask the controller for its containers one at a time.
+ * XXX What if the controller's list changes midway through
+ * this enumaration?
+ * XXX This should be done async.
+ */
+ mi.MntCount = i;
+ rsize = sizeof(mir);
+ if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi),
+ &mir, &rsize)) {
+ debug(2, "Error probing container %d\n", i);
+ continue;
+ }
+ if (rsize != sizeof(mir)) {
+ debug(2, "Container response size too large\n");
+ continue;
+ }
+ /*
+ * Check the container against our list. co->co_found
+ * was already set to 0 in a previous run.
+ */
+ if ((mir.Status == ST_OK) && (mir.MntTable[0].VolType !=
+ CT_NONE)) {
+ found = 0;
+ TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) {
+ if (co->co_mntobj.ObjectId ==
+ mir.MntTable[0].ObjectId) {
+ co->co_found = 1;
+ found = 1;
+ break;
+ }
+ }
+ /* If the container matched, continue on in the list */
+ if (found) {
+ i++;
+ continue;
+ }
+
+ /*
+ * This is a new container. Do all the appropriate things
+ * to set it up.
+ */
+ MALLOC(co, struct aac_container *, sizeof *co, M_AACBUF,
+ M_WAITOK);
+ if ((child = device_add_child(sc->aac_dev, NULL, -1)) ==
+ NULL) {
+ device_printf(sc->aac_dev, "device_add_child failed\n");
+ } else {
+ device_set_ivars(child, co);
+ }
+ device_set_desc(child,
+ aac_describe_code(aac_container_types,
+ mir.MntTable[0].VolType));
+ co->co_disk = child;
+ co->co_found = 1;
+ bcopy(&mir.MntTable[0], &co->co_mntobj,
+ sizeof(struct aac_mntobj));
+ AAC_LOCK_AQUIRE(&sc->aac_container_lock);
+ TAILQ_INSERT_HEAD(&sc->aac_container_tqh, co, co_link);
+ AAC_LOCK_RELEASE(&sc->aac_container_lock);
+ added = 1;
+ }
+ i++;
+ } while ((i < mir.MntRespCount) && (i < AAC_MAX_CONTAINERS));
+
+ /*
+ * Go through our list of containers and see which ones were
+ * not marked 'found'. Since the controller didn't list them
+ * they must have been deleted. Do the appropriate steps to
+ * destroy the device. Also reset the co->co_found field.
+ */
+ co = TAILQ_FIRST(&sc->aac_container_tqh);
+ while (co != NULL) {
+ if (co->co_found == 0) {
+ device_delete_child(sc->aac_dev, co->co_disk);
+ co_next = TAILQ_NEXT(co, co_link);
+ AAC_LOCK_AQUIRE(&sc->aac_container_lock);
+ TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link);
+ AAC_LOCK_RELEASE(&sc->aac_container_lock);
+ FREE(co, M_AACBUF);
+ co = co_next;
+ } else {
+ co->co_found = 0;
+ co = TAILQ_NEXT(co, co_link);
+ }
+ }
+
+ /* Attach the newly created containers */
+ if (added)
+ bus_generic_attach(sc->aac_dev);
+
+ break;
+
+ default:
+ break;
+ }
+
+ default:
+ break;
+ }
+
+ /* Copy the AIF data to the AIF queue for ioctl retrieval */
s = splbio();
next = (sc->aac_aifq_head + 1) % AAC_AIFQ_LENGTH;
if (next != sc->aac_aifq_tail) {
@@ -1927,7 +2315,8 @@ aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif)
wakeup(sc->aac_aifq);
}
splx(s);
- aac_print_aif(sc, aif);
+
+ return;
}
/******************************************************************************
@@ -1943,13 +2332,13 @@ aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif)
#include <machine/../linux/linux_proto.h>
#include <compat/linux/linux_ioctl.h>
-#define AAC_LINUX_IOCTL_MIN 0x2000
-#define AAC_LINUX_IOCTL_MAX 0x21ff
+#define AAC_LINUX_IOCTL_MIN 0x0000
+#define AAC_LINUX_IOCTL_MAX 0xffff
static linux_ioctl_function_t aac_linux_ioctl;
static struct linux_ioctl_handler aac_handler = {aac_linux_ioctl,
- AAC_LINUX_IOCTL_MIN,
- AAC_LINUX_IOCTL_MAX};
+ AAC_LINUX_IOCTL_MIN,
+ AAC_LINUX_IOCTL_MAX};
SYSINIT (aac_register, SI_SUB_KLD, SI_ORDER_MIDDLE,
linux_ioctl_register_handler, &aac_handler);
@@ -1964,6 +2353,7 @@ aac_linux_ioctl(struct proc *p, struct linux_ioctl_args *args)
struct file *fp = p->p_fd->fd_ofiles[args->fd];
u_long cmd = args->cmd;
+ debug_called(2);
/*
* Pass the ioctl off to our standard handler.
*/
@@ -1974,9 +2364,9 @@ aac_linux_ioctl(struct proc *p, struct linux_ioctl_args *args)
/******************************************************************************
* Return the Revision of the driver to userspace and check to see if the
- * userspace app is possibly compatible. This is extremely bogus right now
- * because I have no idea how to handle the versioning of this driver. It is
- * needed, though, to get aaccli working.
+ * userspace app is possibly compatible. This is extremely bogus since
+ * our driver doesn't follow Adaptec's versioning system. Cheat by just
+ * returning what the card reported.
*/
static int
aac_rev_check(struct aac_softc *sc, caddr_t udata)
@@ -2005,7 +2395,7 @@ aac_rev_check(struct aac_softc *sc, caddr_t udata)
rev_check_resp.adapterSWRevision.buildNumber = sc->aac_revision.buildNumber;
return(copyout((caddr_t)&rev_check_resp, udata,
- sizeof(struct aac_rev_check_resp)));
+ sizeof(struct aac_rev_check_resp)));
}
/******************************************************************************
@@ -2024,7 +2414,7 @@ aac_getnext_aif(struct aac_softc *sc, caddr_t arg)
/*
* Check the magic number that we gave the caller.
*/
- if (agf.AdapterFibContext != AAC_AIF_SILLYMAGIC) {
+ if (agf.AdapterFibContext != (int)sc->aifthread) {
error = EFAULT;
} else {
@@ -2062,9 +2452,63 @@ aac_return_aif(struct aac_softc *sc, caddr_t uptr)
} else {
error = copyout(&sc->aac_aifq[sc->aac_aifq_tail], uptr,
sizeof(struct aac_aif_command));
+ if (error)
+ printf("aac_return_aif: copyout returned %d\n", error);
if (!error)
sc->aac_aifq_tail = (sc->aac_aifq_tail + 1) % AAC_AIFQ_LENGTH;
}
splx(s);
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
+ * the containers to have b:t:l numbers. Fake it.
+ */
+static int
+aac_query_disk(struct aac_softc *sc, caddr_t uptr)
+{
+ struct aac_query_disk query_disk;
+ struct aac_container *co;
+ struct aac_disk *disk = NULL;
+ int error, id;
+
+ debug_called(2);
+
+ error = copyin(uptr, (caddr_t)&query_disk, sizeof(struct aac_query_disk));
+ if (error)
+ return (error);
+
+ id = query_disk.ContainerNumber;
+ if (id == -1)
+ return (EINVAL);
+
+ AAC_LOCK_AQUIRE(&sc->aac_container_lock);
+ TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) {
+ if (co->co_mntobj.ObjectId == id)
+ break;
+ }
+
+ if (co == NULL) {
+ query_disk.Valid = 0;
+ query_disk.Locked = 0;
+ query_disk.Deleted = 1; /* XXX is this right? */
+ } else {
+ disk = device_get_softc(co->co_disk);
+ query_disk.Valid = 1;
+ query_disk.Locked = (disk->ad_flags & AAC_DISK_OPEN) ? 1 : 0;
+ query_disk.Deleted = 0;
+ query_disk.Bus = 0;
+ query_disk.Target = disk->unit;
+ query_disk.Lun = 0;
+ query_disk.UnMapped = 0;
+ bcopy(disk->ad_dev_t->si_name, &query_disk.diskDeviceName[0], 10);
+ }
+ AAC_LOCK_RELEASE(&sc->aac_container_lock);
+
+ error = copyout((caddr_t)&query_disk, uptr, sizeof(struct aac_query_disk));
+
+ return (error);
+}
+
diff --git a/sys/dev/aac/aac_debug.c b/sys/dev/aac/aac_debug.c
index 0ebb73c..1db2d50 100644
--- a/sys/dev/aac/aac_debug.c
+++ b/sys/dev/aac/aac_debug.c
@@ -34,7 +34,6 @@
*/
#include "opt_aac.h"
-#ifdef AAC_DEBUG
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -492,4 +491,3 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif)
}
}
#endif /* AAC_DEBUG */
-#endif
diff --git a/sys/dev/aac/aac_disk.c b/sys/dev/aac/aac_disk.c
index d8331ea..931be9d 100644
--- a/sys/dev/aac/aac_disk.c
+++ b/sys/dev/aac/aac_disk.c
@@ -42,6 +42,10 @@
#include <sys/devicestat.h>
#include <sys/disk.h>
+#include <vm/vm.h>
+#include <vm/pmap.h>
+
+#include <machine/md_var.h>
#include <machine/bus.h>
#include <sys/rman.h>
@@ -62,6 +66,7 @@ static int aac_disk_detach(device_t dev);
static d_open_t aac_disk_open;
static d_close_t aac_disk_close;
static d_strategy_t aac_disk_strategy;
+static d_dump_t aac_disk_dump;
#define AAC_DISK_CDEV_MAJOR 151
@@ -76,9 +81,12 @@ static struct cdevsw aac_disk_cdevsw = {
/* strategy */ aac_disk_strategy,
/* name */ "aacd",
/* maj */ AAC_DISK_CDEV_MAJOR,
- /* dump */ nodump,
+ /* dump */ aac_disk_dump,
/* psize */ nopsize,
/* flags */ D_DISK,
+#if __FreeBSD_version < 500005
+ /* bmaj */ -1
+#endif
};
devclass_t aac_disk_devclass;
@@ -108,7 +116,9 @@ TUNABLE_INT("hw.aac.iosize_max", &aac_iosize_max);
SYSCTL_DECL(_hw_aac);
SYSCTL_UINT(_hw_aac, OID_AUTO, iosize_max, CTLFLAG_RD, &aac_iosize_max, 0,
- "Max I/O size per transfer to an array");
+ "Max I/O size per transfer to an array");
+
+#define AAC_MAXIO 65536
/******************************************************************************
* Handle open from generic layer.
@@ -181,6 +191,13 @@ aac_disk_strategy(struct bio *bp)
return;
}
+ /* do-nothing operation? */
+ if (bp->bio_bcount == 0) {
+ bp->bio_resid = bp->bio_bcount;
+ biodone(bp);
+ return;
+ }
+
/* perform accounting */
devstat_start_transaction(&sc->ad_stats);
@@ -190,6 +207,82 @@ aac_disk_strategy(struct bio *bp)
}
/******************************************************************************
+ * Dump memory out to an array
+ *
+ * This queues blocks of memory of size AAC_MAXIO to the controller and waits
+ * for the controller to complete the requests.
+ */
+static int
+aac_disk_dump(dev_t dev)
+{
+ struct aac_disk *ad = dev->si_drv1;
+ struct aac_softc *sc;
+ vm_offset_t addr = 0;
+ long blkcnt;
+ unsigned int count, blkno, secsize;
+ int dumppages = AAC_MAXIO / PAGE_SIZE;
+ int i, error;
+
+ if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize)))
+ return (error);
+
+ if (ad == NULL)
+ return (ENXIO);
+
+ sc= ad->ad_controller;
+
+ blkcnt = howmany(PAGE_SIZE, secsize);
+
+ while (count > 0) {
+ caddr_t va = NULL;
+
+ if ((count / blkcnt) < dumppages)
+ dumppages = count / blkcnt;
+
+ for (i = 0; i < dumppages; ++i) {
+ vm_offset_t a = addr + (i * PAGE_SIZE);
+ if (is_physical_memory(a)) {
+ va = pmap_kenter_temporary(trunc_page(a), i);
+ } else {
+ va = pmap_kenter_temporary(trunc_page(0), i);
+ }
+ }
+
+retry:
+ /*
+ * Queue the block to the controller. If the queue is full, EBUSY
+ * will be returned.
+ */
+ error = aac_dump_enqueue(ad, blkno, va, dumppages);
+ if (error && (error != EBUSY))
+ return (error);
+
+ if (!error) {
+ if (dumpstatus(addr, (long)(count * DEV_BSIZE)) < 0)
+ return (EINTR);
+
+ blkno += blkcnt * dumppages;
+ count -= blkcnt * dumppages;
+ addr += PAGE_SIZE * dumppages;
+ if (count > 0)
+ continue;
+ }
+
+ /*
+ * Either the queue was full on the last attemp, or we have no more
+ * data to dump. Let the queue drain out and retry the block if
+ * the queue was full.
+ */
+ aac_dump_complete(sc);
+
+ if (error == EBUSY)
+ goto retry;
+ }
+
+ return (0);
+}
+
+/******************************************************************************
* Handle completion of an I/O request.
*/
void
@@ -200,8 +293,13 @@ aac_biodone(struct bio *bp)
debug_called(4);
devstat_end_transaction_bio(&sc->ad_stats, bp);
- if (bp->bio_flags & BIO_ERROR)
+ if (bp->bio_flags & BIO_ERROR) {
+#if __FreeBSD_version > 500005
diskerr(bp, (char *)bp->bio_driver1, 0, &sc->ad_label);
+#else
+ diskerr(bp, (char *)bp->bio_driver1, 0, -1, &sc->ad_label);
+#endif
+ }
biodone(bp);
}
@@ -212,7 +310,7 @@ static int
aac_disk_probe(device_t dev)
{
- debug_called(4);
+ debug_called(2);
return (0);
}
@@ -225,7 +323,7 @@ aac_disk_attach(device_t dev)
{
struct aac_disk *sc = (struct aac_disk *)device_get_softc(dev);
- debug_called(4);
+ debug_called(1);
/* initialise our softc */
sc->ad_controller =
@@ -267,6 +365,7 @@ aac_disk_attach(device_t dev)
#endif
sc->ad_dev_t->si_iosize_max = aac_iosize_max;
+ sc->unit = device_get_unit(dev);
return (0);
}
@@ -279,17 +378,16 @@ aac_disk_detach(device_t dev)
{
struct aac_disk *sc = (struct aac_disk *)device_get_softc(dev);
- debug_called(4);
+ debug_called(2);
if (sc->ad_flags & AAC_DISK_OPEN)
return(EBUSY);
devstat_remove_entry(&sc->ad_stats);
+ disk_destroy(sc->ad_dev_t);
#ifdef FREEBSD_4
if (--disks_registered == 0)
- cdevsw_remove(&aac_disk_disk_cdevsw);
-#else
- disk_destroy(sc->ad_dev_t);
+ cdevsw_remove(&aac_disk_cdevsw);
#endif
return(0);
diff --git a/sys/dev/aac/aac_ioctl.h b/sys/dev/aac/aac_ioctl.h
index a0b2f7e..fda2afd 100644
--- a/sys/dev/aac/aac_ioctl.h
+++ b/sys/dev/aac/aac_ioctl.h
@@ -1,8 +1,7 @@
/*-
* Copyright (c) 2000 Michael Smith
- * Copyright (c) 2000-2001 Scott Long
+ * Copyright (c) 2000 Scott Long
* Copyright (c) 2000 BSDi
- * Copyright (c) 2001 Adaptec, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,8 +58,7 @@ union aac_statrequest {
* These bit encodings are actually descended from Windows NT. Ick.
*/
-#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) \
- | ((func) << 2) | (meth))
+#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) | ((func) << 2) | (meth))
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
@@ -108,15 +106,15 @@ union aac_statrequest {
#define FSACTL_LNX_DELETE_DISK 0x163
#define FSACTL_LNX_QUERY_DISK 0x173
-/* Ok, this one is really lame */
+/* Ok, here it gets really lame */
#define FSACTL_LNX_PROBE_CONTAINERS 2131 /* Just guessing */
/* Do the native version of the ioctls. Since the BSD encoding scheme
- * conflicts with the 'standard' AAC encoding scheme, the resulting values
- * must be different. The '8' comes from the fact that the previous scheme
+ * conflicts with the 'standard' AAC encoding scheme, the resulting numbers
+ * will be different. The '8' comes from the fact that the previous scheme
* used 12 bits for the number, with the the 12th bit being the only set
* bit above bit 8. Thus the value of 8, with the lower 8 bits holding the
- * command number. 9 is used for the odd overflow/collision case.
+ * command number. 9 is used for the odd overflow case.
*/
#define FSACTL_SENDFIB _IO('8', 2)
#define FSACTL_GET_COMM_PERF_DATA _IO('8', 36)
@@ -161,9 +159,21 @@ struct aac_rev_check_resp {
/*
* Context passed in by a consumer looking to collect an AIF.
*/
-#define AAC_AIF_SILLYMAGIC 0xdeadbeef
struct get_adapter_fib_ioctl {
u_int32_t AdapterFibContext;
int Wait;
caddr_t AifFib;
};
+
+struct aac_query_disk {
+ int32_t ContainerNumber;
+ int32_t Bus;
+ int32_t Target;
+ int32_t Lun;
+ u_int32_t Valid;
+ u_int32_t Locked;
+ u_int32_t Deleted;
+ int32_t Instance;
+ char diskDeviceName[10];
+ u_int32_t UnMapped;
+};
diff --git a/sys/dev/aac/aac_pci.c b/sys/dev/aac/aac_pci.c
index af1e2fd..4b362c9 100644
--- a/sys/dev/aac/aac_pci.c
+++ b/sys/dev/aac/aac_pci.c
@@ -65,7 +65,6 @@ static device_method_t aac_methods[] = {
DEVMETHOD(device_probe, aac_pci_probe),
DEVMETHOD(device_attach, aac_pci_attach),
DEVMETHOD(device_detach, aac_detach),
- DEVMETHOD(device_shutdown, aac_shutdown),
DEVMETHOD(device_suspend, aac_suspend),
DEVMETHOD(device_resume, aac_resume),
@@ -99,12 +98,10 @@ struct aac_ident
{0x1028, 0x0002, 0x1028, 0x00d9, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
{0x1028, 0x0008, 0x1028, 0x00cf, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
{0x1028, 0x000a, 0x1028, 0x0106, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
- {0x9005, 0x0282, 0x9005, 0x0282, AAC_HWIF_I960RX, "Adaptec AAC-2622"},
{0x1011, 0x0046, 0x9005, 0x0364, AAC_HWIF_STRONGARM, "Adaptec AAC-364"},
{0x1011, 0x0046, 0x9005, 0x0365, AAC_HWIF_STRONGARM,
"Adaptec SCSI RAID 5400S"},
{0x1011, 0x0046, 0x9005, 0x1364, AAC_HWIF_STRONGARM, "Dell PERC 2/QC"},
- {0x1011, 0x0046, 0x9005, 0x1365, AAC_HWIF_STRONGARM, "Dell PERC 3/QC"}, /* XXX guess */
{0x1011, 0x0046, 0x103c, 0x10c2, AAC_HWIF_STRONGARM, "HP NetRaid-4M"},
{0, 0, 0, 0, 0, 0}
};
@@ -193,7 +190,10 @@ aac_pci_attach(device_t dev)
device_printf(sc->aac_dev, "can't allocate interrupt\n");
goto out;
}
- if (bus_setup_intr(sc->aac_dev, sc->aac_irq, INTR_TYPE_BIO|INTR_ENTROPY,
+#if __FreeBSD_version < 500005
+#define INTR_ENTROPY 0
+#endif
+ if (bus_setup_intr(sc->aac_dev, sc->aac_irq, INTR_TYPE_BIO|INTR_ENTROPY,
aac_intr, sc, &sc->aac_intr)) {
device_printf(sc->aac_dev, "can't set up interrupt\n");
goto out;
diff --git a/sys/dev/aac/aacreg.h b/sys/dev/aac/aacreg.h
index fd5c9b9..e349a91 100644
--- a/sys/dev/aac/aacreg.h
+++ b/sys/dev/aac/aacreg.h
@@ -987,7 +987,7 @@ struct aac_mntinforesponse {
*/
struct aac_closecommand {
u_int32_t Command;
- u_int32_t ComainerId;
+ u_int32_t ContainerId;
} __attribute__ ((packed));
/*
diff --git a/sys/dev/aac/aacvar.h b/sys/dev/aac/aacvar.h
index 0353bcc..2ed9221 100644
--- a/sys/dev/aac/aacvar.h
+++ b/sys/dev/aac/aacvar.h
@@ -85,7 +85,7 @@
* Rate at which we periodically check for timed out commands and kick the
* controller.
*/
-#define AAC_PERIODIC_INTERVAL 10 /* seconds */
+#define AAC_PERIODIC_INTERVAL 20 /* seconds */
/*
* Character device major numbers.
@@ -98,8 +98,6 @@
******************************************************************************
******************************************************************************/
-#include "opt_aac.h"
-
#if __FreeBSD_version >= 500005
# include <sys/taskqueue.h>
#endif
@@ -109,8 +107,10 @@
*/
struct aac_container
{
- struct aac_mntobj co_mntobj;
- device_t co_disk;
+ struct aac_mntobj co_mntobj;
+ device_t co_disk;
+ int co_found;
+ TAILQ_ENTRY(aac_container) co_link;
};
/*
@@ -131,6 +131,7 @@ struct aac_disk
int ad_heads;
int ad_sectors;
u_int32_t ad_size;
+ int unit;
};
/*
@@ -170,6 +171,7 @@ struct aac_command
void (* cm_complete)(struct aac_command *cm);
void *cm_private;
time_t cm_timestamp; /* command creation time */
+ int cm_queue;
};
/*
@@ -246,6 +248,23 @@ extern struct aac_interface aac_sa_interface;
#define AAC_GETREG1(sc, reg) bus_space_read_1 (sc->aac_btag, \
sc->aac_bhandle, reg)
+TAILQ_HEAD(aac_container_tq, aac_container);
+
+/* Define the OS version specific locks */
+#if __FreeBSD_version >= 500005
+#include <sys/lock.h>
+#include <sys/mutex.h>
+typedef struct mtx aac_lock_t;
+#define AAC_LOCK_INIT(l) mtx_init(l, "AAC Container Mutex", MTX_DEF)
+#define AAC_LOCK_AQUIRE(l) mtx_lock(l)
+#define AAC_LOCK_RELEASE(l) mtx_unlock(l)
+#else
+typedef struct simplelock aac_lock_t;
+#define AAC_LOCK_INIT(l) simple_lock_init(l)
+#define AAC_LOCK_AQUIRE(l) simple_lock(l)
+#define AAC_LOCK_RELEASE(l) simple_unlock(l)
+#endif
+
/*
* Per-controller structure.
*/
@@ -308,7 +327,8 @@ struct aac_softc
struct aac_qstat aac_qstat[AACQ_COUNT]; /* queue statistics */
/* connected containters */
- struct aac_container aac_container[AAC_MAX_CONTAINERS];
+ struct aac_container_tq aac_container_tqh;
+ aac_lock_t aac_container_lock;
/* delayed activity infrastructure */
#if __FreeBSD_version >= 500005
@@ -322,6 +342,12 @@ struct aac_softc
struct aac_aif_command aac_aifq[AAC_AIFQ_LENGTH];
int aac_aifq_head;
int aac_aifq_tail;
+ struct proc *aifthread;
+ int aifflags;
+#define AAC_AIFFLAGS_RUNNING (1 << 0)
+#define AAC_AIFFLAGS_PENDING (1 << 1)
+#define AAC_AIFFLAGS_EXIT (1 << 2)
+#define AAC_AIFFLAGS_EXITED (1 << 3)
};
@@ -338,6 +364,9 @@ extern void aac_intr(void *arg);
extern devclass_t aac_devclass;
extern void aac_submit_bio(struct bio *bp);
extern void aac_biodone(struct bio *bp);
+extern int aac_dump_enqueue(struct aac_disk *ad, u_int32_t lba,
+ void *data, int nblks);
+extern void aac_dump_complete(struct aac_softc *sc);
/*
* Debugging levels:
@@ -370,9 +399,9 @@ extern void aac_print_aif(struct aac_softc *sc,
# define aac_print_queues(sc)
# define aac_panic(sc, reason)
-# define aac_print_aif(sc, aif)
# define AAC_PRINT_FIB(sc, fib)
+# define aac_print_aif(sc, aac_aif_command)
#endif
struct aac_code_lookup {
@@ -517,3 +546,14 @@ aac_dequeue_bio(struct aac_softc *sc)
splx(s);
return(bp);
}
+
+static __inline void
+aac_print_printf(struct aac_softc *sc)
+{
+ if (sc->aac_common->ac_printf[0]) {
+ device_printf(sc->aac_dev, "**Monitor** %.*s", AAC_PRINTF_BUFSIZE,
+ sc->aac_common->ac_printf);
+ sc->aac_common->ac_printf[0] = 0;
+ AAC_QNOTIFY(sc, AAC_DB_PRINTF);
+ }
+}
diff --git a/sys/sys/aac_ioctl.h b/sys/sys/aac_ioctl.h
index a0b2f7e..fda2afd 100644
--- a/sys/sys/aac_ioctl.h
+++ b/sys/sys/aac_ioctl.h
@@ -1,8 +1,7 @@
/*-
* Copyright (c) 2000 Michael Smith
- * Copyright (c) 2000-2001 Scott Long
+ * Copyright (c) 2000 Scott Long
* Copyright (c) 2000 BSDi
- * Copyright (c) 2001 Adaptec, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -59,8 +58,7 @@ union aac_statrequest {
* These bit encodings are actually descended from Windows NT. Ick.
*/
-#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) \
- | ((func) << 2) | (meth))
+#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) | ((func) << 2) | (meth))
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
@@ -108,15 +106,15 @@ union aac_statrequest {
#define FSACTL_LNX_DELETE_DISK 0x163
#define FSACTL_LNX_QUERY_DISK 0x173
-/* Ok, this one is really lame */
+/* Ok, here it gets really lame */
#define FSACTL_LNX_PROBE_CONTAINERS 2131 /* Just guessing */
/* Do the native version of the ioctls. Since the BSD encoding scheme
- * conflicts with the 'standard' AAC encoding scheme, the resulting values
- * must be different. The '8' comes from the fact that the previous scheme
+ * conflicts with the 'standard' AAC encoding scheme, the resulting numbers
+ * will be different. The '8' comes from the fact that the previous scheme
* used 12 bits for the number, with the the 12th bit being the only set
* bit above bit 8. Thus the value of 8, with the lower 8 bits holding the
- * command number. 9 is used for the odd overflow/collision case.
+ * command number. 9 is used for the odd overflow case.
*/
#define FSACTL_SENDFIB _IO('8', 2)
#define FSACTL_GET_COMM_PERF_DATA _IO('8', 36)
@@ -161,9 +159,21 @@ struct aac_rev_check_resp {
/*
* Context passed in by a consumer looking to collect an AIF.
*/
-#define AAC_AIF_SILLYMAGIC 0xdeadbeef
struct get_adapter_fib_ioctl {
u_int32_t AdapterFibContext;
int Wait;
caddr_t AifFib;
};
+
+struct aac_query_disk {
+ int32_t ContainerNumber;
+ int32_t Bus;
+ int32_t Target;
+ int32_t Lun;
+ u_int32_t Valid;
+ u_int32_t Locked;
+ u_int32_t Deleted;
+ int32_t Instance;
+ char diskDeviceName[10];
+ u_int32_t UnMapped;
+};
OpenPOWER on IntegriCloud