Mega update to the aac driver.

1.  Correctly handle commands initiated by the adapter.  These commands
    are defered to a kthread responsible for their processing, then are
    properly returned to the controller.
2.  Add/remove disk devices when notified by the card that a container was
    created/deleted/offline.
3.  Implement crashdump functionality.
4.  Support all ioctls needed for the management CLI to work.  The linux
    version of this app can be found at the Dell or HP website.  A native
    version will be forthcoming.

MFC-after:	4.4-RELEASE
This commit is contained in:
Scott Long 2001-08-29 23:34:05 +00:00
parent 719077d1be
commit 36e0bf6e9c
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=82527
9 changed files with 719 additions and 129 deletions

View File

@ -48,7 +48,7 @@ Supported controllers include:
.It
AAC-364
.It
AAC-3642
Adaptec SCSI RAID 5400S
.It
HP NetRAID 4M
.It
@ -86,12 +86,6 @@ Compiling the driver with the
option enables the Linux-compatible
.Xr ioctl 2
interface for the management device.
The
.Xr ioctl 2
command set is heavily tailored to existing Linux applications.
Native
.Xr ioctl 2
support is not present at this time.
.Ss Tuning
The read-only sysctl
.Va hw.aac.iosize_max
@ -148,13 +142,9 @@ and is
.An Scott Long
.Aq scottl@FreeBSD.org
.Sh BUGS
This driver has not been tested on Alpha, though it should work.
This driver will not work on systems with more than 4GB of memory.
.Pp
The controller is not actually paused on suspend/resume.
.Pp
Adapter-initiated messages are not returned back to the controller,
possibly causing a resource leak on the controller.
.Pp
Unloading and reloading the driver as a kernel loadable module
without rebooting the system is strongly discouraged.
Unloading driver is not supported at this time.
.Pp

View File

@ -35,11 +35,12 @@
#include "opt_aac.h"
/* include <stddef.h> */
/* #include <stddef.h> */
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/malloc.h>
#include <sys/kernel.h>
#include <sys/kthread.h>
#include <sys/sysctl.h>
#include <dev/aac/aac_compat.h>
@ -51,6 +52,7 @@
#include <sys/file.h>
#include <sys/signalvar.h>
#include <sys/time.h>
#include <sys/eventhandler.h>
#include <machine/bus_memio.h>
#include <machine/bus.h>
@ -101,7 +103,10 @@ static int aac_sync_fib(struct aac_softc *sc, u_int32_t command,
static int aac_enqueue_fib(struct aac_softc *sc, int queue,
struct aac_command *cm);
static int aac_dequeue_fib(struct aac_softc *sc, int queue,
u_int32_t *fib_size, struct aac_fib **fib_addr);
u_int32_t *fib_size,
struct aac_fib **fib_addr);
static int aac_enqueue_response(struct aac_softc *sc, int queue,
struct aac_fib *fib);
/* StrongARM interface */
static int aac_sa_get_fwstatus(struct aac_softc *sc);
@ -147,7 +152,7 @@ struct aac_interface aac_rx_interface = {
/* Debugging and Diagnostics */
static void aac_describe_controller(struct aac_softc *sc);
static char *aac_describe_code(struct aac_code_lookup *table,
static char *aac_describe_code(struct aac_code_lookup *table
u_int32_t code);
/* Management Interface */
@ -156,10 +161,11 @@ static d_close_t aac_close;
static d_ioctl_t aac_ioctl;
static int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib);
static void aac_handle_aif(struct aac_softc *sc,
struct aac_aif_command *aif);
struct aac_fib *fib);
static int aac_rev_check(struct aac_softc *sc, caddr_t udata);
static int aac_getnext_aif(struct aac_softc *sc, caddr_t arg);
static int aac_return_aif(struct aac_softc *sc, caddr_t uptr);
static int aac_query_disk(struct aac_softc *sc, caddr_t uptr);
#define AAC_CDEV_MAJOR 150
@ -177,8 +183,13 @@ static struct cdevsw aac_cdevsw = {
nodump, /* dump */
nopsize, /* psize */
0, /* flags */
#if __FreeBSD_version < 500005
-1, /* bmaj */
#endif
};
MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for the AAC driver");
/* sysctl node */
SYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters");
@ -240,6 +251,9 @@ aac_attach(struct aac_softc *sc)
/*
* Register to probe our containers later.
*/
TAILQ_INIT(&sc->aac_container_tqh);
AAC_LOCK_INIT(&sc->aac_container_lock);
sc->aac_ich.ich_func = aac_startup;
sc->aac_ich.ich_arg = sc;
if (config_intrhook_establish(&sc->aac_ich) != 0) {
@ -253,11 +267,27 @@ aac_attach(struct aac_softc *sc)
unit = device_get_unit(sc->aac_dev);
sc->aac_dev_t = make_dev(&aac_cdevsw, unit, UID_ROOT, GID_WHEEL, 0644,
"aac%d", unit);
#if __FreeBSD_version > 500005
(void)make_dev_alias(sc->aac_dev_t, "afa%d", unit);
(void)make_dev_alias(sc->aac_dev_t, "hpn%d", unit);
#endif
sc->aac_dev_t->si_drv1 = sc;
/* Create the AIF thread */
#if __FreeBSD_version > 500005
if (kthread_create((void(*)(void *))aac_host_command, sc, &sc->aifthread,
0, "aac%daif", unit))
#else
if (kthread_create((void(*)(void *))aac_host_command, sc, &sc->aifthread,
"aac%daif", unit))
#endif
panic("Could not create AIF thread\n");
/* Register the shutdown method to only be called post-dump */
if ((EVENTHANDLER_REGISTER(shutdown_final, aac_shutdown, sc->aac_dev,
SHUTDOWN_PRI_DEFAULT)) == NULL)
device_printf(sc->aac_dev, "shutdown event registration failed\n");
return(0);
}
@ -270,9 +300,10 @@ aac_startup(void *arg)
struct aac_softc *sc = (struct aac_softc *)arg;
struct aac_mntinfo mi;
struct aac_mntinforesponse mir;
struct aac_container *co;
device_t child;
u_int16_t rsize;
int i;
int i = 0;
debug_called(1);
@ -282,7 +313,7 @@ aac_startup(void *arg)
/* loop over possible containers */
mi.Command = VM_NameServe;
mi.MntType = FT_FILESYS;
for (i = 0; i < AAC_MAX_CONTAINERS; i++) {
do {
/* request information on this container */
mi.MntCount = i;
rsize = sizeof(mir);
@ -302,6 +333,9 @@ aac_startup(void *arg)
* possible types may never show up.
*/
if ((mir.Status == ST_OK) && (mir.MntTable[0].VolType != CT_NONE)) {
MALLOC(co, struct aac_container *, sizeof *co, M_AACBUF, M_NOWAIT);
if (co == NULL)
panic("Out of memory?!\n");
debug(1, "%d: id %x name '%.16s' size %u type %d",
i, mir.MntTable[0].ObjectId,
mir.MntTable[0].FileSystemName, mir.MntTable[0].Capacity,
@ -310,14 +344,17 @@ aac_startup(void *arg)
if ((child = device_add_child(sc->aac_dev, NULL, -1)) == NULL) {
device_printf(sc->aac_dev, "device_add_child failed\n");
} else {
device_set_ivars(child, &sc->aac_container[i]);
device_set_ivars(child, co);
}
device_set_desc(child, aac_describe_code(aac_container_types,
mir.MntTable[0].VolType));
sc->aac_container[i].co_disk = child;
sc->aac_container[i].co_mntobj = mir.MntTable[0];
co->co_disk = child;
co->co_found = 0;
bcopy(&mir.MntTable[0], &co->co_mntobj, sizeof(struct aac_mntobj));
TAILQ_INSERT_TAIL(&sc->aac_container_tqh, co, co_link);
}
}
i++;
} while ((i < mir.MntRespCount) && (i < AAC_MAX_CONTAINERS));
/* poke the bus to actually attach the child devices */
if (bus_generic_attach(sc->aac_dev))
@ -390,19 +427,34 @@ int
aac_detach(device_t dev)
{
struct aac_softc *sc = device_get_softc(dev);
#if AAC_BROKEN
int error;
#endif
debug_called(1);
if (sc->aac_state & AAC_STATE_OPEN)
return(EBUSY);
#if AAC_BROKEN
if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
sc->aifflags |= AAC_AIFFLAGS_EXIT;
wakeup(sc->aifthread);
tsleep(sc->aac_dev, PUSER | PCATCH, "aacdch", 30 * hz);
}
if (sc->aifflags & AAC_AIFFLAGS_RUNNING)
panic("Cannot shutdown AIF thread\n");
if ((error = aac_shutdown(dev)))
return(error);
aac_free(sc);
return(0);
#else
return (EBUSY);
#endif
}
/******************************************************************************
@ -439,6 +491,12 @@ aac_shutdown(device_t dev)
printf("FAILED.\n");
} else {
i = 0;
/*
* XXX Issuing this command to the controller makes it shut down,
* but also keeps it from coming back up without a reset of the
* PCI bus. This is not desirable if you are just unloading the
* driver module with the intent to reload it later.
*/
if (aac_sync_fib(sc, FsaHostShutdown, AAC_FIBSTATE_SHUTDOWN, &i,
sizeof(i), NULL, NULL)) {
printf("FAILED.\n");
@ -486,7 +544,7 @@ aac_resume(device_t dev)
return(0);
}
/******************************************************************************
/*******************************************************************************
* Take an interrupt.
*/
void
@ -499,21 +557,24 @@ aac_intr(void *arg)
reason = AAC_GET_ISTATUS(sc);
/* controller wants to talk to the log? XXX should we defer this? */
/* controller wants to talk to the log? Defer it to the AIF thread */
if (reason & AAC_DB_PRINTF) {
if (sc->aac_common->ac_printf[0]) {
device_printf(sc->aac_dev, "** %.*s", AAC_PRINTF_BUFSIZE,
sc->aac_common->ac_printf);
sc->aac_common->ac_printf[0] = 0;
}
AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
AAC_QNOTIFY(sc, AAC_DB_PRINTF);
if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
sc->aifflags |= AAC_AIFFLAGS_PENDING;
wakeup(sc->aifthread);
} else
aac_print_printf(sc);
}
/* controller has a message for us? */
if (reason & AAC_DB_COMMAND_READY) {
AAC_CLEAR_ISTATUS(sc, AAC_DB_COMMAND_READY);
aac_host_command(sc);
/* XXX What happens if the thread is already awake? */
if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
sc->aifflags |= AAC_AIFFLAGS_PENDING;
wakeup(sc->aifthread);
}
}
/* controller has a response for us? */
@ -594,7 +655,7 @@ aac_start(struct aac_command *cm)
* address issue */
/* put the FIB on the outbound queue */
error = aac_enqueue_fib(sc, AAC_ADAP_NORM_CMD_QUEUE, cm);
error = aac_enqueue_fib(sc, cm->cm_queue, cm);
return(error);
}
@ -606,26 +667,74 @@ aac_host_command(struct aac_softc *sc)
{
struct aac_fib *fib;
u_int32_t fib_size;
int size;
debug_called(1);
debug_called(2);
for (;;) {
if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, &fib))
break; /* nothing to do */
sc->aifflags |= AAC_AIFFLAGS_RUNNING;
while(!(sc->aifflags & AAC_AIFFLAGS_EXIT)) {
if (!(sc->aifflags & AAC_AIFFLAGS_PENDING))
tsleep(sc->aifthread, PRIBIO, "aifthd", 15 * hz);
sc->aifflags &= ~AAC_AIFFLAGS_PENDING;
for (;;) {
if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, &fib_size, &fib))
break; /* nothing to do */
switch(fib->Header.Command) {
case AifRequest:
aac_handle_aif(sc, (struct aac_aif_command *)&fib->data[0]);
break;
default:
device_printf(sc->aac_dev, "unknown command from controller\n");
AAC_PRINT_FIB(sc, fib);
break;
}
/* XXX reply to FIBs requesting responses ?? */
/* XXX how do we return these FIBs to the controller? */
switch(fib->Header.Command) {
case AifRequest:
aac_handle_aif(sc, fib);
break;
default:
device_printf(sc->aac_dev, "unknown command from controller\n");
break;
}
/* Return the AIF to the controller. */
if ((fib->Header.XferState == 0) ||
(fib->Header.StructType != AAC_FIBTYPE_TFIB))
break;
if (fib->Header.XferState & AAC_FIBSTATE_FROMADAP) {
if (!(fib->Header.XferState & AAC_FIBSTATE_NORM)) {
/*
* XXX How to recover from this? If anything goes on
* the high priority queue, the controller will panic.
* Since it came on the normal priority queue, just
* punt and return it there.
*/
device_printf(sc->aac_dev, "Error: Attempted to return "
"an AIF not at normal priority\n");
}
fib->Header.XferState |= AAC_FIBSTATE_DONEHOST;
*(AAC_FSAStatus*)fib->data = ST_OK;
/* XXX Compute the Size field? */
size = fib->Header.Size;
if (size > sizeof(struct aac_fib)) {
size = sizeof(struct aac_fib);
fib->Header.Size = size;
}
/*
* Since we did not generate this command, it cannot go
* through the normal enqueue->startio chain.
*/
aac_enqueue_response(sc, AAC_ADAP_NORM_RESP_QUEUE, fib);
}
}
aac_print_printf(sc);
}
sc->aifflags &= ~AAC_AIFFLAGS_RUNNING;
wakeup(sc->aac_dev);
#if __FreeBSD_version > 500005
mtx_lock(&Giant);
#endif
kthread_exit(0);
}
/******************************************************************************
@ -739,6 +848,7 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp)
cm->cm_complete = aac_bio_complete;
cm->cm_private = bp;
cm->cm_timestamp = time_second;
cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
/* build the FIB */
fib = cm->cm_fib;
@ -819,6 +929,95 @@ aac_bio_complete(struct aac_command *cm)
aac_biodone(bp);
}
/******************************************************************************
* Dump a block of data to the controller. If the queue is full, tell the
* caller to hold off and wait for the queue to drain
*/
int
aac_dump_enqueue(struct aac_disk *ad, u_int32_t lba, void *data, int dumppages)
{
struct aac_softc *sc = ad->ad_controller;
struct aac_command *cm = NULL;
struct aac_fib *fib;
struct aac_blockwrite *bw;
if (aac_alloc_command(sc, &cm))
return (EBUSY);
/* fill out the command */
cm->cm_data = data;
cm->cm_datalen = dumppages * PAGE_SIZE;
cm->cm_complete = NULL;
cm->cm_private = NULL;
cm->cm_timestamp = time_second;
cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
/* build the FIB */
fib = cm->cm_fib;
fib->Header.XferState =
AAC_FIBSTATE_HOSTOWNED |
AAC_FIBSTATE_INITIALISED |
AAC_FIBSTATE_FROMHOST |
AAC_FIBSTATE_REXPECTED |
AAC_FIBSTATE_NORM;
fib->Header.Command = ContainerCommand;
fib->Header.Size = sizeof(struct aac_fib_header);
bw = (struct aac_blockwrite *)&fib->data[0];
bw->Command = VM_CtBlockWrite;
bw->ContainerId = ad->ad_container->co_mntobj.ObjectId;
bw->BlockNumber = lba;
bw->ByteCount = dumppages * PAGE_SIZE;
bw->Stable = CUNSTABLE; /* XXX what's appropriate here? */
fib->Header.Size += sizeof(struct aac_blockwrite);
cm->cm_flags |= AAC_CMD_DATAOUT;
cm->cm_sgtable = &bw->SgMap;
return (aac_start(cm));
}
/******************************************************************************
* Wait for the card's queue to drain when dumping. Also check for monitor
* printf's
*/
void
aac_dump_complete(struct aac_softc *sc)
{
struct aac_fib *fib;
struct aac_command *cm;
u_int16_t reason;
u_int32_t pi, ci, fib_size;
do {
reason = AAC_GET_ISTATUS(sc);
if (reason & AAC_DB_RESPONSE_READY) {
AAC_CLEAR_ISTATUS(sc, AAC_DB_RESPONSE_READY);
for (;;) {
if (aac_dequeue_fib(sc, AAC_HOST_NORM_RESP_QUEUE,
&fib_size, &fib))
break;
cm = (struct aac_command *)fib->Header.SenderData;
if (cm == NULL) {
AAC_PRINT_FIB(sc, fib);
} else {
aac_remove_busy(cm);
aac_unmap_command(cm);
aac_enqueue_complete(cm);
aac_release_command(cm);
}
}
}
if (reason & AAC_DB_PRINTF) {
AAC_CLEAR_ISTATUS(sc, AAC_DB_PRINTF);
aac_print_printf(sc);
}
pi = sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_PRODUCER_INDEX];
ci = sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][AAC_CONSUMER_INDEX];
} while (ci != pi);
return;
}
/******************************************************************************
* Submit a command to the controller, return when it completes.
*/
@ -830,11 +1029,14 @@ aac_wait_command(struct aac_command *cm, int timeout)
debug_called(2);
/* Put the command on the ready queue and get things going */
cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE;
aac_enqueue_ready(cm);
aac_startio(cm->cm_sc);
s = splbio();
while(!(cm->cm_flags & AAC_CMD_COMPLETED) && (error != EWOULDBLOCK)) {
error = tsleep(cm, PRIBIO, "aacwait", 0);
error = tsleep(cm, PRIBIO | PCATCH, "aacwait", 0);
if ((error == ERESTART) || (error == EINTR))
break;
}
splx(s);
return(error);
@ -1082,7 +1284,7 @@ aac_init(struct aac_softc *sc)
}
if (time_second > (then + AAC_BOOT_TIMEOUT)) {
device_printf(sc->aac_dev, "FATAL: controller not coming ready, "
"status %x\n", code);
"status %x\n", code);
return(ENXIO);
}
} while (!(code & AAC_UP_AND_RUNNING));
@ -1328,7 +1530,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate,
return(0);
}
/********************************************************************************
/******************************************************************************
* Adapter-space FIB queue manipulation
*
* Note that the queue implementation here is a little funky; neither the PI or
@ -1353,8 +1555,7 @@ static struct {
* EBUSY if the queue is full.
*
* Note: it would be more efficient to defer notifying the controller in
* the case where we may be inserting several entries in rapid succession,
* but implementing this usefully may be difficult (it would involve a
* the case where we may be inserting several entries in rapid succession, * but implementing this usefully may be difficult (it would involve a
* separate queue/notify interface).
*/
static int
@ -1365,11 +1566,11 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
u_int32_t fib_size;
u_int32_t fib_addr;
fib_size = cm->cm_fib->Header.Size;
fib_addr = cm->cm_fib->Header.ReceiverFibAddress;
debug_called(3);
fib_size = cm->cm_fib->Header.Size;
fib_addr = cm->cm_fib->Header.ReceiverFibAddress;
s = splbio();
/* get the producer/consumer indices */
@ -1411,8 +1612,8 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm)
}
/*
* Atomically remove one entry from the nominated queue, returns 0 on success or
* ENOENT if the queue is empty.
* Atomically remove one entry from the nominated queue, returns 0 on
* success or ENOENT if the queue is empty.
*/
static int
aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
@ -1461,6 +1662,58 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size,
return(error);
}
/******************************************************************************
* Put our response to an Adapter Initialed Fib on the response queue
*/
static int
aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib)
{
u_int32_t pi, ci;
int s, error;
u_int32_t fib_size;
u_int32_t fib_addr;
debug_called(1);
/* Tell the adapter where the FIB is */
fib_size = fib->Header.Size;
fib_addr = fib->Header.SenderFibAddress;
fib->Header.ReceiverFibAddress = fib_addr;
s = splbio();
/* get the producer/consumer indices */
pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX];
ci = sc->aac_queues->qt_qindex[queue][AAC_CONSUMER_INDEX];
/* wrap the queue? */
if (pi >= aac_qinfo[queue].size)
pi = 0;
/* check for queue full */
if ((pi + 1) == ci) {
error = EBUSY;
goto out;
}
/* populate queue entry */
(sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size;
(sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr;
/* update producer index */
sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX] = pi + 1;
/* notify the adapter if we know how */
if (aac_qinfo[queue].notify != 0)
AAC_QNOTIFY(sc, aac_qinfo[queue].notify);
error = 0;
out:
splx(s);
return(error);
}
/******************************************************************************
* Check for commands that have been outstanding for a suspiciously long time,
* and complain about them.
@ -1483,19 +1736,19 @@ aac_timeout(struct aac_softc *sc)
s = splbio();
aac_intr(sc);
splx(s);
#endif
/* kick the I/O queue to restart it in the case of deadlock */
aac_startio(sc);
#endif
/* traverse the busy command list, bitch about late commands once only */
deadline = time_second - AAC_CMD_TIMEOUT;
s = splbio();
TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) {
if ((cm->cm_timestamp < deadline)
/* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) {
if ((cm->cm_timestamp < deadline)
/* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) {
cm->cm_flags |= AAC_CMD_TIMEDOUT;
device_printf(sc->aac_dev, "COMMAND %p TIMEOUT AFTER %d SECONDS\n",
device_printf(sc->aac_dev, "COMMAND %p TIMEOUT AFTER %d SECONDS\n",
cm, (int)(time_second - cm->cm_timestamp));
AAC_PRINT_FIB(sc, cm->cm_fib);
}
@ -1699,19 +1952,19 @@ aac_describe_controller(struct aac_softc *sc)
}
info = (struct aac_adapter_info *)&buf[0];
device_printf(sc->aac_dev, "%s %dMHz, %dMB total memory, %s (%d)\n",
device_printf(sc->aac_dev, "%s %dMHz, %dMB cache memory, %s\n",
aac_describe_code(aac_cpu_variant, info->CpuVariant),
info->ClockSpeed, info->TotalMem / (1024 * 1024),
aac_describe_code(aac_battery_platform,
info->batteryPlatform), info->batteryPlatform);
info->ClockSpeed, info->BufferMem / (1024 * 1024),
aac_describe_code(aac_battery_platform, info->batteryPlatform));
/* save the kernel revision structure for later use */
sc->aac_revision = info->KernelRevision;
device_printf(sc->aac_dev, "Kernel %d.%d-%d, S/N %llx\n",
device_printf(sc->aac_dev, "Kernel %d.%d-%d, Build %d, S/N %6X\n",
info->KernelRevision.external.comp.major,
info->KernelRevision.external.comp.minor,
info->KernelRevision.external.comp.dash,
info->SerialNumber); /* XXX format? */
info->KernelRevision.buildNumber,
(u_int32_t)(info->SerialNumber & 0xffffff));
}
/******************************************************************************
@ -1792,7 +2045,7 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
break;
case FSACTL_SENDFIB:
arg = *(caddr_t *)arg;
arg = *(caddr_t*)arg;
case FSACTL_LNX_SENDFIB:
debug(1, "FSACTL_SENDFIB");
error = aac_ioctl_sendfib(sc, arg);
@ -1803,7 +2056,7 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
error = EINVAL;
break;
case FSACTL_OPEN_GET_ADAPTER_FIB:
arg = *(caddr_t *)arg;
arg = *(caddr_t*)arg;
case FSACTL_LNX_OPEN_GET_ADAPTER_FIB:
debug(1, "FSACTL_OPEN_GET_ADAPTER_FIB");
/*
@ -1815,12 +2068,14 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
*
* The Linux code hands the driver a pointer into kernel space,
* and then trusts it when the caller hands it back. Aiee!
* Here, we give it the proc pointer of the per-adapter aif thread.
* It's only used as a sanity check in other calls.
*/
i = AAC_AIF_SILLYMAGIC;
i = (int)sc->aifthread;
error = copyout(&i, arg, sizeof(i));
break;
case FSACTL_GET_NEXT_ADAPTER_FIB:
arg = *(caddr_t *)arg;
arg = *(caddr_t*)arg;
case FSACTL_LNX_GET_NEXT_ADAPTER_FIB:
debug(1, "FSACTL_GET_NEXT_ADAPTER_FIB");
error = aac_getnext_aif(sc, arg);
@ -1831,11 +2086,21 @@ aac_ioctl(dev_t dev, u_long cmd, caddr_t arg, int flag, struct proc *p)
/* don't do anything here */
break;
case FSACTL_MINIPORT_REV_CHECK:
arg = *(caddr_t *)arg;
arg = *(caddr_t*)arg;
case FSACTL_LNX_MINIPORT_REV_CHECK:
debug(1, "FSACTL_MINIPORT_REV_CHECK");
error = aac_rev_check(sc, arg);
break;
case FSACTL_QUERY_DISK:
arg = *(caddr_t*)arg;
case FSACTL_LNX_QUERY_DISK:
debug(1, "FSACTL_QUERY_DISK");
error = aac_query_disk(sc, arg);
break;
case FSACTL_DELETE_DISK:
case FSACTL_LNX_DELETE_DISK:
error = 0;
break;
default:
device_printf(sc->aac_dev, "unsupported cmd 0x%lx\n", cmd);
error = EINVAL;
@ -1907,17 +2172,140 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib)
/******************************************************************************
* Handle an AIF sent to us by the controller; queue it for later reference.
*
* XXX what's the right thing to do here when the queue is full? Drop the older
* or newer entries?
* If the queue fills up, then drop the older entries.
*/
static void
aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif)
aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib)
{
int next, s;
device_t child;
struct aac_aif_command *aif;
struct aac_container *co, *co_next;
struct aac_mntinfo mi;
struct aac_mntinforesponse mir;
u_int16_t rsize;
int next, s, found;
int added = 0, i = 0;
debug_called(2);
aif = (struct aac_aif_command*)&fib->data[0];
aac_print_aif(sc, aif);
/* Is it an event that we should care about? */
switch (aif->command) {
case AifCmdEventNotify:
switch (aif->data.EN.type) {
case AifEnAddContainer:
case AifEnDeleteContainer:
/*
* A container was added or deleted, but the message doesn't tell us
* anything else! Re-enumerate the containers and sort things out.
*/
mi.Command = VM_NameServe;
mi.MntType = FT_FILESYS;
do {
/*
* Ask the controller for its containers one at a time.
* XXX What if the controller's list changes midway through
* this enumaration?
* XXX This should be done async.
*/
mi.MntCount = i;
rsize = sizeof(mir);
if (aac_sync_fib(sc, ContainerCommand, 0, &mi, sizeof(mi),
&mir, &rsize)) {
debug(2, "Error probing container %d\n", i);
continue;
}
if (rsize != sizeof(mir)) {
debug(2, "Container response size too large\n");
continue;
}
/*
* Check the container against our list. co->co_found
* was already set to 0 in a previous run.
*/
if ((mir.Status == ST_OK) && (mir.MntTable[0].VolType !=
CT_NONE)) {
found = 0;
TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) {
if (co->co_mntobj.ObjectId ==
mir.MntTable[0].ObjectId) {
co->co_found = 1;
found = 1;
break;
}
}
/* If the container matched, continue on in the list */
if (found) {
i++;
continue;
}
/*
* This is a new container. Do all the appropriate things
* to set it up.
*/
MALLOC(co, struct aac_container *, sizeof *co, M_AACBUF,
M_WAITOK);
if ((child = device_add_child(sc->aac_dev, NULL, -1)) ==
NULL) {
device_printf(sc->aac_dev, "device_add_child failed\n");
} else {
device_set_ivars(child, co);
}
device_set_desc(child,
aac_describe_code(aac_container_types,
mir.MntTable[0].VolType));
co->co_disk = child;
co->co_found = 1;
bcopy(&mir.MntTable[0], &co->co_mntobj,
sizeof(struct aac_mntobj));
AAC_LOCK_AQUIRE(&sc->aac_container_lock);
TAILQ_INSERT_HEAD(&sc->aac_container_tqh, co, co_link);
AAC_LOCK_RELEASE(&sc->aac_container_lock);
added = 1;
}
i++;
} while ((i < mir.MntRespCount) && (i < AAC_MAX_CONTAINERS));
/*
* Go through our list of containers and see which ones were
* not marked 'found'. Since the controller didn't list them
* they must have been deleted. Do the appropriate steps to
* destroy the device. Also reset the co->co_found field.
*/
co = TAILQ_FIRST(&sc->aac_container_tqh);
while (co != NULL) {
if (co->co_found == 0) {
device_delete_child(sc->aac_dev, co->co_disk);
co_next = TAILQ_NEXT(co, co_link);
AAC_LOCK_AQUIRE(&sc->aac_container_lock);
TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link);
AAC_LOCK_RELEASE(&sc->aac_container_lock);
FREE(co, M_AACBUF);
co = co_next;
} else {
co->co_found = 0;
co = TAILQ_NEXT(co, co_link);
}
}
/* Attach the newly created containers */
if (added)
bus_generic_attach(sc->aac_dev);
break;
default:
break;
}
default:
break;
}
/* Copy the AIF data to the AIF queue for ioctl retrieval */
s = splbio();
next = (sc->aac_aifq_head + 1) % AAC_AIFQ_LENGTH;
if (next != sc->aac_aifq_tail) {
@ -1927,7 +2315,8 @@ aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif)
wakeup(sc->aac_aifq);
}
splx(s);
aac_print_aif(sc, aif);
return;
}
/******************************************************************************
@ -1943,13 +2332,13 @@ aac_handle_aif(struct aac_softc *sc, struct aac_aif_command *aif)
#include <machine/../linux/linux_proto.h>
#include <compat/linux/linux_ioctl.h>
#define AAC_LINUX_IOCTL_MIN 0x2000
#define AAC_LINUX_IOCTL_MAX 0x21ff
#define AAC_LINUX_IOCTL_MIN 0x0000
#define AAC_LINUX_IOCTL_MAX 0xffff
static linux_ioctl_function_t aac_linux_ioctl;
static struct linux_ioctl_handler aac_handler = {aac_linux_ioctl,
AAC_LINUX_IOCTL_MIN,
AAC_LINUX_IOCTL_MAX};
AAC_LINUX_IOCTL_MIN,
AAC_LINUX_IOCTL_MAX};
SYSINIT (aac_register, SI_SUB_KLD, SI_ORDER_MIDDLE,
linux_ioctl_register_handler, &aac_handler);
@ -1964,6 +2353,7 @@ aac_linux_ioctl(struct proc *p, struct linux_ioctl_args *args)
struct file *fp = p->p_fd->fd_ofiles[args->fd];
u_long cmd = args->cmd;
debug_called(2);
/*
* Pass the ioctl off to our standard handler.
*/
@ -1974,9 +2364,9 @@ aac_linux_ioctl(struct proc *p, struct linux_ioctl_args *args)
/******************************************************************************
* Return the Revision of the driver to userspace and check to see if the
* userspace app is possibly compatible. This is extremely bogus right now
* because I have no idea how to handle the versioning of this driver. It is
* needed, though, to get aaccli working.
* userspace app is possibly compatible. This is extremely bogus since
* our driver doesn't follow Adaptec's versioning system. Cheat by just
* returning what the card reported.
*/
static int
aac_rev_check(struct aac_softc *sc, caddr_t udata)
@ -2005,7 +2395,7 @@ aac_rev_check(struct aac_softc *sc, caddr_t udata)
rev_check_resp.adapterSWRevision.buildNumber = sc->aac_revision.buildNumber;
return(copyout((caddr_t)&rev_check_resp, udata,
sizeof(struct aac_rev_check_resp)));
sizeof(struct aac_rev_check_resp)));
}
/******************************************************************************
@ -2024,7 +2414,7 @@ aac_getnext_aif(struct aac_softc *sc, caddr_t arg)
/*
* Check the magic number that we gave the caller.
*/
if (agf.AdapterFibContext != AAC_AIF_SILLYMAGIC) {
if (agf.AdapterFibContext != (int)sc->aifthread) {
error = EFAULT;
} else {
@ -2062,9 +2452,63 @@ aac_return_aif(struct aac_softc *sc, caddr_t uptr)
} else {
error = copyout(&sc->aac_aifq[sc->aac_aifq_tail], uptr,
sizeof(struct aac_aif_command));
if (error)
printf("aac_return_aif: copyout returned %d\n", error);
if (!error)
sc->aac_aifq_tail = (sc->aac_aifq_tail + 1) % AAC_AIFQ_LENGTH;
}
splx(s);
return(error);
}
/******************************************************************************
* Give the userland some information about the container. The AAC arch
* expects the driver to be a SCSI passthrough type driver, so it expects
* the containers to have b:t:l numbers. Fake it.
*/
static int
aac_query_disk(struct aac_softc *sc, caddr_t uptr)
{
struct aac_query_disk query_disk;
struct aac_container *co;
struct aac_disk *disk = NULL;
int error, id;
debug_called(2);
error = copyin(uptr, (caddr_t)&query_disk, sizeof(struct aac_query_disk));
if (error)
return (error);
id = query_disk.ContainerNumber;
if (id == -1)
return (EINVAL);
AAC_LOCK_AQUIRE(&sc->aac_container_lock);
TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) {
if (co->co_mntobj.ObjectId == id)
break;
}
if (co == NULL) {
query_disk.Valid = 0;
query_disk.Locked = 0;
query_disk.Deleted = 1; /* XXX is this right? */
} else {
disk = device_get_softc(co->co_disk);
query_disk.Valid = 1;
query_disk.Locked = (disk->ad_flags & AAC_DISK_OPEN) ? 1 : 0;
query_disk.Deleted = 0;
query_disk.Bus = 0;
query_disk.Target = disk->unit;
query_disk.Lun = 0;
query_disk.UnMapped = 0;
bcopy(disk->ad_dev_t->si_name, &query_disk.diskDeviceName[0], 10);
}
AAC_LOCK_RELEASE(&sc->aac_container_lock);
error = copyout((caddr_t)&query_disk, uptr, sizeof(struct aac_query_disk));
return (error);
}

View File

@ -34,7 +34,6 @@
*/
#include "opt_aac.h"
#ifdef AAC_DEBUG
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@ -492,4 +491,3 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif)
}
}
#endif /* AAC_DEBUG */
#endif

View File

@ -42,6 +42,10 @@
#include <sys/devicestat.h>
#include <sys/disk.h>
#include <vm/vm.h>
#include <vm/pmap.h>
#include <machine/md_var.h>
#include <machine/bus.h>
#include <sys/rman.h>
@ -62,6 +66,7 @@ static int aac_disk_detach(device_t dev);
static d_open_t aac_disk_open;
static d_close_t aac_disk_close;
static d_strategy_t aac_disk_strategy;
static d_dump_t aac_disk_dump;
#define AAC_DISK_CDEV_MAJOR 151
@ -76,9 +81,12 @@ static struct cdevsw aac_disk_cdevsw = {
/* strategy */ aac_disk_strategy,
/* name */ "aacd",
/* maj */ AAC_DISK_CDEV_MAJOR,
/* dump */ nodump,
/* dump */ aac_disk_dump,
/* psize */ nopsize,
/* flags */ D_DISK,
#if __FreeBSD_version < 500005
/* bmaj */ -1
#endif
};
devclass_t aac_disk_devclass;
@ -108,7 +116,9 @@ TUNABLE_INT("hw.aac.iosize_max", &aac_iosize_max);
SYSCTL_DECL(_hw_aac);
SYSCTL_UINT(_hw_aac, OID_AUTO, iosize_max, CTLFLAG_RD, &aac_iosize_max, 0,
"Max I/O size per transfer to an array");
"Max I/O size per transfer to an array");
#define AAC_MAXIO 65536
/******************************************************************************
* Handle open from generic layer.
@ -181,6 +191,13 @@ aac_disk_strategy(struct bio *bp)
return;
}
/* do-nothing operation? */
if (bp->bio_bcount == 0) {
bp->bio_resid = bp->bio_bcount;
biodone(bp);
return;
}
/* perform accounting */
devstat_start_transaction(&sc->ad_stats);
@ -189,6 +206,82 @@ aac_disk_strategy(struct bio *bp)
return;
}
/******************************************************************************
* Dump memory out to an array
*
* This queues blocks of memory of size AAC_MAXIO to the controller and waits
* for the controller to complete the requests.
*/
static int
aac_disk_dump(dev_t dev)
{
struct aac_disk *ad = dev->si_drv1;
struct aac_softc *sc;
vm_offset_t addr = 0;
long blkcnt;
unsigned int count, blkno, secsize;
int dumppages = AAC_MAXIO / PAGE_SIZE;
int i, error;
if ((error = disk_dumpcheck(dev, &count, &blkno, &secsize)))
return (error);
if (ad == NULL)
return (ENXIO);
sc= ad->ad_controller;
blkcnt = howmany(PAGE_SIZE, secsize);
while (count > 0) {
caddr_t va = NULL;
if ((count / blkcnt) < dumppages)
dumppages = count / blkcnt;
for (i = 0; i < dumppages; ++i) {
vm_offset_t a = addr + (i * PAGE_SIZE);
if (is_physical_memory(a)) {
va = pmap_kenter_temporary(trunc_page(a), i);
} else {
va = pmap_kenter_temporary(trunc_page(0), i);
}
}
retry:
/*
* Queue the block to the controller. If the queue is full, EBUSY
* will be returned.
*/
error = aac_dump_enqueue(ad, blkno, va, dumppages);
if (error && (error != EBUSY))
return (error);
if (!error) {
if (dumpstatus(addr, (long)(count * DEV_BSIZE)) < 0)
return (EINTR);
blkno += blkcnt * dumppages;
count -= blkcnt * dumppages;
addr += PAGE_SIZE * dumppages;
if (count > 0)
continue;
}
/*
* Either the queue was full on the last attemp, or we have no more
* data to dump. Let the queue drain out and retry the block if
* the queue was full.
*/
aac_dump_complete(sc);
if (error == EBUSY)
goto retry;
}
return (0);
}
/******************************************************************************
* Handle completion of an I/O request.
*/
@ -200,8 +293,13 @@ aac_biodone(struct bio *bp)
debug_called(4);
devstat_end_transaction_bio(&sc->ad_stats, bp);
if (bp->bio_flags & BIO_ERROR)
if (bp->bio_flags & BIO_ERROR) {
#if __FreeBSD_version > 500005
diskerr(bp, (char *)bp->bio_driver1, 0, &sc->ad_label);
#else
diskerr(bp, (char *)bp->bio_driver1, 0, -1, &sc->ad_label);
#endif
}
biodone(bp);
}
@ -212,7 +310,7 @@ static int
aac_disk_probe(device_t dev)
{
debug_called(4);
debug_called(2);
return (0);
}
@ -225,7 +323,7 @@ aac_disk_attach(device_t dev)
{
struct aac_disk *sc = (struct aac_disk *)device_get_softc(dev);
debug_called(4);
debug_called(1);
/* initialise our softc */
sc->ad_controller =
@ -267,6 +365,7 @@ aac_disk_attach(device_t dev)
#endif
sc->ad_dev_t->si_iosize_max = aac_iosize_max;
sc->unit = device_get_unit(dev);
return (0);
}
@ -279,17 +378,16 @@ aac_disk_detach(device_t dev)
{
struct aac_disk *sc = (struct aac_disk *)device_get_softc(dev);
debug_called(4);
debug_called(2);
if (sc->ad_flags & AAC_DISK_OPEN)
return(EBUSY);
devstat_remove_entry(&sc->ad_stats);
disk_destroy(sc->ad_dev_t);
#ifdef FREEBSD_4
if (--disks_registered == 0)
cdevsw_remove(&aac_disk_disk_cdevsw);
#else
disk_destroy(sc->ad_dev_t);
cdevsw_remove(&aac_disk_cdevsw);
#endif
return(0);

View File

@ -1,8 +1,7 @@
/*-
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2000-2001 Scott Long
* Copyright (c) 2000 Scott Long
* Copyright (c) 2000 BSDi
* Copyright (c) 2001 Adaptec, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -59,8 +58,7 @@ union aac_statrequest {
* These bit encodings are actually descended from Windows NT. Ick.
*/
#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) \
| ((func) << 2) | (meth))
#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) | ((func) << 2) | (meth))
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
@ -108,15 +106,15 @@ union aac_statrequest {
#define FSACTL_LNX_DELETE_DISK 0x163
#define FSACTL_LNX_QUERY_DISK 0x173
/* Ok, this one is really lame */
/* Ok, here it gets really lame */
#define FSACTL_LNX_PROBE_CONTAINERS 2131 /* Just guessing */
/* Do the native version of the ioctls. Since the BSD encoding scheme
* conflicts with the 'standard' AAC encoding scheme, the resulting values
* must be different. The '8' comes from the fact that the previous scheme
* conflicts with the 'standard' AAC encoding scheme, the resulting numbers
* will be different. The '8' comes from the fact that the previous scheme
* used 12 bits for the number, with the the 12th bit being the only set
* bit above bit 8. Thus the value of 8, with the lower 8 bits holding the
* command number. 9 is used for the odd overflow/collision case.
* command number. 9 is used for the odd overflow case.
*/
#define FSACTL_SENDFIB _IO('8', 2)
#define FSACTL_GET_COMM_PERF_DATA _IO('8', 36)
@ -161,9 +159,21 @@ struct aac_rev_check_resp {
/*
* Context passed in by a consumer looking to collect an AIF.
*/
#define AAC_AIF_SILLYMAGIC 0xdeadbeef
struct get_adapter_fib_ioctl {
u_int32_t AdapterFibContext;
int Wait;
caddr_t AifFib;
};
struct aac_query_disk {
int32_t ContainerNumber;
int32_t Bus;
int32_t Target;
int32_t Lun;
u_int32_t Valid;
u_int32_t Locked;
u_int32_t Deleted;
int32_t Instance;
char diskDeviceName[10];
u_int32_t UnMapped;
};

View File

@ -65,7 +65,6 @@ static device_method_t aac_methods[] = {
DEVMETHOD(device_probe, aac_pci_probe),
DEVMETHOD(device_attach, aac_pci_attach),
DEVMETHOD(device_detach, aac_detach),
DEVMETHOD(device_shutdown, aac_shutdown),
DEVMETHOD(device_suspend, aac_suspend),
DEVMETHOD(device_resume, aac_resume),
@ -99,12 +98,10 @@ struct aac_ident
{0x1028, 0x0002, 0x1028, 0x00d9, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
{0x1028, 0x0008, 0x1028, 0x00cf, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
{0x1028, 0x000a, 0x1028, 0x0106, AAC_HWIF_I960RX, "Dell PERC 3/Di"},
{0x9005, 0x0282, 0x9005, 0x0282, AAC_HWIF_I960RX, "Adaptec AAC-2622"},
{0x1011, 0x0046, 0x9005, 0x0364, AAC_HWIF_STRONGARM, "Adaptec AAC-364"},
{0x1011, 0x0046, 0x9005, 0x0365, AAC_HWIF_STRONGARM,
"Adaptec SCSI RAID 5400S"},
{0x1011, 0x0046, 0x9005, 0x1364, AAC_HWIF_STRONGARM, "Dell PERC 2/QC"},
{0x1011, 0x0046, 0x9005, 0x1365, AAC_HWIF_STRONGARM, "Dell PERC 3/QC"}, /* XXX guess */
{0x1011, 0x0046, 0x103c, 0x10c2, AAC_HWIF_STRONGARM, "HP NetRaid-4M"},
{0, 0, 0, 0, 0, 0}
};
@ -193,7 +190,10 @@ aac_pci_attach(device_t dev)
device_printf(sc->aac_dev, "can't allocate interrupt\n");
goto out;
}
if (bus_setup_intr(sc->aac_dev, sc->aac_irq, INTR_TYPE_BIO|INTR_ENTROPY,
#if __FreeBSD_version < 500005
#define INTR_ENTROPY 0
#endif
if (bus_setup_intr(sc->aac_dev, sc->aac_irq, INTR_TYPE_BIO|INTR_ENTROPY,
aac_intr, sc, &sc->aac_intr)) {
device_printf(sc->aac_dev, "can't set up interrupt\n");
goto out;

View File

@ -987,7 +987,7 @@ struct aac_mntinforesponse {
*/
struct aac_closecommand {
u_int32_t Command;
u_int32_t ComainerId;
u_int32_t ContainerId;
} __attribute__ ((packed));
/*

View File

@ -85,7 +85,7 @@
* Rate at which we periodically check for timed out commands and kick the
* controller.
*/
#define AAC_PERIODIC_INTERVAL 10 /* seconds */
#define AAC_PERIODIC_INTERVAL 20 /* seconds */
/*
* Character device major numbers.
@ -98,8 +98,6 @@
******************************************************************************
******************************************************************************/
#include "opt_aac.h"
#if __FreeBSD_version >= 500005
# include <sys/taskqueue.h>
#endif
@ -109,8 +107,10 @@
*/
struct aac_container
{
struct aac_mntobj co_mntobj;
device_t co_disk;
struct aac_mntobj co_mntobj;
device_t co_disk;
int co_found;
TAILQ_ENTRY(aac_container) co_link;
};
/*
@ -131,6 +131,7 @@ struct aac_disk
int ad_heads;
int ad_sectors;
u_int32_t ad_size;
int unit;
};
/*
@ -170,6 +171,7 @@ struct aac_command
void (* cm_complete)(struct aac_command *cm);
void *cm_private;
time_t cm_timestamp; /* command creation time */
int cm_queue;
};
/*
@ -246,6 +248,23 @@ extern struct aac_interface aac_sa_interface;
#define AAC_GETREG1(sc, reg) bus_space_read_1 (sc->aac_btag, \
sc->aac_bhandle, reg)
TAILQ_HEAD(aac_container_tq, aac_container);
/* Define the OS version specific locks */
#if __FreeBSD_version >= 500005
#include <sys/lock.h>
#include <sys/mutex.h>
typedef struct mtx aac_lock_t;
#define AAC_LOCK_INIT(l) mtx_init(l, "AAC Container Mutex", MTX_DEF)
#define AAC_LOCK_AQUIRE(l) mtx_lock(l)
#define AAC_LOCK_RELEASE(l) mtx_unlock(l)
#else
typedef struct simplelock aac_lock_t;
#define AAC_LOCK_INIT(l) simple_lock_init(l)
#define AAC_LOCK_AQUIRE(l) simple_lock(l)
#define AAC_LOCK_RELEASE(l) simple_unlock(l)
#endif
/*
* Per-controller structure.
*/
@ -308,7 +327,8 @@ struct aac_softc
struct aac_qstat aac_qstat[AACQ_COUNT]; /* queue statistics */
/* connected containters */
struct aac_container aac_container[AAC_MAX_CONTAINERS];
struct aac_container_tq aac_container_tqh;
aac_lock_t aac_container_lock;
/* delayed activity infrastructure */
#if __FreeBSD_version >= 500005
@ -322,6 +342,12 @@ struct aac_softc
struct aac_aif_command aac_aifq[AAC_AIFQ_LENGTH];
int aac_aifq_head;
int aac_aifq_tail;
struct proc *aifthread;
int aifflags;
#define AAC_AIFFLAGS_RUNNING (1 << 0)
#define AAC_AIFFLAGS_PENDING (1 << 1)
#define AAC_AIFFLAGS_EXIT (1 << 2)
#define AAC_AIFFLAGS_EXITED (1 << 3)
};
@ -338,6 +364,9 @@ extern void aac_intr(void *arg);
extern devclass_t aac_devclass;
extern void aac_submit_bio(struct bio *bp);
extern void aac_biodone(struct bio *bp);
extern int aac_dump_enqueue(struct aac_disk *ad, u_int32_t lba,
void *data, int nblks);
extern void aac_dump_complete(struct aac_softc *sc);
/*
* Debugging levels:
@ -370,9 +399,9 @@ extern void aac_print_aif(struct aac_softc *sc,
# define aac_print_queues(sc)
# define aac_panic(sc, reason)
# define aac_print_aif(sc, aif)
# define AAC_PRINT_FIB(sc, fib)
# define aac_print_aif(sc, aac_aif_command)
#endif
struct aac_code_lookup {
@ -517,3 +546,14 @@ aac_dequeue_bio(struct aac_softc *sc)
splx(s);
return(bp);
}
static __inline void
aac_print_printf(struct aac_softc *sc)
{
if (sc->aac_common->ac_printf[0]) {
device_printf(sc->aac_dev, "**Monitor** %.*s", AAC_PRINTF_BUFSIZE,
sc->aac_common->ac_printf);
sc->aac_common->ac_printf[0] = 0;
AAC_QNOTIFY(sc, AAC_DB_PRINTF);
}
}

View File

@ -1,8 +1,7 @@
/*-
* Copyright (c) 2000 Michael Smith
* Copyright (c) 2000-2001 Scott Long
* Copyright (c) 2000 Scott Long
* Copyright (c) 2000 BSDi
* Copyright (c) 2001 Adaptec, Inc.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -59,8 +58,7 @@ union aac_statrequest {
* These bit encodings are actually descended from Windows NT. Ick.
*/
#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) \
| ((func) << 2) | (meth))
#define CTL_CODE(devType, func, meth, acc) (((devType) << 16) | ((acc) << 14) | ((func) << 2) | (meth))
#define METHOD_BUFFERED 0
#define METHOD_IN_DIRECT 1
#define METHOD_OUT_DIRECT 2
@ -108,15 +106,15 @@ union aac_statrequest {
#define FSACTL_LNX_DELETE_DISK 0x163
#define FSACTL_LNX_QUERY_DISK 0x173
/* Ok, this one is really lame */
/* Ok, here it gets really lame */
#define FSACTL_LNX_PROBE_CONTAINERS 2131 /* Just guessing */
/* Do the native version of the ioctls. Since the BSD encoding scheme
* conflicts with the 'standard' AAC encoding scheme, the resulting values
* must be different. The '8' comes from the fact that the previous scheme
* conflicts with the 'standard' AAC encoding scheme, the resulting numbers
* will be different. The '8' comes from the fact that the previous scheme
* used 12 bits for the number, with the the 12th bit being the only set
* bit above bit 8. Thus the value of 8, with the lower 8 bits holding the
* command number. 9 is used for the odd overflow/collision case.
* command number. 9 is used for the odd overflow case.
*/
#define FSACTL_SENDFIB _IO('8', 2)
#define FSACTL_GET_COMM_PERF_DATA _IO('8', 36)
@ -161,9 +159,21 @@ struct aac_rev_check_resp {
/*
* Context passed in by a consumer looking to collect an AIF.
*/
#define AAC_AIF_SILLYMAGIC 0xdeadbeef
struct get_adapter_fib_ioctl {
u_int32_t AdapterFibContext;
int Wait;
caddr_t AifFib;
};
struct aac_query_disk {
int32_t ContainerNumber;
int32_t Bus;
int32_t Target;
int32_t Lun;
u_int32_t Valid;
u_int32_t Locked;
u_int32_t Deleted;
int32_t Instance;
char diskDeviceName[10];
u_int32_t UnMapped;
};