aac(4) sync with FreeBSD
Peter Avalos
pavalos at theshell.com
Sun Jan 13 09:35:55 PST 2008
Here's a patch that syncs the aac(4) driver with FreeBSD. I don't have
the hardware to test this, but I need some of these changes before I can
progress with CAM. Please provide comments, and please test if you have
the hardware. I plan on comitting this next weekend.
--Peter
http://www.theshell.com/~pavalos/wip/aac.patch
Major sync with FreeBSD.
diff --git a/sys/dev/raid/aac/aac.c b/sys/dev/raid/aac/aac.c
index d5e6809..4234a75 100644
--- a/sys/dev/raid/aac/aac.c
+++ b/sys/dev/raid/aac/aac.c
@@ -33,6 +33,8 @@
/*
* Driver for the Adaptec 'FSA' family of PCI/SCSI RAID adapters.
*/
+#define AAC_DRIVER_VERSION 0x02000000
+#define AAC_DRIVERNAME "aac"
#include "opt_aac.h"
@@ -44,13 +46,6 @@
#include <sys/kthread.h>
#include <sys/sysctl.h>
#include <sys/poll.h>
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500005
-#include <sys/selinfo.h>
-#else
-#include <sys/select.h>
-#endif
-
-#include "aac_compat.h"
#include <sys/bus.h>
#include <sys/conf.h>
@@ -59,12 +54,15 @@
#include <sys/signalvar.h>
#include <sys/time.h>
#include <sys/eventhandler.h>
+#include <sys/rman.h>
+
+#include <bus/pci/pcireg.h>
+#include <bus/pci/pcivar.h>
#include "aacreg.h"
#include "aac_ioctl.h"
#include "aacvar.h"
#include "aac_tables.h"
-#include "aac_cam.h"
static void aac_startup(void *arg);
static void aac_add_container(struct aac_softc *sc,
@@ -74,20 +72,20 @@ static int aac_shutdown(device_t dev);
/* Command Processing */
static void aac_timeout(void *ssc);
-static int aac_start(struct aac_command *cm);
+static int aac_map_command(struct aac_command *cm);
static void aac_complete(void *context, int pending);
static int aac_bio_command(struct aac_softc *sc, struct aac_command **cmp);
static void aac_bio_complete(struct aac_command *cm);
-static int aac_wait_command(struct aac_command *cm, int timeout);
-static void aac_host_command(struct aac_softc *sc);
-static void aac_host_response(struct aac_softc *sc);
+static int aac_wait_command(struct aac_command *cm);
+static void aac_command_thread(struct aac_softc *sc);
/* Command Buffer Management */
+static void aac_map_command_sg(void *arg, bus_dma_segment_t *segs,
+ int nseg, int error);
static void aac_map_command_helper(void *arg, bus_dma_segment_t *segs,
int nseg, int error);
static int aac_alloc_commands(struct aac_softc *sc);
static void aac_free_commands(struct aac_softc *sc);
-static void aac_map_command(struct aac_command *cm);
static void aac_unmap_command(struct aac_command *cm);
/* Hardware Interface */
@@ -123,7 +121,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 */
@@ -144,10 +143,11 @@ 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 */
+/* i960Rx interface */
static int aac_rx_get_fwstatus(struct aac_softc *sc);
static void aac_rx_qnotify(struct aac_softc *sc, int qbit);
static int aac_rx_get_istatus(struct aac_softc *sc);
@@ -157,6 +157,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,
@@ -165,7 +168,37 @@ 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 */
+static int aac_rkt_get_fwstatus(struct aac_softc *sc);
+static void aac_rkt_qnotify(struct aac_softc *sc, int qbit);
+static int aac_rkt_get_istatus(struct aac_softc *sc);
+static void aac_rkt_clear_istatus(struct aac_softc *sc, int mask);
+static void aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command,
+ u_int32_t arg0, u_int32_t arg1,
+ 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,
+ aac_rkt_qnotify,
+ aac_rkt_get_istatus,
+ aac_rkt_clear_istatus,
+ aac_rkt_set_mailbox,
+ aac_rkt_get_mailbox,
+ aac_rkt_set_interrupts,
+ aac_rkt_send_command,
+ aac_rkt_get_outb_queue,
+ aac_rkt_set_outb_queue
};
/* Debugging and Diagnostics */
@@ -178,13 +211,16 @@ static d_open_t aac_open;
static d_close_t aac_close;
static d_ioctl_t aac_ioctl;
static d_poll_t aac_poll;
-static int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib);
+static int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) __unused;
static void aac_handle_aif(struct aac_softc *sc,
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);
+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);
#define AAC_CDEV_MAJOR 150
@@ -227,15 +263,10 @@ aac_attach(struct aac_softc *sc)
aac_initq_complete(sc);
aac_initq_bio(sc);
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500005
/*
* Initialise command-completion task.
*/
TASK_INIT(&sc->aac_task_complete, 0, aac_complete, sc);
-#endif
-
- /* 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;
@@ -246,8 +277,18 @@ aac_attach(struct aac_softc *sc)
if ((error = aac_check_firmware(sc)) != 0)
return(error);
- /* Init the sync fib lock */
- AAC_LOCK_INIT(&sc->aac_sync_lock, "AAC sync FIB lock");
+ /*
+ * Initialize locks
+ */
+ AAC_LOCK_INIT(&sc->aac_aifq_lock, "AAC AIF lock");
+ AAC_LOCK_INIT(&sc->aac_io_lock, "AAC I/O lock");
+ AAC_LOCK_INIT(&sc->aac_container_lock, "AAC container lock");
+ TAILQ_INIT(&sc->aac_container_tqh);
+ TAILQ_INIT(&sc->aac_ev_cmfree);
+
+
+ /* Initialize the local AIF queue pointers */
+ sc->aac_aifq_head = sc->aac_aifq_tail = AAC_AIFQ_LENGTH;
/*
* Initialise the adapter.
@@ -255,22 +296,48 @@ aac_attach(struct aac_softc *sc)
if ((error = aac_init(sc)) != 0)
return(error);
- /*
- * Print a little information about the controller.
+ /*
+ * Allocate and connect our interrupt.
*/
- aac_describe_controller(sc);
+ 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, aac_new_intr,
+ sc, &sc->aac_intr, NULL)) {
+ 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, aac_fast_intr,
+ sc, &sc->aac_intr, NULL)) {
+ device_printf(sc->aac_dev,
+ "can't set up FAST interrupt\n");
+ if (bus_setup_intr(sc->aac_dev, sc->aac_irq,
+ INTR_MPSAFE, aac_fast_intr,
+ sc, &sc->aac_intr, NULL)) {
+ device_printf(sc->aac_dev,
+ "can't set up MPSAFE interrupt\n");
+ return (EINVAL);
+ }
+ }
+ }
/*
- * Register to probe our containers later.
+ * Print a little information about the controller.
*/
- TAILQ_INIT(&sc->aac_container_tqh);
- AAC_LOCK_INIT(&sc->aac_container_lock, "AAC container lock");
+ aac_describe_controller(sc);
/*
- * Lock for the AIF queue
+ * Register to probe our containers later.
*/
- AAC_LOCK_INIT(&sc->aac_aifq_lock, "AAC AIF lock");
-
sc->aac_ich.ich_func = aac_startup;
sc->aac_ich.ich_arg = sc;
sc->aac_ich.ich_desc = "aac";
@@ -285,37 +352,48 @@ aac_attach(struct aac_softc *sc)
*/
unit = device_get_unit(sc->aac_dev);
dev_ops_add(&aac_ops, -1, unit);
- sc->aac_dev_t = make_dev(&aac_ops, unit, UID_ROOT, GID_WHEEL, 0644,
+ sc->aac_dev_t = make_dev(&aac_ops, unit, UID_ROOT, GID_OPERATOR, 0640,
"aac%d", unit);
-#if defined(__FreeBSD__) && __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;
reference_dev(sc->aac_dev_t);
/* Create the AIF thread */
-#if defined(__FreeBSD__) && __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,
+ if (kthread_create((void(*)(void *))aac_command_thread, 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_post_sync, aac_shutdown, sc->aac_dev,
- SHUTDOWN_PRI_DRIVER)) == NULL)
- device_printf(sc->aac_dev, "shutdown event registration failed\n");
+ if ((sc->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, aac_shutdown,
+ sc->aac_dev, SHUTDOWN_PRI_DRIVER)) == NULL)
+ device_printf(sc->aac_dev,
+ "shutdown event registration failed\n");
/* Register with CAM for the non-DASD devices */
- if ((sc->flags & AAC_FLAGS_ENABLE_CAM) != 0)
+ if ((sc->flags & AAC_FLAGS_ENABLE_CAM) != 0) {
+ TAILQ_INIT(&sc->aac_sim_tqh);
aac_get_bus_info(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.
*/
@@ -335,7 +413,8 @@ aac_startup(void *arg)
/* disconnect ourselves from the intrhook chain */
config_intrhook_disestablish(&sc->aac_ich);
- aac_alloc_sync_fib(sc, &fib, 0);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ aac_alloc_sync_fib(sc, &fib);
mi = (struct aac_mntinfo *)&fib->data[0];
/* loop over possible containers */
@@ -361,6 +440,7 @@ aac_startup(void *arg)
} while ((i < count) && (i < AAC_MAX_CONTAINERS));
aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
/* poke the bus to actually attach the child devices */
if (bus_generic_attach(sc->aac_dev))
@@ -371,10 +451,6 @@ aac_startup(void *arg)
/* enable interrupts now */
AAC_UNMASK_INTERRUPTS(sc);
-
- /* enable the timeout watchdog */
- callout_reset(&sc->aac_watchdog, AAC_PERIODIC_INTERVAL * hz,
- aac_timeout, sc);
}
/*
@@ -386,18 +462,18 @@ aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f)
struct aac_container *co;
device_t child;
- /*
+ /*
* Check container volume type for validity. Note that many of
* the 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_INTWAIT);
- debug(1, "id %x name '%.16s' size %u type %d",
+ co = (struct aac_container *)kmalloc(sizeof *co, M_AACBUF,
+ M_INTWAIT | M_ZERO);
+ debug(1, "id %x name '%.16s' size %u type %d",
mir->MntTable[0].ObjectId,
mir->MntTable[0].FileSystemName,
mir->MntTable[0].Capacity, mir->MntTable[0].VolType);
-
+
if ((child = device_add_child(sc->aac_dev, "aacd", -1)) == NULL)
device_printf(sc->aac_dev, "device_add_child failed\n");
else
@@ -422,6 +498,7 @@ aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f)
void
aac_free(struct aac_softc *sc)
{
+
debug_called(1);
/* remove the control device */
@@ -429,11 +506,12 @@ aac_free(struct aac_softc *sc)
destroy_dev(sc->aac_dev_t);
/* throw away any FIB buffers, discard the FIB DMA tag */
- if (sc->aac_fibs != NULL)
- aac_free_commands(sc);
+ aac_free_commands(sc);
if (sc->aac_fib_dmat)
bus_dma_tag_destroy(sc->aac_fib_dmat);
+ kfree(sc->aac_commands, M_AACBUF);
+
/* destroy the common area */
if (sc->aac_common) {
bus_dmamap_unload(sc->aac_common_dmat, sc->aac_common_dmamap);
@@ -473,9 +551,9 @@ int
aac_detach(device_t dev)
{
struct aac_softc *sc;
-#if AAC_BROKEN
+ struct aac_container *co;
+ struct aac_sim *sim;
int error;
-#endif
debug_called(1);
@@ -484,9 +562,26 @@ aac_detach(device_t dev)
callout_stop(&sc->aac_watchdog);
if (sc->aac_state & AAC_STATE_OPEN)
- return(EBUSY);
+ return(EBUSY);
+
+ /* Remove the child containers */
+ while ((co = TAILQ_FIRST(&sc->aac_container_tqh)) != NULL) {
+ error = device_delete_child(dev, co->co_disk);
+ if (error)
+ return (error);
+ TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link);
+ kfree(co, M_AACBUF);
+ }
+
+ /* Remove the CAM SIMs */
+ while ((sim = TAILQ_FIRST(&sc->aac_sim_tqh)) != NULL) {
+ TAILQ_REMOVE(&sc->aac_sim_tqh, sim, sim_link);
+ error = device_delete_child(dev, sim->sim_dev);
+ if (error)
+ return (error);
+ kfree(sim, M_AACBUF);
+ }
-#if AAC_BROKEN
if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
sc->aifflags |= AAC_AIFFLAGS_EXIT;
wakeup(sc->aifthread);
@@ -499,12 +594,15 @@ aac_detach(device_t dev)
if ((error = aac_shutdown(dev)))
return(error);
+ EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->eh);
+
aac_free(sc);
+ lockuninit(&sc->aac_aifq_lock);
+ lockuninit(&sc->aac_io_lock);
+ lockuninit(&sc->aac_container_lock);
+
return(0);
-#else
- return (EBUSY);
-#endif
}
/*
@@ -526,18 +624,17 @@ aac_shutdown(device_t dev)
sc = device_get_softc(dev);
- crit_enter();
-
sc->aac_state |= AAC_STATE_SUSPEND;
- /*
+ /*
* Send a Container shutdown followed by a HostShutdown FIB to the
* controller to convince it that we don't want to talk to it anymore.
* We've been closed and all I/O completed already
*/
device_printf(sc->aac_dev, "shutting down controller...");
- aac_alloc_sync_fib(sc, &fib, AAC_SYNC_LOCK_FORCE);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ aac_alloc_sync_fib(sc, &fib);
cc = (struct aac_close_command *)&fib->data[0];
bzero(cc, sizeof(struct aac_close_command));
@@ -546,6 +643,9 @@ aac_shutdown(device_t dev)
if (aac_sync_fib(sc, ContainerCommand, 0, fib,
sizeof(struct aac_close_command)))
kprintf("FAILED.\n");
+ else
+ kprintf("done\n");
+#if 0
else {
fib->data[0] = 0;
/*
@@ -561,10 +661,12 @@ aac_shutdown(device_t dev)
kprintf("done.\n");
}
}
+#endif
AAC_MASK_INTERRUPTS(sc);
+ aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
- crit_exit();
return(0);
}
@@ -580,12 +682,9 @@ aac_suspend(device_t dev)
sc = device_get_softc(dev);
- crit_enter();
-
sc->aac_state |= AAC_STATE_SUSPEND;
-
+
AAC_MASK_INTERRUPTS(sc);
- crit_exit();
return(0);
}
@@ -607,48 +706,122 @@ 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;
+
+ AAC_LOCK_ACQUIRE(&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 *)kmalloc(sizeof *fib, M_AACBUF,
+ M_INTWAIT | M_ZERO);
+ 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);
+ kfree(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);
+
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+}
+
+void
+aac_fast_intr(void *arg)
{
struct aac_softc *sc;
u_int16_t reason;
- u_int32_t *resp_queue;
debug_called(2);
sc = (struct aac_softc *)arg;
/*
- * Optimize the common case of adapter response interrupts.
- * We must read from the card prior to processing the responses
- * to ensure the clear is flushed prior to accessing the queues.
- * Reading the queues from local memory might save us a PCI read.
+ * Read the status register directly. This is faster than taking the
+ * driver lock and reading the queues directly. It also saves having
+ * to turn parts of the driver lock into a spin mutex, which would be
+ * ugly.
*/
- resp_queue = sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE];
- if (resp_queue[AAC_PRODUCER_INDEX] != resp_queue[AAC_CONSUMER_INDEX])
- reason = AAC_DB_RESPONSE_READY;
- else
- reason = AAC_GET_ISTATUS(sc);
+ reason = AAC_GET_ISTATUS(sc);
AAC_CLEAR_ISTATUS(sc, reason);
- (void)AAC_GET_ISTATUS(sc);
- /* It's not ok to return here because of races with the previous step */
+ /* handle completion processing */
if (reason & AAC_DB_RESPONSE_READY)
- aac_host_response(sc);
+ taskqueue_enqueue(taskqueue_swi, &sc->aac_task_complete);
- /* controller wants to talk to the log */
- if (reason & AAC_DB_PRINTF)
- aac_print_printf(sc);
+ /* controller wants to talk to us */
+ if (reason & (AAC_DB_PRINTF | AAC_DB_COMMAND_READY)) {
+ /*
+ * XXX Make sure that we don't get fooled by strange messages
+ * that start with a NULL.
+ */
+ if ((reason & AAC_DB_PRINTF) &&
+ (sc->aac_common->ac_printf[0] == 0))
+ sc->aac_common->ac_printf[0] = 32;
- /* controller has a message for us? */
- if (reason & AAC_DB_COMMAND_READY) {
- /* XXX What happens if the thread is already awake? */
- if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
- sc->aifflags |= AAC_AIFFLAGS_PENDING;
- wakeup(sc->aifthread);
- }
+ /*
+ * This might miss doing the actual wakeup. However, the
+ * msleep that this is waking up has a timeout, so it will
+ * wake up eventually. AIFs and printfs are low enough
+ * priority that they can handle hanging out for a few seconds
+ * if needed.
+ */
+ wakeup(sc->aifthread);
}
}
@@ -666,15 +839,18 @@ aac_startio(struct aac_softc *sc)
debug_called(2);
+ if (sc->flags & AAC_QUEUE_FRZN)
+ return;
+
for (;;) {
/*
- * Try to get a command that's been put off for lack of
+ * Try to get a command that's been put off for lack of
* resources
*/
cm = aac_dequeue_ready(sc);
/*
- * Try to build a command off the bio queue (ignore error
+ * Try to build a command off the bio queue (ignore error
* return)
*/
if (cm == NULL)
@@ -684,12 +860,12 @@ aac_startio(struct aac_softc *sc)
if (cm == NULL)
break;
- /* try to give the command to the controller */
- if (aac_start(cm) == EBUSY) {
- /* put it on the ready queue for later */
- aac_requeue_ready(cm);
- break;
- }
+ /*
+ * Try to give the command to the controller. Any error is
+ * catastrophic since it means that bus_dmamap_load() failed.
+ */
+ if (aac_map_command(cm) != 0)
+ panic("aac: error mapping command %p\n", cm);
}
}
@@ -698,7 +874,7 @@ aac_startio(struct aac_softc *sc)
* last moment when possible.
*/
static int
-aac_start(struct aac_command *cm)
+aac_map_command(struct aac_command *cm)
{
struct aac_softc *sc;
int error;
@@ -706,48 +882,88 @@ aac_start(struct aac_command *cm)
debug_called(2);
sc = cm->cm_sc;
+ error = 0;
- /* get the command mapped */
- aac_map_command(cm);
-
- /* fix up the address values in the FIB */
- cm->cm_fib->Header.SenderFibAddress = (u_int32_t)cm->cm_fib;
- cm->cm_fib->Header.ReceiverFibAddress = cm->cm_fibphys;
+ /* don't map more than once */
+ if (cm->cm_flags & AAC_CMD_MAPPED)
+ panic("aac: command %p already mapped", cm);
- /* save a pointer to the command for speedy reverse-lookup */
- cm->cm_fib->Header.SenderData = (u_int32_t)cm; /* XXX 64-bit physical
- * address issue */
- /* put the FIB on the outbound queue */
- error = aac_enqueue_fib(sc, cm->cm_queue, cm);
- return(error);
+ if (cm->cm_datalen != 0) {
+ error = bus_dmamap_load(sc->aac_buffer_dmat, cm->cm_datamap,
+ cm->cm_data, cm->cm_datalen,
+ aac_map_command_sg, cm, 0);
+ if (error == EINPROGRESS) {
+ debug(1, "freezing queue\n");
+ sc->flags |= AAC_QUEUE_FRZN;
+ error = 0;
+ }
+ } else {
+ aac_map_command_sg(cm, NULL, 0, 0);
+ }
+ return (error);
}
/*
* Handle notification of one or more FIBs coming from the controller.
*/
static void
-aac_host_command(struct aac_softc *sc)
+aac_command_thread(struct aac_softc *sc)
{
struct aac_fib *fib;
u_int32_t fib_size;
- int size;
+ int size, retval;
debug_called(2);
- sc->aifflags |= AAC_AIFFLAGS_RUNNING;
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ sc->aifflags = AAC_AIFFLAGS_RUNNING;
- while (!(sc->aifflags & AAC_AIFFLAGS_EXIT)) {
- if (!(sc->aifflags & AAC_AIFFLAGS_PENDING))
- tsleep(sc->aifthread, 0, "aifthd", 15 * hz);
+ while ((sc->aifflags & AAC_AIFFLAGS_EXIT) == 0) {
+ retval = 0;
+ if ((sc->aifflags & AAC_AIFFLAGS_PENDING) == 0) {
+ crit_enter();
+ tsleep_interlock(sc->aifthread);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+ retval = tsleep(sc->aifthread, 0,
+ "aifthd", AAC_PERIODIC_INTERVAL * hz);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ crit_exit();
+ }
+ /*
+ * First see if any FIBs need to be allocated. This needs
+ * to be called without the driver lock because contigmalloc
+ * will grab Giant, and would result in an LOR.
+ */
+ if ((sc->aifflags & AAC_AIFFLAGS_ALLOCFIBS) != 0) {
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+ aac_alloc_commands(sc);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ sc->aifflags &= ~AAC_AIFFLAGS_ALLOCFIBS;
+ aac_startio(sc);
+ }
+
+ /*
+ * While we're here, check to see if any commands are stuck.
+ * This is pretty low-priority, so it's ok if it doesn't
+ * always fire.
+ */
+ if (retval == EWOULDBLOCK)
+ aac_timeout(sc);
+
+ /* Check the hardware printf message buffer */
+ if (sc->aac_common->ac_printf[0] != 0)
+ aac_print_printf(sc);
- sc->aifflags &= ~AAC_AIFFLAGS_PENDING;
+ /* Also check to see if the adapter has a command for us. */
+ if (sc->flags & AAC_FLAGS_NEW_COMM)
+ continue;
for (;;) {
if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE,
&fib_size, &fib))
- break; /* nothing to do */
-
+ break;
+
AAC_PRINT_FIB(sc, fib);
-
+
switch (fib->Header.Command) {
case AifRequest:
aac_handle_aif(sc, fib);
@@ -758,11 +974,12 @@ aac_host_command(struct aac_softc *sc)
break;
}
- /* Return the AIF to the controller. */
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) {
fib->Header.XferState |= AAC_FIBSTATE_DONEHOST;
*(AAC_FSAStatus*)fib->data = ST_OK;
@@ -779,75 +996,50 @@ aac_host_command(struct aac_softc *sc)
* enqueue->startio chain.
*/
aac_enqueue_response(sc,
- AAC_ADAP_NORM_RESP_QUEUE,
- fib);
+ AAC_ADAP_NORM_RESP_QUEUE,
+ fib);
}
}
}
sc->aifflags &= ~AAC_AIFFLAGS_RUNNING;
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
wakeup(sc->aac_dev);
-#if defined(__FreeBSD__) && __FreeBSD_version > 500005
- mtx_lock(&Giant);
-#endif
kthread_exit();
}
/*
- * Handle notification of one or more FIBs completed by the controller
+ * Process completed commands.
*/
static void
-aac_host_response(struct aac_softc *sc)
+aac_complete(void *context, int pending)
{
+ struct aac_softc *sc;
struct aac_command *cm;
struct aac_fib *fib;
u_int32_t fib_size;
debug_called(2);
+ sc = (struct aac_softc *)context;
+
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+
+ /* pull completed commands off the queue */
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 queue for later processing */
- cm = (struct aac_command *)fib->Header.SenderData;
+ cm = sc->aac_commands + fib->Header.SenderData;
if (cm == NULL) {
AAC_PRINT_FIB(sc, fib);
- } else {
- aac_remove_busy(cm);
- aac_unmap_command(cm); /* XXX defer? */
- aac_enqueue_complete(cm);
- }
- }
-
- /* handle completion processing */
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500005
- taskqueue_enqueue(taskqueue_swi, &sc->aac_task_complete);
-#else
- aac_complete(sc, 0);
-#endif
-}
-
-/*
- * Process completed commands.
- */
-static void
-aac_complete(void *context, int pending)
-{
- struct aac_softc *sc;
- struct aac_command *cm;
-
- debug_called(2);
-
- sc = (struct aac_softc *)context;
-
- /* pull completed commands off the queue */
- for (;;) {
- cm = aac_dequeue_complete(sc);
- if (cm == NULL)
break;
+ }
+ aac_remove_busy(cm);
+ aac_unmap_command(cm); /* XXX defer? */
cm->cm_flags |= AAC_CMD_COMPLETED;
/* is there a completion handler? */
}
/* see if we can start some more I/O */
+ sc->flags &= ~AAC_QUEUE_FRZN;
aac_startio(sc);
+
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
}
/*
@@ -889,8 +1084,6 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
{
struct aac_command *cm;
struct aac_fib *fib;
- struct aac_blockread *br;
- struct aac_blockwrite *bw;
struct aac_disk *ad;
struct bio *bio;
struct buf *bp;
@@ -899,10 +1092,11 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
/* get the resources we will need */
cm = NULL;
- if ((bio = aac_dequeue_bio(sc)) == NULL)
- goto fail;
+ bio = NULL;
if (aac_alloc_command(sc, &cm)) /* get a command */
goto fail;
+ if ((bio = aac_dequeue_bio(sc)) == NULL)
+ goto fail;
/* fill out the command */
bp = bio->bio_buf;
@@ -915,39 +1109,89 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
/* build the FIB */
fib = cm->cm_fib;
- fib->Header.XferState =
- AAC_FIBSTATE_HOSTOWNED |
- AAC_FIBSTATE_INITIALISED |
- AAC_FIBSTATE_EMPTY |
+ fib->Header.Size = sizeof(struct aac_fib_header);
+ fib->Header.XferState =
+ AAC_FIBSTATE_HOSTOWNED |
+ AAC_FIBSTATE_INITIALISED |
+ AAC_FIBSTATE_EMPTY |
AAC_FIBSTATE_FROMHOST |
AAC_FIBSTATE_REXPECTED |
AAC_FIBSTATE_NORM |
AAC_FIBSTATE_ASYNC |
AAC_FIBSTATE_FAST_RESPONSE;
- fib->Header.Command = ContainerCommand;
- fib->Header.Size = sizeof(struct aac_fib_header);
/* build the read/write request */
ad = (struct aac_disk *)bio->bio_driver_info;
- if (bp->b_cmd == BUF_CMD_READ) {
- br = (struct aac_blockread *)&fib->data[0];
- br->Command = VM_CtBlockRead;
- br->ContainerId = ad->ad_container->co_mntobj.ObjectId;
- br->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
- br->ByteCount = bp->b_bcount;
- fib->Header.Size += sizeof(struct aac_blockread);
- cm->cm_sgtable = &br->SgMap;
- cm->cm_flags |= AAC_CMD_DATAIN;
+
+ 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 = bio->bio_offset / AAC_BLOCK_SIZE;
+ raw->ByteCount = bp->b_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->b_cmd == BUF_CMD_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->b_cmd == BUF_CMD_READ) {
+ struct aac_blockread *br;
+ br = (struct aac_blockread *)&fib->data[0];
+ br->Command = VM_CtBlockRead;
+ br->ContainerId = ad->ad_container->co_mntobj.ObjectId;
+ br->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
+ br->ByteCount = bp->b_bcount;
+ fib->Header.Size += sizeof(struct aac_blockread);
+ cm->cm_sgtable = &br->SgMap;
+ cm->cm_flags |= AAC_CMD_DATAIN;
+ } else {
+ struct aac_blockwrite *bw;
+ bw = (struct aac_blockwrite *)&fib->data[0];
+ bw->Command = VM_CtBlockWrite;
+ bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
+ bw->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
+ bw->ByteCount = bp->b_bcount;
+ bw->Stable = CUNSTABLE;
+ fib->Header.Size += sizeof(struct aac_blockwrite);
+ cm->cm_flags |= AAC_CMD_DATAOUT;
+ cm->cm_sgtable = &bw->SgMap;
+ }
} else {
- bw = (struct aac_blockwrite *)&fib->data[0];
- bw->Command = VM_CtBlockWrite;
- bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
- bw->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
- bw->ByteCount = bp->b_bcount;
- 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;
+ fib->Header.Command = ContainerCommand64;
+ if (bp->b_cmd == BUF_CMD_READ) {
+ struct aac_blockread64 *br;
+ br = (struct aac_blockread64 *)&fib->data[0];
+ br->Command = VM_CtHostRead64;
+ br->ContainerId = ad->ad_container->co_mntobj.ObjectId;
+ br->SectorCount = bp->b_bcount / AAC_BLOCK_SIZE;
+ br->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
+ br->Pad = 0;
+ br->Flags = 0;
+ fib->Header.Size += sizeof(struct aac_blockread64);
+ cm->cm_flags |= AAC_CMD_DATAOUT;
+ cm->cm_sgtable = (struct aac_sg_table *)&br->SgMap64;
+ } else {
+ struct aac_blockwrite64 *bw;
+ bw = (struct aac_blockwrite64 *)&fib->data[0];
+ bw->Command = VM_CtHostWrite64;
+ bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
+ bw->SectorCount = bp->b_bcount / AAC_BLOCK_SIZE;
+ bw->BlockNumber = bio->bio_offset / AAC_BLOCK_SIZE;
+ bw->Pad = 0;
+ bw->Flags = 0;
+ fib->Header.Size += sizeof(struct aac_blockwrite64);
+ cm->cm_flags |= AAC_CMD_DATAIN;
+ cm->cm_sgtable = (struct aac_sg_table *)&bw->SgMap64;
+ }
}
*cmp = cm;
@@ -1048,7 +1292,7 @@ aac_dump_enqueue(struct aac_disk *ad, u_int64_t lba, void *data, int dumppages)
cm->cm_flags |= AAC_CMD_DATAOUT;
cm->cm_sgtable = &bw->SgMap;
- return (aac_start(cm));
+ return (aac_map_command(cm));
}
/*
@@ -1101,29 +1345,33 @@ aac_dump_complete(struct aac_softc *sc)
* Submit a command to the controller, return when it completes.
* XXX This is very dangerous! If the card has gone out to lunch, we could
* be stuck here forever. At the same time, signals are not caught
- * because there is a risk that a signal could wakeup the tsleep before
- * the card has a chance to complete the command. The passed in timeout
- * is ignored for the same reason. Since there is no way to cancel a
- * command in progress, we should probably create a 'dead' queue where
- * commands go that have been interrupted/timed-out/etc, that keeps them
- * out of the free pool. That way, if the card is just slow, it won't
- * spam the memory of a command that has been recycled.
+ * because there is a risk that a signal could wakeup the sleep before
+ * the card has a chance to complete the command. Since there is no way
+ * to cancel a command that is in progress, we can't protect against the
+ * card completing a command late and spamming the command and data
+ * memory. So, we are held hostage until the command completes.
*/
static int
-aac_wait_command(struct aac_command *cm, int timeout)
+aac_wait_command(struct aac_command *cm)
{
- int error = 0;
+ struct aac_softc *sc;
+ int error;
debug_called(2);
+ sc = cm->cm_sc;
+
/* 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);
+ aac_startio(sc);
+ /* Lock is held */
+ KKASSERT(lockstatus(&sc->aac_io_lock, curthread) != 0);
crit_enter();
- while (!(cm->cm_flags & AAC_CMD_COMPLETED) && (error != EWOULDBLOCK)) {
- error = tsleep(cm, 0, "aacwait", 0);
- }
+ tsleep_interlock(cm);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+ error = tsleep(cm, 0, "aacwait", 0);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
crit_exit();
return(error);
}
@@ -1142,8 +1390,13 @@ aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp)
debug_called(3);
- if ((cm = aac_dequeue_free(sc)) == NULL)
- return(ENOMEM);
+ if ((cm = aac_dequeue_free(sc)) == NULL) {
+ if (sc->total_fibs < sc->aac_max_fibs) {
+ sc->aifflags |= AAC_AIFFLAGS_ALLOCFIBS;
+ wakeup(sc->aifthread);
+ }
+ return (EBUSY);
+ }
*cmp = cm;
return(0);
@@ -1155,6 +1408,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 */
@@ -1165,18 +1421,24 @@ 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
* intermediate stage may have destroyed them. They're left
* initialised here for debugging purposes only.
*/
- cm->cm_fib->Header.SenderFibAddress = (u_int32_t)cm->cm_fib;
cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys;
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);
+ }
}
/*
@@ -1185,13 +1447,13 @@ aac_release_command(struct aac_command *cm)
static void
aac_map_command_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
- struct aac_softc *sc;
+ uint64_t *fibphys;
- sc = (struct aac_softc *)arg;
+ fibphys = (uint64_t *)arg;
debug_called(3);
- sc->aac_fibphys = segs[0].ds_addr;
+ *fibphys = segs[0].ds_addr;
}
/*
@@ -1201,32 +1463,63 @@ static int
aac_alloc_commands(struct aac_softc *sc)
{
struct aac_command *cm;
- int i;
-
- debug_called(1);
+ struct aac_fibmap *fm;
+ uint64_t fibphys;
+ int i, error;
+
+ debug_called(2);
+
+ if (sc->total_fibs + sc->aac_max_fibs_alloc > sc->aac_max_fibs)
+ return (ENOMEM);
+
+ fm = kmalloc(sizeof(struct aac_fibmap), M_AACBUF, M_INTWAIT | M_ZERO);
/* allocate the FIBs in DMAable memory and load them */
- if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&sc->aac_fibs,
- BUS_DMA_NOWAIT, &sc->aac_fibmap)) {
- return(ENOMEM);
+ if (bus_dmamem_alloc(sc->aac_fib_dmat, (void **)&fm->aac_fibs,
+ BUS_DMA_NOWAIT, &fm->aac_fibmap)) {
+ device_printf(sc->aac_dev,
+ "Not enough contiguous memory available.\n");
+ kfree(fm, M_AACBUF);
+ return (ENOMEM);
}
- bus_dmamap_load(sc->aac_fib_dmat, sc->aac_fibmap, sc->aac_fibs,
- AAC_FIB_COUNT * sizeof(struct aac_fib),
- aac_map_command_helper, sc, 0);
+ /* Ignore errors since this doesn't bounce */
+ bus_dmamap_load(sc->aac_fib_dmat, fm->aac_fibmap, fm->aac_fibs,
+ sc->aac_max_fibs_alloc * sc->aac_max_fib_size,
+ aac_map_command_helper, &fibphys, 0);
/* initialise constant fields in the command structure */
- bzero(sc->aac_fibs, AAC_FIB_COUNT * sizeof(struct aac_fib));
- for (i = 0; i < AAC_FIB_COUNT; i++) {
- cm = &sc->aac_command[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 = sc->aac_fibs + i;
- cm->cm_fibphys = sc->aac_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 (!bus_dmamap_create(sc->aac_buffer_dmat, 0, &cm->cm_datamap))
- aac_release_command(cm);
+ if ((error = bus_dmamap_create(sc->aac_buffer_dmat, 0,
+ &cm->cm_datamap)) != 0)
+ break;
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ aac_release_command(cm);
+ sc->total_fibs++;
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
}
- return(0);
+
+ if (i > 0) {
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ TAILQ_INSERT_TAIL(&sc->aac_fibmap_tqh, fm, fm_link);
+ debug(1, "total_fibs= %d\n", sc->total_fibs);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+ return (0);
+ }
+
+ bus_dmamap_unload(sc->aac_fib_dmat, fm->aac_fibmap);
+ bus_dmamem_free(sc->aac_fib_dmat, fm->aac_fibs, fm->aac_fibmap);
+ kfree(fm, M_AACBUF);
+ return (ENOMEM);
}
/*
@@ -1235,16 +1528,27 @@ aac_alloc_commands(struct aac_softc *sc)
static void
aac_free_commands(struct aac_softc *sc)
{
+ struct aac_fibmap *fm;
+ struct aac_command *cm;
int i;
debug_called(1);
- for (i = 0; i < AAC_FIB_COUNT; i++)
- bus_dmamap_destroy(sc->aac_buffer_dmat,
- sc->aac_command[i].cm_datamap);
+ while ((fm = TAILQ_FIRST(&sc->aac_fibmap_tqh)) != NULL) {
- bus_dmamap_unload(sc->aac_fib_dmat, sc->aac_fibmap);
- bus_dmamem_free(sc->aac_fib_dmat, sc->aac_fibs, sc->aac_fibmap);
+ TAILQ_REMOVE(&sc->aac_fibmap_tqh, fm, fm_link);
+ /*
+ * We check against total_fibs to handle partially
+ * allocated blocks.
+ */
+ 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);
+ }
+ bus_dmamap_unload(sc->aac_fib_dmat, fm->aac_fibmap);
+ bus_dmamem_free(sc->aac_fib_dmat, fm->aac_fibs, fm->aac_fibmap);
+ kfree(fm, M_AACBUF);
+ }
}
/*
@@ -1253,61 +1557,92 @@ aac_free_commands(struct aac_softc *sc)
static void
aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error)
{
+ struct aac_softc *sc;
struct aac_command *cm;
struct aac_fib *fib;
- struct aac_sg_table *sg;
int i;
debug_called(3);
cm = (struct aac_command *)arg;
+ sc = cm->cm_sc;
fib = cm->cm_fib;
- /* find the s/g table */
- sg = cm->cm_sgtable;
-
/* copy into the FIB */
- if (sg != NULL) {
- sg->SgCount = nseg;
- for (i = 0; i < nseg; i++) {
- sg->SgEntry[i].SgAddress = segs[i].ds_addr;
- sg->SgEntry[i].SgByteCount = segs[i].ds_len;
+ if (cm->cm_sgtable != NULL) {
+ 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;
+ for (i = 0; i < nseg; i++) {
+ sg->SgEntry[i].SgAddress = segs[i].ds_addr;
+ 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);
+ } else {
+ struct aac_sg_table64 *sg;
+ sg = (struct aac_sg_table64 *)cm->cm_sgtable;
+ sg->SgCount = nseg;
+ for (i = 0; i < nseg; i++) {
+ sg->SgEntry64[i].SgAddress = segs[i].ds_addr;
+ sg->SgEntry64[i].SgByteCount = segs[i].ds_len;
+ }
+ /* update the FIB size for the s/g count */
+ fib->Header.Size += nseg*sizeof(struct aac_sg_entry64);
}
- /* update the FIB size for the s/g count */
- fib->Header.Size += nseg * sizeof(struct aac_sg_entry);
}
-}
-
-/*
- * Map a command into controller-visible space.
- */
-static void
-aac_map_command(struct aac_command *cm)
-{
- struct aac_softc *sc;
-
- debug_called(2);
-
- sc = cm->cm_sc;
-
- /* don't map more than once */
- if (cm->cm_flags & AAC_CMD_MAPPED)
- return;
+ /* 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
+ * and for the AIF bit
+ */
+ cm->cm_fib->Header.SenderFibAddress = (cm->cm_index << 2);
+ cm->cm_fib->Header.ReceiverFibAddress = (u_int32_t)cm->cm_fibphys;
- if (cm->cm_datalen != 0) {
- bus_dmamap_load(sc->aac_buffer_dmat, cm->cm_datamap,
- cm->cm_data, cm->cm_datalen,
- aac_map_command_sg, cm, 0);
+ /* save a pointer to the command for speedy reverse-lookup */
+ cm->cm_fib->Header.SenderData = cm->cm_index;
+
+ if (cm->cm_flags & AAC_CMD_DATAIN)
+ bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
+ BUS_DMASYNC_PREREAD);
+ if (cm->cm_flags & AAC_CMD_DATAOUT)
+ bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
+ BUS_DMASYNC_PREWRITE);
+ cm->cm_flags |= AAC_CMD_MAPPED;
- if (cm->cm_flags & AAC_CMD_DATAIN)
- bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
- BUS_DMASYNC_PREREAD);
- if (cm->cm_flags & AAC_CMD_DATAOUT)
- bus_dmamap_sync(sc->aac_buffer_dmat, cm->cm_datamap,
- BUS_DMASYNC_PREWRITE);
+ 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);
+ }
}
- cm->cm_flags |= AAC_CMD_MAPPED;
}
/*
@@ -1360,7 +1695,8 @@ 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 = 0, atu_size = 0;
+ int status;
debug_called(1);
@@ -1389,20 +1725,91 @@ aac_check_firmware(struct aac_softc *sc)
/*
* Retrieve the capabilities/supported options word so we know what
- * work-arounds to enable.
+ * work-arounds to enable. Some firmware revs don't support this
+ * command.
*/
- if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, NULL)) {
- device_printf(sc->aac_dev, "RequestAdapterInfo failed\n");
- return (EIO);
+ if (aac_sync_command(sc, AAC_MONKER_GETINFO, 0, 0, 0, 0, &status)) {
+ if (status != AAC_SRB_STS_INVALID_REQUEST) {
+ device_printf(sc->aac_dev,
+ "RequestAdapterInfo failed\n");
+ return (EIO);
+ }
+ } else {
+ options = AAC_GET_MAILBOX(sc, 1);
+ atu_size = AAC_GET_MAILBOX(sc, 2);
+ sc->supported_options = options;
+
+ if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 &&
+ (sc->flags & AAC_FLAGS_NO4GB) == 0)
+ sc->flags |= AAC_FLAGS_4GB_WINDOW;
+ if (options & AAC_SUPPORTED_NONDASD)
+ sc->flags |= AAC_FLAGS_ENABLE_CAM;
+ if ((options & AAC_SUPPORTED_SGMAP_HOST64) != 0
+ && (sizeof(bus_addr_t) > 4)) {
+ 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;
}
- options = AAC_GET_MAILBOX(sc, 1);
- sc->supported_options = options;
- if ((options & AAC_SUPPORTED_4GB_WINDOW) != 0 &&
- (sc->flags & AAC_FLAGS_NO4GB) == 0)
- sc->flags |= AAC_FLAGS_4GB_WINDOW;
- if (options & AAC_SUPPORTED_NONDASD)
- sc->flags |= AAC_FLAGS_ENABLE_CAM;
+ /* Check for broken hardware that does a lower number of commands */
+ 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);
}
@@ -1412,8 +1819,7 @@ aac_init(struct aac_softc *sc)
{
struct aac_adapter_init *ip;
time_t then;
- u_int32_t code;
- u_int8_t *qaddr;
+ u_int32_t code, qoffset;
int error;
debug_called(1);
@@ -1447,11 +1853,13 @@ aac_init(struct aac_softc *sc)
*/
if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */
1, 0, /* algnmnt, boundary */
+ (sc->flags & AAC_FLAGS_SG_64BIT) ?
+ BUS_SPACE_MAXADDR :
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
BUS_SPACE_MAXADDR, /* highaddr */
NULL, NULL, /* filter, filterarg */
MAXBSIZE, /* maxsize */
- AAC_MAXSGENTRIES, /* nsegments */
+ sc->aac_sg_tablesize, /* nsegments */
MAXBSIZE, /* maxsegsize */
BUS_DMA_ALLOCNOW, /* flags */
&sc->aac_buffer_dmat)) {
@@ -1469,12 +1877,12 @@ 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 */
- BUS_DMA_ALLOCNOW, /* flags */
+ sc->aac_max_fibs_alloc *
+ sc->aac_max_fib_size, /* maxsegsize */
+ 0, /* flags */
&sc->aac_fib_dmat)) {
device_printf(sc->aac_dev, "can't allocate FIB DMA tag\n");
goto out;
@@ -1493,7 +1901,7 @@ aac_init(struct aac_softc *sc)
8192 + sizeof(struct aac_common), /* maxsize */
1, /* nsegments */
BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */
- BUS_DMA_ALLOCNOW, /* flags */
+ 0, /* flags */
&sc->aac_common_dmat)) {
device_printf(sc->aac_dev,
"can't allocate common structure DMA tag\n");
@@ -1522,7 +1930,14 @@ aac_init(struct aac_softc *sc)
bzero(sc->aac_common, sizeof(*sc->aac_common));
/* Allocate some FIBs and associated command structs */
- if (aac_alloc_commands(sc) != 0)
+ TAILQ_INIT(&sc->aac_fibmap_tqh);
+ sc->aac_commands = kmalloc(sc->aac_max_fibs * sizeof(struct aac_command),
+ M_AACBUF, M_INTWAIT | M_ZERO);
+ while (sc->total_fibs < AAC_PREALLOCATE_FIBS) {
+ if (aac_alloc_commands(sc) != 0)
+ break;
+ }
+ if (sc->total_fibs == 0)
goto out;
/*
@@ -1531,11 +1946,15 @@ 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 +
offsetof(struct aac_common, ac_fibs);
- ip->AdapterFibsVirtualAddress = (aac_phys_addr_t)&sc->aac_common->ac_fibs[0];
+ ip->AdapterFibsVirtualAddress = 0;
ip->AdapterFibsSize = AAC_ADAPTER_FIBS * sizeof(struct aac_fib);
ip->AdapterFibAlign = sizeof(struct aac_fib);
@@ -1543,34 +1962,51 @@ aac_init(struct aac_softc *sc)
offsetof(struct aac_common, ac_printf);
ip->PrintfBufferSize = AAC_PRINTF_BUFSIZE;
- /* The adapter assumes that pages are 4K in size */
+ /*
+ * The adapter assumes that pages are 4K in size, except on some
+ * broken firmware versions that do the page->byte conversion twice,
+ * therefore 'assuming' that this value is in 16MB units (2^24).
+ * Round up since the granularity is so high.
+ */
/* XXX why should the adapter care? */
ip->HostPhysMemPages = ctob((int)Maxmem) / AAC_PAGE_SIZE;
+ if (sc->flags & AAC_FLAGS_BROKEN_MEMMAP) {
+ ip->HostPhysMemPages =
+ (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE;
+ }
ip->HostElapsedSeconds = time_second; /* 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
* adapter, which is only told about the base of the queue index fields.
*
* The initial values of the indices are assumed to inform the adapter
- * of the sizes of the respective queues, and theoretically it could
+ * of the sizes of the respective queues, and theoretically it could
* work out the entire layout of the queue structures from this. We
* take the easy route and just lay this area out like everyone else
* does.
*
- * The Linux driver uses a much more complex scheme whereby several
- * header records are kept for each queue. We use a couple of generic
+ * The Linux driver uses a much more complex scheme whereby several
+ * header records are kept for each queue. We use a couple of generic
* list manipulation functions which 'know' the size of each list by
* virtue of a table.
*/
- qaddr = &sc->aac_common->ac_qbuf[0] + AAC_QUEUE_ALIGN;
- qaddr -= (u_int32_t)qaddr % AAC_QUEUE_ALIGN;
- sc->aac_queues = (struct aac_queue_table *)qaddr;
- ip->CommHeaderAddress = sc->aac_common_busaddr +
- ((u_int32_t)sc->aac_queues -
- (u_int32_t)sc->aac_common);
- bzero(sc->aac_queues, sizeof(struct aac_queue_table));
+ qoffset = offsetof(struct aac_common, ac_qbuf) + AAC_QUEUE_ALIGN;
+ qoffset &= ~(AAC_QUEUE_ALIGN - 1);
+ sc->aac_queues =
+ (struct aac_queue_table *)((uintptr_t)sc->aac_common + qoffset);
+ ip->CommHeaderAddress = sc->aac_common_busaddr + qoffset;
sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX] =
AAC_HOST_NORM_CMD_ENTRIES;
@@ -1628,12 +2064,17 @@ aac_init(struct aac_softc *sc)
case AAC_HWIF_I960RX:
AAC_SETREG4(sc, AAC_RX_ODBR, ~0);
break;
+ case AAC_HWIF_RKT:
+ AAC_SETREG4(sc, AAC_RKT_ODBR, ~0);
+ break;
+ default:
+ break;
}
/*
* Give the init structure to the controller.
*/
- if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
+ if (aac_sync_command(sc, AAC_MONKER_INITSTRUCT,
sc->aac_common_busaddr +
offsetof(struct aac_common, ac_init), 0, 0, 0,
NULL)) {
@@ -1650,6 +2091,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,
@@ -1686,46 +2128,18 @@ aac_sync_command(struct aac_softc *sc, u_int32_t command,
status = AAC_GET_MAILBOX(sc, 0);
if (sp != NULL)
*sp = status;
- return(0);
-}
-
-/*
- * Grab the sync fib area.
- */
-int
-aac_alloc_sync_fib(struct aac_softc *sc, struct aac_fib **fib, int flags)
-{
-
- /*
- * If the force flag is set, the system is shutting down, or in
- * trouble. Ignore the mutex.
- */
- if (!(flags & AAC_SYNC_LOCK_FORCE))
- AAC_LOCK_ACQUIRE(&sc->aac_sync_lock);
-
- *fib = &sc->aac_common->ac_sync_fib;
-
- return (1);
-}
-
-/*
- * Release the sync fib area.
- */
-void
-aac_release_sync_fib(struct aac_softc *sc)
-{
- AAC_LOCK_RELEASE(&sc->aac_sync_lock);
+ if (status != AAC_SRB_STS_SUCCESS)
+ return (-1);
+ return(0);
}
-/*
- * Send a synchronous FIB to the controller and wait for a result.
- */
int
-aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
+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);
+ KKASSERT(lockstatus(&sc->aac_io_lock, curthread) != 0);
if (datasize > AAC_FIB_DATASIZE)
return(EINVAL);
@@ -1741,7 +2155,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
fib->Header.StructType = AAC_FIBTYPE_TFIB;
fib->Header.Size = sizeof(struct aac_fib) + datasize;
fib->Header.SenderSize = sizeof(struct aac_fib);
- fib->Header.SenderFibAddress = (u_int32_t)fib;
+ fib->Header.SenderFibAddress = 0; /* Not needed */
fib->Header.ReceiverFibAddress = sc->aac_common_busaddr +
offsetof(struct aac_common,
ac_sync_fib);
@@ -1797,11 +2211,9 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
debug_called(3);
- fib_size = cm->cm_fib->Header.Size;
+ fib_size = cm->cm_fib->Header.Size;
fib_addr = cm->cm_fib->Header.ReceiverFibAddress;
- crit_enter();
-
/* 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];
@@ -1837,7 +2249,6 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
error = 0;
out:
- crit_exit();
return(error);
}
@@ -1850,13 +2261,12 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
struct aac_fib **fib_addr)
{
u_int32_t pi, ci;
+ u_int32_t fib_index;
int error;
int notify;
debug_called(3);
- crit_enter();
-
/* 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];
@@ -1881,18 +2291,52 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
/* fetch the entry */
*fib_size = (sc->aac_qentries[queue] + ci)->aq_fib_size;
- *fib_addr = (struct aac_fib *)(sc->aac_qentries[queue] +
- ci)->aq_fib_addr;
- /*
- * Is this a fast response? If it is, update the fib fields in
- * local memory so the whole fib doesn't have to be DMA'd back up.
- */
- if (*(uintptr_t *)fib_addr & 0x01) {
- *(uintptr_t *)fib_addr &= ~0x01;
- (*fib_addr)->Header.XferState |= AAC_FIBSTATE_DONEADAP;
- *((u_int32_t*)((*fib_addr)->data)) = AAC_ERROR_NORMAL;
+ switch (queue) {
+ case AAC_HOST_NORM_CMD_QUEUE:
+ case AAC_HOST_HIGH_CMD_QUEUE:
+ /*
+ * The aq_fib_addr is only 32 bits wide so it can't be counted
+ * on to hold an address. For AIF's, the adapter assumes
+ * that it's giving us an address into the array of AIF fibs.
+ * Therefore, we have to convert it to an index.
+ */
+ fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr /
+ sizeof(struct aac_fib);
+ *fib_addr = &sc->aac_common->ac_fibs[fib_index];
+ break;
+
+ case AAC_HOST_NORM_RESP_QUEUE:
+ case AAC_HOST_HIGH_RESP_QUEUE:
+ {
+ struct aac_command *cm;
+
+ /*
+ * As above, an index is used instead of an actual address.
+ * Gotta shift the index to account for the fast response
+ * bit. No other correction is needed since this value was
+ * originally provided by the driver via the SenderFibAddress
+ * field.
+ */
+ fib_index = (sc->aac_qentries[queue] + ci)->aq_fib_addr;
+ cm = sc->aac_commands + (fib_index >> 2);
+ *fib_addr = cm->cm_fib;
+
+ /*
+ * Is this a fast response? If it is, update the fib fields in
+ * local memory since the whole fib isn't DMA'd back up.
+ */
+ if (fib_index & 0x01) {
+ (*fib_addr)->Header.XferState |= AAC_FIBSTATE_DONEADAP;
+ *((u_int32_t*)((*fib_addr)->data)) = AAC_ERROR_NORMAL;
+ }
+ break;
+ }
+ default:
+ panic("Invalid queue in aac_dequeue_fib()");
+ break;
}
+
/* update consumer index */
sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX] = ci + 1;
@@ -1902,7 +2346,6 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
error = 0;
out:
- crit_exit();
return(error);
}
@@ -1920,12 +2363,10 @@ aac_enqueue_response(struct aac_softc *sc, int queu debug_called(1);
/* Tell the adapter where the FIB is */
- fib_size = fib->Header.Size;
+ fib_size = fib->Header.Size;
fib_addr = fib->Header.SenderFibAddress;
fib->Header.ReceiverFibAddress = fib_addr;
- crit_enter();
-
/* 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];
@@ -1954,7 +2395,6 @@ aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
error = 0;
out:
- crit_exit();
return(error);
}
@@ -1969,29 +2409,12 @@ aac_timeout(void *xsc)
struct aac_command *cm;
time_t deadline;
int timedout, code;
-#if 0
- /* simulate an interrupt to handle possibly-missed interrupts */
- /*
- * XXX This was done to work around another bug which has since been
- * fixed. It is dangerous anyways because you don't want multiple
- * threads in the interrupt handler at the same time! If calling
- * is deamed neccesary in the future, proper mutexes must be used.
- */
- crit_enter();
- aac_intr(sc);
- crit_exit();
-
- /* 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
+ * Traverse the busy command list, bitch about late commands once
* only.
*/
timedout = 0;
deadline = time_second - AAC_CMD_TIMEOUT;
- crit_enter();
TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) {
if ((cm->cm_timestamp < deadline)
/* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) {
@@ -2011,11 +2434,6 @@ aac_timeout(void *xsc)
}
}
- crit_exit();
-
- /* reset the timer for next time */
- callout_reset(&sc->aac_watchdog, AAC_PERIODIC_INTERVAL * hz,
- aac_timeout, sc);
}
/*
@@ -2052,6 +2470,14 @@ aac_fa_get_fwstatus(struct aac_softc *sc)
return (val);
}
+static int
+aac_rkt_get_fwstatus(struct aac_softc *sc)
+{
+ debug_called(3);
+
+ return(AAC_GETREG4(sc, AAC_RKT_FWSTATUS));
+}
+
/*
* Notify the controller of a change in a given queue
*/
@@ -2081,6 +2507,14 @@ aac_fa_qnotify(struct aac_softc *sc, int qbit)
AAC_FA_HACK(sc);
}
+static void
+aac_rkt_qnotify(struct aac_softc *sc, int qbit)
+{
+ debug_called(3);
+
+ AAC_SETREG4(sc, AAC_RKT_IDBR, qbit);
+}
+
/*
* Get the interrupt reason bits
*/
@@ -2111,6 +2545,14 @@ aac_fa_get_istatus(struct aac_softc *sc)
return (val);
}
+static int
+aac_rkt_get_istatus(struct aac_softc *sc)
+{
+ debug_called(3);
+
+ return(AAC_GETREG4(sc, AAC_RKT_ODBR));
+}
+
/*
* Clear some interrupt reason bits
*/
@@ -2139,6 +2581,14 @@ aac_fa_clear_istatus(struct aac_softc *sc, int mask)
AAC_FA_HACK(sc);
}
+static void
+aac_rkt_clear_istatus(struct aac_softc *sc, int mask)
+{
+ debug_called(3);
+
+ AAC_SETREG4(sc, AAC_RKT_ODBR, mask);
+}
+
/*
* Populate the mailbox and set the command word
*/
@@ -2186,6 +2636,19 @@ aac_fa_set_mailbox(struct aac_softc *sc, u_int32_t command,
AAC_FA_HACK(sc);
}
+static void
+aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0,
+ u_int32_t arg1, u_int32_t arg2, u_int32_t arg3)
+{
+ debug_called(4);
+
+ AAC_SETREG4(sc, AAC_RKT_MAILBOX, command);
+ AAC_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0);
+ AAC_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1);
+ AAC_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2);
+ AAC_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3);
+}
+
/*
* Fetch the immediate command status word
*/
@@ -2216,6 +2679,14 @@ aac_fa_get_mailbox(struct aac_softc *sc, int mb)
return (val);
}
+static int
+aac_rkt_get_mailbox(struct aac_softc *sc, int mb)
+{
+ debug_called(4);
+
+ return(AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4)));
+}
+
/*
* Set/clear interrupt masks
*/
@@ -2237,7 +2708,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);
}
@@ -2257,6 +2731,105 @@ aac_fa_set_interrupts(struct aac_softc *sc, int enable)
}
}
+static void
+aac_rkt_set_interrupts(struct aac_softc *sc, int enable)
+{
+ debug(2, "%sable interrupts", enable ? "en" : "dis");
+
+ if (enable) {
+ 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
*/
@@ -2272,34 +2845,45 @@ aac_describe_controller(struct aac_softc *sc)
debug_called(2);
- aac_alloc_sync_fib(sc, &fib, 0);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ aac_alloc_sync_fib(sc, &fib);
fib->data[0] = 0;
if (aac_sync_fib(sc, RequestAdapterInfo, 0, fib, 1)) {
device_printf(sc->aac_dev, "RequestAdapterInfo failed\n");
aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
return;
}
- info = (struct aac_adapter_info *)&fib->data[0];
-
- device_printf(sc->aac_dev, "%s %dMHz, %dMB cache memory, %s\n",
- aac_describe_code(aac_cpu_variant, info->CpuVariant),
- info->ClockSpeed, info->BufferMem / (1024 * 1024),
- aac_describe_code(aac_battery_platform,
- info->batteryPlatform));
/* save the kernel revision structure for later use */
+ info = (struct aac_adapter_info *)&fib->data[0];
sc->aac_revision = info->KernelRevision;
- 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->KernelRevision.buildNumber,
- (u_int32_t)(info->SerialNumber & 0xffffff));
- aac_release_sync_fib(sc);
+ 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",
+ aac_describe_code(aac_cpu_variant, info->CpuVariant),
+ info->ClockSpeed, info->TotalMem / (1024 * 1024),
+ info->BufferMem / (1024 * 1024),
+ info->ExecutionMem / (1024 * 1024),
+ aac_describe_code(aac_battery_platform,
+ info->batteryPlatform));
+
+ 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->KernelRevision.buildNumber,
+ (u_int32_t)(info->SerialNumber & 0xffffff));
- if (1 || bootverbose) {
device_printf(sc->aac_dev, "Supported Options=%b\n",
sc->supported_options,
"\20"
@@ -2315,8 +2899,16 @@ aac_describe_controller(struct aac_softc *sc)
"\12NORECOND"
"\13SGMAP64"
"\14ALARM"
- "\15NONDASD");
+ "\15NONDASD"
+ "\16SCSIMGT"
+ "\17RAIDSCSI"
+ "\21ADPTINFO"
+ "\22NEWCOMM"
+ "\23ARRAY64BIT"
+ "\24HEATSENSOR");
}
+ aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
}
/*
@@ -2380,7 +2972,7 @@ aac_ioctl(struct dev_ioctl_args *ap)
caddr_t arg = ap->a_data;
struct aac_softc *sc = dev->si_drv1;
int error = 0;
- int i;
+ uint32_t cookie;
debug_called(2);
@@ -2426,11 +3018,11 @@ aac_ioctl(struct dev_ioctl_args *ap)
*
* 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
+ * 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 = (int)sc->aifthread;
- error = copyout(&i, arg, sizeof(i));
+ cookie = (uint32_t)(uintptr_t)sc->aifthread;
+ error = copyout(&cookie, arg, sizeof(cookie));
break;
case FSACTL_GET_NEXT_ADAPTER_FIB:
debug(1, "FSACTL_GET_NEXT_ADAPTER_FIB");
@@ -2447,15 +3039,21 @@ aac_ioctl(struct dev_ioctl_args *ap)
case FSACTL_QUERY_DISK:
debug(1, "FSACTL_QUERY_DISK");
error = aac_query_disk(sc, arg);
- break;
+ break;
case FSACTL_DELETE_DISK:
/*
* We don't trust the underland to tell us when to delete a
- * container, rather we rely on an AIF coming from the
+ * container, rather we rely on an AIF coming from the
* controller
*/
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", ap->a_cmd);
error = EINVAL;
@@ -2489,6 +3087,27 @@ aac_poll(struct dev_poll_args *ap)
return (0);
}
+static void
+aac_ioctl_event(struct aac_softc *sc, struct aac_event *event, void *arg)
+{
+
+ switch (event->ev_type) {
+ case AAC_EVENT_CMFREE:
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ if (aac_alloc_command(sc, (struct aac_command **)arg)) {
+ aac_add_event(sc, event);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+ return;
+ }
+ kfree(event, M_AACBUF);
+ wakeup(arg);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+ break;
+ default:
+ break;
+ }
+}
+
/*
* Send a FIB supplied from userspace
*/
@@ -2505,10 +3124,24 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib)
/*
* Get a command
*/
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
if (aac_alloc_command(sc, &cm)) {
- error = EBUSY;
- goto out;
+ struct aac_event *event;
+
+ event = kmalloc(sizeof(struct aac_event), M_AACBUF,
+ M_INTWAIT | M_ZERO);
+ event->ev_type = AAC_EVENT_CMFREE;
+ event->ev_callback = aac_ioctl_event;
+ event->ev_arg = &cm;
+ aac_add_event(sc, event);
+ crit_enter();
+ tsleep_interlock(&cm);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+ tsleep(&cm, 0, "sendfib", 0);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ crit_exit();
}
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
/*
* Fetch the FIB header, then re-copy to get data as well.
@@ -2518,7 +3151,7 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib)
goto out;
size = cm->cm_fib->Header.Size + sizeof(struct aac_fib_header);
if (size > sizeof(struct aac_fib)) {
- device_printf(sc->aac_dev, "incoming FIB oversized (%d > %d)\n",
+ device_printf(sc->aac_dev, "incoming FIB oversized (%d > %zd)\n",
size, sizeof(struct aac_fib));
size = sizeof(struct aac_fib);
}
@@ -2530,26 +3163,32 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib)
/*
* Pass the FIB to the controller, wait for it to complete.
*/
- if ((error = aac_wait_command(cm, 30)) != 0) { /* XXX user timeout? */
- kprintf("aac_wait_command return %d\n", error);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ if ((error = aac_wait_command(cm)) != 0) {
+ device_printf(sc->aac_dev,
+ "aac_wait_command return %d\n", error);
goto out;
}
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
/*
* Copy the FIB and data back out to the caller.
*/
size = cm->cm_fib->Header.Size;
if (size > sizeof(struct aac_fib)) {
- device_printf(sc->aac_dev, "outbound FIB oversized (%d > %d)\n",
+ device_printf(sc->aac_dev, "outbound FIB oversized (%d > %zd)\n",
size, sizeof(struct aac_fib));
size = sizeof(struct aac_fib);
}
error = copyout(cm->cm_fib, ufib, size);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
out:
if (cm != NULL) {
aac_release_command(cm);
}
+
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
return(error);
}
@@ -2580,11 +3219,11 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
case AifEnAddContainer:
case AifEnDeleteContainer:
/*
- * A container was added or deleted, but the message
+ * A container was added or deleted, but the message
* doesn't tell us anything else! Re-enumerate the
* containers and sort things out.
*/
- aac_alloc_sync_fib(sc, &fib, 0);
+ aac_alloc_sync_fib(sc, &fib);
mi = (struct aac_mntinfo *)&fib->data[0];
do {
/*
@@ -2619,7 +3258,7 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
(mir->MntTable[0].VolType != CT_NONE)) {
found = 0;
TAILQ_FOREACH(co,
- &sc->aac_container_tqh,
+ &sc->aac_container_tqh,
co_link) {
if (co->co_mntobj.ObjectId ==
mir->MntTable[0].ObjectId) {
@@ -2639,7 +3278,8 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
/*
* This is a new container. Do all the
- * appropriate things to set it up. */
+ * appropriate things to set it up.
+ */
aac_add_container(sc, mir, 1);
added = 1;
}
@@ -2657,8 +3297,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) {
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+ get_mplock();
device_delete_child(sc->aac_dev,
co->co_disk);
+ rel_mplock();
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
co_next = TAILQ_NEXT(co, co_link);
AAC_LOCK_ACQUIRE(&sc->
aac_container_lock);
@@ -2666,7 +3310,7 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
co_link);
AAC_LOCK_RELEASE(&sc->
aac_container_lock);
- FREE(co, M_AACBUF);
+ kfree(co, M_AACBUF);
co = co_next;
} else {
co->co_found = 0;
@@ -2675,10 +3319,15 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
}
/* Attach the newly created containers */
- if (added)
+ if (added) {
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+ get_mplock();
bus_generic_attach(sc->aac_dev);
-
- break;
+ rel_mplock();
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ }
+
+ break;
default:
break;
@@ -2763,11 +3412,10 @@ aac_getnext_aif(struct aac_softc *sc, caddr_t arg)
/*
* Check the magic number that we gave the caller.
*/
- if (agf.AdapterFibContext != (int)sc->aifthread) {
+ if (agf.AdapterFibContext != (int)(uintptr_t)sc->aifthread) {
error = EFAULT;
} else {
- crit_enter();
error = aac_return_aif(sc, agf.AifFib);
if ((error == EAGAIN) && (agf.Wait)) {
@@ -2781,7 +3429,6 @@ aac_getnext_aif(struct aac_softc *sc, caddr_t arg)
}
sc->aac_state &= ~AAC_STATE_AIF_SLEEPER;
}
- crit_exit();
}
}
return(error);
@@ -2795,26 +3442,49 @@ aac_getnext_aif(struct aac_softc *sc, caddr_t arg)
static int
aac_return_aif(struct aac_softc *sc, caddr_t uptr)
{
- int error;
+ int next, error;
debug_called(2);
AAC_LOCK_ACQUIRE(&sc->aac_aifq_lock);
if (sc->aac_aifq_tail == sc->aac_aifq_head) {
- error = EAGAIN;
- } else {
- error = copyout(&sc->aac_aifq[sc->aac_aifq_tail], uptr,
- sizeof(struct aac_aif_command));
- if (error)
- kprintf("aac_return_aif: copyout returned %d\n", error);
- if (!error)
- sc->aac_aifq_tail = (sc->aac_aifq_tail + 1) %
- AAC_AIFQ_LENGTH;
+ AAC_LOCK_RELEASE(&sc->aac_aifq_lock);
+ return (EAGAIN);
}
+
+ next = (sc->aac_aifq_tail + 1) % AAC_AIFQ_LENGTH;
+ error = copyout(&sc->aac_aifq[next], uptr,
+ sizeof(struct aac_aif_command));
+ if (error)
+ device_printf(sc->aac_dev,
+ "aac_return_aif: copyout returned %d\n", error);
+ else
+ sc->aac_aifq_tail = next;
+
AAC_LOCK_RELEASE(&sc->aac_aifq_lock);
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
@@ -2847,23 +3517,23 @@ aac_query_disk(struct aac_softc *sc, caddr_t uptr)
break;
}
- if (co == NULL) {
+ 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 = device_get_unit(sc->aac_dev);
- 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);
- }
+ } 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 = device_get_unit(sc->aac_dev);
+ 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,
@@ -2881,11 +3551,12 @@ aac_get_bus_info(struct aac_softc *sc)
struct aac_vmioctl *vmi;
struct aac_vmi_businf_resp *vmi_resp;
struct aac_getbusinf businfo;
- struct aac_cam_inf *caminf;
+ struct aac_sim *caminf;
device_t child;
int i, found, error;
- aac_alloc_sync_fib(sc, &fib, 0);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ aac_alloc_sync_fib(sc, &fib);
c_cmd = (struct aac_ctcfg *)&fib->data[0];
bzero(c_cmd, sizeof(struct aac_ctcfg));
@@ -2899,6 +3570,7 @@ aac_get_bus_info(struct aac_softc *sc)
device_printf(sc->aac_dev, "Error %d sending "
"VM_ContainerConfig command\n", error);
aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
return;
}
@@ -2907,6 +3579,7 @@ aac_get_bus_info(struct aac_softc *sc)
device_printf(sc->aac_dev, "VM_ContainerConfig returned 0x%x\n",
c_resp->Status);
aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
return;
}
@@ -2927,6 +3600,7 @@ aac_get_bus_info(struct aac_softc *sc)
device_printf(sc->aac_dev, "Error %d sending VMIoctl command\n",
error);
aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
return;
}
@@ -2934,33 +3608,40 @@ aac_get_bus_info(struct aac_softc *sc)
if (vmi_resp->Status != ST_OK) {
debug(1, "VM_Ioctl returned %d\n", vmi_resp->Status);
aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
return;
}
bcopy(&vmi_resp->BusInf, &businfo, sizeof(struct aac_getbusinf));
aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
found = 0;
for (i = 0; i < businfo.BusCount; i++) {
if (businfo.BusValid[i] != AAC_BUS_VALID)
continue;
- MALLOC(caminf, struct aac_cam_inf *,
- sizeof(struct aac_cam_inf), M_AACBUF, M_INTWAIT | M_ZERO);
+ caminf = (struct aac_sim *)kmalloc(sizeof(struct aac_sim),
+ M_AACBUF, M_INTWAIT | M_ZERO);
child = device_add_child(sc->aac_dev, "aacp", -1);
if (child == NULL) {
- device_printf(sc->aac_dev, "device_add_child failed\n");
- continue;
- }
+ device_printf(sc->aac_dev,
+ "device_add_child failed for passthrough bus %d\n",
+ i);
+ kfree(caminf, M_AACBUF);
+ break;
+ };
caminf->TargetsPerBus = businfo.TargetsPerBus;
caminf->BusNumber = i;
caminf->InitiatorBusId = businfo.InitiatorBusId[i];
caminf->aac_sc = sc;
+ caminf->sim_dev = child;
device_set_ivars(child, caminf);
device_set_desc(child, "SCSI Passthrough Bus");
+ TAILQ_INSERT_TAIL(&sc->aac_sim_tqh, caminf, sim_link);
found = 1;
}
diff --git a/sys/dev/raid/aac/aac_cam.c b/sys/dev/raid/aac/aac_cam.c
index 1f8496f..6e2d1d2 100644
--- a/sys/dev/raid/aac/aac_cam.c
+++ b/sys/dev/raid/aac/aac_cam.c
@@ -1,4 +1,4 @@
-/*
+/*-
* Copyright (c) 2002 Adaptec, Inc.
* All rights reserved.
*
@@ -38,6 +38,7 @@
#include <sys/kernel.h>
#include <sys/sysctl.h>
#include <sys/malloc.h>
+#include <sys/module.h>
#include <bus/cam/cam.h>
#include <bus/cam/cam_ccb.h>
@@ -47,7 +48,6 @@
#include <bus/cam/scsi/scsi_all.h>
#include <bus/cam/scsi/scsi_message.h>
-#include "aac_compat.h"
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/devicestat.h>
@@ -62,11 +62,10 @@
#include "aacreg.h"
#include "aac_ioctl.h"
#include "aacvar.h"
-#include "aac_cam.h"
struct aac_cam {
device_t dev;
- struct aac_cam_inf *inf;
+ struct aac_sim *inf;
struct cam_sim *sim;
struct cam_path *path;
};
@@ -80,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;
@@ -102,10 +100,29 @@ 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;
+ kfree(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)
{
-
debug_called(2);
return (0);
@@ -114,6 +131,19 @@ aac_cam_probe(device_t dev)
static int
aac_cam_detach(device_t dev)
{
+ struct aac_cam *camsc;
+ debug_called(2);
+
+ camsc = (struct aac_cam *)device_get_softc(dev);
+
+ get_mplock();
+
+ xpt_async(AC_LOST_DEVICE, camsc->path, NULL);
+ xpt_free_path(camsc->path);
+ xpt_bus_deregister(cam_sim_path(camsc->sim));
+ cam_sim_free(camsc->sim);
+
+ rel_mplock();
return (0);
}
@@ -128,12 +158,12 @@ aac_cam_attach(device_t dev)
struct cam_sim *sim;
struct cam_path *path;
struct aac_cam *camsc;
- struct aac_cam_inf *inf;
+ struct aac_sim *inf;
debug_called(1);
camsc = (struct aac_cam *)device_get_softc(dev);
- inf = (struct aac_cam_inf *)device_get_ivars(dev);
+ inf = (struct aac_sim *)device_get_ivars(dev);
camsc->inf = inf;
devq = cam_simq_alloc(inf->TargetsPerBus);
@@ -220,6 +250,8 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb)
cpi->version_num = 1;
cpi->hba_inquiry = PI_WIDE_16;
cpi->target_sprt = 0;
+
+ /* Resetting via the passthrough causes problems. */
cpi->hba_misc = PIM_NOBUSRESET;
cpi->hba_eng_cnt = 0;
cpi->max_target = camsc->inf->TargetsPerBus;
@@ -243,12 +275,26 @@ 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);
+#ifdef CAM_NEW_TRAN_CODE
+ struct ccb_trans_settings_scsi *scsi =
+ &ccb->cts.proto_specific.scsi;
+ struct ccb_trans_settings_spi *spi =
+ &ccb->cts.xport_specific.spi;
+ ccb->cts.protocol = PROTO_SCSI;
+ ccb->cts.protocol_version = SCSI_REV_2;
+ ccb->cts.transport = XPORT_SPI;
+ ccb->cts.transport_version = 2;
+ if (ccb->ccb_h.target_lun != CAM_LUN_WILDCARD) {
+ scsi->valid = CTS_SCSI_VALID_TQ;
+ spi->valid |= CTS_SPI_VALID_DISC;
+ } else {
+ scsi->valid = 0;
+ }
+#else
+ ccb->cts.flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
+ ccb->cts.valid = CCB_TRANS_DISC_VALID | CCB_TRANS_TQ_VALID;
+#endif
+ ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
return;
}
@@ -282,10 +328,20 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb)
/* Async ops that require communcation with the controller */
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
if (aac_alloc_command(sc, &cm)) {
+ struct aac_event *event;
+
xpt_freeze_simq(sim, 1);
ccb->ccb_h.status = CAM_REQUEUE_REQ;
xpt_done(ccb);
+ event = kmalloc(sizeof(struct aac_event), M_AACCAM,
+ M_INTWAIT | M_ZERO);
+ event->ev_callback = aac_cam_event;
+ event->ev_arg = camsc;
+ event->ev_type = AAC_EVENT_CMFREE;
+ aac_add_event(sc, event);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
return;
}
@@ -335,9 +391,14 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb)
if ((ccb->ccb_h.flags & CAM_SCATTER_VALID) == 0) {
srb->data_len = csio->dxfer_len;
if (ccb->ccb_h.flags & CAM_DATA_PHYS) {
+ /*
+ * XXX This isn't 64-bit clean.
+ * However, this condition is not
+ * normally used in CAM.
+ */
srb->sg_map32.SgCount = 1;
srb->sg_map32.SgEntry[0].SgAddress =
- (u_int32_t)csio->data_ptr;
+ (uint32_t)(uintptr_t)csio->data_ptr;
srb->sg_map32.SgEntry[0].SgByteCount =
csio->dxfer_len;
} else {
@@ -368,6 +429,7 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb)
} else {
ccb->ccb_h.status = CAM_REQ_CMP;
xpt_done(ccb);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
return;
}
default:
@@ -398,6 +460,8 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb)
aac_enqueue_ready(cm);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
+
return;
}
@@ -452,7 +516,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 */
@@ -478,7 +542,6 @@ aac_cam_complete(struct aac_command *cm)
}
aac_release_command(cm);
-
xpt_done(ccb);
return;
@@ -502,7 +565,8 @@ aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb)
return (CAM_REQ_ABORTED);
}
- aac_alloc_sync_fib(sc, &fib, 0);
+ AAC_LOCK_ACQUIRE(&sc->aac_io_lock);
+ aac_alloc_sync_fib(sc, &fib);
vmi = (struct aac_vmioctl *)&fib->data[0];
bzero(vmi, sizeof(struct aac_vmioctl));
@@ -519,13 +583,15 @@ aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb)
e = aac_sync_fib(sc, ContainerCommand, 0, fib,
sizeof(struct aac_vmioctl));
if (e) {
- device_printf(sc->aac_dev, "Error 0x%x sending passthrough\n",
+ device_printf(sc->aac_dev,"Error %d sending ResetBus command\n",
e);
aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
return (CAM_REQ_ABORTED);
}
aac_release_sync_fib(sc);
+ AAC_LOCK_RELEASE(&sc->aac_io_lock);
return (CAM_REQ_CMP);
}
@@ -540,57 +606,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, 0);
- 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 VMIoctl 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) {
- debug(1, "VM_Ioctl returned %d\n", vmi_resp->Status);
- aac_release_sync_fib(sc);
- return (CAM_REQ_CMP_ERR);
- }
-
- cts->bus_width = ((vmi_resp->Inquiry7 & 0x60) >> 5);
- if (vmi_resp->ScsiRate) {
- cts->sync_period =
- scsi_calc_syncparam((10000 / vmi_resp->ScsiRate));
- cts->sync_offset = vmi_resp->ScsiOffset;
- } else {
- cts->sync_period = 0;
- cts->sync_offset = 0;
- }
- cts->flags &= ~(CCB_TRANS_DISC_ENB | CCB_TRANS_TAG_ENB);
- cts->valid = CCB_TRANS_DISC_VALID |
- CCB_TRANS_SYNC_RATE_VALID |
- CCB_TRANS_SYNC_OFFSET_VALID |
- CCB_TRANS_BUS_WIDTH_VALID |
- CCB_TRANS_TQ_VALID;
-
- aac_release_sync_fib(sc);
- return (CAM_REQ_CMP);
-}
diff --git a/sys/dev/raid/aac/aac_cam.h b/sys/dev/raid/aac/aac_cam.h
deleted file mode 100644
index 1110d78..0000000
--- a/sys/dev/raid/aac/aac_cam.h
+++ /dev/null
@@ -1,35 +0,0 @@
-/*
- * Copyright (c) 2002 Adaptec, Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD: src/sys/dev/aac/aac_cam.h,v 1.1.2.1 2002/04/30 22:58:37 scottl Exp $
- * $DragonFly: src/sys/dev/raid/aac/aac_cam.h,v 1.2 2003/06/17 04:28:21 dillon Exp $
- */
-
-struct aac_cam_inf {
- int TargetsPerBus;
- int BusNumber;
- int InitiatorBusId;
- struct aac_softc *aac_sc;
-};
diff --git a/sys/dev/raid/aac/aac_compat.h b/sys/dev/raid/aac/aac_compat.h
deleted file mode 100644
index 6dfe1a7..0000000
--- a/sys/dev/raid/aac/aac_compat.h
+++ /dev/null
@@ -1,42 +0,0 @@
-/*-
- * Copyright (c) 2000 Michael Smith
- * Copyright (c) 2000 BSDi
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- *
- * $FreeBSD: src/sys/dev/aac/aac_compat.h,v 1.2.2.2 2001/09/19 19:09:11 scottl Exp $
- * $DragonFly: src/sys/dev/raid/aac/aac_compat.h,v 1.8 2006/04/30 17:22:16 dillon Exp $
- */
-/*
- * Backwards compatibility support.
- */
-
-/*
- * Handle the new/old bio/buf changeover
- */
-
-#ifdef __DragonFly__
-#include <sys/proc.h>
-#include <sys/buf.h>
-#include <sys/buf2.h>
-#endif
diff --git a/sys/dev/raid/aac/aac_debug.c b/sys/dev/raid/aac/aac_debug.c
index 3ba1a2e..b2c8ddf 100644
--- a/sys/dev/raid/aac/aac_debug.c
+++ b/sys/dev/raid/aac/aac_debug.c
@@ -39,7 +39,6 @@
#include <sys/systm.h>
#include <sys/kernel.h>
-#include "aac_compat.h"
#include <sys/bus.h>
#include <sys/devicestat.h>
#include <sys/disk.h>
@@ -345,10 +344,10 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif)
break;
case AifEnDiskSetEvent: /* A disk set event occured. */
device_printf(sc->aac_dev, "(DiskSetEvent) event %d "
- "diskset %lld creator %lld\n",
+ "diskset %jd creator %jd\n",
aif->data.EN.data.EDS.eventType,
- aif->data.EN.data.EDS.DsNum,
- aif->data.EN.data.EDS.CreatorId);
+ (intmax_t)aif->data.EN.data.EDS.DsNum,
+ (intmax_t)aif->data.EN.data.EDS.CreatorId);
break;
case AifDenMorphComplete: /* A morph operation
* completed */
diff --git a/sys/dev/raid/aac/aac_disk.c b/sys/dev/raid/aac/aac_disk.c
index 8987a3a..bf00ec6 100644
--- a/sys/dev/raid/aac/aac_disk.c
+++ b/sys/dev/raid/aac/aac_disk.c
@@ -35,9 +35,9 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/module.h>
#include <sys/sysctl.h>
-#include "aac_compat.h"
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/devicestat.h>
@@ -204,10 +204,13 @@ aac_disk_strategy(struct dev_strategy_args *ap)
}
/* perform accounting */
- devstat_start_transaction(&sc->ad_stats);
/* pass the bio to the controller - it can work out who we are */
+ AAC_LOCK_ACQUIRE(&sc->ad_controller->aac_io_lock);
+ devstat_start_transaction(&sc->ad_stats);
aac_submit_bio(sc, bio);
+ AAC_LOCK_RELEASE(&sc->ad_controller->aac_io_lock);
+
return(0);
}
diff --git a/sys/dev/raid/aac/aac_linux.c b/sys/dev/raid/aac/aac_linux.c
index 71fc5d0..e2694f1 100644
--- a/sys/dev/raid/aac/aac_linux.c
+++ b/sys/dev/raid/aac/aac_linux.c
@@ -34,6 +34,7 @@
#include <sys/systm.h>
#include <sys/conf.h>
#include <sys/kernel.h>
+#include <sys/module.h>
#include <sys/file.h>
#include <sys/ioccom.h>
#include <sys/mapped_ioctl.h>
diff --git a/sys/dev/raid/aac/aac_pci.c b/sys/dev/raid/aac/aac_pci.c
index eebfe7d..7f7cfe6 100644
--- a/sys/dev/raid/aac/aac_pci.c
+++ b/sys/dev/raid/aac/aac_pci.c
@@ -39,8 +39,8 @@
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
+#include <sys/module.h>
-#include "aac_compat.h"
#include <sys/bus.h>
#include <sys/conf.h>
#include <sys/devicestat.h>
@@ -110,8 +110,8 @@ static struct aac_ident
"Dell PERC 3/Di"},
{0x1011, 0x0046, 0x9005, 0x0364, AAC_HWIF_STRONGARM, 0,
"Adaptec AAC-364"},
- {0x1011, 0x0046, 0x9005, 0x0365, AAC_HWIF_STRONGARM, 0,
- "Adaptec SCSI RAID 5400S"},
+ {0x1011, 0x0046, 0x9005, 0x0365, AAC_HWIF_STRONGARM,
+ AAC_FLAGS_BROKEN_MEMMAP, "Adaptec SCSI RAID 5400S"},
{0x1011, 0x0046, 0x9005, 0x1364, AAC_HWIF_STRONGARM, AAC_FLAGS_PERC2QC,
"Dell PERC 2/QC"},
{0x1011, 0x0046, 0x103c, 0x10c2, AAC_HWIF_STRONGARM, 0,
@@ -123,35 +123,110 @@ static struct aac_ident
{0x9005, 0x0285, 0x9005, 0x0286, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB,
"Adaptec SCSI RAID 2120S"},
{0x9005, 0x0285, 0x9005, 0x0290, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB,
- "Adaptec SCSI RAID 2410SA"},
+ "Adaptec SATA RAID 2410SA"},
{0x9005, 0x0285, 0x1028, 0x0291, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB,
"Dell CERC SATA RAID 2"},
{0x9005, 0x0285, 0x9005, 0x0292, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB,
- "Adaptec SCSI RAID 2810SA"},
+ "Adaptec SATA RAID 2810SA"},
+ {0x9005, 0x0285, 0x9005, 0x0293, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB,
+ "Adaptec SATA RAID 21610SA"},
+ {0x9005, 0x0285, 0x103c, 0x3227, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB,
+ "HP ML110 G2 (Adaptec 2610SA)"},
+ {0x9005, 0x0286, 0x9005, 0x028c, AAC_HWIF_RKT, 0,
+ "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,
+ "ICP ICP9024RO SCSI RAID"},
+ {0x9005, 0x0286, 0x9005, 0x029f, AAC_HWIF_RKT, 0,
+ "ICP ICP9014RO SCSI 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 ICP9085LI SAS RAID"},
+ {0x9005, 0x0285, 0x9005, 0x02a5, AAC_HWIF_I960RX, 0,
+ "ICP ICP5085BR SAS RAID"},
+ {0x9005, 0x0286, 0x9005, 0x02a0, AAC_HWIF_RKT, 0,
+ "ICP ICP9047MA SATA RAID"},
+ {0x9005, 0x0286, 0x9005, 0x02a1, AAC_HWIF_RKT, 0,
+ "ICP ICP9087MA SATA RAID"},
+ {0x9005, 0x0285, 0x9005, 0x02bb, AAC_HWIF_I960RX, 0,
+ "Adaptec RAID 3405"},
+ {0x9005, 0x0285, 0x9005, 0x02bc, AAC_HWIF_I960RX, 0,
+ "Adaptec RAID 3805"},
+ {0x9005, 0x0286, 0x1014, 0x9580, AAC_HWIF_RKT, 0,
+ "IBM ServeRAID-8k"},
{0, 0, 0, 0, 0, 0, 0}
};
+static struct aac_ident *
+aac_find_ident(device_t dev)
+{
+ struct aac_ident *m;
+
+ for (m = aac_identifiers; m->vendor != 0; m++) {
+ if ((m->vendor == pci_get_vendor(dev)) &&
+ (m->device == pci_get_device(dev)) &&
+ (m->subvendor == pci_get_subvendor(dev)) &&
+ (m->subdevice == pci_get_subdevice(dev)))
+ return (m);
+ }
+
+ return (NULL);
+}
+
/*
* Determine whether this is one of our supported adapters.
*/
static int
aac_pci_probe(device_t dev)
{
- struct aac_ident *m;
+ struct aac_ident *id;
debug_called(1);
- for (m = aac_identifiers; m->vendor != 0; m++) {
- if ((m->vendor == pci_get_vendor(dev)) &&
- (m->device == pci_get_device(dev)) &&
- ((m->subvendor == 0) || (m->subvendor ==
- pci_get_subvendor(dev))) &&
- ((m->subdevice == 0) || ((m->subdevice ==
- pci_get_subdevice(dev))))) {
-
- device_set_desc(dev, m->desc);
- return(-10); /* allow room to be overridden */
- }
+ if ((id = aac_find_ident(dev)) != NULL) {
+ device_set_desc(dev, id->desc);
+ return(BUS_PROBE_DEFAULT);
}
return(ENXIO);
}
@@ -163,7 +238,8 @@ static int
aac_pci_attach(device_t dev)
{
struct aac_softc *sc;
- int i, error;
+ struct aac_ident *id;
+ int error;
u_int32_t command;
debug_called(1);
@@ -197,12 +273,12 @@ aac_pci_attach(device_t dev)
/*
* Allocate the PCI register window.
*/
- sc->aac_regs_rid = 0x10; /* first base address register */
- if ((sc->aac_regs_resource = bus_alloc_resource(sc->aac_dev,
- SYS_RES_MEMORY,
- &sc->aac_regs_rid,
- 0, ~0, 1,
- RF_ACTIVE)) == NULL) {
+ sc->aac_regs_rid = PCIR_BAR(0);
+ if ((sc->aac_regs_resource = bus_alloc_resource_any(sc->aac_dev,
+ SYS_RES_MEMORY,
+ &sc->aac_regs_rid,
+ RF_ACTIVE)) ==
+ NULL) {
device_printf(sc->aac_dev,
"couldn't allocate register window\n");
goto out;
@@ -210,23 +286,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(sc->aac_dev, SYS_RES_IRQ,
- &sc->aac_irq_rid, 0, ~0, 1,
- 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, 0,
- aac_intr, sc, &sc->aac_intr, NULL)) {
- device_printf(sc->aac_dev, "can't set up interrupt\n");
- goto out;
- }
-
/* assume failure is 'out of memory' */
error = ENOMEM;
@@ -237,11 +296,11 @@ aac_pci_attach(device_t dev)
*/
if (bus_dma_tag_create(NULL, /* parent */
PAGE_SIZE, 0, /* algnmnt, boundary */
- BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
+ BUS_SPACE_MAXADDR, /* lowaddr */
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 */
&sc->aac_parent_dmat)) {
@@ -253,49 +312,103 @@ aac_pci_attach(device_t dev)
* Detect the hardware interface version, set up the bus interface
* indirection.
*/
- sc->aac_hwif = AAC_HWIF_UNKNOWN;
- for (i = 0; aac_identifiers[i].vendor != 0; i++) {
- if ((aac_identifiers[i].vendor == pci_get_vendor(dev)) &&
- (aac_identifiers[i].device == pci_get_device(dev)) &&
- (aac_identifiers[i].subvendor == pci_get_subvendor(dev)) &&
- (aac_identifiers[i].subdevice == pci_get_subdevice(dev))) {
- sc->aac_hwif = aac_identifiers[i].hwif;
- switch(sc->aac_hwif) {
- case AAC_HWIF_I960RX:
- debug(2, "set hardware up for i960Rx");
- sc->aac_if = aac_rx_interface;
- break;
-
- case AAC_HWIF_STRONGARM:
- debug(2, "set hardware up for StrongARM");
- sc->aac_if = aac_sa_interface;
- break;
- case AAC_HWIF_FALCON:
- debug(2, "set hardware up for Falcon/PPC");
- sc->aac_if = aac_fa_interface;
- break;
- }
-
- /* Set up quirks */
- sc->flags = aac_identifiers[i].quirks;
-
- break;
- }
- }
- if (sc->aac_hwif == AAC_HWIF_UNKNOWN) {
+ id = aac_find_ident(dev);
+ sc->aac_hwif = id->hwif;
+ switch(sc->aac_hwif) {
+ case AAC_HWIF_I960RX:
+ debug(2, "set hardware up for i960Rx");
+ sc->aac_if = aac_rx_interface;
+ break;
+ case AAC_HWIF_STRONGARM:
+ debug(2, "set hardware up for StrongARM");
+ sc->aac_if = aac_sa_interface;
+ break;
+ case AAC_HWIF_FALCON:
+ debug(2, "set hardware up for Falcon/PPC");
+ sc->aac_if = aac_fa_interface;
+ break;
+ case AAC_HWIF_RKT:
+ debug(2, "set hardware up for Rocket/MIPS");
+ sc->aac_if = aac_rkt_interface;
+ break;
+ default:
+ sc->aac_hwif = AAC_HWIF_UNKNOWN;
device_printf(sc->aac_dev, "unknown hardware type\n");
error = ENXIO;
goto out;
}
+ /* Set up quirks */
+ sc->flags = id->quirks;
/*
* Do bus-independent initialisation.
*/
error = aac_attach(sc);
-
+
out:
if (error)
aac_free(sc);
return(error);
}
+
+/*
+ * Do nothing driver that will attach to the SCSI channels of a Dell PERC
+ * controller. This is needed to keep the power management subsystem from
+ * trying to power down these devices.
+ */
+static int aacch_probe(device_t dev);
+static int aacch_attach(device_t dev);
+static int aacch_detach(device_t dev);
+
+static device_method_t aacch_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, aacch_probe),
+ DEVMETHOD(device_attach, aacch_attach),
+ DEVMETHOD(device_detach, aacch_detach),
+ { 0, 0 }
+};
+
+struct aacch_softc {
+ device_t dev;
+};
+
+static driver_t aacch_driver = {
+ "aacch",
+ aacch_methods,
+ sizeof(struct aacch_softc)
+};
+
+static devclass_t aacch_devclass;
+DRIVER_MODULE(aacch, pci, aacch_driver, aacch_devclass, 0, 0);
+
+static int
+aacch_probe(device_t dev)
+{
+
+ if ((pci_get_vendor(dev) != 0x9005) ||
+ (pci_get_device(dev) != 0x00c5))
+ return (ENXIO);
+
+ device_set_desc(dev, "AAC RAID Channel");
+ return (-10);
+}
+
+static int
+aacch_attach(device_t dev)
+{
+ struct aacch_softc *sc;
+
+ sc = device_get_softc(dev);
+
+ sc->dev = dev;
+
+ return (0);
+}
+
+static int
+aacch_detach(device_t dev)
+{
+
+ return (0);
+}
diff --git a/sys/dev/raid/aac/aac_tables.h b/sys/dev/raid/aac/aac_tables.h
index c2e8ca0..42974fa 100644
--- a/sys/dev/raid/aac/aac_tables.h
+++ b/sys/dev/raid/aac/aac_tables.h
@@ -41,7 +41,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},
@@ -67,7 +67,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}
@@ -80,8 +80,12 @@ 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},
{NULL, 0},
@@ -113,6 +117,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/raid/aac/aacreg.h b/sys/dev/raid/aac/aacreg.h
index de02783..bd5a648 100644
--- a/sys/dev/raid/aac/aacreg.h
+++ b/sys/dev/raid/aac/aacreg.h
@@ -201,12 +201,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,
@@ -215,7 +220,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;
/*
@@ -271,6 +290,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;
@@ -285,6 +305,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 */
} __attribute__ ((packed));
typedef u_int32_t aac_phys_addr_t;
@@ -311,6 +337,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;
/*
@@ -344,6 +375,19 @@ struct aac_sg_entry {
u_int32_t SgByteCount;
} __attribute__ ((packed));
+struct aac_sg_entry64 {
+ u_int64_t SgAddress;
+ 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];
@@ -353,13 +397,19 @@ struct aac_sg_table {
* Host-side scatter/gather list for 64-bit commands.
*/
struct aac_sg_table64 {
- u_int8_t SgCount;
- u_int8_t SgSectorsPerPage;
- u_int16_t SgByteOffset;
- u_int64_t SgEntry[0];
+ u_int32_t SgCount;
+ struct aac_sg_entry64 SgEntry64[0];
} __attribute__ ((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 +467,8 @@ typedef enum {
CPU_ALPHA,
CPU_P7,
CPU_I960_RX,
+ CPU_MIPS,
+ CPU_XSCALE,
CPU__last
} AAC_CpuType;
@@ -427,8 +479,12 @@ typedef enum {
CPUI960_RX,
CPUARM_SA110,
CPUARM_xxx,
- CPUMPC_824x,
+ CPUPPC_603e,
CPUPPC_xxx,
+ CPUI960_80303,
+ CPU_XSCALE_80321,
+ CPU_MIPS_4KC,
+ CPU_MIPS_5KC,
CPUSUBTYPE__last
} AAC_CpuSubType;
@@ -453,6 +509,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;
@@ -462,9 +532,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;
@@ -498,6 +573,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.
@@ -533,10 +614,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
@@ -551,6 +638,7 @@ struct aac_adapter_info {
* state of the adapter.
*/
#define AAC_SELF_TEST_FAILED 0x00000004
+#define AAC_MONITOR_PANIC 0x00000020
#define AAC_UP_AND_RUNNING 0x00000080
#define AAC_KERNEL_PANIC 0x00000100
@@ -656,6 +744,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 */
@@ -669,6 +758,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 */
@@ -851,9 +946,10 @@ struct aac_aif_command {
u_int32_t seqNumber; /* To allow ordering of
* reports (if necessary) */
union {
- struct aac_AifEventNotify EN; /* Event notify structure */
- struct aac_AifJobProgressReport PR[1]; /* Progress report */
- u_int8_t AR[AAC_AIF_REPORT_MAX_SIZE];
+ struct aac_AifEventNotify EN; /* Event notify */
+ struct aac_AifJobProgressReport PR[1]; /* Progress report */
+ u_int8_t AR[AAC_AIF_REPORT_MAX_SIZE];
+ u_int8_t data[AAC_FIB_DATASIZE - 8];
} data;
} __attribute__ ((packed));
@@ -972,6 +1068,10 @@ typedef enum _VM_COMMANDS {
VM_CtBlockRead64,
VM_CtBlockWrite64,
VM_CtBlockVerify64,
+ VM_CtHostRead64,
+ VM_CtHostWrite64,
+ VM_DrvErrTblLog, /* drive error table/log type of command */
+ VM_NameServe64
} AAC_VMCommand;
/*
@@ -1066,8 +1166,15 @@ struct aac_vmi_businf_resp {
struct aac_getbusinf BusInf;
} __attribute__ ((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 {
@@ -1145,6 +1252,16 @@ struct aac_blockread {
struct aac_sg_table SgMap; /* variable size */
} __attribute__ ((packed));
+struct aac_blockread64 {
+ u_int32_t Command;
+ u_int16_t ContainerId;
+ u_int16_t SectorCount;
+ u_int32_t BlockNumber;
+ u_int16_t Pad;
+ u_int16_t Flags;
+ struct aac_sg_table64 SgMap64;
+} __packed;
+
struct aac_blockread_response {
u_int32_t Status;
u_int32_t ByteCount;
@@ -1159,12 +1276,32 @@ struct aac_blockwrite {
struct aac_sg_table SgMap; /* variable size */
} __attribute__ ((packed));
+struct aac_blockwrite64 {
+ u_int32_t Command; /* not FSACommand! */
+ u_int16_t ContainerId;
+ u_int16_t SectorCount;
+ u_int32_t BlockNumber;
+ u_int16_t Pad;
+ u_int16_t Flags;
+ struct aac_sg_table64 SgMap64; /* variable size */
+} __packed;
+
struct aac_blockwrite_response {
u_int32_t Status;
u_int32_t ByteCount;
} __attribute__ ((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.
*/
@@ -1231,6 +1368,11 @@ struct aac_srb_response {
u_int8_t sense[AAC_HOST_SENSE_DATA_MAX];
};
+/*
+ * Status codes for SCSI passthrough commands. Since they are based on ASPI,
+ * they also exactly match CAM status codes in both enumeration and meaning.
+ * They seem to also be used as status codes for synchronous FIBs.
+ */
enum {
AAC_SRB_STS_PENDING = 0x00,
AAC_SRB_STS_SUCCESS,
@@ -1309,11 +1451,30 @@ 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
/*
+ * Register definitions for the Adaptec 'Rocket' RAID-On-Chip adapters.
+ * Unsurprisingly, it's quite similar to the i960!
+ */
+
+#define AAC_RKT_IDBR 0x20 /* inbound doorbell register */
+#define AAC_RKT_IISR 0x24 /* inbound interrupt status register */
+#define AAC_RKT_IIMR 0x28 /* inbound interrupt mask register */
+#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) */
+
+/*
* Common bit definitions for the doorbell registers.
*/
@@ -1343,3 +1504,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/raid/aac/aacvar.h b/sys/dev/raid/aac/aacvar.h
index 3d3cb7b..b15a50c 100644
--- a/sys/dev/raid/aac/aacvar.h
+++ b/sys/dev/raid/aac/aacvar.h
@@ -30,6 +30,12 @@
* $DragonFly: src/sys/dev/raid/aac/aacvar.h,v 1.19 2007/11/10 19:50:29 swildner Exp $
*/
+#include <sys/buf.h>
+#include <sys/buf2.h>
+#include <sys/eventhandler.h>
+#include <sys/lock.h>
+#include <sys/selinfo.h>
+#include <sys/taskqueue.h>
#include <sys/thread2.h>
/*
@@ -48,13 +54,11 @@
#define AAC_ADAPTER_FIBS 8
/*
- * FIBs are allocated up-front, and the pool isn't grown. We should allocate
- * enough here to let us keep the adapter busy without wasting large amounts
- * of kernel memory. The current interface implementation limits us to 512
- * FIBs queued for the adapter at any one time.
+ * FIBs are allocated in page-size chunks and can grow up to the 512
+ * limit imposed by the hardware.
*/
-#define AAC_FIB_COUNT 128
-
+#define AAC_PREALLOCATE_FIBS 128
+#define AAC_NUM_MGT_FIB 8
/*
* The controller reports status events in AIFs. We hang on to a number of
* these in order to pass them out to user-space management tools.
@@ -94,14 +98,6 @@
#define AAC_DISK_MAJOR 200
/*
- * Driver Variable Definitions
- */
-
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500005
-# include <sys/taskqueue.h>
-#endif
-
-/*
* Per-container data structure
*/
struct aac_container
@@ -113,6 +109,19 @@ struct aac_container
};
/*
+ * Per-SIM data structure
+ */
+struct aac_sim
+{
+ device_t sim_dev;
+ int TargetsPerBus;
+ int BusNumber;
+ int InitiatorBusId;
+ struct aac_softc *aac_sc;
+ TAILQ_ENTRY(aac_sim) sim_link;
+};
+
+/*
* Per-disk structure
*/
struct aac_disk
@@ -143,7 +152,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 buf *cm_data; /* pointer to data in kernel
* space */
u_int32_t cm_datalen; /* data length */
@@ -163,12 +172,24 @@ struct aac_command
#define AAC_ON_AACQ_READY (1<<6)
#define AAC_ON_AACQ_BUSY (1<<7)
#define AAC_ON_AACQ_COMPLETE (1<<8)
-#define AAC_ON_AACQ_MASK ((1<<5)|(1<<6)|(1<<7)|(1<<8))
+#define AAC_ON_AACQ_NORM (1<<10)
+#define AAC_ON_AACQ_AIF (1<<11)
+#define AAC_ON_AACQ_MASK ((1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<10)|(1<11))
+#define AAC_QUEUE_FRZN (1<<9) /* Freeze the processing of
+ * commands on the queue. */
void (* cm_complete)(struct aac_command *cm);
void *cm_private;
time_t cm_timestamp; /* command creation time */
int cm_queue;
+ int cm_index;
+};
+
+struct aac_fibmap {
+ TAILQ_ENTRY(aac_fibmap) fm_link; /* list linkage */
+ struct aac_fib *aac_fibs;
+ bus_dmamap_t aac_fibmap;
+ struct aac_command *aac_commands;
};
/*
@@ -216,10 +237,14 @@ 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;
extern struct aac_interface aac_fa_interface;
+extern struct aac_interface aac_rkt_interface;
#define AAC_GET_FWSTATUS(sc) ((sc)->aac_if.aif_get_fwstatus((sc)))
#define AAC_QNOTIFY(sc, qbit) ((sc)->aac_if.aif_qnotify((sc), (qbit)))
@@ -235,6 +260,9 @@ extern struct aac_interface aac_fa_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)
@@ -249,24 +277,11 @@ extern struct aac_interface aac_fa_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 defined(__FreeBSD__) && __FreeBSD_version >= 500005
-#include <sys/lock.h>
-#include <sys/mutex.h>
-typedef struct mtx aac_lock_t;
-#define AAC_LOCK_INIT(l, s) mtx_init(l, s, MTX_DEF)
-#define AAC_LOCK_ACQUIRE(l) mtx_lock(l)
-#define AAC_LOCK_RELEASE(l) mtx_unlock(l)
-#else
typedef struct lock aac_lock_t;
-#define AAC_LOCK_INIT(l, s) lockinit(l, "aac", 0, 0)
-#define AAC_LOCK_ACQUIRE(l) lockmgr(l, LK_EXCLUSIVE|LK_RETRY)
+#define AAC_LOCK_INIT(l, s) lockinit(l, s, 0, LK_EXCLUSIVE|LK_CANRECURSE)
+#define AAC_LOCK_ACQUIRE(l) lockmgr(l, LK_EXCLUSIVE)
#define AAC_LOCK_RELEASE(l) lockmgr(l, LK_RELEASE)
-#endif
-
-#include <sys/selinfo.h>
/*
* Per-controller structure.
@@ -287,6 +302,7 @@ struct aac_softc
struct resource *aac_irq; /* interrupt */
int aac_irq_rid;
void *aac_intr; /* interrupt handle */
+ eventhandler_tag eh;
/* controller features, limits and status */
int aac_state;
@@ -300,7 +316,8 @@ struct aac_softc
int aac_hwif;
#define AAC_HWIF_I960RX 0
#define AAC_HWIF_STRONGARM 1
-#define AAC_HWIF_FALCON 2
+#define AAC_HWIF_FALCON 2
+#define AAC_HWIF_RKT 3
#define AAC_HWIF_UNKNOWN -1
bus_dma_tag_t aac_common_dmat; /* common structure
* DMA tag */
@@ -312,10 +329,9 @@ struct aac_softc
/* command/fib resources */
bus_dma_tag_t aac_fib_dmat; /* DMA tag for allocing FIBs */
- struct aac_fib *aac_fibs;
- bus_dmamap_t aac_fibmap;
- u_int32_t aac_fibphys;
- struct aac_command aac_command[AAC_FIB_COUNT];
+ TAILQ_HEAD(,aac_fibmap) aac_fibmap_tqh;
+ u_int total_fibs;
+ struct aac_command *aac_commands;
/* command management */
TAILQ_HEAD(,aac_command) aac_free; /* command structures
@@ -325,6 +341,11 @@ struct aac_softc
TAILQ_HEAD(,aac_command) aac_busy;
TAILQ_HEAD(,aac_command) aac_complete; /* commands which have been
* returned by the controller */
+ 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];
@@ -332,18 +353,18 @@ struct aac_softc
struct aac_qstat aac_qstat[AACQ_COUNT]; /* queue statistics */
/* connected containters */
- struct aac_container_tq aac_container_tqh;
+ TAILQ_HEAD(,aac_container) aac_container_tqh;
aac_lock_t aac_container_lock;
- /* Protect the sync fib */
-#define AAC_SYNC_LOCK_FORCE (1 << 0)
- aac_lock_t aac_sync_lock;
+ /*
+ * The general I/O lock. This protects the sync fib, the lists, the
+ * queues, and the registers.
+ */
+ aac_lock_t aac_io_lock;
/* delayed activity infrastructure */
-#if defined(__FreeBSD__) && __FreeBSD_version >= 500005
struct task aac_task_complete; /* deferred-completion
* task */
-#endif
struct intr_config_hook aac_ich;
/* management interface */
@@ -356,23 +377,61 @@ struct aac_softc
struct thread *aifthread;
int aifflags;
#define AAC_AIFFLAGS_RUNNING (1 << 0)
-#define AAC_AIFFLAGS_PENDING (1 << 1)
+#define AAC_AIFFLAGS_AIF (1 << 1)
#define AAC_AIFFLAGS_EXIT (1 << 2)
#define AAC_AIFFLAGS_EXITED (1 << 3)
+#define AAC_AIFFLAGS_PRINTF (1 << 4)
+#define AAC_AIFFLAGS_ALLOCFIBS (1 << 5)
+#define AAC_AIFFLAGS_PENDING (AAC_AIFFLAGS_AIF | AAC_AIFFLAGS_PRINTF | \
+ AAC_AIFFLAGS_ALLOCFIBS)
u_int32_t flags;
#define AAC_FLAGS_PERC2QC (1 << 0)
#define AAC_FLAGS_ENABLE_CAM (1 << 1) /* No SCSI passthrough */
#define AAC_FLAGS_CAM_NORESET (1 << 2) /* Fake SCSI resets */
#define AAC_FLAGS_CAM_PASSONLY (1 << 3) /* Only create pass devices */
+#define AAC_FLAGS_SG_64BIT (1 << 4) /* Use 64-bit S/G addresses */
#define AAC_FLAGS_4GB_WINDOW (1 << 5) /* Device can access host mem
* 2GB-4GB range */
#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;
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;
};
+#ifndef AAC_DRIVER_BUILD
+# define AAC_DRIVER_BUILD 1
+#endif
/*
* Public functions
@@ -382,7 +441,8 @@ extern int aac_attach(struct aac_softc *sc);
extern int aac_detach(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 devclass_t aac_devclass;
extern void aac_submit_bio(struct aac_disk *ad, struct bio *bio);
extern void aac_biodone(struct bio *bio, const char *code);
@@ -393,12 +453,11 @@ extern void aac_startio(struct aac_softc *sc);
extern int aac_alloc_command(struct aac_softc *sc,
struct aac_command **cmp);
extern void aac_release_command(struct aac_command *cm);
-extern int aac_alloc_sync_fib(struct aac_softc *sc,
- struct aac_fib **fib, int flags);
-extern void aac_release_sync_fib(struct aac_softc *sc);
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:
@@ -468,7 +527,6 @@ aac_initq_ ## name (struct aac_softc *sc) \
static __inline void \
aac_enqueue_ ## name (struct aac_command *cm) \
{ \
- crit_enter(); \
if ((cm->cm_flags & AAC_ON_AACQ_MASK) != 0) { \
kprintf("command %p is on another queue, flags = %#x\n", \
cm, cm->cm_flags); \
@@ -477,12 +535,10 @@ aac_enqueue_ ## name (struct aac_command *cm) \
TAILQ_INSERT_TAIL(&cm->cm_sc->aac_ ## name, cm, cm_link); \
cm->cm_flags |= AAC_ON_ ## index; \
AACQ_ADD(cm->cm_sc, index); \
- crit_exit(); \
} \
static __inline void \
aac_requeue_ ## name (struct aac_command *cm) \
{ \
- crit_enter(); \
if ((cm->cm_flags & AAC_ON_AACQ_MASK) != 0) { \
kprintf("command %p is on another queue, flags = %#x\n", \
cm, cm->cm_flags); \
@@ -491,14 +547,12 @@ aac_requeue_ ## name (struct aac_command *cm) \
TAILQ_INSERT_HEAD(&cm->cm_sc->aac_ ## name, cm, cm_link); \
cm->cm_flags |= AAC_ON_ ## index; \
AACQ_ADD(cm->cm_sc, index); \
- crit_exit(); \
} \
static __inline struct aac_command * \
aac_dequeue_ ## name (struct aac_softc *sc) \
{ \
struct aac_command *cm; \
\
- crit_enter(); \
if ((cm = TAILQ_FIRST(&sc->aac_ ## name)) != NULL) { \
if ((cm->cm_flags & AAC_ON_ ## index) == 0) { \
kprintf("command %p not in queue, flags = %#x, " \
@@ -510,13 +564,11 @@ aac_dequeue_ ## name (struct aac_softc *sc) \
cm->cm_flags &= ~AAC_ON_ ## index; \
AACQ_REMOVE(sc, index); \
} \
- crit_exit(); \
return(cm); \
} \
static __inline void \
aac_remove_ ## name (struct aac_command *cm) \
{ \
- crit_enter(); \
if ((cm->cm_flags & AAC_ON_ ## index) == 0) { \
kprintf("command %p not in queue, flags = %#x, " \
"bit = %#x\n", cm, cm->cm_flags, \
@@ -526,7 +578,6 @@ aac_remove_ ## name (struct aac_command *cm) \
TAILQ_REMOVE(&cm->cm_sc->aac_ ## name, cm, cm_link); \
cm->cm_flags &= ~AAC_ON_ ## index; \
AACQ_REMOVE(cm->cm_sc, index); \
- crit_exit(); \
} \
struct hack
@@ -548,10 +599,8 @@ aac_initq_bio(struct aac_softc *sc)
static __inline void
aac_enqueue_bio(struct aac_softc *sc, struct bio *bio)
{
- crit_enter();
bioq_insert_tail(&sc->aac_bioq, bio);
AACQ_ADD(sc, AACQ_BIO);
- crit_exit();
}
static __inline struct bio *
@@ -559,12 +608,10 @@ aac_dequeue_bio(struct aac_softc *sc)
{
struct bio *bio;
- crit_enter();
if ((bio = bioq_first(&sc->aac_bioq)) != NULL) {
bioq_remove(&sc->aac_bioq, bio);
AACQ_REMOVE(sc, AACQ_BIO);
}
- crit_exit();
return(bio);
}
@@ -577,5 +624,23 @@ aac_print_printf(struct aac_softc *sc)
*/
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);
}
+
+static __inline int
+aac_alloc_sync_fib(struct aac_softc *sc, struct aac_fib **fib)
+{
+
+ KKASSERT(lockstatus(&sc->aac_io_lock, curthread) != 0);
+ *fib = &sc->aac_common->ac_sync_fib;
+ return (0);
+}
+
+static __inline void
+aac_release_sync_fib(struct aac_softc *sc)
+{
+
+ KKASSERT(lockstatus(&sc->aac_io_lock, curthread) != 0);
+}
+
Attachment:
pgp00001.pgp
-------------- next part --------------
A non-text attachment was scrubbed...
Name: pgp00001.pgp
Type: application/octet-stream
Size: 189 bytes
Desc: "Description: PGP signature"
URL: <http://lists.dragonflybsd.org/pipermail/submit/attachments/20080113/c4fc692f/attachment-0018.obj>
More information about the Submit
mailing list