From: Sascha Wildner Date: Fri, 7 Jan 2011 05:14:19 +0000 (+0100) Subject: aac(4): Update to version 2.1.9-1 (current FreeBSD). X-Git-Tag: v2.11.0~383 X-Git-Url: https://gitweb.dragonflybsd.org/dragonfly.git/commitdiff_plain/e9ae7f4fcc6d7bd3cead63918d847460a06582d5 aac(4): Update to version 2.1.9-1 (current FreeBSD). This brings in support for ~40 additional controllers of the family. See the manual page for the full list. It also fixes dumping to aac(4). Tested with a Dell PERC 320/DC. Reported-by: Archimedes Gaviola Dragonfly-bug: --- diff --git a/share/man/man4/aac.4 b/share/man/man4/aac.4 index 21f1e0eb66..7a9fbfe35f 100644 --- a/share/man/man4/aac.4 +++ b/share/man/man4/aac.4 @@ -22,9 +22,8 @@ .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" -.\" $FreeBSD: src/share/man/man4/aac.4,v 1.31.2.1.2.1 2006/12/14 23:56:26 brueffer Exp $ -.\" $DragonFly: src/share/man/man4/aac.4,v 1.8 2008/09/02 11:50:46 matthias Exp $ -.Dd May 8, 2009 +.\" $FreeBSD: src/share/man/man4/aac.4,v 1.41 2009/07/11 08:10:18 jkim Exp $ +.Dd January 7, 2011 .Dt AAC 4 .Os .Sh NAME @@ -40,7 +39,7 @@ kernel configuration file: .Cd device aacp .Pp To compile in debugging code: -.Cd options AAC_DEBUG=N +.Cd options AAC_DEBUG .Ed .Pp Alternatively, to load the driver as a @@ -74,7 +73,7 @@ The aliases .Pa /dev/afa? and .Pa /dev/hpn? -exist for compatibilty with the Dell and HP versions of management tools, +exist for compatibility with the Dell and HP versions of management tools, respectively. If the kernel is compiled with the .Dv COMPAT_LINUX @@ -87,24 +86,6 @@ Linux-compatible .Xr ioctl 2 interface for the management device will be enabled and will allow Linux-based management applications to control the card. -.Ss Tuning -The read-only sysctl -.Va hw.aac.iosize_max -defaults to 65536 and may be set at boot time to another value via -.Xr loader 8 . -This value determines the maximum data transfer size allowed -to/from an array. -Setting it higher will result in better performance, -especially for large sequential access patterns. -.Em Beware : -internal limitations -of the card limit this value to 64K for arrays with many members. -While it may be safe to raise this value, this is done -.Em at the operator's own risk . -Note also that -performance peaks at a value of 96K, -and drops off dramatically at 128K, -due to other limitations of the card. .Sh HARDWARE Controllers supported by the .Nm @@ -114,6 +95,42 @@ driver include: .It Adaptec AAC-364 .It +Adaptec RAID 2045 +.It +Adaptec RAID 2405 +.It +Adaptec RAID 2445 +.It +Adaptec RAID 2805 +.It +Adaptec RAID 3085 +.It +Adaptec RAID 31205 +.It +Adaptec RAID 31605 +.It +Adaptec RAID 5085 +.It +Adaptec RAID 51205 +.It +Adaptec RAID 51245 +.It +Adaptec RAID 51605 +.It +Adaptec RAID 51645 +.It +Adaptec RAID 52445 +.It +Adaptec RAID 5405 +.It +Adaptec RAID 5445 +.It +Adaptec RAID 5805 +.It +Adaptec SAS RAID 3405 +.It +Adaptec SAS RAID 3805 +.It Adaptec SAS RAID 4000SAS .It Adaptec SAS RAID 4005SAS @@ -184,12 +201,36 @@ IBM ServeRAID 8i .It IBM ServeRAID 8k .It +IBM ServeRAID 8s +.It +ICP RAID ICP5045BL +.It +ICP RAID ICP5085BL +.It +ICP RAID ICP5085SL +.It +ICP RAID ICP5125BR +.It +ICP RAID ICP5125SL +.It +ICP RAID ICP5165BR +.It +ICP RAID ICP5165SL +.It +ICP RAID ICP5445SL +.It +ICP RAID ICP5805BL +.It +ICP RAID ICP5805SL +.It ICP ICP5085BR SAS RAID .It ICP ICP9085LI SAS RAID .It ICP ICP9047MA SATA RAID .It +ICP ICP9067MA SATA RAID +.It ICP ICP9087MA SATA RAID .It ICP ICP9014RO SCSI RAID @@ -199,9 +240,29 @@ ICP ICP9024RO SCSI RAID Legend S220 .It Legend S230 +.It +Sun STK RAID REM +.It +Sun STK RAID EM +.It +SG-XPCIESAS-R-IN +.It +SG-XPCIESAS-R-EX +.It +AOC-USAS-S4i +.It +AOC-USAS-S8i +.It +AOC-USAS-S4iR +.It +AOC-USAS-S8iR +.It +AOC-USAS-S8i-LP +.It +AOC-USAS-S8iR-LP .El .Sh FILES -.Bl -tag -width ".Pa /dev/aacd?" -compact +.Bl -tag -width /boot/kernel/aac.ko -compact .It Pa /dev/aac? aac management interface .It Pa /dev/aacd? @@ -210,8 +271,7 @@ disk/container interface .Sh DIAGNOSTICS Compiling with .Dv AAC_DEBUG -set to a number between 0 and 2 -will enable increasingly verbose debug messages. +will enable debug messages. .Pp The adapter can send status and alert messages asynchronously to the driver. @@ -221,9 +281,7 @@ and are also queued for retrieval by a management application. .Xr kld 4 , .Xr linux 4 , .Xr scsi 4 , -.Xr kldload 8 , -.Xr loader 8 , -.Xr sysctl 8 +.Xr kldload 8 .Sh HISTORY The .Nm @@ -240,6 +298,4 @@ firmware. The firmware version is the same as the kernel version printed in the BIOS POST and driver attach messages. .Pp -.\"This driver will not work on systems with more than 4GB of memory. -.\".Pp The controller is not actually paused on suspend/resume. diff --git a/sys/conf/files b/sys/conf/files index 3a0ce75f55..41dfcfc2e1 100644 --- a/sys/conf/files +++ b/sys/conf/files @@ -118,12 +118,12 @@ ddb/db_trap.c optional ddb ddb/db_variables.c optional ddb ddb/db_watch.c optional ddb ddb/db_write_cmd.c optional ddb -dev/raid/aac/aac.c optional nowerror aac +dev/raid/aac/aac.c optional aac +dev/raid/aac/aac_cam.c optional aacp aac dev/raid/aac/aac_debug.c optional aac dev/raid/aac/aac_disk.c optional aac -dev/raid/aac/aac_pci.c optional aac pci dev/raid/aac/aac_linux.c optional aac compat_linux -dev/raid/aac/aac_cam.c optional aacp aac +dev/raid/aac/aac_pci.c optional aac pci dev/raid/arcmsr/arcmsr.c optional arcmsr pci diff --git a/sys/conf/options b/sys/conf/options index a16ab1122f..6ac400b628 100644 --- a/sys/conf/options +++ b/sys/conf/options @@ -31,15 +31,7 @@ # opt_.h # Adaptec Array Controller driver options -AAC_DEBUG opt_aac.h # Debugging levels: - # 0 - quiet, only emit warnings - # 1 - noisy, emit major function - # points and things done - # 2 - noisier, emit trace items - # in loops, etc. - # 3 - even more noisy, more function - # points - # 4 - noisiest +AAC_DEBUG opt_aac.h # Adaptec aic7xxx SCSI controller options AHC_ALLOW_MEMIO opt_aic7xxx.h # Allow PCI devices to use memory diff --git a/sys/config/LINT b/sys/config/LINT index f7ad2ade6b..323c77722b 100644 --- a/sys/config/LINT +++ b/sys/config/LINT @@ -1248,7 +1248,7 @@ device stg0 at isa? port 0x140 irq 11 # the Dell PERC 2/QC and the HP NetRAID-4M # device aac -options AAC_DEBUG=4 +options AAC_DEBUG device aacp # SCSI Passthrough interface (optional, CAM required) # diff --git a/sys/dev/raid/aac/Makefile b/sys/dev/raid/aac/Makefile index d3faf41b66..962a103522 100644 --- a/sys/dev/raid/aac/Makefile +++ b/sys/dev/raid/aac/Makefile @@ -1,12 +1,15 @@ -# $FreeBSD: src/sys/modules/aac/Makefile,v 1.2.2.4 2003/03/28 19:51:37 scottl Exp $ +# $FreeBSD: src/sys/modules/aac/Makefile,v 1.9 2010/08/23 06:13:29 imp Exp $ +.if ${MACHINE_ARCH} == "i386" SUBDIR= aac_linux +.endif KMOD= aac SRCS= aac.c aac_pci.c aac_disk.c aac_cam.c SRCS+= opt_scsi.h opt_cam.h opt_aac.h SRCS+= device_if.h bus_if.h pci_if.h +# To enable debug output from the driver, uncomment these two lines. #CFLAGS+= -DAAC_DEBUG=2 #SRCS+= aac_debug.c diff --git a/sys/dev/raid/aac/Makefile_linux.module b/sys/dev/raid/aac/Makefile_linux.module deleted file mode 100644 index 112bf6fa54..0000000000 --- a/sys/dev/raid/aac/Makefile_linux.module +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD: src/sys/modules/aac/aac_linux/Makefile,v 1.1.4.1 2003/03/28 19:51:37 scottl Exp $ -# $DragonFly: src/sys/dev/raid/aac/Makefile_linux.module,v 1.2 2003/06/17 04:28:43 dillon Exp $ - -.PATH: ${.CURDIR}/../../../dev/aac - -KMOD= aac_linux -SRCS= aac_linux.c - -.include diff --git a/sys/dev/raid/aac/aac.c b/sys/dev/raid/aac/aac.c index d9927bf2cb..8868af532c 100644 --- a/sys/dev/raid/aac/aac.c +++ b/sys/dev/raid/aac/aac.c @@ -26,13 +26,12 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/aac/aac.c,v 1.9.2.14 2003/04/08 13:22:08 scottl Exp $ + * $FreeBSD: src/sys/dev/aac/aac.c,v 1.165 2010/09/29 14:22:00 emaste Exp $ */ /* * 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,36 +43,35 @@ #include #include #include -#include +#include #include #include -#include -#include #include #include #include #include +#include +#include #include #include #include -#include "aacreg.h" -#include "aac_ioctl.h" -#include "aacvar.h" -#include "aac_tables.h" +#include +#include +#include +#include static void aac_startup(void *arg); static void aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f); static void aac_get_bus_info(struct aac_softc *sc); -static int aac_shutdown(device_t dev); +static void aac_daemon(void *arg); /* Command Processing */ -static void aac_timeout(void *ssc); -static int aac_map_command(struct aac_command *cm); +static void aac_timeout(struct aac_softc *sc); 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); @@ -90,6 +88,7 @@ static void aac_free_commands(struct aac_softc *sc); static void aac_unmap_command(struct aac_command *cm); /* Hardware Interface */ +static int aac_alloc(struct aac_softc *sc); static void aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error); static int aac_check_firmware(struct aac_softc *sc); @@ -97,6 +96,7 @@ static int aac_init(struct aac_softc *sc); static int aac_sync_command(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, u_int32_t arg1, u_int32_t arg2, u_int32_t arg3, u_int32_t *sp); +static int aac_setup_intr(struct aac_softc *sc); 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, @@ -104,28 +104,6 @@ static int aac_dequeue_fib(struct aac_softc *sc, int queue, static int aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib); -/* Falcon/PPC interface */ -static int aac_fa_get_fwstatus(struct aac_softc *sc); -static void aac_fa_qnotify(struct aac_softc *sc, int qbit); -static int aac_fa_get_istatus(struct aac_softc *sc); -static void aac_fa_clear_istatus(struct aac_softc *sc, int mask); -static void aac_fa_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_fa_get_mailbox(struct aac_softc *sc, int mb); -static void aac_fa_set_interrupts(struct aac_softc *sc, int enable); - -struct aac_interface aac_fa_interface = { - aac_fa_get_fwstatus, - aac_fa_qnotify, - aac_fa_get_istatus, - aac_fa_clear_istatus, - aac_fa_set_mailbox, - aac_fa_get_mailbox, - aac_fa_set_interrupts, - NULL, NULL, NULL -}; - /* StrongARM interface */ static int aac_sa_get_fwstatus(struct aac_softc *sc); static void aac_sa_qnotify(struct aac_softc *sc, int qbit); @@ -213,17 +191,25 @@ static d_close_t aac_close; static d_ioctl_t aac_ioctl; static d_kqfilter_t aac_kqfilter; static void aac_filter_detach(struct knote *kn); -static int aac_filter(struct knote *kn, long hint); -static int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) __unused; +static int aac_filter_read(struct knote *kn, long hint); +static int aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib); +static int aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg); 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_open_aif(struct aac_softc *sc, caddr_t arg); +static int aac_close_aif(struct aac_softc *sc, caddr_t arg); 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_return_aif(struct aac_softc *sc, + struct aac_fib_context *ctx, 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 int aac_supported_features(struct aac_softc *sc, caddr_t uptr); static void aac_ioctl_event(struct aac_softc *sc, - struct aac_event *event, void *arg); + struct aac_event *event, void *arg); +static struct aac_mntinforesp * + aac_get_container_info(struct aac_softc *sc, struct aac_fib *fib, int cid); + static struct dev_ops aac_ops = { { "aac", 0, 0 }, .d_open = aac_open, @@ -232,8 +218,6 @@ static struct dev_ops aac_ops = { .d_kqfilter = aac_kqfilter }; -DECLARE_DUMMY_MODULE(aac); - MALLOC_DEFINE(M_AACBUF, "aacbuf", "Buffers for the AAC driver"); /* sysctl node */ @@ -244,27 +228,25 @@ SYSCTL_NODE(_hw, OID_AUTO, aac, CTLFLAG_RD, 0, "AAC driver parameters"); */ /* - * Initialise the controller and softc + * Initialize the controller and softc */ int aac_attach(struct aac_softc *sc) { int error, unit; - debug_called(1); - callout_init(&sc->aac_watchdog); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* - * Initialise per-controller queues. + * Initialize per-controller queues. */ aac_initq_free(sc); aac_initq_ready(sc); aac_initq_busy(sc); - aac_initq_complete(sc); aac_initq_bio(sc); /* - * Initialise command-completion task. + * Initialize command-completion task. */ TASK_INIT(&sc->aac_task_complete, 0, aac_complete, sc); @@ -280,54 +262,28 @@ aac_attach(struct aac_softc *sc) /* * 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"); + lockinit(&sc->aac_aifq_lock, "AAC AIF lock", 0, LK_CANRECURSE); + lockinit(&sc->aac_io_lock, "AAC I/O lock", 0, LK_CANRECURSE); + lockinit(&sc->aac_container_lock, "AAC container lock", 0, LK_CANRECURSE); 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; + /* Initialize the clock daemon callout. */ + callout_init(&sc->aac_daemontime); /* - * Initialise the adapter. + * Initialize the adapter. */ + if ((error = aac_alloc(sc)) != 0) + return(error); if ((error = aac_init(sc)) != 0) return(error); /* * Allocate and connect our interrupt. */ - sc->aac_irq_rid = 0; - if ((sc->aac_irq = bus_alloc_resource_any(sc->aac_dev, SYS_RES_IRQ, - &sc->aac_irq_rid, - RF_SHAREABLE | - RF_ACTIVE)) == NULL) { - device_printf(sc->aac_dev, "can't allocate interrupt\n"); - return (EINVAL); - } - if (sc->flags & AAC_FLAGS_NEW_COMM) { - if (bus_setup_intr(sc->aac_dev, sc->aac_irq, - 0, 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, 0, - 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, - 0, aac_fast_intr, - sc, &sc->aac_intr, NULL)) { - device_printf(sc->aac_dev, - "can't set up MPSAFE interrupt\n"); - return (EINVAL); - } - } - } + if ((error = aac_setup_intr(sc)) != 0) + return(error); /* * Print a little information about the controller. @@ -339,7 +295,6 @@ aac_attach(struct aac_softc *sc) */ sc->aac_ich.ich_func = aac_startup; sc->aac_ich.ich_arg = sc; - sc->aac_ich.ich_desc = "aac"; if (config_intrhook_establish(&sc->aac_ich) != 0) { device_printf(sc->aac_dev, "can't establish configuration hook\n"); @@ -352,17 +307,18 @@ aac_attach(struct aac_softc *sc) unit = device_get_unit(sc->aac_dev); sc->aac_dev_t = make_dev(&aac_ops, unit, UID_ROOT, GID_OPERATOR, 0640, "aac%d", unit); + (void)make_dev_alias(sc->aac_dev_t, "afa%d", unit); + (void)make_dev_alias(sc->aac_dev_t, "hpn%d", unit); sc->aac_dev_t->si_drv1 = sc; - reference_dev(sc->aac_dev_t); /* Create the AIF thread */ if (kthread_create(aac_command_thread, sc, &sc->aifthread, "aac%daif", unit)) - panic("Could not create AIF thread\n"); + panic("Could not create AIF thread"); /* Register the shutdown method to only be called post-dump */ - if ((sc->eh = EVENTHANDLER_REGISTER(shutdown_post_sync, aac_shutdown, - sc->aac_dev, SHUTDOWN_PRI_DRIVER)) == NULL) + if ((sc->eh = EVENTHANDLER_REGISTER(shutdown_final, aac_shutdown, + sc->aac_dev, SHUTDOWN_PRI_DEFAULT)) == NULL) device_printf(sc->aac_dev, "shutdown event registration failed\n"); @@ -372,9 +328,35 @@ aac_attach(struct aac_softc *sc) aac_get_bus_info(sc); } + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); + callout_reset(&sc->aac_daemontime, 60 * hz, aac_daemon, sc); + lockmgr(&sc->aac_io_lock, LK_RELEASE); + return(0); } +static void +aac_daemon(void *arg) +{ + struct timeval tv; + struct aac_softc *sc; + struct aac_fib *fib; + + sc = arg; + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); + + if (callout_pending(&sc->aac_daemontime) || + callout_active(&sc->aac_daemontime) == 0) + return; + getmicrotime(&tv); + aac_alloc_sync_fib(sc, &fib); + *(uint32_t *)fib->data = tv.tv_sec; + aac_sync_fib(sc, SendHostTime, 0, fib, sizeof(uint32_t)); + aac_release_sync_fib(sc); + lockmgr(&sc->aac_io_lock, LK_RELEASE); + callout_reset(&sc->aac_daemontime, 30 * 60 * hz, aac_daemon, sc); +} + void aac_add_event(struct aac_softc *sc, struct aac_event *event) { @@ -392,6 +374,30 @@ aac_add_event(struct aac_softc *sc, struct aac_event *event) return; } +/* + * Request information of container #cid + */ +static struct aac_mntinforesp * +aac_get_container_info(struct aac_softc *sc, struct aac_fib *fib, int cid) +{ + struct aac_mntinfo *mi; + + mi = (struct aac_mntinfo *)&fib->data[0]; + /* use 64-bit LBA if enabled */ + mi->Command = (sc->flags & AAC_FLAGS_LBA_64BIT) ? + VM_NameServe64 : VM_NameServe; + mi->MntType = FT_FILESYS; + mi->MntCount = cid; + + if (aac_sync_fib(sc, ContainerCommand, 0, fib, + sizeof(struct aac_mntinfo))) { + device_printf(sc->aac_dev, "Error probing container %d\n", cid); + return (NULL); + } + + return ((struct aac_mntinforesp *)&fib->data[0]); +} + /* * Probe for containers, create disks. */ @@ -400,45 +406,30 @@ aac_startup(void *arg) { struct aac_softc *sc; struct aac_fib *fib; - struct aac_mntinfo *mi; - struct aac_mntinforesp *mir = NULL; + struct aac_mntinforesp *mir; int count = 0, i = 0; - - debug_called(1); sc = (struct aac_softc *)arg; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* disconnect ourselves from the intrhook chain */ config_intrhook_disestablish(&sc->aac_ich); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); aac_alloc_sync_fib(sc, &fib); - mi = (struct aac_mntinfo *)&fib->data[0]; /* loop over possible containers */ do { - /* request information on this container */ - bzero(mi, sizeof(struct aac_mntinfo)); - mi->Command = VM_NameServe; - mi->MntType = FT_FILESYS; - mi->MntCount = i; - if (aac_sync_fib(sc, ContainerCommand, 0, fib, - sizeof(struct aac_mntinfo))) { - device_printf(sc->aac_dev, - "error probing container %d", i); - + if ((mir = aac_get_container_info(sc, fib, i)) == NULL) continue; - } - - mir = (struct aac_mntinforesp *)&fib->data[0]; - /* XXX Need to check if count changed */ - count = mir->MntRespCount; + if (i == 0) + count = mir->MntRespCount; aac_add_container(sc, mir, 0); i++; } while ((i < count) && (i < AAC_MAX_CONTAINERS)); aac_release_sync_fib(sc); - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); /* poke the bus to actually attach the child devices */ if (bus_generic_attach(sc->aac_dev)) @@ -452,7 +443,7 @@ aac_startup(void *arg) } /* - * Create a device to respresent a new container + * Create a device to represent a new container */ static void aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f) @@ -467,7 +458,7 @@ aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f) if ((mir->Status == ST_OK) && (mir->MntTable[0].VolType != CT_NONE)) { co = (struct aac_container *)kmalloc(sizeof *co, M_AACBUF, M_INTWAIT | M_ZERO); - debug(1, "id %x name '%.16s' size %u type %d", + fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "id %x name '%.16s' size %u type %d", mir->MntTable[0].ObjectId, mir->MntTable[0].FileSystemName, mir->MntTable[0].Capacity, mir->MntTable[0].VolType); @@ -482,10 +473,115 @@ aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f) co->co_found = f; bcopy(&mir->MntTable[0], &co->co_mntobj, sizeof(struct aac_mntobj)); - AAC_LOCK_ACQUIRE(&sc->aac_container_lock); + lockmgr(&sc->aac_container_lock, LK_EXCLUSIVE); TAILQ_INSERT_TAIL(&sc->aac_container_tqh, co, co_link); - AAC_LOCK_RELEASE(&sc->aac_container_lock); + lockmgr(&sc->aac_container_lock, LK_RELEASE); + } +} + +/* + * Allocate resources associated with (sc) + */ +static int +aac_alloc(struct aac_softc *sc) +{ + + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + + /* + * Create DMA tag for mapping buffers into controller-addressable space. + */ + 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 */ + sc->aac_sg_tablesize, /* nsegments */ + MAXBSIZE, /* maxsegsize */ + BUS_DMA_ALLOCNOW, /* flags */ + &sc->aac_buffer_dmat)) { + device_printf(sc->aac_dev, "can't allocate buffer DMA tag\n"); + return (ENOMEM); + } + + /* + * Create DMA tag for mapping FIBs into controller-addressable space.. + */ + if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */ + 1, 0, /* algnmnt, boundary */ + (sc->flags & AAC_FLAGS_4GB_WINDOW) ? + BUS_SPACE_MAXADDR_32BIT : + 0x7fffffff, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + sc->aac_max_fibs_alloc * + sc->aac_max_fib_size, /* maxsize */ + 1, /* nsegments */ + sc->aac_max_fibs_alloc * + sc->aac_max_fib_size, /* maxsize */ + 0, /* flags */ + &sc->aac_fib_dmat)) { + device_printf(sc->aac_dev, "can't allocate FIB DMA tag\n"); + return (ENOMEM); } + + /* + * Create DMA tag for the common structure and allocate it. + */ + if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */ + 1, 0, /* algnmnt, boundary */ + (sc->flags & AAC_FLAGS_4GB_WINDOW) ? + BUS_SPACE_MAXADDR_32BIT : + 0x7fffffff, /* lowaddr */ + BUS_SPACE_MAXADDR, /* highaddr */ + NULL, NULL, /* filter, filterarg */ + 8192 + sizeof(struct aac_common), /* maxsize */ + 1, /* nsegments */ + BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ + 0, /* flags */ + &sc->aac_common_dmat)) { + device_printf(sc->aac_dev, + "can't allocate common structure DMA tag\n"); + return (ENOMEM); + } + if (bus_dmamem_alloc(sc->aac_common_dmat, (void **)&sc->aac_common, + BUS_DMA_NOWAIT, &sc->aac_common_dmamap)) { + device_printf(sc->aac_dev, "can't allocate common structure\n"); + return (ENOMEM); + } + + /* + * Work around a bug in the 2120 and 2200 that cannot DMA commands + * below address 8192 in physical memory. + * XXX If the padding is not needed, can it be put to use instead + * of ignored? + */ + (void)bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap, + sc->aac_common, 8192 + sizeof(*sc->aac_common), + aac_common_map, sc, 0); + + if (sc->aac_common_busaddr < 8192) { + sc->aac_common = (struct aac_common *) + ((uint8_t *)sc->aac_common + 8192); + sc->aac_common_busaddr += 8192; + } + bzero(sc->aac_common, sizeof(*sc->aac_common)); + + /* Allocate some FIBs and associated command structs */ + TAILQ_INIT(&sc->aac_fibmap_tqh); + sc->aac_commands = kmalloc(sc->aac_max_fibs * sizeof(struct aac_command), + M_AACBUF, M_WAITOK|M_ZERO); + while (sc->total_fibs < sc->aac_max_fibs) { + if (aac_alloc_commands(sc) != 0) + break; + } + if (sc->total_fibs == 0) + return (ENOMEM); + + return (0); } /* @@ -497,7 +593,7 @@ void aac_free(struct aac_softc *sc) { - debug_called(1); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* remove the control device */ if (sc->aac_dev_t != NULL) @@ -535,10 +631,12 @@ aac_free(struct aac_softc *sc) bus_dma_tag_destroy(sc->aac_parent_dmat); /* release the register window mapping */ - if (sc->aac_regs_resource != NULL) { + if (sc->aac_regs_res0 != NULL) bus_release_resource(sc->aac_dev, SYS_RES_MEMORY, - sc->aac_regs_rid, sc->aac_regs_resource); - } + sc->aac_regs_rid0, sc->aac_regs_res0); + if (sc->aac_hwif == AAC_HWIF_NARK && sc->aac_regs_res1 != NULL) + bus_release_resource(sc->aac_dev, SYS_RES_MEMORY, + sc->aac_regs_rid1, sc->aac_regs_res1); dev_ops_remove_minor(&aac_ops, device_get_unit(sc->aac_dev)); } @@ -553,14 +651,10 @@ aac_detach(device_t dev) struct aac_sim *sim; int error; - debug_called(1); - sc = device_get_softc(dev); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - callout_stop(&sc->aac_watchdog); - - if (sc->aac_state & AAC_STATE_OPEN) - return(EBUSY); + callout_stop(&sc->aac_daemontime); /* Remove the child containers */ while ((co = TAILQ_FIRST(&sc->aac_container_tqh)) != NULL) { @@ -587,12 +681,12 @@ aac_detach(device_t dev) } if (sc->aifflags & AAC_AIFFLAGS_RUNNING) - panic("Cannot shutdown AIF thread\n"); + panic("Cannot shutdown AIF thread"); if ((error = aac_shutdown(dev))) return(error); - EVENTHANDLER_DEREGISTER(shutdown_post_sync, sc->eh); + EVENTHANDLER_DEREGISTER(shutdown_final, sc->eh); aac_free(sc); @@ -611,16 +705,15 @@ aac_detach(device_t dev) * Note that we can assume that the bioq on the controller is empty, as we won't * allow shutdown if any device is open. */ -static int +int aac_shutdown(device_t dev) { struct aac_softc *sc; struct aac_fib *fib; struct aac_close_command *cc; - debug_called(1); - sc = device_get_softc(dev); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); sc->aac_state |= AAC_STATE_SUSPEND; @@ -631,7 +724,7 @@ aac_shutdown(device_t dev) */ device_printf(sc->aac_dev, "shutting down controller..."); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); aac_alloc_sync_fib(sc, &fib); cc = (struct aac_close_command *)&fib->data[0]; @@ -663,7 +756,7 @@ aac_shutdown(device_t dev) AAC_MASK_INTERRUPTS(sc); aac_release_sync_fib(sc); - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); return(0); } @@ -676,10 +769,9 @@ aac_suspend(device_t dev) { struct aac_softc *sc; - debug_called(1); - sc = device_get_softc(dev); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); sc->aac_state |= AAC_STATE_SUSPEND; AAC_MASK_INTERRUPTS(sc); @@ -694,10 +786,9 @@ aac_resume(device_t dev) { struct aac_softc *sc; - debug_called(1); - sc = device_get_softc(dev); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); sc->aac_state &= ~AAC_STATE_SUSPEND; AAC_UNMASK_INTERRUPTS(sc); return(0); @@ -715,11 +806,10 @@ aac_new_intr(void *arg) struct aac_fib *fib; int i; - debug_called(2); - sc = (struct aac_softc *)arg; - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); while (1) { index = AAC_GET_OUTB_QUEUE(sc); if (index == 0xffffffff) @@ -738,7 +828,7 @@ aac_new_intr(void *arg) 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); + ((u_int32_t *)fib)[i] = AAC_MEM1_GETREG4(sc, index + i*4); aac_handle_aif(sc, fib); kfree(fib, M_AACBUF); @@ -776,19 +866,21 @@ aac_new_intr(void *arg) if ((sc->flags & AAC_QUEUE_FRZN) == 0) aac_startio(sc); - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); } +/* + * Interrupt filter for !NEW_COMM interface. + */ void -aac_fast_intr(void *arg) +aac_filter(void *arg) { struct aac_softc *sc; u_int16_t reason; - debug_called(2); - sc = (struct aac_softc *)arg; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* * Read the status register directly. This is faster than taking the * driver lock and reading the queues directly. It also saves having @@ -814,7 +906,7 @@ aac_fast_intr(void *arg) /* * This might miss doing the actual wakeup. However, the - * ssleep that this is waking up has a timeout, so it will + * lksleep 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. @@ -834,13 +926,18 @@ void aac_startio(struct aac_softc *sc) { struct aac_command *cm; + int error; - debug_called(2); - - if (sc->flags & AAC_QUEUE_FRZN) - return; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); for (;;) { + /* + * This flag might be set if the card is out of resources. + * Checking it here prevents an infinite loop of deferrals. + */ + if (sc->flags & AAC_QUEUE_FRZN) + break; + /* * Try to get a command that's been put off for lack of * resources @@ -858,47 +955,30 @@ aac_startio(struct aac_softc *sc) if (cm == NULL) break; + /* don't map more than once */ + if (cm->cm_flags & AAC_CMD_MAPPED) + panic("aac: command %p already mapped", cm); + /* - * Try to give the command to the controller. Any error is - * catastrophic since it means that bus_dmamap_load() failed. + * Set up the command to go to the controller. If there are no + * data buffers associated with the command then it can bypass + * busdma. */ - if (aac_map_command(cm) != 0) - panic("aac: error mapping command %p\n", cm); - } -} - -/* - * Deliver a command to the controller; allocate controller resources at the - * last moment when possible. - */ -static int -aac_map_command(struct aac_command *cm) -{ - struct aac_softc *sc; - int error; - - debug_called(2); - - sc = cm->cm_sc; - error = 0; - - /* don't map more than once */ - if (cm->cm_flags & AAC_CMD_MAPPED) - panic("aac: command %p already mapped", cm); - - 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); + 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) { + fwprintf(sc, HBA_FLAGS_DBG_COMM_B, "freezing queue\n"); + sc->flags |= AAC_QUEUE_FRZN; + error = 0; + } else if (error != 0) + panic("aac_startio: unexpected error %d from " + "busdma", error); + } else + aac_map_command_sg(cm, NULL, 0, 0); } - return (error); } /* @@ -912,30 +992,27 @@ aac_command_thread(void *arg) u_int32_t fib_size; int size, retval; - get_mplock(); - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); sc->aifflags = AAC_AIFFLAGS_RUNNING; while ((sc->aifflags & AAC_AIFFLAGS_EXIT) == 0) { + retval = 0; - if ((sc->aifflags & AAC_AIFFLAGS_PENDING) == 0) { - tsleep_interlock(sc->aifthread, 0); - AAC_LOCK_RELEASE(&sc->aac_io_lock); - retval = tsleep(sc->aifthread, PINTERLOCKED, + if ((sc->aifflags & AAC_AIFFLAGS_PENDING) == 0) + retval = lksleep(sc->aifthread, &sc->aac_io_lock, 0, "aifthd", AAC_PERIODIC_INTERVAL * hz); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); - } + /* * 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); + lockmgr(&sc->aac_io_lock, LK_RELEASE); aac_alloc_commands(sc); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); sc->aifflags &= ~AAC_AIFFLAGS_ALLOCFIBS; aac_startio(sc); } @@ -957,7 +1034,7 @@ aac_command_thread(void *arg) continue; for (;;) { if (aac_dequeue_fib(sc, AAC_HOST_NORM_CMD_QUEUE, - &fib_size, &fib)) + &fib_size, &fib)) break; AAC_PRINT_FIB(sc, fib); @@ -1000,10 +1077,8 @@ aac_command_thread(void *arg) } } sc->aifflags &= ~AAC_AIFFLAGS_RUNNING; - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); wakeup(sc->aac_dev); - - rel_mplock(); } /* @@ -1017,11 +1092,10 @@ aac_complete(void *context, int pending) struct aac_fib *fib; u_int32_t fib_size; - debug_called(2); - sc = (struct aac_softc *)context; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); /* pull completed commands off the queue */ for (;;) { @@ -1030,14 +1104,20 @@ aac_complete(void *context, int pending) &fib)) break; /* nothing to do */ - /* get the command, unmap and queue for later processing */ + /* get the command, unmap and hand off for processing */ cm = sc->aac_commands + fib->Header.SenderData; if (cm == NULL) { AAC_PRINT_FIB(sc, fib); break; } + if ((cm->cm_flags & AAC_CMD_TIMEDOUT) != 0) + device_printf(sc->aac_dev, + "COMMAND %p COMPLETED AFTER %d SECONDS\n", + cm, (int)(time_second-cm->cm_timestamp)); + aac_remove_busy(cm); - aac_unmap_command(cm); /* XXX defer? */ + + aac_unmap_command(cm); cm->cm_flags |= AAC_CMD_COMPLETED; /* is there a completion handler? */ @@ -1053,7 +1133,7 @@ aac_complete(void *context, int pending) sc->flags &= ~AAC_QUEUE_FRZN; aac_startio(sc); - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); } /* @@ -1064,10 +1144,9 @@ aac_submit_bio(struct aac_disk *ad, struct bio *bio) { struct aac_softc *sc; - debug_called(2); - bio->bio_driver_info = ad; sc = ad->ad_controller; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* queue the BIO and try to get some work done */ aac_enqueue_bio(sc, bio); @@ -1086,7 +1165,7 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp) struct bio *bio; struct buf *bp; - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* get the resources we will need */ cm = NULL; @@ -1103,7 +1182,6 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp) cm->cm_complete = aac_bio_complete; cm->cm_private = bio; cm->cm_timestamp = time_second; - cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; /* build the FIB */ fib = cm->cm_fib; @@ -1175,7 +1253,7 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp) br->Pad = 0; br->Flags = 0; fib->Header.Size += sizeof(struct aac_blockread64); - cm->cm_flags |= AAC_CMD_DATAOUT; + cm->cm_flags |= AAC_CMD_DATAIN; cm->cm_sgtable = (struct aac_sg_table *)&br->SgMap64; } else { struct aac_blockwrite64 *bw; @@ -1187,7 +1265,7 @@ aac_bio_command(struct aac_softc *sc, struct aac_command **cmp) bw->Pad = 0; bw->Flags = 0; fib->Header.Size += sizeof(struct aac_blockwrite64); - cm->cm_flags |= AAC_CMD_DATAIN; + cm->cm_flags |= AAC_CMD_DATAOUT; cm->cm_sgtable = (struct aac_sg_table *)&bw->SgMap64; } } @@ -1241,104 +1319,6 @@ aac_bio_complete(struct aac_command *cm) aac_biodone(bio, code); } -/* - * 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_int64_t lba, void *data, int dumppages) -{ - struct aac_softc *sc; - struct aac_command *cm; - struct aac_fib *fib; - struct aac_blockwrite *bw; - - sc = ad->ad_controller; - cm = NULL; - - KKASSERT(lba <= 0x100000000ULL); - - 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_map_command(cm)); -} - -/* - * Wait for the card's queue to drain when dumping. Also check for monitor - * kprintf'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. * XXX This is very dangerous! If the card has gone out to lunch, we could @@ -1355,20 +1335,13 @@ aac_wait_command(struct aac_command *cm) struct aac_softc *sc; int error; - debug_called(2); - sc = cm->cm_sc; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* 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(sc); - /* Lock is held */ - KKASSERT(lockstatus(&sc->aac_io_lock, curthread) != 0); - tsleep_interlock(cm, 0); - AAC_LOCK_RELEASE(&sc->aac_io_lock); - error = tsleep(cm, PINTERLOCKED, "aacwait", 0); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + error = lksleep(cm, &sc->aac_io_lock, 0, "aacwait", 0); return(error); } @@ -1384,7 +1357,7 @@ aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp) { struct aac_command *cm; - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); if ((cm = aac_dequeue_free(sc)) == NULL) { if (sc->total_fibs < sc->aac_max_fibs) { @@ -1407,13 +1380,15 @@ aac_release_command(struct aac_command *cm) struct aac_event *event; struct aac_softc *sc; - debug_called(3); + sc = cm->cm_sc; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - /* (re)initialise the command/FIB */ + /* (re)initialize the command/FIB */ cm->cm_sgtable = NULL; cm->cm_flags = 0; cm->cm_complete = NULL; cm->cm_private = NULL; + cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; cm->cm_fib->Header.XferState = AAC_FIBSTATE_EMPTY; cm->cm_fib->Header.StructType = AAC_FIBTYPE_TFIB; cm->cm_fib->Header.Flags = 0; @@ -1422,16 +1397,18 @@ aac_release_command(struct aac_command *cm) /* * 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. + * initialized here for debugging purposes only. */ 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) { + /* + * Dequeue all events so that there's no risk of events getting + * stranded. + */ + while ((event = TAILQ_FIRST(&sc->aac_ev_cmfree)) != NULL) { TAILQ_REMOVE(&sc->aac_ev_cmfree, event, ev_links); event->ev_callback(sc, event, event->ev_arg); } @@ -1447,13 +1424,11 @@ aac_map_command_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) fibphys = (uint64_t *)arg; - debug_called(3); - *fibphys = segs[0].ds_addr; } /* - * Allocate and initialise commands/FIBs for this adapter. + * Allocate and initialize commands/FIBs for this adapter. */ static int aac_alloc_commands(struct aac_softc *sc) @@ -1463,7 +1438,7 @@ aac_alloc_commands(struct aac_softc *sc) uint64_t fibphys; int i, error; - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); if (sc->total_fibs + sc->aac_max_fibs_alloc > sc->aac_max_fibs) return (ENOMEM); @@ -1480,11 +1455,11 @@ aac_alloc_commands(struct aac_softc *sc) } /* 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); + (void)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 */ + /* initialize constant fields in the command structure */ 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; @@ -1498,17 +1473,17 @@ aac_alloc_commands(struct aac_softc *sc) if ((error = bus_dmamap_create(sc->aac_buffer_dmat, 0, &cm->cm_datamap)) != 0) break; - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); aac_release_command(cm); sc->total_fibs++; - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); } if (i > 0) { - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); 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); + fwprintf(sc, HBA_FLAGS_DBG_COMM_B, "total_fibs= %d\n", sc->total_fibs); + lockmgr(&sc->aac_io_lock, LK_RELEASE); return (0); } @@ -1528,7 +1503,7 @@ aac_free_commands(struct aac_softc *sc) struct aac_command *cm; int i; - debug_called(1); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); while ((fm = TAILQ_FIRST(&sc->aac_fibmap_tqh)) != NULL) { @@ -1558,11 +1533,10 @@ aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) struct aac_fib *fib; int i; - debug_called(3); - cm = (struct aac_command *)arg; sc = cm->cm_sc; fib = cm->cm_fib; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* copy into the FIB */ if (cm->cm_sgtable != NULL) { @@ -1628,7 +1602,6 @@ aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) aac_unmap_command(cm); sc->flags |= AAC_QUEUE_FRZN; aac_requeue_ready(cm); - break; } DELAY(5); /* wait 5 usec. */ } @@ -1640,6 +1613,8 @@ aac_map_command_sg(void *arg, bus_dma_segment_t *segs, int nseg, int error) aac_requeue_ready(cm); } } + + return; } /* @@ -1650,9 +1625,8 @@ aac_unmap_command(struct aac_command *cm) { struct aac_softc *sc; - debug_called(2); - sc = cm->cm_sc; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); if (!(cm->cm_flags & AAC_CMD_MAPPED)) return; @@ -1675,16 +1649,15 @@ aac_unmap_command(struct aac_command *cm) */ /* - * Initialise the adapter. + * Initialize the adapter. */ static void aac_common_map(void *arg, bus_dma_segment_t *segs, int nseg, int error) { struct aac_softc *sc; - debug_called(1); - sc = (struct aac_softc *)arg; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); sc->aac_common_busaddr = segs[0].ds_addr; } @@ -1692,10 +1665,33 @@ 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 = 0, atu_size = 0; + u_int32_t code, major, minor, options = 0, atu_size = 0; int status; + time_t then; - debug_called(1); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + /* + * Wait for the adapter to come ready. + */ + then = time_second; + do { + code = AAC_GET_FWSTATUS(sc); + if (code & AAC_SELF_TEST_FAILED) { + device_printf(sc->aac_dev, "FATAL: selftest failed\n"); + return(ENXIO); + } + if (code & AAC_KERNEL_PANIC) { + device_printf(sc->aac_dev, + "FATAL: controller kernel panic"); + return(ENXIO); + } + if (time_second > (then + AAC_BOOT_TIMEOUT)) { + device_printf(sc->aac_dev, + "FATAL: controller not coming ready, " + "status %x\n", code); + return(ENXIO); + } + } while (!(code & AAC_UP_AND_RUNNING)); /* * Retrieve the firmware version numbers. Dell PERC2/QC cards with @@ -1759,26 +1755,33 @@ aac_check_firmware(struct aac_softc *sc) /* Remap mem. resource, if required */ if ((sc->flags & AAC_FLAGS_NEW_COMM) && - atu_size > rman_get_size(sc->aac_regs_resource)) { + atu_size > rman_get_size(sc->aac_regs_res1)) { 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, + sc->aac_regs_rid1, sc->aac_regs_res1); + sc->aac_regs_res1 = bus_alloc_resource( + sc->aac_dev, SYS_RES_MEMORY, &sc->aac_regs_rid1, 0ul, ~0ul, atu_size, RF_ACTIVE); - if (sc->aac_regs_resource == NULL) { - sc->aac_regs_resource = bus_alloc_resource_any( + if (sc->aac_regs_res1 == NULL) { + sc->aac_regs_res1 = bus_alloc_resource_any( sc->aac_dev, SYS_RES_MEMORY, - &sc->aac_regs_rid, RF_ACTIVE); - if (sc->aac_regs_resource == NULL) { + &sc->aac_regs_rid1, RF_ACTIVE); + if (sc->aac_regs_res1 == 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); + sc->aac_btag1 = rman_get_bustag(sc->aac_regs_res1); + sc->aac_bhandle1 = rman_get_bushandle(sc->aac_regs_res1); + + if (sc->aac_hwif == AAC_HWIF_NARK) { + sc->aac_regs_res0 = sc->aac_regs_res1; + sc->aac_regs_rid0 = sc->aac_regs_rid1; + sc->aac_btag0 = sc->aac_btag1; + sc->aac_bhandle0 = sc->aac_bhandle1; + } } /* Read preferred settings */ @@ -1786,14 +1789,12 @@ aac_check_firmware(struct aac_softc *sc) 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); + - sizeof(struct aac_blockwrite64)) + / sizeof(struct aac_sg_entry64); else sc->aac_sg_tablesize = (AAC_FIB_DATASIZE - - sizeof(struct aac_blockwrite) - + sizeof(struct aac_sg_table)) - / sizeof(struct aac_sg_table); + - sizeof(struct aac_blockwrite)) + / sizeof(struct aac_sg_entry); if (!aac_sync_command(sc, AAC_MONKER_GETCOMMPREF, 0, 0, 0, 0, NULL)) { options = AAC_GET_MAILBOX(sc, 1); @@ -1808,6 +1809,16 @@ aac_check_firmware(struct aac_softc *sc) sc->aac_max_fib_size = PAGE_SIZE; sc->aac_max_fibs_alloc = PAGE_SIZE / sc->aac_max_fib_size; + if (sc->aac_max_fib_size > sizeof(struct aac_fib)) { + sc->flags |= AAC_FLAGS_RAW_IO; + device_printf(sc->aac_dev, "Enable Raw I/O\n"); + } + if ((sc->flags & AAC_FLAGS_RAW_IO) && + (sc->flags & AAC_FLAGS_ARRAY_64BIT)) { + sc->flags |= AAC_FLAGS_LBA_64BIT; + device_printf(sc->aac_dev, "Enable 64-bit array\n"); + } + return (0); } @@ -1815,127 +1826,10 @@ static int aac_init(struct aac_softc *sc) { struct aac_adapter_init *ip; - time_t then; - u_int32_t code, qoffset; + u_int32_t qoffset; int error; - debug_called(1); - - /* - * First wait for the adapter to come ready. - */ - then = time_second; - do { - code = AAC_GET_FWSTATUS(sc); - if (code & AAC_SELF_TEST_FAILED) { - device_printf(sc->aac_dev, "FATAL: selftest failed\n"); - return(ENXIO); - } - if (code & AAC_KERNEL_PANIC) { - device_printf(sc->aac_dev, - "FATAL: controller kernel panic\n"); - return(ENXIO); - } - if (time_second > (then + AAC_BOOT_TIMEOUT)) { - device_printf(sc->aac_dev, - "FATAL: controller not coming ready, " - "status %x\n", code); - return(ENXIO); - } - } while (!(code & AAC_UP_AND_RUNNING)); - - error = ENOMEM; - /* - * Create DMA tag for mapping buffers into controller-addressable space. - */ - 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 */ - sc->aac_sg_tablesize, /* nsegments */ - MAXBSIZE, /* maxsegsize */ - BUS_DMA_ALLOCNOW, /* flags */ - &sc->aac_buffer_dmat)) { - device_printf(sc->aac_dev, "can't allocate buffer DMA tag\n"); - goto out; - } - - /* - * Create DMA tag for mapping FIBs into controller-addressable space.. - */ - if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */ - 1, 0, /* algnmnt, boundary */ - (sc->flags & AAC_FLAGS_4GB_WINDOW) ? - BUS_SPACE_MAXADDR_32BIT : - 0x7fffffff, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - sc->aac_max_fibs_alloc * - sc->aac_max_fib_size, /* maxsize */ - 1, /* nsegments */ - 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; - } - - /* - * Create DMA tag for the common structure and allocate it. - */ - if (bus_dma_tag_create(sc->aac_parent_dmat, /* parent */ - 1, 0, /* algnmnt, boundary */ - (sc->flags & AAC_FLAGS_4GB_WINDOW) ? - BUS_SPACE_MAXADDR_32BIT : - 0x7fffffff, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - 8192 + sizeof(struct aac_common), /* maxsize */ - 1, /* nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - 0, /* flags */ - &sc->aac_common_dmat)) { - device_printf(sc->aac_dev, - "can't allocate common structure DMA tag\n"); - goto out; - } - if (bus_dmamem_alloc(sc->aac_common_dmat, (void **)&sc->aac_common, - BUS_DMA_NOWAIT, &sc->aac_common_dmamap)) { - device_printf(sc->aac_dev, "can't allocate common structure\n"); - goto out; - } - /* - * Work around a bug in the 2120 and 2200 that cannot DMA commands - * below address 8192 in physical memory. - * XXX If the padding is not needed, can it be put to use instead - * of ignored? - */ - bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap, - sc->aac_common, 8192 + sizeof(*sc->aac_common), - aac_common_map, sc, 0); - - if (sc->aac_common_busaddr < 8192) { - sc->aac_common = - (struct aac_common *)((uint8_t *)sc->aac_common + 8192); - sc->aac_common_busaddr += 8192; - } - bzero(sc->aac_common, sizeof(*sc->aac_common)); - - /* Allocate some FIBs and associated command structs */ - 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; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* * Fill in the init structure. This tells the adapter about the @@ -1965,8 +1859,7 @@ aac_init(struct aac_softc *sc) * 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; + ip->HostPhysMemPages = ctob(physmem) / AAC_PAGE_SIZE; if (sc->flags & AAC_FLAGS_BROKEN_MEMMAP) { ip->HostPhysMemPages = (ip->HostPhysMemPages + AAC_PAGE_SIZE) / AAC_PAGE_SIZE; @@ -1975,7 +1868,7 @@ aac_init(struct aac_softc *sc) ip->InitFlags = 0; if (sc->flags & AAC_FLAGS_NEW_COMM) { - ip->InitFlags = INITFLAGS_NEW_COMM_SUPPORTED; + ip->InitFlags |= AAC_INITFLAGS_NEW_COMM_SUPPORTED; device_printf(sc->aac_dev, "New comm. interface enabled\n"); } @@ -1984,7 +1877,7 @@ aac_init(struct aac_softc *sc) ip->MaxFibSize = sc->aac_max_fib_size; /* - * Initialise FIB queues. Note that it appears that the layout of the + * Initialize 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. * @@ -2059,10 +1952,10 @@ aac_init(struct aac_softc *sc) */ switch (sc->aac_hwif) { case AAC_HWIF_I960RX: - AAC_SETREG4(sc, AAC_RX_ODBR, ~0); + AAC_MEM0_SETREG4(sc, AAC_RX_ODBR, ~0); break; case AAC_HWIF_RKT: - AAC_SETREG4(sc, AAC_RKT_ODBR, ~0); + AAC_MEM0_SETREG4(sc, AAC_RKT_ODBR, ~0); break; default: break; @@ -2086,6 +1979,36 @@ out: return(error); } +static int +aac_setup_intr(struct aac_softc *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, + 0, aac_filter, + sc, &sc->aac_intr, NULL)) { + device_printf(sc->aac_dev, + "can't set up interrupt filter\n"); + return (EINVAL); + } + } + return (0); +} + /* * Send a synchronous command to the controller and wait for a result. * Indicate if the controller completed the command with an error status. @@ -2098,7 +2021,7 @@ aac_sync_command(struct aac_softc *sc, u_int32_t command, time_t then; u_int32_t status; - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* populate the mailbox */ AAC_SET_MAILBOX(sc, command, arg0, arg1, arg2, arg3); @@ -2113,7 +2036,7 @@ aac_sync_command(struct aac_softc *sc, u_int32_t command, then = time_second; do { if (time_second > (then + AAC_IMMEDIATE_TIMEOUT)) { - debug(1, "timed out"); + fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, "timed out"); return(EIO); } } while (!(AAC_GET_ISTATUS(sc) & AAC_DB_SYNC_COMMAND)); @@ -2135,8 +2058,10 @@ int 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); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); +#if 0 /* XXX swildner */ KKASSERT(lockstatus(&sc->aac_io_lock, curthread) != 0); +#endif if (datasize > AAC_FIB_DATASIZE) return(EINVAL); @@ -2150,7 +2075,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, fib->Header.XferState |= xferstate; fib->Header.Command = command; fib->Header.StructType = AAC_FIBTYPE_TFIB; - fib->Header.Size = sizeof(struct aac_fib) + datasize; + fib->Header.Size = sizeof(struct aac_fib_header) + datasize; fib->Header.SenderSize = sizeof(struct aac_fib); fib->Header.SenderFibAddress = 0; /* Not needed */ fib->Header.ReceiverFibAddress = sc->aac_common_busaddr + @@ -2162,7 +2087,7 @@ aac_sync_fib(struct aac_softc *sc, u_int32_t command, u_int32_t xferstate, */ if (aac_sync_command(sc, AAC_MONKER_SYNCFIB, fib->Header.ReceiverFibAddress, 0, 0, 0, NULL)) { - debug(2, "IO error"); + fwprintf(sc, HBA_FLAGS_DBG_ERROR_B, "IO error"); return(EIO); } @@ -2206,7 +2131,7 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm) u_int32_t fib_size; u_int32_t fib_addr; - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); fib_size = cm->cm_fib->Header.Size; fib_addr = cm->cm_fib->Header.ReceiverFibAddress; @@ -2224,14 +2149,13 @@ aac_enqueue_fib(struct aac_softc *sc, int queue, struct aac_command *cm) error = EBUSY; goto out; } + /* * To avoid a race with its completion interrupt, place this command on * the busy queue prior to advertising it to the controller. */ aac_enqueue_busy(cm); - - /* populate queue entry */ (sc->aac_qentries[queue] + pi)->aq_fib_size = fib_size; (sc->aac_qentries[queue] + pi)->aq_fib_addr = fib_addr; @@ -2262,7 +2186,7 @@ aac_dequeue_fib(struct aac_softc *sc, int queue, u_int32_t *fib_size, int error; int notify; - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* get the producer/consumer indices */ pi = sc->aac_queues->qt_qindex[queue][AAC_PRODUCER_INDEX]; @@ -2357,7 +2281,7 @@ aac_enqueue_response(struct aac_softc *sc, int queue, struct aac_fib *fib) u_int32_t fib_size; u_int32_t fib_addr; - debug_called(1); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* Tell the adapter where the FIB is */ fib_size = fib->Header.Size; @@ -2400,12 +2324,12 @@ out: * and complain about them. */ static void -aac_timeout(void *xsc) +aac_timeout(struct aac_softc *sc) { - struct aac_softc *sc = xsc; struct aac_command *cm; time_t deadline; int timedout, code; + /* * Traverse the busy command list, bitch about late commands once * only. @@ -2414,23 +2338,25 @@ aac_timeout(void *xsc) deadline = time_second - AAC_CMD_TIMEOUT; TAILQ_FOREACH(cm, &sc->aac_busy, cm_link) { if ((cm->cm_timestamp < deadline) - /* && !(cm->cm_flags & AAC_CMD_TIMEDOUT) */) { + && !(cm->cm_flags & AAC_CMD_TIMEDOUT)) { cm->cm_flags |= AAC_CMD_TIMEDOUT; device_printf(sc->aac_dev, - "COMMAND %p TIMEOUT AFTER %d SECONDS\n", - cm, (int)(time_second-cm->cm_timestamp)); + "COMMAND %p (TYPE %d) TIMEOUT AFTER %d SECONDS\n", + cm, cm->cm_fib->Header.Command, + (int)(time_second-cm->cm_timestamp)); AAC_PRINT_FIB(sc, cm->cm_fib); timedout++; } } + if (timedout) { code = AAC_GET_FWSTATUS(sc); if (code != AAC_UP_AND_RUNNING) { device_printf(sc->aac_dev, "WARNING! Controller is no " "longer running! code= 0x%x\n", code); - } } + return; } /* @@ -2443,36 +2369,27 @@ aac_timeout(void *xsc) static int aac_sa_get_fwstatus(struct aac_softc *sc) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - return(AAC_GETREG4(sc, AAC_SA_FWSTATUS)); + return(AAC_MEM0_GETREG4(sc, AAC_SA_FWSTATUS)); } static int aac_rx_get_fwstatus(struct aac_softc *sc) { - debug_called(3); - - return(AAC_GETREG4(sc, AAC_RX_FWSTATUS)); -} - -static int -aac_fa_get_fwstatus(struct aac_softc *sc) -{ - int val; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - debug_called(3); - - val = AAC_GETREG4(sc, AAC_FA_FWSTATUS); - return (val); + return(AAC_MEM0_GETREG4(sc, sc->flags & AAC_FLAGS_NEW_COMM ? + AAC_RX_OMR0 : AAC_RX_FWSTATUS)); } static int aac_rkt_get_fwstatus(struct aac_softc *sc) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - return(AAC_GETREG4(sc, AAC_RKT_FWSTATUS)); + return(AAC_MEM0_GETREG4(sc, sc->flags & AAC_FLAGS_NEW_COMM ? + AAC_RKT_OMR0 : AAC_RKT_FWSTATUS)); } /* @@ -2482,34 +2399,25 @@ aac_rkt_get_fwstatus(struct aac_softc *sc) static void aac_sa_qnotify(struct aac_softc *sc, int qbit) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit); + AAC_MEM0_SETREG2(sc, AAC_SA_DOORBELL1_SET, qbit); } static void aac_rx_qnotify(struct aac_softc *sc, int qbit) { - debug_called(3); - - AAC_SETREG4(sc, AAC_RX_IDBR, qbit); -} - -static void -aac_fa_qnotify(struct aac_softc *sc, int qbit) -{ - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_SETREG2(sc, AAC_FA_DOORBELL1, qbit); - AAC_FA_HACK(sc); + AAC_MEM0_SETREG4(sc, AAC_RX_IDBR, qbit); } static void aac_rkt_qnotify(struct aac_softc *sc, int qbit) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_SETREG4(sc, AAC_RKT_IDBR, qbit); + AAC_MEM0_SETREG4(sc, AAC_RKT_IDBR, qbit); } /* @@ -2518,36 +2426,25 @@ aac_rkt_qnotify(struct aac_softc *sc, int qbit) static int aac_sa_get_istatus(struct aac_softc *sc) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - return(AAC_GETREG2(sc, AAC_SA_DOORBELL0)); + return(AAC_MEM0_GETREG2(sc, AAC_SA_DOORBELL0)); } static int aac_rx_get_istatus(struct aac_softc *sc) { - debug_called(3); - - return(AAC_GETREG4(sc, AAC_RX_ODBR)); -} - -static int -aac_fa_get_istatus(struct aac_softc *sc) -{ - int val; - - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - val = AAC_GETREG2(sc, AAC_FA_DOORBELL0); - return (val); + return(AAC_MEM0_GETREG4(sc, AAC_RX_ODBR)); } static int aac_rkt_get_istatus(struct aac_softc *sc) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - return(AAC_GETREG4(sc, AAC_RKT_ODBR)); + return(AAC_MEM0_GETREG4(sc, AAC_RKT_ODBR)); } /* @@ -2556,34 +2453,25 @@ aac_rkt_get_istatus(struct aac_softc *sc) static void aac_sa_clear_istatus(struct aac_softc *sc, int mask) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask); + AAC_MEM0_SETREG2(sc, AAC_SA_DOORBELL0_CLEAR, mask); } static void aac_rx_clear_istatus(struct aac_softc *sc, int mask) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_SETREG4(sc, AAC_RX_ODBR, mask); -} - -static void -aac_fa_clear_istatus(struct aac_softc *sc, int mask) -{ - debug_called(3); - - AAC_SETREG2(sc, AAC_FA_DOORBELL0_CLEAR, mask); - AAC_FA_HACK(sc); + AAC_MEM0_SETREG4(sc, AAC_RX_ODBR, mask); } static void aac_rkt_clear_istatus(struct aac_softc *sc, int mask) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_SETREG4(sc, AAC_RKT_ODBR, mask); + AAC_MEM0_SETREG4(sc, AAC_RKT_ODBR, mask); } /* @@ -2593,57 +2481,39 @@ static void aac_sa_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); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_SETREG4(sc, AAC_SA_MAILBOX, command); - AAC_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0); - AAC_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1); - AAC_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2); - AAC_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3); + AAC_MEM1_SETREG4(sc, AAC_SA_MAILBOX, command); + AAC_MEM1_SETREG4(sc, AAC_SA_MAILBOX + 4, arg0); + AAC_MEM1_SETREG4(sc, AAC_SA_MAILBOX + 8, arg1); + AAC_MEM1_SETREG4(sc, AAC_SA_MAILBOX + 12, arg2); + AAC_MEM1_SETREG4(sc, AAC_SA_MAILBOX + 16, arg3); } static void aac_rx_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_RX_MAILBOX, command); - AAC_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0); - AAC_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1); - AAC_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2); - AAC_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3); -} - -static void -aac_fa_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); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_SETREG4(sc, AAC_FA_MAILBOX, command); - AAC_FA_HACK(sc); - AAC_SETREG4(sc, AAC_FA_MAILBOX + 4, arg0); - AAC_FA_HACK(sc); - AAC_SETREG4(sc, AAC_FA_MAILBOX + 8, arg1); - AAC_FA_HACK(sc); - AAC_SETREG4(sc, AAC_FA_MAILBOX + 12, arg2); - AAC_FA_HACK(sc); - AAC_SETREG4(sc, AAC_FA_MAILBOX + 16, arg3); - AAC_FA_HACK(sc); + AAC_MEM1_SETREG4(sc, AAC_RX_MAILBOX, command); + AAC_MEM1_SETREG4(sc, AAC_RX_MAILBOX + 4, arg0); + AAC_MEM1_SETREG4(sc, AAC_RX_MAILBOX + 8, arg1); + AAC_MEM1_SETREG4(sc, AAC_RX_MAILBOX + 12, arg2); + AAC_MEM1_SETREG4(sc, AAC_RX_MAILBOX + 16, arg3); } 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); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - 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); + AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX, command); + AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX + 4, arg0); + AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX + 8, arg1); + AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX + 12, arg2); + AAC_MEM1_SETREG4(sc, AAC_RKT_MAILBOX + 16, arg3); } /* @@ -2652,36 +2522,25 @@ aac_rkt_set_mailbox(struct aac_softc *sc, u_int32_t command, u_int32_t arg0, static int aac_sa_get_mailbox(struct aac_softc *sc, int mb) { - debug_called(4); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - return(AAC_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4))); + return(AAC_MEM1_GETREG4(sc, AAC_SA_MAILBOX + (mb * 4))); } static int aac_rx_get_mailbox(struct aac_softc *sc, int mb) { - debug_called(4); - - return(AAC_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4))); -} - -static int -aac_fa_get_mailbox(struct aac_softc *sc, int mb) -{ - int val; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - debug_called(4); - - val = AAC_GETREG4(sc, AAC_FA_MAILBOX + (mb * 4)); - return (val); + return(AAC_MEM1_GETREG4(sc, AAC_RX_MAILBOX + (mb * 4))); } static int aac_rkt_get_mailbox(struct aac_softc *sc, int mb) { - debug_called(4); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - return(AAC_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4))); + return(AAC_MEM1_GETREG4(sc, AAC_RKT_MAILBOX + (mb * 4))); } /* @@ -2690,56 +2549,42 @@ aac_rkt_get_mailbox(struct aac_softc *sc, int mb) static void aac_sa_set_interrupts(struct aac_softc *sc, int enable) { - debug(2, "%sable interrupts", enable ? "en" : "dis"); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "%sable interrupts", enable ? "en" : "dis"); if (enable) { - AAC_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS); + AAC_MEM0_SETREG2((sc), AAC_SA_MASK0_CLEAR, AAC_DB_INTERRUPTS); } else { - AAC_SETREG2((sc), AAC_SA_MASK0_SET, ~0); + AAC_MEM0_SETREG2((sc), AAC_SA_MASK0_SET, ~0); } } static void aac_rx_set_interrupts(struct aac_softc *sc, int enable) { - debug(2, "%sable interrupts", enable ? "en" : "dis"); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "%sable interrupts", enable ? "en" : "dis"); if (enable) { if (sc->flags & AAC_FLAGS_NEW_COMM) - AAC_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INT_NEW_COMM); + AAC_MEM0_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); - } -} - -static void -aac_fa_set_interrupts(struct aac_softc *sc, int enable) -{ - debug(2, "%sable interrupts", enable ? "en" : "dis"); - - if (enable) { - AAC_SETREG2((sc), AAC_FA_MASK0_CLEAR, AAC_DB_INTERRUPTS); - AAC_FA_HACK(sc); + AAC_MEM0_SETREG4(sc, AAC_RX_OIMR, ~AAC_DB_INTERRUPTS); } else { - AAC_SETREG2((sc), AAC_FA_MASK0, ~0); - AAC_FA_HACK(sc); + AAC_MEM0_SETREG4(sc, AAC_RX_OIMR, ~0); } } static void aac_rkt_set_interrupts(struct aac_softc *sc, int enable) { - debug(2, "%sable interrupts", enable ? "en" : "dis"); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "%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); + AAC_MEM0_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INT_NEW_COMM); else - AAC_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS); + AAC_MEM0_SETREG4(sc, AAC_RKT_OIMR, ~AAC_DB_INTERRUPTS); } else { - AAC_SETREG4(sc, AAC_RKT_OIMR, ~0); + AAC_MEM0_SETREG4(sc, AAC_RKT_OIMR, ~0); } } @@ -2751,21 +2596,21 @@ aac_rx_send_command(struct aac_softc *sc, struct aac_command *cm) { u_int32_t index, device; - debug(2, "send command (new comm.)"); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "send command (new comm.)"); - index = AAC_GETREG4(sc, AAC_RX_IQUE); + index = AAC_MEM0_GETREG4(sc, AAC_RX_IQUE); if (index == 0xffffffffL) - index = AAC_GETREG4(sc, AAC_RX_IQUE); + index = AAC_MEM0_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)); + AAC_MEM1_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys & 0xffffffffUL)); device += 4; - AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys >> 32)); + AAC_MEM1_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); + AAC_MEM1_SETREG4(sc, device, cm->cm_fib->Header.Size); + AAC_MEM0_SETREG4(sc, AAC_RX_IQUE, index); return 0; } @@ -2774,21 +2619,21 @@ aac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm) { u_int32_t index, device; - debug(2, "send command (new comm.)"); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "send command (new comm.)"); - index = AAC_GETREG4(sc, AAC_RKT_IQUE); + index = AAC_MEM0_GETREG4(sc, AAC_RKT_IQUE); if (index == 0xffffffffL) - index = AAC_GETREG4(sc, AAC_RKT_IQUE); + index = AAC_MEM0_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)); + AAC_MEM1_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys & 0xffffffffUL)); device += 4; - AAC_SETREG4(sc, device, (u_int32_t)(cm->cm_fibphys >> 32)); + AAC_MEM1_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); + AAC_MEM1_SETREG4(sc, device, cm->cm_fib->Header.Size); + AAC_MEM0_SETREG4(sc, AAC_RKT_IQUE, index); return 0; } @@ -2798,33 +2643,33 @@ aac_rkt_send_command(struct aac_softc *sc, struct aac_command *cm) static int aac_rx_get_outb_queue(struct aac_softc *sc) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - return(AAC_GETREG4(sc, AAC_RX_OQUE)); + return(AAC_MEM0_GETREG4(sc, AAC_RX_OQUE)); } static int aac_rkt_get_outb_queue(struct aac_softc *sc) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - return(AAC_GETREG4(sc, AAC_RKT_OQUE)); + return(AAC_MEM0_GETREG4(sc, AAC_RKT_OQUE)); } static void aac_rx_set_outb_queue(struct aac_softc *sc, int index) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_SETREG4(sc, AAC_RX_OQUE, index); + AAC_MEM0_SETREG4(sc, AAC_RX_OQUE, index); } static void aac_rkt_set_outb_queue(struct aac_softc *sc, int index) { - debug_called(3); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_SETREG4(sc, AAC_RKT_OQUE, index); + AAC_MEM0_SETREG4(sc, AAC_RKT_OQUE, index); } /* @@ -2839,17 +2684,18 @@ aac_describe_controller(struct aac_softc *sc) { struct aac_fib *fib; struct aac_adapter_info *info; + char *adapter_type = "Adaptec RAID controller"; - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); 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); + lockmgr(&sc->aac_io_lock, LK_RELEASE); return; } @@ -2857,12 +2703,6 @@ aac_describe_controller(struct aac_softc *sc) info = (struct aac_adapter_info *)&fib->data[0]; sc->aac_revision = info->KernelRevision; - device_printf(sc->aac_dev, "Adaptec Raid Controller %d.%d.%d-%d\n", - AAC_DRIVER_VERSION >> 24, - (AAC_DRIVER_VERSION >> 16) & 0xFF, - AAC_DRIVER_VERSION & 0xFF, - AAC_DRIVER_BUILD); - if (bootverbose) { device_printf(sc->aac_dev, "%s %dMHz, %dMB memory " "(%dMB cache, %dMB execution), %s\n", @@ -2904,8 +2744,23 @@ aac_describe_controller(struct aac_softc *sc) "\23ARRAY64BIT" "\24HEATSENSOR"); } + + if (sc->supported_options & AAC_SUPPORTED_SUPPLEMENT_ADAPTER_INFO) { + fib->data[0] = 0; + if (aac_sync_fib(sc, RequestSupplementAdapterInfo, 0, fib, 1)) + device_printf(sc->aac_dev, + "RequestSupplementAdapterInfo failed\n"); + else + adapter_type = ((struct aac_supplement_adapter_info *) + &fib->data[0])->AdapterTypeText; + } + device_printf(sc->aac_dev, "%s, aac driver %d.%d.%d-%d\n", + adapter_type, + AAC_DRIVER_MAJOR_VERSION, AAC_DRIVER_MINOR_VERSION, + AAC_DRIVER_BUGFIX_LEVEL, AAC_DRIVER_BUILD); + aac_release_sync_fib(sc); - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); } /* @@ -2933,31 +2788,9 @@ aac_open(struct dev_open_args *ap) cdev_t dev = ap->a_head.a_dev; struct aac_softc *sc; - debug_called(2); - - sc = dev->si_drv1; - - /* Check to make sure the device isn't already open */ - if (sc->aac_state & AAC_STATE_OPEN) { - return EBUSY; - } - sc->aac_state |= AAC_STATE_OPEN; - - return 0; -} - -static int -aac_close(struct dev_close_args *ap) -{ - cdev_t dev = ap->a_head.a_dev; - struct aac_softc *sc; - - debug_called(2); - sc = dev->si_drv1; - - /* Mark this unit as no longer open */ - sc->aac_state &= ~AAC_STATE_OPEN; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + device_busy(sc->aac_dev); return 0; } @@ -2965,23 +2798,24 @@ aac_close(struct dev_close_args *ap) static int aac_ioctl(struct dev_ioctl_args *ap) { - cdev_t dev = ap->a_head.a_dev; caddr_t arg = ap->a_data; - struct aac_softc *sc = dev->si_drv1; + cdev_t dev = ap->a_head.a_dev; + u_long cmd = ap->a_cmd; + union aac_statrequest *as; + struct aac_softc *sc; int error = 0; - uint32_t cookie; - debug_called(2); - - if (ap->a_cmd == AACIO_STATS) { - union aac_statrequest *as = (union aac_statrequest *)arg; + as = (union aac_statrequest *)arg; + sc = dev->si_drv1; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + switch (cmd) { + case AACIO_STATS: switch (as->as_item) { case AACQ_FREE: case AACQ_BIO: case AACQ_READY: case AACQ_BUSY: - case AACQ_COMPLETE: bcopy(&sc->aac_qstat[as->as_item], &as->as_qstat, sizeof(struct aac_qstat)); break; @@ -2989,55 +2823,59 @@ aac_ioctl(struct dev_ioctl_args *ap) error = ENOENT; break; } - return(error); - } + break; - arg = *(caddr_t *)arg; - - switch (ap->a_cmd) { - /* AACIO_STATS already handled above */ case FSACTL_SENDFIB: - debug(1, "FSACTL_SENDFIB"); + case FSACTL_SEND_LARGE_FIB: + arg = *(caddr_t*)arg; + case FSACTL_LNX_SENDFIB: + case FSACTL_LNX_SEND_LARGE_FIB: + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_SENDFIB"); error = aac_ioctl_sendfib(sc, arg); break; + case FSACTL_SEND_RAW_SRB: + arg = *(caddr_t*)arg; + case FSACTL_LNX_SEND_RAW_SRB: + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_SEND_RAW_SRB"); + error = aac_ioctl_send_raw_srb(sc, arg); + break; case FSACTL_AIF_THREAD: - debug(1, "FSACTL_AIF_THREAD"); + case FSACTL_LNX_AIF_THREAD: + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_AIF_THREAD"); error = EINVAL; break; case FSACTL_OPEN_GET_ADAPTER_FIB: - debug(1, "FSACTL_OPEN_GET_ADAPTER_FIB"); - /* - * Pass the caller out an AdapterFibContext. - * - * Note that because we only support one opener, we - * basically ignore this. Set the caller's context to a magic - * number just in case. - * - * 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. - */ - cookie = (uint32_t)(uintptr_t)sc->aifthread; - error = copyout(&cookie, arg, sizeof(cookie)); + arg = *(caddr_t*)arg; + case FSACTL_LNX_OPEN_GET_ADAPTER_FIB: + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_OPEN_GET_ADAPTER_FIB"); + error = aac_open_aif(sc, arg); break; case FSACTL_GET_NEXT_ADAPTER_FIB: - debug(1, "FSACTL_GET_NEXT_ADAPTER_FIB"); + arg = *(caddr_t*)arg; + case FSACTL_LNX_GET_NEXT_ADAPTER_FIB: + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_GET_NEXT_ADAPTER_FIB"); error = aac_getnext_aif(sc, arg); break; case FSACTL_CLOSE_GET_ADAPTER_FIB: - debug(1, "FSACTL_CLOSE_GET_ADAPTER_FIB"); - /* don't do anything here */ + arg = *(caddr_t*)arg; + case FSACTL_LNX_CLOSE_GET_ADAPTER_FIB: + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_CLOSE_GET_ADAPTER_FIB"); + error = aac_close_aif(sc, arg); break; case FSACTL_MINIPORT_REV_CHECK: - debug(1, "FSACTL_MINIPORT_REV_CHECK"); + arg = *(caddr_t*)arg; + case FSACTL_LNX_MINIPORT_REV_CHECK: + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_MINIPORT_REV_CHECK"); error = aac_rev_check(sc, arg); break; case FSACTL_QUERY_DISK: - debug(1, "FSACTL_QUERY_DISK"); + arg = *(caddr_t*)arg; + case FSACTL_LNX_QUERY_DISK: + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_QUERY_DISK"); error = aac_query_disk(sc, arg); break; case FSACTL_DELETE_DISK: + case FSACTL_LNX_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 @@ -3048,11 +2886,17 @@ aac_ioctl(struct dev_ioctl_args *ap) case FSACTL_GET_PCI_INFO: arg = *(caddr_t*)arg; case FSACTL_LNX_GET_PCI_INFO: - debug(1, "FSACTL_GET_PCI_INFO"); + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_GET_PCI_INFO"); error = aac_get_pci_info(sc, arg); break; + case FSACTL_GET_FEATURES: + arg = *(caddr_t*)arg; + case FSACTL_LNX_GET_FEATURES: + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "FSACTL_GET_FEATURES"); + error = aac_supported_features(sc, arg); + break; default: - debug(1, "unsupported cmd 0x%lx\n", ap->a_cmd); + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "unsupported cmd 0x%lx\n", cmd); error = EINVAL; break; } @@ -3060,7 +2904,7 @@ aac_ioctl(struct dev_ioctl_args *ap) } static struct filterops aac_filterops = - { FILTEROP_ISFD, NULL, aac_filter_detach, aac_filter }; + { FILTEROP_ISFD|FILTEROP_MPSAFE, NULL, aac_filter_detach, aac_filter_read }; static int aac_kqfilter(struct dev_kqfilter_args *ap) @@ -3099,19 +2943,21 @@ aac_filter_detach(struct knote *kn) } static int -aac_filter(struct knote *kn, long hint) +aac_filter_read(struct knote *kn, long hint) { - struct aac_softc *sc = (struct aac_softc *)kn->kn_hook; - int ready = 0; + struct aac_softc *sc; + struct aac_fib_context *ctx; - AAC_LOCK_ACQUIRE(&sc->aac_aifq_lock); - if (sc->aac_aifq_tail != sc->aac_aifq_head) - ready = 1; - AAC_LOCK_RELEASE(&sc->aac_aifq_lock); + sc = (struct aac_softc *)kn->kn_hook; - return (ready); -} + lockmgr(&sc->aac_aifq_lock, LK_EXCLUSIVE); + for (ctx = sc->fibctx; ctx; ctx = ctx->next) + if (ctx->ctx_idx != sc->aifq_idx || ctx->ctx_wrap) + return(1); + lockmgr(&sc->aac_aifq_lock, LK_RELEASE); + return (0); +} static void aac_ioctl_event(struct aac_softc *sc, struct aac_event *event, void *arg) @@ -3119,15 +2965,13 @@ 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); + KKASSERT(lockstatus(&sc->aac_io_lock, curthread) != 0); 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; @@ -3143,14 +2987,14 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) struct aac_command *cm; int size, error; - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); cm = NULL; /* * Get a command */ - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); if (aac_alloc_command(sc, &cm)) { struct aac_event *event; @@ -3160,12 +3004,9 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) event->ev_callback = aac_ioctl_event; event->ev_arg = &cm; aac_add_event(sc, event); - tsleep_interlock(&cm, 0); - AAC_LOCK_RELEASE(&sc->aac_io_lock); - tsleep(&cm, PINTERLOCKED, "sendfib", 0); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lksleep(&cm, &sc->aac_io_lock, 0, "sendfib", 0); } - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); /* * Fetch the FIB header, then re-copy to get data as well. @@ -3174,10 +3015,10 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) sizeof(struct aac_fib_header))) != 0) 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 > %zd)\n", - size, sizeof(struct aac_fib)); - size = sizeof(struct aac_fib); + if (size > sc->aac_max_fib_size) { + device_printf(sc->aac_dev, "incoming FIB oversized (%d > %d)\n", + size, sc->aac_max_fib_size); + size = sc->aac_max_fib_size; } if ((error = copyin(ufib, cm->cm_fib, size)) != 0) goto out; @@ -3187,35 +3028,195 @@ aac_ioctl_sendfib(struct aac_softc *sc, caddr_t ufib) /* * Pass the FIB to the controller, wait for it to complete. */ - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); - if ((error = aac_wait_command(cm)) != 0) { + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); + error = aac_wait_command(cm); + lockmgr(&sc->aac_io_lock, LK_RELEASE); + if (error != 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 > %zd)\n", - size, sizeof(struct aac_fib)); - size = sizeof(struct aac_fib); + if (size > sc->aac_max_fib_size) { + device_printf(sc->aac_dev, "outbound FIB oversized (%d > %d)\n", + size, sc->aac_max_fib_size); + size = sc->aac_max_fib_size; } error = copyout(cm->cm_fib, ufib, size); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); out: if (cm != NULL) { + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); aac_release_command(cm); + lockmgr(&sc->aac_io_lock, LK_RELEASE); + } + return(error); +} + +/* + * Send a passthrough FIB supplied from userspace + */ +static int +aac_ioctl_send_raw_srb(struct aac_softc *sc, caddr_t arg) +{ + struct aac_command *cm; + struct aac_event *event; + struct aac_fib *fib; + struct aac_srb *srbcmd, *user_srb; + struct aac_sg_entry *sge; + struct aac_sg_entry64 *sge64; + void *srb_sg_address, *ureply; + uint32_t fibsize, srb_sg_bytecount; + int error, transfer_data; + + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + + cm = NULL; + transfer_data = 0; + fibsize = 0; + user_srb = (struct aac_srb *)arg; + + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); + if (aac_alloc_command(sc, &cm)) { + event = kmalloc(sizeof(struct aac_event), M_AACBUF, + M_NOWAIT | M_ZERO); + if (event == NULL) { + error = EBUSY; + lockmgr(&sc->aac_io_lock, LK_RELEASE); + goto out; + } + event->ev_type = AAC_EVENT_CMFREE; + event->ev_callback = aac_ioctl_event; + event->ev_arg = &cm; + aac_add_event(sc, event); + lksleep(cm, &sc->aac_io_lock, 0, "aacraw", 0); + } + lockmgr(&sc->aac_io_lock, LK_RELEASE); + + cm->cm_data = NULL; + fib = cm->cm_fib; + srbcmd = (struct aac_srb *)fib->data; + error = copyin(&user_srb->data_len, &fibsize, sizeof(uint32_t)); + if (error != 0) + goto out; + if (fibsize > (sc->aac_max_fib_size - sizeof(struct aac_fib_header))) { + error = EINVAL; + goto out; + } + error = copyin(user_srb, srbcmd, fibsize); + if (error != 0) + goto out; + srbcmd->function = 0; + srbcmd->retry_limit = 0; + if (srbcmd->sg_map.SgCount > 1) { + error = EINVAL; + goto out; + } + + /* Retrieve correct SG entries. */ + if (fibsize == (sizeof(struct aac_srb) + + srbcmd->sg_map.SgCount * sizeof(struct aac_sg_entry))) { + sge = srbcmd->sg_map.SgEntry; + sge64 = NULL; + srb_sg_bytecount = sge->SgByteCount; + srb_sg_address = (void *)(uintptr_t)sge->SgAddress; + } +#ifdef __amd64__ + else if (fibsize == (sizeof(struct aac_srb) + + srbcmd->sg_map.SgCount * sizeof(struct aac_sg_entry64))) { + sge = NULL; + sge64 = (struct aac_sg_entry64 *)srbcmd->sg_map.SgEntry; + srb_sg_bytecount = sge64->SgByteCount; + srb_sg_address = (void *)sge64->SgAddress; + if (sge64->SgAddress > 0xffffffffull && + (sc->flags & AAC_FLAGS_SG_64BIT) == 0) { + error = EINVAL; + goto out; + } + } +#endif + else { + error = EINVAL; + goto out; + } + ureply = (char *)arg + fibsize; + srbcmd->data_len = srb_sg_bytecount; + if (srbcmd->sg_map.SgCount == 1) + transfer_data = 1; + + cm->cm_sgtable = (struct aac_sg_table *)&srbcmd->sg_map; + if (transfer_data) { + cm->cm_datalen = srb_sg_bytecount; + cm->cm_data = kmalloc(cm->cm_datalen, M_AACBUF, M_NOWAIT); + if (cm->cm_data == NULL) { + error = ENOMEM; + goto out; + } + if (srbcmd->flags & AAC_SRB_FLAGS_DATA_IN) + cm->cm_flags |= AAC_CMD_DATAIN; + if (srbcmd->flags & AAC_SRB_FLAGS_DATA_OUT) { + cm->cm_flags |= AAC_CMD_DATAOUT; + error = copyin(srb_sg_address, cm->cm_data, + cm->cm_datalen); + if (error != 0) + goto out; + } } - AAC_LOCK_RELEASE(&sc->aac_io_lock); + fib->Header.Size = sizeof(struct aac_fib_header) + + sizeof(struct aac_srb); + 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 = (sc->flags & AAC_FLAGS_SG_64BIT) != 0 ? + ScsiPortCommandU64 : ScsiPortCommand; + + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); + aac_wait_command(cm); + lockmgr(&sc->aac_io_lock, LK_RELEASE); + + if (transfer_data && (srbcmd->flags & AAC_SRB_FLAGS_DATA_IN) != 0) { + error = copyout(cm->cm_data, srb_sg_address, cm->cm_datalen); + if (error != 0) + goto out; + } + error = copyout(fib->data, ureply, sizeof(struct aac_srb_response)); +out: + if (cm != NULL) { + if (cm->cm_data != NULL) + kfree(cm->cm_data, M_AACBUF); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); + aac_release_command(cm); + lockmgr(&sc->aac_io_lock, LK_RELEASE); + } return(error); } +static int +aac_close(struct dev_close_args *ap) +{ + cdev_t dev = ap->a_head.a_dev; + struct aac_softc *sc; + + sc = dev->si_drv1; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + get_mplock(); + device_unbusy(sc->aac_dev); + rel_mplock(); + + return 0; +} + /* * Handle an AIF sent to us by the controller; queue it for later reference. * If the queue fills up, then drop the older entries. @@ -3225,13 +3226,13 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) { struct aac_aif_command *aif; struct aac_container *co, *co_next; - struct aac_mntinfo *mi; - struct aac_mntinforesp *mir = NULL; - u_int16_t rsize; - int next, found; + struct aac_fib_context *ctx; + struct aac_mntinforesp *mir; + int next, current, found; int count = 0, added = 0, i = 0; + uint32_t channel; - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); aif = (struct aac_aif_command*)&fib->data[0]; aac_print_aif(sc, aif); @@ -3248,7 +3249,6 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) * containers and sort things out. */ aac_alloc_sync_fib(sc, &fib); - mi = (struct aac_mntinfo *)&fib->data[0]; do { /* * Ask the controller for its containers one at @@ -3257,22 +3257,10 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) * midway through this enumaration? * XXX This should be done async. */ - bzero(mi, sizeof(struct aac_mntinfo)); - mi->Command = VM_NameServe; - mi->MntType = FT_FILESYS; - mi->MntCount = i; - rsize = sizeof(mir); - if (aac_sync_fib(sc, ContainerCommand, 0, fib, - sizeof(struct aac_mntinfo))) { - device_printf(sc->aac_dev, - "Error probing container %d\n", i); - + if ((mir = aac_get_container_info(sc, fib, i)) == NULL) continue; - } - mir = (struct aac_mntinforesp *)&fib->data[0]; - /* XXX Need to check if count changed */ - count = mir->MntRespCount; - + if (i == 0) + count = mir->MntRespCount; /* * Check the container against our list. * co->co_found was already set to 0 in a @@ -3321,19 +3309,17 @@ 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); + lockmgr(&sc->aac_io_lock, LK_RELEASE); get_mplock(); device_delete_child(sc->aac_dev, co->co_disk); rel_mplock(); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); co_next = TAILQ_NEXT(co, co_link); - AAC_LOCK_ACQUIRE(&sc-> - aac_container_lock); + lockmgr(&sc->aac_container_lock, LK_EXCLUSIVE); TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link); - AAC_LOCK_RELEASE(&sc-> - aac_container_lock); + lockmgr(&sc->aac_container_lock, LK_RELEASE); kfree(co, M_AACBUF); co = co_next; } else { @@ -3344,13 +3330,34 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) /* Attach the newly created containers */ if (added) { - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); get_mplock(); bus_generic_attach(sc->aac_dev); rel_mplock(); - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); + } + + break; + + case AifEnEnclosureManagement: + switch (aif->data.EN.data.EEE.eventType) { + case AIF_EM_DRIVE_INSERTION: + case AIF_EM_DRIVE_REMOVAL: + channel = aif->data.EN.data.EEE.unitID; + if (sc->cam_rescan_cb != NULL) + sc->cam_rescan_cb(sc, + (channel >> 24) & 0xF, + (channel & 0xFFFF)); + break; } + break; + case AifEnAddJBOD: + case AifEnDeleteJBOD: + channel = aif->data.EN.data.ECE.container; + if (sc->cam_rescan_cb != NULL) + sc->cam_rescan_cb(sc, (channel >> 24) & 0xF, + AAC_CAM_TARGET_WILDCARD); break; default: @@ -3362,21 +3369,30 @@ aac_handle_aif(struct aac_softc *sc, struct aac_fib *fib) } /* Copy the AIF data to the AIF queue for ioctl retrieval */ - AAC_LOCK_ACQUIRE(&sc->aac_aifq_lock); - next = (sc->aac_aifq_head + 1) % AAC_AIFQ_LENGTH; - if (next != sc->aac_aifq_tail) { - bcopy(aif, &sc->aac_aifq[next], sizeof(struct aac_aif_command)); - sc->aac_aifq_head = next; - - /* On the off chance that someone is sleeping for an aif... */ - if (sc->aac_state & AAC_STATE_AIF_SLEEPER) - wakeup(sc->aac_aifq); - /* token may have been lost */ - /* Wakeup any poll()ers */ - KNOTE(&sc->rcv_kq.ki_note, 0); - /* token may have been lost */ - } - AAC_LOCK_RELEASE(&sc->aac_aifq_lock); + lockmgr(&sc->aac_aifq_lock, LK_EXCLUSIVE); + current = sc->aifq_idx; + next = (current + 1) % AAC_AIFQ_LENGTH; + if (next == 0) + sc->aifq_filled = 1; + bcopy(fib, &sc->aac_aifq[current], sizeof(struct aac_fib)); + /* modify AIF contexts */ + if (sc->aifq_filled) { + for (ctx = sc->fibctx; ctx; ctx = ctx->next) { + if (next == ctx->ctx_idx) + ctx->ctx_wrap = 1; + else if (current == ctx->ctx_idx && ctx->ctx_wrap) + ctx->ctx_idx = next; + } + } + sc->aifq_idx = next; + /* On the off chance that someone is sleeping for an aif... */ + if (sc->aac_state & AAC_STATE_AIF_SLEEPER) + wakeup(sc->aac_aifq); + /* token may have been lost */ + /* Wakeup any poll()ers */ + KNOTE(&sc->rcv_kq.ki_note, 0); + /* token may have been lost */ + lockmgr(&sc->aac_aifq_lock, LK_RELEASE); return; } @@ -3394,7 +3410,7 @@ aac_rev_check(struct aac_softc *sc, caddr_t udata) struct aac_rev_check_resp rev_check_resp; int error = 0; - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* * Copyin the revision struct from userspace @@ -3404,22 +3420,103 @@ aac_rev_check(struct aac_softc *sc, caddr_t udata) return error; } - debug(2, "Userland revision= %d\n", + fwprintf(sc, HBA_FLAGS_DBG_IOCTL_COMMANDS_B, "Userland revision= %d\n", rev_check.callingRevision.buildNumber); /* * Doctor up the response struct. */ rev_check_resp.possiblyCompatible = 1; - rev_check_resp.adapterSWRevision.external.ul = - sc->aac_revision.external.ul; + rev_check_resp.adapterSWRevision.external.comp.major = + AAC_DRIVER_MAJOR_VERSION; + rev_check_resp.adapterSWRevision.external.comp.minor = + AAC_DRIVER_MINOR_VERSION; + rev_check_resp.adapterSWRevision.external.comp.type = + AAC_DRIVER_TYPE; + rev_check_resp.adapterSWRevision.external.comp.dash = + AAC_DRIVER_BUGFIX_LEVEL; rev_check_resp.adapterSWRevision.buildNumber = - sc->aac_revision.buildNumber; + AAC_DRIVER_BUILD; return(copyout((caddr_t)&rev_check_resp, udata, sizeof(struct aac_rev_check_resp))); } +/* + * Pass the fib context to the caller + */ +static int +aac_open_aif(struct aac_softc *sc, caddr_t arg) +{ + struct aac_fib_context *fibctx, *ctx; + int error = 0; + + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + + fibctx = kmalloc(sizeof(struct aac_fib_context), M_AACBUF, M_NOWAIT|M_ZERO); + if (fibctx == NULL) + return (ENOMEM); + + lockmgr(&sc->aac_aifq_lock, LK_EXCLUSIVE); + /* all elements are already 0, add to queue */ + if (sc->fibctx == NULL) + sc->fibctx = fibctx; + else { + for (ctx = sc->fibctx; ctx->next; ctx = ctx->next) + ; + ctx->next = fibctx; + fibctx->prev = ctx; + } + + /* evaluate unique value */ + fibctx->unique = (*(u_int32_t *)&fibctx & 0xffffffff); + ctx = sc->fibctx; + while (ctx != fibctx) { + if (ctx->unique == fibctx->unique) { + fibctx->unique++; + ctx = sc->fibctx; + } else { + ctx = ctx->next; + } + } + lockmgr(&sc->aac_aifq_lock, LK_RELEASE); + + error = copyout(&fibctx->unique, (void *)arg, sizeof(u_int32_t)); + if (error) + aac_close_aif(sc, (caddr_t)ctx); + return error; +} + +/* + * Close the caller's fib context + */ +static int +aac_close_aif(struct aac_softc *sc, caddr_t arg) +{ + struct aac_fib_context *ctx; + + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + + lockmgr(&sc->aac_aifq_lock, LK_EXCLUSIVE); + for (ctx = sc->fibctx; ctx; ctx = ctx->next) { + if (ctx->unique == *(uint32_t *)&arg) { + if (ctx == sc->fibctx) + sc->fibctx = NULL; + else { + ctx->prev->next = ctx->next; + if (ctx->next) + ctx->next->prev = ctx->prev; + } + break; + } + } + lockmgr(&sc->aac_aifq_lock, LK_RELEASE); + if (ctx) + kfree(ctx, M_AACBUF); + + return 0; +} + /* * Pass the caller the next AIF in their queue */ @@ -3427,32 +3524,30 @@ static int aac_getnext_aif(struct aac_softc *sc, caddr_t arg) { struct get_adapter_fib_ioctl agf; + struct aac_fib_context *ctx; int error; - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); if ((error = copyin(arg, &agf, sizeof(agf))) == 0) { - - /* - * Check the magic number that we gave the caller. - */ - if (agf.AdapterFibContext != (int)(uintptr_t)sc->aifthread) { - error = EFAULT; - } else { - - error = aac_return_aif(sc, agf.AifFib); - - if ((error == EAGAIN) && (agf.Wait)) { - sc->aac_state |= AAC_STATE_AIF_SLEEPER; - while (error == EAGAIN) { - error = tsleep(sc->aac_aifq, - PCATCH, "aacaif", 0); - if (error == 0) - error = aac_return_aif(sc, - agf.AifFib); - } - sc->aac_state &= ~AAC_STATE_AIF_SLEEPER; + for (ctx = sc->fibctx; ctx; ctx = ctx->next) { + if (agf.AdapterFibContext == ctx->unique) + break; + } + if (!ctx) + return (EFAULT); + + error = aac_return_aif(sc, ctx, agf.AifFib); + if (error == EAGAIN && agf.Wait) { + fwprintf(sc, HBA_FLAGS_DBG_AIF_B, "aac_getnext_aif(): waiting for AIF"); + sc->aac_state |= AAC_STATE_AIF_SLEEPER; + while (error == EAGAIN) { + error = tsleep(sc->aac_aifq, + PCATCH, "aacaif", 0); + if (error == 0) + error = aac_return_aif(sc, ctx, agf.AifFib); } + sc->aac_state &= ~AAC_STATE_AIF_SLEEPER; } } return(error); @@ -3460,32 +3555,31 @@ aac_getnext_aif(struct aac_softc *sc, caddr_t arg) /* * Hand the next AIF off the top of the queue out to userspace. - * - * YYY token could be lost during copyout */ static int -aac_return_aif(struct aac_softc *sc, caddr_t uptr) +aac_return_aif(struct aac_softc *sc, struct aac_fib_context *ctx, caddr_t uptr) { - int next, error; + int current, error; - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - AAC_LOCK_ACQUIRE(&sc->aac_aifq_lock); - if (sc->aac_aifq_tail == sc->aac_aifq_head) { - AAC_LOCK_RELEASE(&sc->aac_aifq_lock); + lockmgr(&sc->aac_aifq_lock, LK_EXCLUSIVE); + current = ctx->ctx_idx; + if (current == sc->aifq_idx && !ctx->ctx_wrap) { + /* empty */ + lockmgr(&sc->aac_aifq_lock, LK_RELEASE); return (EAGAIN); } - - next = (sc->aac_aifq_tail + 1) % AAC_AIFQ_LENGTH; - error = copyout(&sc->aac_aifq[next], uptr, - sizeof(struct aac_aif_command)); + error = + copyout(&sc->aac_aifq[current], (void *)uptr, sizeof(struct aac_fib)); 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); + else { + ctx->ctx_wrap = 0; + ctx->ctx_idx = (current + 1) % AAC_AIFQ_LENGTH; + } + lockmgr(&sc->aac_aifq_lock, LK_RELEASE); return(error); } @@ -3498,7 +3592,7 @@ aac_get_pci_info(struct aac_softc *sc, caddr_t uptr) } pciinf; int error; - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); pciinf.bus = pci_get_bus(sc->aac_dev); pciinf.slot = pci_get_slot(sc->aac_dev); @@ -3509,6 +3603,43 @@ aac_get_pci_info(struct aac_softc *sc, caddr_t uptr) return (error); } +static int +aac_supported_features(struct aac_softc *sc, caddr_t uptr) +{ + struct aac_features f; + int error; + + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); + + if ((error = copyin(uptr, &f, sizeof (f))) != 0) + return (error); + + /* + * When the management driver receives FSACTL_GET_FEATURES ioctl with + * ALL zero in the featuresState, the driver will return the current + * state of all the supported features, the data field will not be + * valid. + * When the management driver receives FSACTL_GET_FEATURES ioctl with + * a specific bit set in the featuresState, the driver will return the + * current state of this specific feature and whatever data that are + * associated with the feature in the data field or perform whatever + * action needed indicates in the data field. + */ + if (f.feat.fValue == 0) { + f.feat.fBits.largeLBA = + (sc->flags & AAC_FLAGS_LBA_64BIT) ? 1 : 0; + /* TODO: In the future, add other features state here as well */ + } else { + if (f.feat.fBits.largeLBA) + f.feat.fBits.largeLBA = + (sc->flags & AAC_FLAGS_LBA_64BIT) ? 1 : 0; + /* TODO: Add other features state and data in the future */ + } + + error = copyout(&f, uptr, sizeof (f)); + 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 @@ -3522,7 +3653,7 @@ aac_query_disk(struct aac_softc *sc, caddr_t uptr) struct aac_disk *disk; int error, id; - debug_called(2); + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); disk = NULL; @@ -3535,7 +3666,7 @@ aac_query_disk(struct aac_softc *sc, caddr_t uptr) if (id == -1) return (EINVAL); - AAC_LOCK_ACQUIRE(&sc->aac_container_lock); + lockmgr(&sc->aac_container_lock, LK_EXCLUSIVE); TAILQ_FOREACH(co, &sc->aac_container_tqh, co_link) { if (co->co_mntobj.ObjectId == id) break; @@ -3558,7 +3689,7 @@ aac_query_disk(struct aac_softc *sc, caddr_t uptr) bcopy(disk->ad_dev_t->si_name, &query_disk.diskDeviceName[0], 10); } - AAC_LOCK_RELEASE(&sc->aac_container_lock); + lockmgr(&sc->aac_container_lock, LK_RELEASE); error = copyout((caddr_t)&query_disk, uptr, sizeof(struct aac_query_disk)); @@ -3579,7 +3710,7 @@ aac_get_bus_info(struct aac_softc *sc) device_t child; int i, found, error; - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); aac_alloc_sync_fib(sc, &fib); c_cmd = (struct aac_ctcfg *)&fib->data[0]; bzero(c_cmd, sizeof(struct aac_ctcfg)); @@ -3594,7 +3725,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); + lockmgr(&sc->aac_io_lock, LK_RELEASE); return; } @@ -3603,7 +3734,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); + lockmgr(&sc->aac_io_lock, LK_RELEASE); return; } @@ -3619,26 +3750,27 @@ aac_get_bus_info(struct aac_softc *sc) vmi->IoctlCmd = GetBusInfo; error = aac_sync_fib(sc, ContainerCommand, 0, fib, - sizeof(struct aac_vmioctl)); + sizeof(struct aac_vmi_businf_resp)); if (error) { device_printf(sc->aac_dev, "Error %d sending VMIoctl command\n", error); aac_release_sync_fib(sc); - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); return; } vmi_resp = (struct aac_vmi_businf_resp *)&fib->data[0]; if (vmi_resp->Status != ST_OK) { - debug(1, "VM_Ioctl returned %d\n", vmi_resp->Status); + device_printf(sc->aac_dev, "VM_Ioctl returned %d\n", + vmi_resp->Status); aac_release_sync_fib(sc); - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); return; } bcopy(&vmi_resp->BusInf, &businfo, sizeof(struct aac_getbusinf)); aac_release_sync_fib(sc); - AAC_LOCK_RELEASE(&sc->aac_io_lock); + lockmgr(&sc->aac_io_lock, LK_RELEASE); found = 0; for (i = 0; i < businfo.BusCount; i++) { @@ -3655,7 +3787,7 @@ aac_get_bus_info(struct aac_softc *sc) i); kfree(caminf, M_AACBUF); break; - }; + } caminf->TargetsPerBus = businfo.TargetsPerBus; caminf->BusNumber = i; diff --git a/sys/dev/raid/aac/aac_cam.c b/sys/dev/raid/aac/aac_cam.c index da26f25249..8537aa26c8 100644 --- a/sys/dev/raid/aac/aac_cam.c +++ b/sys/dev/raid/aac/aac_cam.c @@ -23,8 +23,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/aac/aac_cam.c,v 1.2.2.4 2003/04/08 13:22:08 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aac_cam.c,v 1.10 2008/05/18 20:30:23 pavalos Exp $ + * $FreeBSD: src/sys/dev/aac/aac_cam.c,v 1.40 2010/12/06 17:06:21 jhb Exp $ */ /* @@ -37,33 +36,33 @@ #include #include #include +#include #include #include #include #include #include +#include #include +#include #include #include #include #include #include -#include #include -#include #include - -#include +#include #include #include -#include "aacreg.h" -#include "aac_ioctl.h" -#include "aacvar.h" +#include +#include +#include struct aac_cam { device_t dev; @@ -78,6 +77,10 @@ static int aac_cam_detach(device_t dev); static void aac_cam_action(struct cam_sim *, union ccb *); static void aac_cam_poll(struct cam_sim *); static void aac_cam_complete(struct aac_command *); +static void aac_cam_rescan(struct aac_softc *sc, uint32_t channel, + uint32_t target_id); +static void aac_bus_scan_cb(struct cam_periph *periph, union ccb *ccb); + 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 *); @@ -102,16 +105,71 @@ MODULE_DEPEND(aacp, cam, 1, 1, 1); MALLOC_DEFINE(M_AACCAM, "aaccam", "AAC CAM info"); +static void +aac_cam_rescan(struct aac_softc *sc, uint32_t channel, uint32_t target_id) +{ + union ccb *ccb; + struct aac_sim *sim; + struct aac_cam *camsc; + + if (target_id == AAC_CAM_TARGET_WILDCARD) + target_id = CAM_TARGET_WILDCARD; + + TAILQ_FOREACH(sim, &sc->aac_sim_tqh, sim_link) { + camsc = sim->aac_cam; + if (camsc == NULL || camsc->inf == NULL || + camsc->inf->BusNumber != channel) + continue; + + ccb = xpt_alloc_ccb(); + if (ccb == NULL) { + device_printf(sc->aac_dev, + "Cannot allocate ccb for bus rescan.\n"); + return; + } + + if (xpt_create_path(&ccb->ccb_h.path, xpt_periph, + cam_sim_path(camsc->sim), + target_id, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { + xpt_free_ccb(ccb); + device_printf(sc->aac_dev, + "Cannot create path for bus rescan.\n"); + return; + } + xpt_setup_ccb(&ccb->ccb_h, ccb->ccb_h.path, 5/*priority (low)*/); + ccb->ccb_h.func_code = XPT_SCAN_BUS; + ccb->ccb_h.cbfcnp = aac_bus_scan_cb; + ccb->crcn.flags = CAM_FLAG_NONE; + xpt_action(ccb); + break; + } +} + +static void +aac_bus_scan_cb(struct cam_periph *periph, union ccb *ccb) +{ + if (ccb->ccb_h.status != CAM_REQ_CMP) + kprintf("cam_scan_callback: failure status = %x\n", + ccb->ccb_h.status); + + xpt_free_path(ccb->ccb_h.path); + kfree(ccb, M_TEMP); +} + static void aac_cam_event(struct aac_softc *sc, struct aac_event *event, void *arg) { + union ccb *ccb; struct aac_cam *camsc; switch (event->ev_type) { case AAC_EVENT_CMFREE: - camsc = arg; + ccb = arg; + camsc = ccb->ccb_h.sim_priv.entries[0].ptr; kfree(event, M_AACCAM); xpt_release_simq(camsc->sim, 1); + ccb->ccb_h.status = CAM_REQUEUE_REQ; + xpt_done(ccb); break; default: device_printf(sc->aac_dev, "unknown event %d in aac_cam\n", @@ -125,7 +183,7 @@ aac_cam_event(struct aac_softc *sc, struct aac_event *event, void *arg) static int aac_cam_probe(device_t dev) { - debug_called(2); + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); return (0); } @@ -133,19 +191,24 @@ aac_cam_probe(device_t dev) static int aac_cam_detach(device_t dev) { + struct aac_softc *sc; struct aac_cam *camsc; - debug_called(2); + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); camsc = (struct aac_cam *)device_get_softc(dev); + sc = camsc->inf->aac_sc; + camsc->inf->aac_cam = NULL; - get_mplock(); + lockmgr(&sc->aac_io_lock, LK_EXCLUSIVE); 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(); + sc->cam_rescan_cb = NULL; + + lockmgr(&sc->aac_io_lock, LK_RELEASE); return (0); } @@ -162,26 +225,28 @@ aac_cam_attach(device_t dev) struct aac_cam *camsc; struct aac_sim *inf; - debug_called(1); + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); camsc = (struct aac_cam *)device_get_softc(dev); inf = (struct aac_sim *)device_get_ivars(dev); camsc->inf = inf; + camsc->inf->aac_cam = camsc; devq = cam_simq_alloc(inf->TargetsPerBus); if (devq == NULL) return (EIO); sim = cam_sim_alloc(aac_cam_action, aac_cam_poll, "aacp", camsc, - device_get_unit(dev), &sim_mplock, 1, 1, devq); + device_get_unit(dev), &inf->aac_sc->aac_io_lock, 1, 1, devq); cam_simq_release(devq); - if (sim == NULL) { + if (sim == NULL) return (EIO); - } /* Since every bus has it's own sim, every bus 'appears' as bus 0 */ + lockmgr(&inf->aac_sc->aac_io_lock, LK_EXCLUSIVE); if (xpt_bus_register(sim, 0) != CAM_SUCCESS) { cam_sim_free(sim); + lockmgr(&inf->aac_sc->aac_io_lock, LK_RELEASE); return (EIO); } @@ -189,8 +254,11 @@ aac_cam_attach(device_t dev) CAM_TARGET_WILDCARD, CAM_LUN_WILDCARD) != CAM_REQ_CMP) { xpt_bus_deregister(cam_sim_path(sim)); cam_sim_free(sim); + lockmgr(&inf->aac_sc->aac_io_lock, LK_RELEASE); return (EIO); } + inf->aac_sc->cam_rescan_cb = aac_cam_rescan; + lockmgr(&inf->aac_sc->aac_io_lock, LK_RELEASE); camsc->sim = sim; camsc->path = path; @@ -203,14 +271,13 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb) { struct aac_cam *camsc; struct aac_softc *sc; - struct aac_srb32 *srb; + struct aac_srb *srb; struct aac_fib *fib; struct aac_command *cm; - debug_called(2); - camsc = (struct aac_cam *)cam_sim_softc(sim); sc = camsc->inf->aac_sc; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* Synchronous ops, and ops that don't require communication with the * controller */ @@ -253,8 +320,11 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb) cpi->hba_inquiry = PI_WIDE_16; cpi->target_sprt = 0; - /* Resetting via the passthrough causes problems. */ - cpi->hba_misc = PIM_NOBUSRESET; + /* + * Resetting via the passthrough or parallel bus scan + * causes problems. + */ + cpi->hba_misc = PIM_NOBUSRESET | PIM_SEQSCAN; cpi->hba_eng_cnt = 0; cpi->max_target = camsc->inf->TargetsPerBus; cpi->max_lun = 8; /* Per the controller spec */ @@ -265,10 +335,10 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb) strncpy(cpi->hba_vid, "Adaptec", HBA_IDLEN); strncpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); cpi->unit_number = cam_sim_unit(sim); - cpi->transport = XPORT_SPI; - cpi->transport_version = 2; - cpi->protocol = PROTO_SCSI; - cpi->protocol_version = SCSI_REV_2; + cpi->transport = XPORT_SPI; + cpi->transport_version = 2; + cpi->protocol = PROTO_SCSI; + cpi->protocol_version = SCSI_REV_2; ccb->ccb_h.status = CAM_REQ_CMP; xpt_done(ccb); return; @@ -323,25 +393,23 @@ 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); + ccb->ccb_h.status = CAM_RESRC_UNAVAIL; + ccb->ccb_h.sim_priv.entries[0].ptr = camsc; event = kmalloc(sizeof(struct aac_event), M_AACCAM, M_INTWAIT | M_ZERO); event->ev_callback = aac_cam_event; - event->ev_arg = camsc; + event->ev_arg = ccb; event->ev_type = AAC_EVENT_CMFREE; aac_add_event(sc, event); - AAC_LOCK_RELEASE(&sc->aac_io_lock); return; } fib = cm->cm_fib; - srb = (struct aac_srb32 *)&fib->data[0]; + srb = (struct aac_srb *)&fib->data[0]; cm->cm_datalen = 0; switch (ccb->ccb_h.flags & CAM_DIR_MASK) { @@ -381,20 +449,21 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb) bcopy(csio->cdb_io.cdb_bytes, (u_int8_t *)&srb->cdb[0], srb->cdb_len); + /* Set command */ + fib->Header.Command = (sc->flags & AAC_FLAGS_SG_64BIT) ? + ScsiPortCommandU64 : ScsiPortCommand; + /* Map the s/g list. XXX 32bit addresses only! */ if ((ccb->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) { 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 = + /* Send a 32bit command */ + fib->Header.Command = ScsiPortCommand; + srb->sg_map.SgCount = 1; + srb->sg_map.SgEntry[0].SgAddress = (uint32_t)(uintptr_t)csio->data_ptr; - srb->sg_map32.SgEntry[0].SgByteCount = + srb->sg_map.SgEntry[0].SgByteCount = csio->dxfer_len; } else { /* @@ -403,15 +472,15 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb) */ cm->cm_data = (void *)csio->data_ptr; cm->cm_datalen = csio->dxfer_len; - cm->cm_sgtable = &srb->sg_map32; + cm->cm_sgtable = &srb->sg_map; } } else { /* XXX Need to handle multiple s/g elements */ panic("aac_cam: multiple s/g elements"); } } else { - srb->sg_map32.SgCount = 0; - srb->sg_map32.SgEntry[0].SgByteCount = 0; + srb->sg_map.SgCount = 0; + srb->sg_map.SgEntry[0].SgByteCount = 0; srb->data_len = 0; } @@ -424,7 +493,6 @@ 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: @@ -440,7 +508,6 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb) cm->cm_complete = aac_cam_complete; cm->cm_private = ccb; cm->cm_timestamp = time_second; - cm->cm_queue = AAC_ADAP_NORM_CMD_QUEUE; fib->Header.XferState = AAC_FIBSTATE_HOSTOWNED | @@ -448,15 +515,12 @@ aac_cam_action(struct cam_sim *sim, union ccb *ccb) AAC_FIBSTATE_FROMHOST | AAC_FIBSTATE_REXPECTED | AAC_FIBSTATE_NORM; - fib->Header.Command = ScsiPortCommand; fib->Header.Size = sizeof(struct aac_fib_header) + - sizeof(struct aac_srb32); + sizeof(struct aac_srb); aac_enqueue_ready(cm); aac_startio(cm->cm_sc); - AAC_LOCK_RELEASE(&sc->aac_io_lock); - return; } @@ -476,9 +540,8 @@ aac_cam_complete(struct aac_command *cm) struct aac_srb_response *srbr; struct aac_softc *sc; - debug_called(2); - sc = cm->cm_sc; + fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); ccb = cm->cm_private; srbr = (struct aac_srb_response *)&cm->cm_fib->data[0]; @@ -504,14 +567,14 @@ aac_cam_complete(struct aac_command *cm) scsi_sense_len = sizeof(struct scsi_sense_data); bzero(&ccb->csio.sense_data, scsi_sense_len); - sense_len = (srbr->sense_len > + sense_len = (srbr->sense_len > scsi_sense_len) ? scsi_sense_len : srbr->sense_len; bcopy(&srbr->sense[0], &ccb->csio.sense_data, 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 */ @@ -520,8 +583,8 @@ aac_cam_complete(struct aac_command *cm) else command = ccb->csio.cdb_io.cdb_bytes[0]; - if ((command == INQUIRY) && - (ccb->ccb_h.status == CAM_REQ_CMP)) { + if (command == INQUIRY) { + if (ccb->ccb_h.status == CAM_REQ_CMP) { device = ccb->csio.data_ptr[0] & 0x1f; /* * We want DASD and PROC devices to only be @@ -533,6 +596,11 @@ aac_cam_complete(struct aac_command *cm) ccb->csio.data_ptr[0] = ((ccb->csio.data_ptr[0] & 0xe0) | T_NODEVICE); + } else if (ccb->ccb_h.status == CAM_SEL_TIMEOUT && + ccb->ccb_h.target_lun != 0) { + /* fix for INQUIRYs on Lun>0 */ + ccb->ccb_h.status = CAM_DEV_NOT_THERE; + } } } } @@ -557,11 +625,10 @@ aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb) sc = camsc->inf->aac_sc; if (sc == NULL) { - kprintf("Null sc?\n"); + kprintf("aac: Null sc?\n"); return (CAM_REQ_ABORTED); } - AAC_LOCK_ACQUIRE(&sc->aac_io_lock); aac_alloc_sync_fib(sc, &fib); vmi = (struct aac_vmioctl *)&fib->data[0]; @@ -582,12 +649,10 @@ aac_cam_reset_bus(struct cam_sim *sim, union ccb *ccb) 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); } diff --git a/sys/dev/raid/aac/aac_debug.c b/sys/dev/raid/aac/aac_debug.c index ac4209b17e..7165419dfb 100644 --- a/sys/dev/raid/aac/aac_debug.c +++ b/sys/dev/raid/aac/aac_debug.c @@ -26,8 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/aac/aac_debug.c,v 1.2.2.5 2003/01/11 18:39:39 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aac_debug.c,v 1.8 2008/01/20 03:40:35 pavalos Exp $ + * $FreeBSD: src/sys/dev/aac/aac_debug.c,v 1.26 2010/04/13 00:33:07 emaste Exp $ */ /* @@ -38,20 +37,18 @@ #include #include #include +#include #include -#include -#include -#include "aacreg.h" -#include "aac_ioctl.h" -#include "aacvar.h" +#include +#include +#include #ifdef AAC_DEBUG +int aac_debug_enable = 0; void aac_printstate0(void); -static void aac_print_queues(struct aac_softc *sc); - /* * Dump the command queue indices */ @@ -61,66 +58,63 @@ aac_print_queues(struct aac_softc *sc) device_printf(sc->aac_dev, "FIB queue header at %p queues at %p\n", &sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][0], &sc->aac_queues->qt_HostNormCmdQueue[0]); - device_printf(sc->aac_dev, "HOST_NORM_CMD %d/%d (%d)\n", + device_printf(sc->aac_dev, "HOST_NORM_CMD %d/%d (%d)\n", sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][ AAC_PRODUCER_INDEX], sc->aac_queues->qt_qindex[AAC_HOST_NORM_CMD_QUEUE][ - AAC_CONSUMER_INDEX], + AAC_CONSUMER_INDEX], AAC_HOST_NORM_CMD_ENTRIES); - device_printf(sc->aac_dev, "HOST_HIGH_CMD %d/%d (%d)\n", + device_printf(sc->aac_dev, "HOST_HIGH_CMD %d/%d (%d)\n", sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][ AAC_PRODUCER_INDEX], sc->aac_queues->qt_qindex[AAC_HOST_HIGH_CMD_QUEUE][ - AAC_CONSUMER_INDEX], + AAC_CONSUMER_INDEX], AAC_HOST_HIGH_CMD_ENTRIES); - device_printf(sc->aac_dev, "ADAP_NORM_CMD %d/%d (%d)\n", + device_printf(sc->aac_dev, "ADAP_NORM_CMD %d/%d (%d)\n", sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][ AAC_PRODUCER_INDEX], sc->aac_queues->qt_qindex[AAC_ADAP_NORM_CMD_QUEUE][ - AAC_CONSUMER_INDEX], + AAC_CONSUMER_INDEX], AAC_ADAP_NORM_CMD_ENTRIES); - device_printf(sc->aac_dev, "ADAP_HIGH_CMD %d/%d (%d)\n", + device_printf(sc->aac_dev, "ADAP_HIGH_CMD %d/%d (%d)\n", sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][ AAC_PRODUCER_INDEX], sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_CMD_QUEUE][ - AAC_CONSUMER_INDEX], + AAC_CONSUMER_INDEX], AAC_ADAP_HIGH_CMD_ENTRIES); - device_printf(sc->aac_dev, "HOST_NORM_RESP %d/%d (%d)\n", + device_printf(sc->aac_dev, "HOST_NORM_RESP %d/%d (%d)\n", sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][ AAC_PRODUCER_INDEX], sc->aac_queues->qt_qindex[AAC_HOST_NORM_RESP_QUEUE][ AAC_CONSUMER_INDEX], AAC_HOST_NORM_RESP_ENTRIES); - device_printf(sc->aac_dev, "HOST_HIGH_RESP %d/%d (%d)\n", + device_printf(sc->aac_dev, "HOST_HIGH_RESP %d/%d (%d)\n", sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][ AAC_PRODUCER_INDEX], sc->aac_queues->qt_qindex[AAC_HOST_HIGH_RESP_QUEUE][ AAC_CONSUMER_INDEX], AAC_HOST_HIGH_RESP_ENTRIES); - device_printf(sc->aac_dev, "ADAP_NORM_RESP %d/%d (%d)\n", + device_printf(sc->aac_dev, "ADAP_NORM_RESP %d/%d (%d)\n", sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][ AAC_PRODUCER_INDEX], sc->aac_queues->qt_qindex[AAC_ADAP_NORM_RESP_QUEUE][ AAC_CONSUMER_INDEX], AAC_ADAP_NORM_RESP_ENTRIES); - device_printf(sc->aac_dev, "ADAP_HIGH_RESP %d/%d (%d)\n", + device_printf(sc->aac_dev, "ADAP_HIGH_RESP %d/%d (%d)\n", sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][ AAC_PRODUCER_INDEX], sc->aac_queues->qt_qindex[AAC_ADAP_HIGH_RESP_QUEUE][ AAC_CONSUMER_INDEX], AAC_ADAP_HIGH_RESP_ENTRIES); - device_printf(sc->aac_dev, "AACQ_FREE %d/%d\n", + device_printf(sc->aac_dev, "AACQ_FREE %d/%d\n", sc->aac_qstat[AACQ_FREE].q_length, sc->aac_qstat[AACQ_FREE].q_max); - device_printf(sc->aac_dev, "AACQ_BIO %d/%d\n", + device_printf(sc->aac_dev, "AACQ_BIO %d/%d\n", sc->aac_qstat[AACQ_BIO].q_length, sc->aac_qstat[AACQ_BIO].q_max); - device_printf(sc->aac_dev, "AACQ_READY %d/%d\n", + device_printf(sc->aac_dev, "AACQ_READY %d/%d\n", sc->aac_qstat[AACQ_READY].q_length, sc->aac_qstat[AACQ_READY].q_max); - device_printf(sc->aac_dev, "AACQ_BUSY %d/%d\n", + device_printf(sc->aac_dev, "AACQ_BUSY %d/%d\n", sc->aac_qstat[AACQ_BUSY].q_length, sc->aac_qstat[AACQ_BUSY].q_max); - device_printf(sc->aac_dev, "AACQ_COMPLETE %d/%d\n", - sc->aac_qstat[AACQ_COMPLETE].q_length, - sc->aac_qstat[AACQ_COMPLETE].q_max); } /* @@ -131,22 +125,23 @@ aac_printstate0(void) { struct aac_softc *sc; - sc = devclass_get_softc(aac_devclass, 0); + sc = devclass_get_softc(devclass_find("aac"), 0); aac_print_queues(sc); switch (sc->aac_hwif) { case AAC_HWIF_I960RX: + case AAC_HWIF_NARK: device_printf(sc->aac_dev, "IDBR 0x%08x IIMR 0x%08x " - "IISR 0x%08x\n", AAC_GETREG4(sc, AAC_RX_IDBR), - AAC_GETREG4(sc, AAC_RX_IIMR), AAC_GETREG4(sc, AAC_RX_IISR)); + "IISR 0x%08x\n", AAC_MEM0_GETREG4(sc, AAC_RX_IDBR), + AAC_MEM0_GETREG4(sc, AAC_RX_IIMR), AAC_MEM0_GETREG4(sc, AAC_RX_IISR)); device_printf(sc->aac_dev, "ODBR 0x%08x OIMR 0x%08x " - "OISR 0x%08x\n", AAC_GETREG4(sc, AAC_RX_ODBR), - AAC_GETREG4(sc, AAC_RX_OIMR), AAC_GETREG4(sc, AAC_RX_OISR)); - AAC_SETREG4(sc, AAC_RX_OIMR, 0/*~(AAC_DB_COMMAND_READY | + "OISR 0x%08x\n", AAC_MEM0_GETREG4(sc, AAC_RX_ODBR), + AAC_MEM0_GETREG4(sc, AAC_RX_OIMR), AAC_MEM0_GETREG4(sc, AAC_RX_OISR)); + AAC_MEM0_SETREG4(sc, AAC_RX_OIMR, 0/*~(AAC_DB_COMMAND_READY | AAC_DB_RESPONSE_READY | AAC_DB_PRINTF)*/); device_printf(sc->aac_dev, "ODBR 0x%08x OIMR 0x%08x " - "OISR 0x%08x\n", AAC_GETREG4(sc, AAC_RX_ODBR), - AAC_GETREG4(sc, AAC_RX_OIMR), AAC_GETREG4(sc, AAC_RX_OISR)); + "OISR 0x%08x\n", AAC_MEM0_GETREG4(sc, AAC_RX_ODBR), + AAC_MEM0_GETREG4(sc, AAC_RX_OIMR), AAC_MEM0_GETREG4(sc, AAC_RX_OISR)); break; case AAC_HWIF_STRONGARM: /* XXX implement */ @@ -154,6 +149,16 @@ aac_printstate0(void) } } +/* + * Panic in a slightly informative fashion + */ +void +aac_panic(struct aac_softc *sc, char *reason) +{ + aac_print_queues(sc); + panic(reason); +} + /* * Print a FIB */ @@ -216,8 +221,8 @@ aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller) if (br->Command == VM_CtBlockRead) { device_printf(sc->aac_dev, - " BlockRead: container %d 0x%x/%d\n", - br->ContainerId, br->BlockNumber, + " BlockRead: container %d 0x%x/%d\n", + br->ContainerId, br->BlockNumber, br->ByteCount); sg = &br->SgMap; } @@ -225,7 +230,7 @@ aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller) device_printf(sc->aac_dev, " BlockWrite: container %d 0x%x/%d " "(%s)\n", bw->ContainerId, - bw->BlockNumber, bw->ByteCount, + bw->BlockNumber, bw->ByteCount, bw->Stable == CSTABLE ? "stable" : "unstable"); sg = &bw->SgMap; @@ -258,7 +263,7 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) device_printf(sc->aac_dev, "EventNotify(%d)\n", aif->seqNumber); switch(aif->data.EN.type) { case AifEnGeneric: /* Generic notification */ - device_printf(sc->aac_dev, "(Generic) %.*s\n", + device_printf(sc->aac_dev, "(Generic) %.*s\n", (int)sizeof(aif->data.EN.data.EG), aif->data.EN.data.EG.text); break; @@ -272,21 +277,21 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) case AifEnContainerChange: /* Adapter specific container * configuration change */ device_printf(sc->aac_dev, "(ContainerChange) " - "container %d,%d\n", - aif->data.EN.data.ECC.container[0], + "container %d,%d\n", + aif->data.EN.data.ECC.container[0], aif->data.EN.data.ECC.container[1]); break; case AifEnDeviceFailure: /* SCSI device failed */ device_printf(sc->aac_dev, "(DeviceFailure) " - "handle %d\n", + "handle %d\n", aif->data.EN.data.EDF.deviceHandle); break; case AifEnMirrorFailover: /* Mirror failover started */ device_printf(sc->aac_dev, "(MirrorFailover) " "container %d failed, " "migrating from slice %d to %d\n", - aif->data.EN.data.EMF.container, - aif->data.EN.data.EMF.failedSlice, + aif->data.EN.data.EMF.container, + aif->data.EN.data.EMF.failedSlice, aif->data.EN.data.EMF.creatingSlice); break; case AifEnContainerEvent: /* Significant container @@ -316,7 +321,7 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) device_printf(sc->aac_dev, "(EnclosureManagement) " "EMPID %d unit %d " "event %d\n", aif->data.EN.data.EEE.empID, - aif->data.EN.data.EEE.unitID, + aif->data.EN.data.EEE.unitID, aif->data.EN.data.EEE.eventType); break; case AifEnBatteryEvent: /* Significant NV battery @@ -339,14 +344,14 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) device_printf(sc->aac_dev, "(BatteryNeedsRecond)\n"); break; case AifEnClusterEvent: /* Some cluster event */ - device_printf(sc->aac_dev, "(ClusterEvent) event %d\n", + device_printf(sc->aac_dev, "(ClusterEvent) event %d\n", aif->data.EN.data.ECLE.eventType); break; case AifEnDiskSetEvent: /* A disk set event occured. */ device_printf(sc->aac_dev, "(DiskSetEvent) event %d " "diskset %jd creator %jd\n", - aif->data.EN.data.EDS.eventType, - (intmax_t)aif->data.EN.data.EDS.DsNum, + aif->data.EN.data.EDS.eventType, + (intmax_t)aif->data.EN.data.EDS.DsNum, (intmax_t)aif->data.EN.data.EDS.CreatorId); break; case AifDenMorphComplete: /* A morph operation @@ -383,7 +388,7 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) } device_printf(sc->aac_dev, "JobProgress (%d) - %s (%d, %d)\n", - aif->seqNumber, status, + aif->seqNumber, status, aif->data.PR[0].currentTick, aif->data.PR[0].finalTick); switch(aif->data.PR[0].jd.type) { @@ -409,12 +414,12 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) break; case AifJobCtrZero: /* Container clear operation */ device_printf(sc->aac_dev, - "(ContainerZero) container %d\n", + "(ContainerZero) container %d\n", aif->data.PR[0].jd.client.container.src); break; case AifJobCtrCopy: /* Container copy operation */ device_printf(sc->aac_dev, - "(ContainerCopy) container %d to %d\n", + "(ContainerCopy) container %d to %d\n", aif->data.PR[0].jd.client.container.src, aif->data.PR[0].jd.client.container.dst); break; @@ -447,12 +452,12 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) case AifJobCtrScrubRaid5: /* Container Scrub Raid5 * operation */ device_printf(sc->aac_dev, - "(ContainerScrubRaid5) container %d\n", + "(ContainerScrubRaid5) container %d\n", aif->data.PR[0].jd.client.container.src); break; case AifJobCtrMorph: /* Container morph operation */ device_printf(sc->aac_dev, - "(ContainerMorph) container %d\n", + "(ContainerMorph) container %d\n", aif->data.PR[0].jd.client.container.src); /* XXX two containers? */ break; @@ -467,13 +472,13 @@ aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif) case AifJobCtrRebuildMirror: /* Container Rebuild Mirror * operation */ device_printf(sc->aac_dev, - "(ContainerRebuildMirror) container " + "(ContainerRebuildMirror) container " "%d\n", aif->data.PR[0].jd.client.container.src); break; case AifJobCtrCrazyCache: /* crazy cache */ device_printf(sc->aac_dev, - "(ContainerCrazyCache) container %d\n", + "(ContainerCrazyCache) container %d\n", aif->data.PR[0].jd.client.container.src); /* XXX two containers? */ break; diff --git a/sys/dev/raid/aac/aac_disk.c b/sys/dev/raid/aac/aac_disk.c index 85812d01b3..f8abf75432 100644 --- a/sys/dev/raid/aac/aac_disk.c +++ b/sys/dev/raid/aac/aac_disk.c @@ -26,8 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/aac/aac_disk.c,v 1.3.2.8 2003/01/11 18:39:39 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aac_disk.c,v 1.20 2008/01/20 03:40:35 pavalos Exp $ + * $FreeBSD: src/sys/dev/aac/aac_disk.c,v 1.49 2010/09/16 23:33:24 emaste Exp $ */ #include "opt_aac.h" @@ -36,23 +35,21 @@ #include #include #include -#include #include #include -#include #include #include -#include #include #include #include +#include -#include "aacreg.h" -#include "aac_ioctl.h" -#include "aacvar.h" +#include +#include +#include /* * Interface to parent. @@ -69,10 +66,8 @@ 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 - static struct dev_ops aac_disk_ops = { - { "aacd", AAC_DISK_CDEV_MAJOR, D_DISK }, + { "aacd", 0, D_DISK }, .d_open = aac_disk_open, .d_close = aac_disk_close, .d_read = physread, @@ -96,33 +91,22 @@ static driver_t aac_disk_driver = { sizeof(struct aac_disk) }; -#define AAC_MAXIO 65536 - DRIVER_MODULE(aacd, aac, aac_disk_driver, aac_disk_devclass, 0, 0); -/* sysctl tunables */ -static unsigned int aac_iosize_max = AAC_MAXIO; /* due to limits of the card */ -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"); - /* * Handle open from generic layer. * - * This is called by the diskslice code on first open in order to get the + * This is called by the diskslice code on first open in order to get the * basic device geometry paramters. */ static int aac_disk_open(struct dev_open_args *ap) { - cdev_t dev = ap->a_head.a_dev; struct aac_disk *sc; - debug_called(0); + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - sc = (struct aac_disk *)dev->si_drv1; + sc = ap->a_head.a_dev->si_drv1; if (sc == NULL) { kprintf("aac_disk_open: No Softc\n"); @@ -131,25 +115,12 @@ aac_disk_open(struct dev_open_args *ap) /* check that the controller is up and running */ if (sc->ad_controller->aac_state & AAC_STATE_SUSPEND) { - kprintf("Controller Suspended controller state = 0x%x\n", - sc->ad_controller->aac_state); + device_printf(sc->ad_controller->aac_dev, + "Controller Suspended controller state = 0x%x\n", + sc->ad_controller->aac_state); return(ENXIO); } - /* build synthetic label */ -#if 0 - bzero(&info, sizeof(info)); - info.d_media_blksize= AAC_BLOCK_SIZE; /* mandatory */ - info.d_media_blocks = sc->ad_size; - - info.d_type = DTYPE_ESDI; /* optional */ - info.d_secpertrack = sc->ad_sectors; - info.d_nheads = sc->ad_heads; - info.d_ncylinders = sc->ad_cylinders; - info.d_secpercyl = sc->ad_sectors * sc->ad_heads; - - disk_setdiskinfo(&sc->ad_disk, &info); -#endif sc->ad_flags |= AAC_DISK_OPEN; return (0); } @@ -160,12 +131,11 @@ aac_disk_open(struct dev_open_args *ap) static int aac_disk_close(struct dev_close_args *ap) { - cdev_t dev = ap->a_head.a_dev; struct aac_disk *sc; - debug_called(0); + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); - sc = (struct aac_disk *)dev->si_drv1; + sc = ap->a_head.a_dev->si_drv1; if (sc == NULL) return (ENXIO); @@ -180,120 +150,195 @@ aac_disk_close(struct dev_close_args *ap) static int aac_disk_strategy(struct dev_strategy_args *ap) { - cdev_t dev = ap->a_head.a_dev; struct bio *bio = ap->a_bio; struct buf *bp = bio->bio_buf; struct aac_disk *sc; - debug_called(4); - - sc = (struct aac_disk *)dev->si_drv1; + sc = ap->a_head.a_dev->si_drv1; + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* bogus disk? */ if (sc == NULL) { bp->b_flags |= B_ERROR; bp->b_error = EINVAL; biodone(bio); - return(0); + return (0); } /* do-nothing operation? */ if (bp->b_bcount == 0) { bp->b_resid = bp->b_bcount; biodone(bio); - return(0); + return (0); } /* perform accounting */ /* pass the bio to the controller - it can work out who we are */ - AAC_LOCK_ACQUIRE(&sc->ad_controller->aac_io_lock); + lockmgr(&sc->ad_controller->aac_io_lock, LK_EXCLUSIVE); devstat_start_transaction(&sc->ad_stats); aac_submit_bio(sc, bio); - AAC_LOCK_RELEASE(&sc->ad_controller->aac_io_lock); + lockmgr(&sc->ad_controller->aac_io_lock, LK_RELEASE); - return(0); + return (0); +} + +/* + * Map the S/G elements for doing a dump. + */ +static void +aac_dump_map_sg(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct aac_fib *fib; + struct aac_blockwrite *bw; + struct aac_sg_table *sg; + int i; + + fib = (struct aac_fib *)arg; + bw = (struct aac_blockwrite *)&fib->data[0]; + sg = &bw->SgMap; + + if (sg != NULL) { + sg->SgCount = nsegs; + for (i = 0; i < nsegs; i++) { + if (segs[i].ds_addr >= BUS_SPACE_MAXADDR_32BIT) + return; + sg->SgEntry[i].SgAddress = segs[i].ds_addr; + sg->SgEntry[i].SgByteCount = segs[i].ds_len; + } + fib->Header.Size = nsegs * sizeof(struct aac_sg_entry); + } +} + +/* + * Map the S/G elements for doing a dump on 64-bit capable devices. + */ +static void +aac_dump_map_sg64(void *arg, bus_dma_segment_t *segs, int nsegs, int error) +{ + struct aac_fib *fib; + struct aac_blockwrite64 *bw; + struct aac_sg_table64 *sg; + int i; + + fib = (struct aac_fib *)arg; + bw = (struct aac_blockwrite64 *)&fib->data[0]; + sg = &bw->SgMap64; + + if (sg != NULL) { + sg->SgCount = nsegs; + for (i = 0; i < nsegs; i++) { + sg->SgEntry64[i].SgAddress = segs[i].ds_addr; + sg->SgEntry64[i].SgByteCount = segs[i].ds_len; + } + fib->Header.Size = nsegs * sizeof(struct aac_sg_entry64); + } } /* * 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. + * Send out one command at a time with up to maxio of data. */ static int aac_disk_dump(struct dev_dump_args *ap) { - kprintf("dumps on aac are currently broken, not dumping\n"); - return (ENXIO); -#if 0 cdev_t dev = ap->a_head.a_dev; + size_t length = ap->a_length; + off_t offset = ap->a_offset; + void *virtual = ap->a_virtual; + vm_offset_t physical = ap->a_physical; struct aac_disk *ad; struct aac_softc *sc; - vm_offset_t addr; - long blkcnt; - int dumppages; - int i, error; + struct aac_fib *fib; + size_t len, maxio; + int size; + static bus_dmamap_t dump_datamap; + static int first = 0; + bus_dmamap_callback_t *callback; + u_int32_t command; ad = dev->si_drv1; - addr = 0; - dumppages = AAC_MAXIO / PAGE_SIZE; if (ad == NULL) - return (ENXIO); + return (EINVAL); sc= ad->ad_controller; - blkcnt = howmany(PAGE_SIZE, ap->a_secsize); - - while (ap->a_count > 0) { - caddr_t va = NULL; - - if ((ap->a_count / blkcnt) < dumppages) - dumppages = ap->a_count / blkcnt; + if (!first) { + first = 1; + if (bus_dmamap_create(sc->aac_buffer_dmat, 0, &dump_datamap)) { + device_printf(sc->aac_dev, + "bus_dmamap_create failed\n"); + return (ENOMEM); + } + } - 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); - } + /* Skip aac_alloc_sync_fib(). We don't want to mess with sleep locks */ + fib = &sc->aac_common->ac_sync_fib; + + while (length > 0) { + maxio = sc->aac_max_sectors << 9; + len = (length > maxio) ? maxio : length; + if ((sc->flags & AAC_FLAGS_SG_64BIT) == 0) { + 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 = offset / AAC_BLOCK_SIZE; + bw->ByteCount = len; + bw->Stable = CUNSTABLE; + command = ContainerCommand; + callback = aac_dump_map_sg; + size = sizeof(struct aac_blockwrite); + } 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->BlockNumber = offset / AAC_BLOCK_SIZE; + bw->SectorCount = len / AAC_BLOCK_SIZE; + bw->Pad = 0; + bw->Flags = 0; + command = ContainerCommand64; + callback = aac_dump_map_sg64; + size = sizeof(struct aac_blockwrite64); } -retry: /* - * Queue the block to the controller. If the queue is full, - * EBUSY will be returned. + * There really isn't any way to recover from errors or + * resource shortages here. Oh well. Because of that, don't + * bother trying to send the command from the callback; there + * is too much required context. */ - error = aac_dump_enqueue(ad, ap->a_blkno, va, dumppages); - if (error && (error != EBUSY)) - return (error); - - if (!error) { - if (dumpstatus(addr, (off_t)(ap->a_count * DEV_BSIZE)) < 0) - return (EINTR); - - ap->a_blkno += blkcnt * dumppages; - ap->a_count -= blkcnt * dumppages; - addr += PAGE_SIZE * dumppages; - if (ap->a_count > 0) - continue; + if (bus_dmamap_load(sc->aac_buffer_dmat, dump_datamap, virtual, + len, callback, fib, BUS_DMA_NOWAIT) != 0) + return (ENOMEM); + + bus_dmamap_sync(sc->aac_buffer_dmat, dump_datamap, + BUS_DMASYNC_PREWRITE); + + /* fib->Header.Size is set in aac_dump_map_sg */ + size += fib->Header.Size; + + if (aac_sync_fib(sc, command, 0, fib, size)) { + device_printf(sc->aac_dev, + "Error dumping block 0x%jx\n", + (uintmax_t)physical); + return (EIO); } - /* - * 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); + bus_dmamap_sync(sc->aac_buffer_dmat, dump_datamap, + BUS_DMASYNC_POSTWRITE); + + bus_dmamap_unload(sc->aac_buffer_dmat, dump_datamap); - if (error == EBUSY) - goto retry; + length -= len; + offset += len; + virtual = (uint8_t *)virtual + len; } return (0); -#endif } /* @@ -305,15 +350,15 @@ aac_biodone(struct bio *bio, const char *code) struct buf *bp = bio->bio_buf; struct aac_disk *sc; - debug_called(4); - sc = (struct aac_disk *)bio->bio_driver_info; + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); devstat_end_transaction_buf(&sc->ad_stats, bp); if (bp->b_flags & B_ERROR) { diskerr(bio, sc->ad_dev_t, code, 0, 0); } + biodone(bio); } @@ -324,7 +369,7 @@ static int aac_disk_probe(device_t dev) { - debug_called(2); + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); return (0); } @@ -338,9 +383,8 @@ aac_disk_attach(device_t dev) struct disk_info info; struct aac_disk *sc; - debug_called(0); - sc = (struct aac_disk *)device_get_softc(dev); + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* initialise our softc */ sc->ad_controller = @@ -353,6 +397,9 @@ aac_disk_attach(device_t dev) * disk! */ sc->ad_size = sc->ad_container->co_mntobj.Capacity; + if (sc->ad_controller->flags & AAC_FLAGS_LBA_64BIT) + sc->ad_size += (u_int64_t) + sc->ad_container->co_mntobj.CapacityHigh << 32; if (sc->ad_size >= (2 * 1024 * 1024)) { /* 2GB */ sc->ad_heads = 255; sc->ad_sectors = 63; @@ -365,10 +412,9 @@ aac_disk_attach(device_t dev) } sc->ad_cylinders = (sc->ad_size / (sc->ad_heads * sc->ad_sectors)); - device_printf(dev, "%uMB (%u sectors)\n", - sc->ad_size / ((1024 * 1024) / AAC_BLOCK_SIZE), - sc->ad_size); - + device_printf(dev, "%juMB (%ju sectors)\n", + (intmax_t)sc->ad_size / ((1024 * 1024) / AAC_BLOCK_SIZE), + (intmax_t)sc->ad_size); devstat_add_entry(&sc->ad_stats, "aacd", device_get_unit(dev), AAC_BLOCK_SIZE, DEVSTAT_NO_ORDERED_TAGS, DEVSTAT_TYPE_STORARRAY | DEVSTAT_TYPE_IF_OTHER, @@ -379,7 +425,7 @@ aac_disk_attach(device_t dev) &aac_disk_ops); sc->ad_dev_t->si_drv1 = sc; - sc->ad_dev_t->si_iosize_max = aac_iosize_max; + sc->ad_dev_t->si_iosize_max = sc->ad_controller->aac_max_sectors << 9; sc->unit = device_get_unit(dev); /* @@ -409,14 +455,14 @@ aac_disk_detach(device_t dev) { struct aac_disk *sc; - debug_called(2); - sc = (struct aac_disk *)device_get_softc(dev); + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); if (sc->ad_flags & AAC_DISK_OPEN) return(EBUSY); devstat_remove_entry(&sc->ad_stats); disk_destroy(&sc->ad_disk); + return(0); } diff --git a/sys/dev/raid/aac/aac_ioctl.h b/sys/dev/raid/aac/aac_ioctl.h index a2456ea54e..1c83a81c42 100644 --- a/sys/dev/raid/aac/aac_ioctl.h +++ b/sys/dev/raid/aac/aac_ioctl.h @@ -25,8 +25,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/aac/aac_ioctl.h,v 1.2.2.2 2001/09/19 19:09:11 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aac_ioctl.h,v 1.2 2003/06/17 04:28:21 dillon Exp $ + * $FreeBSD: src/sys/sys/aac_ioctl.h,v 1.14 2009/10/29 17:21:41 emaste Exp $ */ #include @@ -38,8 +37,7 @@ #define AACQ_BIO 1 #define AACQ_READY 2 #define AACQ_BUSY 3 -#define AACQ_COMPLETE 4 -#define AACQ_COUNT 5 /* total number of queues */ +#define AACQ_COUNT 4 /* total number of queues */ struct aac_qstat { u_int32_t q_length; @@ -73,6 +71,8 @@ union aac_statrequest { #define FSACTL_LNX_SENDFIB CTL_CODE(FILE_DEVICE_CONTROLLER, 2050, \ METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSACTL_LNX_SEND_RAW_SRB CTL_CODE(FILE_DEVICE_CONTROLLER, 2067, \ + METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSACTL_LNX_GET_COMM_PERF_DATA CTL_CODE(FILE_DEVICE_CONTROLLER, 2084, \ METHOD_BUFFERED, FILE_ANY_ACCESS) #define FSACTL_LNX_OPENCLS_COMM_PERF_DATA CTL_CODE(FILE_DEVICE_CONTROLLER, \ @@ -97,6 +97,10 @@ union aac_statrequest { METHOD_NEITHER, FILE_ANY_ACCESS) #define FSACTL_LNX_AIF_THREAD CTL_CODE(FILE_DEVICE_CONTROLLER, 2127, \ METHOD_NEITHER, FILE_ANY_ACCESS) +#define FSACTL_LNX_SEND_LARGE_FIB CTL_CODE(FILE_DEVICE_CONTROLLER, 2138, \ + METHOD_BUFFERED, FILE_ANY_ACCESS) +#define FSACTL_LNX_GET_FEATURES CTL_CODE(FILE_DEVICE_CONTROLLER, 2139, \ + METHOD_BUFFERED, FILE_ANY_ACCESS) /* Why these don't follow the previous convention, I don't know */ #define FSACTL_LNX_NULL_IO_TEST 0x43 @@ -120,6 +124,7 @@ union aac_statrequest { * command number. 9 is used for the odd overflow case. */ #define FSACTL_SENDFIB _IO('8', 2) +#define FSACTL_SEND_RAW_SRB _IO('8', 19) #define FSACTL_GET_COMM_PERF_DATA _IO('8', 36) #define FSACTL_OPENCLS_COMM_PERF_DATA _IO('8', 37) #define FSACTL_OPEN_GET_ADAPTER_FIB _IO('8', 52) @@ -132,6 +137,8 @@ union aac_statrequest { #define FSACTL_GET_PCI_INFO _IO('8', 71) #define FSACTL_FORCE_DELETE_DISK _IO('8', 72) #define FSACTL_AIF_THREAD _IO('8', 79) +#define FSACTL_SEND_LARGE_FIB _IO('8', 90) +#define FSACTL_GET_FEATURES _IO('8', 91) #define FSACTL_NULL_IO_TEST _IO('8', 67) #define FSACTL_SIM_IO_TEST _IO('8', 83) @@ -145,7 +152,7 @@ union aac_statrequest { #define FSACTL_PROBE_CONTAINERS _IO('9', 83) /* Just guessing */ - +#ifdef _KERNEL /* * Support for faking the "miniport" version. */ @@ -180,3 +187,24 @@ struct aac_query_disk { char diskDeviceName[10]; u_int32_t UnMapped; }; + +/* Features, asked from the tools to know if the driver + * supports drives >2TB + */ +typedef union { + struct { + u_int32_t largeLBA : 1; /* disk support greater 2TB */ + u_int32_t IoctlBuf : 1; /* ARCIOCTL call support */ + u_int32_t AIFSupport: 1; /* AIF support */ + u_int32_t JBODSupport:1; /* fw + driver support JBOD */ + u_int32_t fReserved : 28; + } fBits; + u_int32_t fValue; +} featuresState; + +struct aac_features { + featuresState feat; + u_int32_t data[31]; + u_int32_t reserved[32]; +} __packed; +#endif diff --git a/sys/dev/raid/aac/aac_linux.c b/sys/dev/raid/aac/aac_linux.c index 1c5ba18483..4dc3229dc4 100644 --- a/sys/dev/raid/aac/aac_linux.c +++ b/sys/dev/raid/aac/aac_linux.c @@ -1,8 +1,5 @@ /*- - * Copyright (c) 2000 Michael Smith - * Copyright (c) 2001 Scott Long - * Copyright (c) 2000 BSDi - * Copyright (c) 2001 Adaptec, Inc. + * Copyright (c) 2002 Scott Long * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -26,8 +23,11 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/aac/aac_linux.c,v 1.1.4.1 2003/03/28 19:50:17 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aac_linux.c,v 1.7 2008/01/20 03:40:35 pavalos Exp $ + * $FreeBSD: src/sys/dev/aac/aac_linux.c,v 1.4 2006/12/20 17:10:53 delphij Exp $ + */ + +/* + * Linux ioctl handler for the aac device driver */ #include @@ -38,13 +38,17 @@ #include #include #include -#include +#ifdef __amd64__ +#include +#include +#else #include #include +#endif #include -#include "aacreg.h" /* needed by aac_ioctl.h */ -#include "aac_ioctl.h" +#include /* needed by aac_ioctl.h */ +#include /* Define ioctl mappings */ static struct ioctl_map_range aac_linux_ioctl_cmds[] = { @@ -93,4 +97,4 @@ aac_linux_modevent(module_t mod, int type, void *data) } DEV_MODULE(aac_linux, aac_linux_modevent, NULL); -MODULE_DEPEND(aac, linux, 1, 1, 1); +MODULE_DEPEND(aac_linux, linux, 1, 1, 1); diff --git a/sys/dev/raid/aac/aac_linux/Makefile b/sys/dev/raid/aac/aac_linux/Makefile index 01cfa2b0bb..5ada686475 100644 --- a/sys/dev/raid/aac/aac_linux/Makefile +++ b/sys/dev/raid/aac/aac_linux/Makefile @@ -1,8 +1,8 @@ -# $DragonFly: src/sys/dev/raid/aac/aac_linux/Makefile,v 1.1 2003/08/15 08:32:31 dillon Exp $ +# $FreeBSD: src/sys/modules/aac/aac_linux/Makefile,v 1.1 2002/09/25 05:00:25 scottl Exp $ .PATH: ${.CURDIR}/.. -KMOD= aac_linux -SRCS= aac_linux.c +KMOD= aac_linux +SRCS= aac_linux.c .include diff --git a/sys/dev/raid/aac/aac_pci.c b/sys/dev/raid/aac/aac_pci.c index 8704ee28ac..8becbdee24 100644 --- a/sys/dev/raid/aac/aac_pci.c +++ b/sys/dev/raid/aac/aac_pci.c @@ -26,8 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/aac/aac_pci.c,v 1.3.2.19 2003/11/01 18:44:51 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aac_pci.c,v 1.13 2008/01/20 03:40:35 pavalos Exp $ + * $FreeBSD: src/sys/dev/aac/aac_pci.c,v 1.74 2010/04/13 01:16:15 emaste Exp $ */ /* @@ -41,18 +40,19 @@ #include #include +#include #include #include -#include #include + #include #include #include -#include "aacreg.h" -#include "aac_ioctl.h" -#include "aacvar.h" +#include +#include +#include static int aac_pci_probe(device_t dev); static int aac_pci_attach(device_t dev); @@ -76,11 +76,13 @@ static driver_t aac_pci_driver = { sizeof(struct aac_softc) }; -devclass_t aac_devclass; +static devclass_t aac_devclass; DRIVER_MODULE(aac, pci, aac_pci_driver, aac_devclass, 0, 0); +MODULE_DEPEND(aac, pci, 1, 1, 1); + -static struct aac_ident +struct aac_ident { u_int16_t vendor; u_int16_t device; @@ -113,15 +115,15 @@ static struct aac_ident {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"}, + "Dell PERC 2/QC"}, {0x1011, 0x0046, 0x103c, 0x10c2, AAC_HWIF_STRONGARM, 0, - "HP NetRaid-4M"}, - {0x9005, 0x0285, 0x9005, 0x0285, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB, - "Adaptec SCSI RAID 2200S"}, - {0x9005, 0x0285, 0x1028, 0x0287, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB, - "Dell PERC 320/DC"}, - {0x9005, 0x0285, 0x9005, 0x0286, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB, - "Adaptec SCSI RAID 2120S"}, + "HP NetRaid-4M"}, + {0x9005, 0x0285, 0x9005, 0x0285, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB | + AAC_FLAGS_256FIBS, "Adaptec SCSI RAID 2200S"}, + {0x9005, 0x0285, 0x1028, 0x0287, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB | + AAC_FLAGS_256FIBS, "Dell PERC 320/DC"}, + {0x9005, 0x0285, 0x9005, 0x0286, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB | + AAC_FLAGS_256FIBS, "Adaptec SCSI RAID 2120S"}, {0x9005, 0x0285, 0x9005, 0x0290, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB, "Adaptec SATA RAID 2410SA"}, {0x9005, 0x0285, 0x1028, 0x0291, AAC_HWIF_I960RX, AAC_FLAGS_NO4GB, @@ -163,16 +165,16 @@ static struct aac_ident "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, 0x1014, 0x0312, AAC_HWIF_I960RX, 0, + "IBM ServeRAID 8i"}, {0x9005, 0x0285, 0x9005, 0x0298, AAC_HWIF_I960RX, 0, - "Adaptec SAS RAID 4000SAS"}, + "Adaptec RAID 4000"}, {0x9005, 0x0285, 0x9005, 0x0299, AAC_HWIF_I960RX, 0, "Adaptec SAS RAID 4800SAS"}, {0x9005, 0x0285, 0x9005, 0x029a, AAC_HWIF_I960RX, 0, @@ -189,14 +191,96 @@ static struct aac_ident "ICP ICP9047MA SATA RAID"}, {0x9005, 0x0286, 0x9005, 0x02a1, AAC_HWIF_RKT, 0, "ICP ICP9087MA SATA RAID"}, + {0x9005, 0x0286, 0x9005, 0x02a6, AAC_HWIF_RKT, 0, + "ICP9067MA SATA RAID"}, + {0x9005, 0x0285, 0x9005, 0x02b5, AAC_HWIF_I960RX, 0, + "Adaptec RAID 5445"}, + {0x9005, 0x0285, 0x9005, 0x02b6, AAC_HWIF_I960RX, 0, + "Adaptec RAID 5805"}, + {0x9005, 0x0285, 0x9005, 0x02b7, AAC_HWIF_I960RX, 0, + "Adaptec RAID 5085"}, + {0x9005, 0x0285, 0x9005, 0x02b8, AAC_HWIF_I960RX, 0, + "ICP RAID ICP5445SL"}, + {0x9005, 0x0285, 0x9005, 0x02b9, AAC_HWIF_I960RX, 0, + "ICP RAID ICP5085SL"}, + {0x9005, 0x0285, 0x9005, 0x02ba, AAC_HWIF_I960RX, 0, + "ICP RAID ICP5805SL"}, {0x9005, 0x0285, 0x9005, 0x02bb, AAC_HWIF_I960RX, 0, "Adaptec RAID 3405"}, {0x9005, 0x0285, 0x9005, 0x02bc, AAC_HWIF_I960RX, 0, "Adaptec RAID 3805"}, + {0x9005, 0x0285, 0x9005, 0x02bd, AAC_HWIF_I960RX, 0, + "Adaptec RAID 31205"}, + {0x9005, 0x0285, 0x9005, 0x02be, AAC_HWIF_I960RX, 0, + "Adaptec RAID 31605"}, + {0x9005, 0x0285, 0x9005, 0x02bf, AAC_HWIF_I960RX, 0, + "ICP RAID ICP5045BL"}, + {0x9005, 0x0285, 0x9005, 0x02c0, AAC_HWIF_I960RX, 0, + "ICP RAID ICP5085BL"}, + {0x9005, 0x0285, 0x9005, 0x02c1, AAC_HWIF_I960RX, 0, + "ICP RAID ICP5125BR"}, + {0x9005, 0x0285, 0x9005, 0x02c2, AAC_HWIF_I960RX, 0, + "ICP RAID ICP5165BR"}, + {0x9005, 0x0285, 0x9005, 0x02c3, AAC_HWIF_I960RX, 0, + "Adaptec RAID 51205"}, + {0x9005, 0x0285, 0x9005, 0x02c4, AAC_HWIF_I960RX, 0, + "Adaptec RAID 51605"}, + {0x9005, 0x0285, 0x9005, 0x02c5, AAC_HWIF_I960RX, 0, + "ICP RAID ICP5125SL"}, + {0x9005, 0x0285, 0x9005, 0x02c6, AAC_HWIF_I960RX, 0, + "ICP RAID ICP5165SL"}, + {0x9005, 0x0285, 0x9005, 0x02c7, AAC_HWIF_I960RX, 0, + "Adaptec RAID 3085"}, + {0x9005, 0x0285, 0x9005, 0x02c8, AAC_HWIF_I960RX, 0, + "ICP RAID ICP5805BL"}, + {0x9005, 0x0285, 0x9005, 0x02ce, AAC_HWIF_I960RX, 0, + "Adaptec RAID 51245"}, + {0x9005, 0x0285, 0x9005, 0x02cf, AAC_HWIF_I960RX, 0, + "Adaptec RAID 51645"}, + {0x9005, 0x0285, 0x9005, 0x02d0, AAC_HWIF_I960RX, 0, + "Adaptec RAID 52445"}, {0x9005, 0x0285, 0x9005, 0x02d1, AAC_HWIF_I960RX, 0, "Adaptec RAID 5405"}, + {0x9005, 0x0285, 0x9005, 0x02d4, AAC_HWIF_I960RX, 0, + "Adaptec RAID 2045"}, + {0x9005, 0x0285, 0x9005, 0x02d5, AAC_HWIF_I960RX, 0, + "Adaptec RAID 2405"}, + {0x9005, 0x0285, 0x9005, 0x02d6, AAC_HWIF_I960RX, 0, + "Adaptec RAID 2445"}, + {0x9005, 0x0285, 0x9005, 0x02d7, AAC_HWIF_I960RX, 0, + "Adaptec RAID 2805"}, {0x9005, 0x0286, 0x1014, 0x9580, AAC_HWIF_RKT, 0, "IBM ServeRAID-8k"}, + {0x9005, 0x0285, 0x1014, 0x034d, AAC_HWIF_I960RX, 0, + "IBM ServeRAID 8s"}, + {0x9005, 0x0285, 0x108e, 0x7aac, AAC_HWIF_I960RX, 0, + "Sun STK RAID REM"}, + {0x9005, 0x0285, 0x108e, 0x7aae, AAC_HWIF_I960RX, 0, + "Sun STK RAID EM"}, + {0x9005, 0x0285, 0x108e, 0x286, AAC_HWIF_I960RX, 0, + "SG-XPCIESAS-R-IN"}, + {0x9005, 0x0285, 0x108e, 0x287, AAC_HWIF_I960RX, 0, + "SG-XPCIESAS-R-EX"}, + {0x9005, 0x0285, 0x15d9, 0x2b5, AAC_HWIF_I960RX, 0, + "AOC-USAS-S4i"}, + {0x9005, 0x0285, 0x15d9, 0x2b6, AAC_HWIF_I960RX, 0, + "AOC-USAS-S8i"}, + {0x9005, 0x0285, 0x15d9, 0x2c9, AAC_HWIF_I960RX, 0, + "AOC-USAS-S4iR"}, + {0x9005, 0x0285, 0x15d9, 0x2ca, AAC_HWIF_I960RX, 0, + "AOC-USAS-S8iR"}, + {0x9005, 0x0285, 0x15d9, 0x2d2, AAC_HWIF_I960RX, 0, + "AOC-USAS-S8i-LP"}, + {0x9005, 0x0285, 0x15d9, 0x2d3, AAC_HWIF_I960RX, 0, + "AOC-USAS-S8iR-LP"}, + {0, 0, 0, 0, 0, 0, 0} +}; +struct aac_ident +aac_family_identifiers[] = { + {0x9005, 0x0285, 0, 0, AAC_HWIF_I960RX, 0, + "Adaptec RAID Controller"}, + {0x9005, 0x0286, 0, 0, AAC_HWIF_RKT, 0, + "Adaptec RAID Controller"}, {0, 0, 0, 0, 0, 0, 0} }; @@ -204,13 +288,23 @@ static struct aac_ident * aac_find_ident(device_t dev) { struct aac_ident *m; + u_int16_t vendid, devid, sub_vendid, sub_devid; + + vendid = pci_get_vendor(dev); + devid = pci_get_device(dev); + sub_vendid = pci_get_subvendor(dev); + sub_devid = pci_get_subdevice(dev); 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); + if ((m->vendor == vendid) && (m->device == devid) && + (m->subvendor == sub_vendid) && + (m->subdevice == sub_devid)) + return (m); + } + + for (m = aac_family_identifiers; m->vendor != 0; m++) { + if ((m->vendor == vendid) && (m->device == devid)) + return (m); } return (NULL); @@ -224,7 +318,7 @@ aac_pci_probe(device_t dev) { struct aac_ident *id; - debug_called(1); + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); if ((id = aac_find_ident(dev)) != NULL) { device_set_desc(dev, id->desc); @@ -244,7 +338,7 @@ aac_pci_attach(device_t dev) int error; u_int32_t command; - debug_called(1); + fwprintf(NULL, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, ""); /* * Initialise softc. @@ -256,7 +350,7 @@ aac_pci_attach(device_t dev) /* assume failure is 'not configured' */ error = ENXIO; - /* + /* * Verify that the adapter is correctly set up in PCI space. */ command = pci_read_config(sc->aac_dev, PCIR_COMMAND, 2); @@ -275,25 +369,36 @@ aac_pci_attach(device_t dev) /* * Allocate the PCI register window. */ - 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) { + sc->aac_regs_rid0 = PCIR_BAR(0); + if ((sc->aac_regs_res0 = bus_alloc_resource_any(sc->aac_dev, + SYS_RES_MEMORY, &sc->aac_regs_rid0, RF_ACTIVE)) == NULL) { device_printf(sc->aac_dev, - "couldn't allocate register window\n"); + "couldn't allocate register window 0\n"); goto out; } - sc->aac_btag = rman_get_bustag(sc->aac_regs_resource); - sc->aac_bhandle = rman_get_bushandle(sc->aac_regs_resource); - - /* assume failure is 'out of memory' */ - error = ENOMEM; + sc->aac_btag0 = rman_get_bustag(sc->aac_regs_res0); + sc->aac_bhandle0 = rman_get_bushandle(sc->aac_regs_res0); + + if (sc->aac_hwif == AAC_HWIF_NARK) { + sc->aac_regs_rid1 = PCIR_BAR(1); + if ((sc->aac_regs_res1 = bus_alloc_resource_any(sc->aac_dev, + SYS_RES_MEMORY, &sc->aac_regs_rid1, RF_ACTIVE)) == NULL) { + device_printf(sc->aac_dev, + "couldn't allocate register window 1\n"); + goto out; + } + sc->aac_btag1 = rman_get_bustag(sc->aac_regs_res1); + sc->aac_bhandle1 = rman_get_bushandle(sc->aac_regs_res1); + } else { + sc->aac_regs_res1 = sc->aac_regs_res0; + sc->aac_regs_rid1 = sc->aac_regs_rid0; + sc->aac_btag1 = sc->aac_btag0; + sc->aac_bhandle1 = sc->aac_bhandle0; + } /* * Allocate the parent bus DMA tag appropriate for our PCI interface. - * + * * Note that some of these controllers are 64-bit capable. */ if (bus_dma_tag_create(NULL, /* parent */ @@ -310,7 +415,7 @@ aac_pci_attach(device_t dev) goto out; } - /* + /* * Detect the hardware interface version, set up the bus interface * indirection. */ @@ -318,19 +423,16 @@ aac_pci_attach(device_t dev) sc->aac_hwif = id->hwif; switch(sc->aac_hwif) { case AAC_HWIF_I960RX: - debug(2, "set hardware up for i960Rx"); + case AAC_HWIF_NARK: + fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for i960Rx/NARK"); sc->aac_if = aac_rx_interface; break; case AAC_HWIF_STRONGARM: - debug(2, "set hardware up for StrongARM"); + fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "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"); + fwprintf(sc, HBA_FLAGS_DBG_INIT_B, "set hardware up for Rocket/MIPS"); sc->aac_if = aac_rkt_interface; break; default: diff --git a/sys/dev/raid/aac/aac_tables.h b/sys/dev/raid/aac/aac_tables.h index 807579838c..ae26799229 100644 --- a/sys/dev/raid/aac/aac_tables.h +++ b/sys/dev/raid/aac/aac_tables.h @@ -24,8 +24,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/aac/aac_tables.h,v 1.1.2.3 2001/12/04 02:38:04 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aac_tables.h,v 1.3 2008/01/20 03:40:35 pavalos Exp $ + * $FreeBSD: src/sys/dev/aac/aac_tables.h,v 1.8 2010/04/13 12:10:55 emaste Exp $ */ /* @@ -35,40 +34,42 @@ * relevant only to FSA operations. */ static struct aac_code_lookup aac_command_status_table[] = { - {"OK", 0}, - {"operation not permitted", 1}, - {"not found", 2}, - {"I/O error", 5}, - {"device not configured", 6}, - {"too big", 7}, - {"permission denied", 13}, - {"file exists", 17}, - {"cross-device link", 18}, - {"operation not supported by device", 19}, - {"not a directory", 20}, - {"is a directory", 21}, - {"invalid argument", 22}, - {"file too large", 27}, - {"no space on device", 28}, - {"readonly filesystem", 30}, - {"too many links", 31}, - {"operation would block", 35}, - {"file name too long", 63}, - {"directory not empty", 66}, - {"quota exceeded", 69}, - {"stale file handle", 70}, - {"too many levels of remote in path", 71}, - {"bad file handle", 10001}, - {"not sync", 10002}, - {"bad cookie", 10003}, - {"operation not supported", 10004}, - {"too small", 10005}, - {"server fault", 10006}, - {"bad type", 10007}, - {"jukebox", 10008}, - {"not mounted", 10009}, - {"in maintenance mode", 10010}, - {"stale ACL", 10011}, + {"OK", ST_OK}, + {"operation not permitted", ST_PERM}, + {"not found", ST_NOENT}, + {"I/O error", ST_IO}, + {"device not configured", ST_NXIO}, + {"too big", ST_E2BIG}, + {"permission denied", ST_ACCES}, + {"file exists", ST_EXIST}, + {"cross-device link", ST_XDEV}, + {"operation not supported by device", ST_NODEV}, + {"not a directory", ST_NOTDIR}, + {"is a directory", ST_ISDIR}, + {"invalid argument", ST_INVAL}, + {"file too large", ST_FBIG}, + {"no space on device", ST_NOSPC}, + {"readonly filesystem", ST_ROFS}, + {"too many links", ST_MLINK}, + {"operation would block", ST_WOULDBLOCK}, + {"file name too long", ST_NAMETOOLONG}, + {"directory not empty", ST_NOTEMPTY}, + {"quota exceeded", ST_DQUOT}, + {"stale file handle", ST_STALE}, + {"too many levels of remote in path", ST_REMOTE}, + {"device busy (spinning up)", ST_NOT_READY}, + {"bad file handle", ST_BADHANDLE}, + {"not sync", ST_NOT_SYNC}, + {"bad cookie", ST_BAD_COOKIE}, + {"operation not supported", ST_NOTSUPP}, + {"too small", ST_TOOSMALL}, + {"server fault", ST_SERVERFAULT}, + {"bad type", ST_BADTYPE}, + {"jukebox", ST_JUKEBOX}, + {"not mounted", ST_NOTMOUNTED}, + {"in maintenance mode", ST_MAINTMODE}, + {"stale ACL", ST_STALEACL}, + {"bus reset - command aborted", ST_BUS_RESET}, {NULL, 0}, {"unknown command status", 0} }; diff --git a/sys/dev/raid/aac/aacreg.h b/sys/dev/raid/aac/aacreg.h index 5900935f58..17fe7ce34a 100644 --- a/sys/dev/raid/aac/aacreg.h +++ b/sys/dev/raid/aac/aacreg.h @@ -26,8 +26,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/aac/aacreg.h,v 1.4.2.7 2003/04/08 13:22:08 scottl Exp $ - * $DragonFly: src/sys/dev/raid/aac/aacreg.h,v 1.4 2008/01/20 03:40:35 pavalos Exp $ + * $FreeBSD: src/sys/dev/aac/aacreg.h,v 1.34 2010/09/29 14:22:00 emaste Exp $ */ /* @@ -85,7 +84,7 @@ struct aac_queue_entry { u_int32_t aq_fib_size; /* FIB size in bytes */ u_int32_t aq_fib_addr; /* receiver-space address of the FIB */ -} __attribute__ ((packed)); +} __packed; #define AAC_PRODUCER_INDEX 0 #define AAC_CONSUMER_INDEX 1 @@ -107,7 +106,7 @@ struct aac_queue_table { struct aac_queue_entry qt_HostHighRespQueue[AAC_HOST_HIGH_RESP_ENTRIES]; struct aac_queue_entry qt_AdapNormRespQueue[AAC_ADAP_NORM_RESP_ENTRIES]; struct aac_queue_entry qt_AdapHighRespQueue[AAC_ADAP_HIGH_RESP_ENTRIES]; -} __attribute__ ((packed)); +} __packed; /* * Queue names @@ -129,9 +128,9 @@ struct aac_queue_table { * our private command structure and don't touch these) */ struct aac_fib_list_entry { - u_int32_t Flink; - u_int32_t Blink; -} __attribute__ ((packed)); + u_int32_t Flink; + u_int32_t Blink; +} __packed; /* * FIB (FSA Interface Block?); this is the datastructure passed between the host @@ -154,14 +153,14 @@ struct aac_fib_header { } _s; struct aac_fib_list_entry FibLinks; } _u; -} __attribute__ ((packed)); +} __packed; #define AAC_FIB_DATASIZE (512 - sizeof(struct aac_fib_header)) struct aac_fib { struct aac_fib_header Header; u_int8_t data[AAC_FIB_DATASIZE]; -} __attribute__ ((packed)); +} __packed; /* * FIB commands @@ -221,20 +220,20 @@ typedef enum { IsAdapterPaused = 704, SendHostTime = 705, RequestSupplementAdapterInfo = 706, /* Supp. Info for set in UCC - * use only if supported + * use only if supported * (RequestAdapterInfo first) */ LastMiscCommand = 707, - - OnLineDiagnostic = 800, - FduAdapterTest = 801, + + OnLineDiagnostic = 800, + FduAdapterTest = 801, RequestCompatibilityId = 802, AdapterEnvironmentInfo = 803, /* temp. sensors */ NvsramEventLog = 900, ResetNvsramEventLogPointers = 901, EnableEventLog = 902, DisableEventLog = 903, - EncryptedKeyTransportFIB= 904, - KeyableFeaturesFIB= 905 + EncryptedKeyTransportFIB= 904, + KeyableFeaturesFIB= 905 } AAC_FibCommands; /* @@ -284,7 +283,7 @@ typedef enum { #define AAC_ERROR_FIB_DEALLOCATION_FAILED 0x08 /* - * Adapter Init Structure: this is passed to the adapter with the + * Adapter Init Structure: this is passed to the adapter with the * AAC_MONKER_INITSTRUCT command to point it at our control structures. */ struct aac_adapter_init { @@ -307,13 +306,13 @@ struct aac_adapter_init { 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 +#define AAC_INITFLAGS_NEW_COMM_SUPPORTED 1 +#define AAC_INITFLAGS_DRIVER_USES_UTC_TIME 0x10 +#define AAC_INITFLAGS_DRIVER_SUPPORTS_PM 0x20 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; +} __packed; /* * Shared data types @@ -332,14 +331,14 @@ typedef enum { CT_MORPH, CT_PASSTHRU, CT_RAID4, - CT_RAID10, /* stripe of mirror */ - CT_RAID00, /* stripe of stripe */ - CT_VOLUME_OF_MIRRORS, /* volume of mirror */ - CT_PSEUDO_RAID3, /* really raid4 */ - CT_RAID50, /* stripe of raid5 */ - CT_RAID5D, /* raid5 distributed hot-sparing */ + CT_RAID10, /* stripe of mirror */ + CT_RAID00, /* stripe of stripe */ + 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_RAID1E, /* extended raid1 mirroring */ CT_RAID6, CT_RAID60, } AAC_FSAVolType; @@ -348,23 +347,23 @@ typedef enum { * Host-addressable object types */ typedef enum { - FT_REG = 1, /* regular file */ - FT_DIR, /* directory */ - FT_BLK, /* "block" device - reserved */ - FT_CHR, /* "character special" device - reserved */ - FT_LNK, /* symbolic link */ - FT_SOCK, /* socket */ - FT_FIFO, /* fifo */ - FT_FILESYS, /* ADAPTEC's "FSA"(tm) filesystem */ - FT_DRIVE, /* physical disk - addressable in scsi by b/t/l */ - FT_SLICE, /* virtual disk - raw volume - slice */ - FT_PARTITION, /* FSA partition - carved out of a slice - building + FT_REG = 1, /* regular file */ + FT_DIR, /* directory */ + FT_BLK, /* "block" device - reserved */ + FT_CHR, /* "character special" device - reserved */ + FT_LNK, /* symbolic link */ + FT_SOCK, /* socket */ + FT_FIFO, /* fifo */ + FT_FILESYS, /* ADAPTEC's "FSA"(tm) filesystem */ + FT_DRIVE, /* physical disk - addressable in scsi by b/t/l */ + FT_SLICE, /* virtual disk - raw volume - slice */ + FT_PARTITION, /* FSA partition - carved out of a slice - building * block for containers */ - FT_VOLUME, /* Container - Volume Set */ - FT_STRIPE, /* Container - Stripe Set */ - FT_MIRROR, /* Container - Mirror Set */ - FT_RAID5, /* Container - Raid 5 Set */ - FT_DATABASE /* Storage object with "foreign" content manager */ + FT_VOLUME, /* Container - Volume Set */ + FT_STRIPE, /* Container - Stripe Set */ + FT_MIRROR, /* Container - Mirror Set */ + FT_RAID5, /* Container - Raid 5 Set */ + FT_DATABASE /* Storage object with "foreign" content manager */ } AAC_FType; /* @@ -373,7 +372,7 @@ typedef enum { struct aac_sg_entry { u_int32_t SgAddress; u_int32_t SgByteCount; -} __attribute__ ((packed)); +} __packed; struct aac_sg_entry64 { u_int64_t SgAddress; @@ -391,7 +390,7 @@ struct aac_sg_entryraw { struct aac_sg_table { u_int32_t SgCount; struct aac_sg_entry SgEntry[0]; -} __attribute__ ((packed)); +} __packed; /* * Host-side scatter/gather list for 64-bit commands. @@ -399,7 +398,7 @@ struct aac_sg_table { struct aac_sg_table64 { u_int32_t SgCount; struct aac_sg_entry64 SgEntry64[0]; -} __attribute__ ((packed)); +} __packed; /* * s/g list for raw commands @@ -423,7 +422,7 @@ struct aac_container_creation { u_int32_t Minute:6; /* 0-59 */ u_int32_t Second:6; /* 0-59 */ u_int64_t ViaAdapterSerialNumber; -} __attribute__ ((packed)); +} __packed; /* * Revision number handling @@ -452,7 +451,7 @@ struct FsaRevision { u_int32_t ul; } external; u_int32_t buildNumber; -} __attribute__ ((packed)); +} __packed; /* * Adapter Information @@ -470,7 +469,7 @@ typedef enum { CPU_MIPS, CPU_XSCALE, CPU__last -} AAC_CpuType; +} AAC_CpuType; typedef enum { CPUI960_JX = 1, @@ -547,7 +546,7 @@ typedef enum { * XXX the aac-2622 with no battery present reports PLATFORM_BAT_OPT_PRESENT */ typedef enum -{ +{ PLATFORM_BAT_REQ_PRESENT = 1, /* BATTERY REQUIRED AND PRESENT */ PLATFORM_BAT_REQ_NOTPRESENT, /* BATTERY REQUIRED AND NOT PRESENT */ PLATFORM_BAT_OPT_PRESENT, /* BATTERY OPTIONAL AND PRESENT */ @@ -555,9 +554,9 @@ typedef enum PLATFORM_BAT_NOT_SUPPORTED /* BATTERY NOT SUPPORTED */ } AAC_BatteryPlatform; -/* +/* * options supported by this board - * there has to be a one to one mapping of these defines and the ones in + * there has to be a one to one mapping of these defines and the ones in * fsaapi.h, search for FSA_SUPPORT_SNAPSHOT */ #define AAC_SUPPORTED_SNAPSHOT 0x01 @@ -580,24 +579,24 @@ typedef enum #define AAC_SUPPORTED_64BIT_ARRAYSIZE 0x40000 #define AAC_SUPPORTED_HEAT_SENSOR 0x80000 -/* +/* * Structure used to respond to a RequestAdapterInfo fib. */ struct aac_adapter_info { - AAC_Platform PlatformBase; /* adapter type */ + AAC_Platform PlatformBase; /* adapter type */ AAC_CpuType CpuArchitecture; /* adapter CPU type */ - AAC_CpuSubType CpuVariant; /* adapter CPU subtype */ - u_int32_t ClockSpeed; /* adapter CPU clockspeed */ - u_int32_t ExecutionMem; /* adapter Execution Memory + AAC_CpuSubType CpuVariant; /* adapter CPU subtype */ + u_int32_t ClockSpeed; /* adapter CPU clockspeed */ + u_int32_t ExecutionMem; /* adapter Execution Memory * size */ - u_int32_t BufferMem; /* adapter Data Memory */ - u_int32_t TotalMem; /* adapter Total Memory */ + u_int32_t BufferMem; /* adapter Data Memory */ + u_int32_t TotalMem; /* adapter Total Memory */ struct FsaRevision KernelRevision; /* adapter Kernel Software * Revision */ struct FsaRevision MonitorRevision; /* adapter Monitor/Diagnostic * Software Revision */ struct FsaRevision HardwareRevision;/* TBD */ - struct FsaRevision BIOSRevision; /* adapter BIOS Revision */ + struct FsaRevision BIOSRevision; /* adapter BIOS Revision */ u_int32_t ClusteringEnabled; u_int32_t ClusterChannelMask; u_int64_t SerialNumber; @@ -605,7 +604,59 @@ struct aac_adapter_info { u_int32_t SupportedOptions; /* supported features of this * controller */ AAC_OemFlavor OemVariant; -} __attribute__ ((packed)); +} __packed; + +/* + * Structure used to respond to a RequestSupplementAdapterInfo fib. + */ +struct vpd_info { + u_int8_t AssemblyPn[8]; + u_int8_t FruPn[8]; + u_int8_t BatteryFruPn[8]; + u_int8_t EcVersionString[8]; + u_int8_t Tsid[12]; +} __packed; + +#define MFG_PCBA_SERIAL_NUMBER_WIDTH 12 +#define MFG_WWN_WIDTH 8 + +struct aac_supplement_adapter_info { + /* The assigned Adapter Type Text, extra byte for null termination */ + int8_t AdapterTypeText[17+1]; + /* Pad for the text above */ + int8_t Pad[2]; + /* Size in bytes of the memory that is flashed */ + u_int32_t FlashMemoryByteSize; + /* The assigned IMAGEID_xxx for this adapter */ + u_int32_t FlashImageId; + /* + * The maximum number of Phys available on a SATA/SAS + * Controller, 0 otherwise + */ + u_int32_t MaxNumberPorts; + /* Version of expansion area */ + u_int32_t Version; + u_int32_t FeatureBits; + u_int8_t SlotNumber; + u_int8_t ReservedPad0[3]; + u_int8_t BuildDate[12]; + /* The current number of Ports on a SAS controller, 0 otherwise */ + u_int32_t CurrentNumberPorts; + + struct vpd_info VpdInfo; + + /* Firmware Revision (Vmaj.min-dash.) */ + struct FsaRevision FlashFirmwareRevision; + u_int32_t RaidTypeMorphOptions; + /* Firmware's boot code Revision (Vmaj.min-dash.) */ + struct FsaRevision FlashFirmwareBootRevision; + /* PCBA serial no. from th MFG sector */ + u_int8_t MfgPcbaSerialNo[MFG_PCBA_SERIAL_NUMBER_WIDTH]; + /* WWN from the MFG sector */ + u_int8_t MfgWWNName[MFG_WWN_WIDTH]; + /* Growth Area for future expansion ((7*4) - 12 - 8)/4 = 2 words */ + u_int32_t ReservedGrowth[2]; +} __packed; /* * Monitor/Kernel interface. @@ -643,7 +694,7 @@ struct aac_adapter_info { #define AAC_KERNEL_PANIC 0x00000100 /* - * Data types relating to control and monitoring of the NVRAM/WriteCache + * Data types relating to control and monitoring of the NVRAM/WriteCache * subsystem. */ @@ -695,7 +746,7 @@ struct aac_nvramdevinfo { u_int32_t NV_NDirty; /* count of dirty NVRAM buffers */ u_int32_t NV_NActive; /* count of NVRAM buffers being * written */ -} __attribute__ ((packed)); +} __packed; struct aac_nvraminfo { AAC_NVSTATUS NV_Status; /* nvram subsystem status */ @@ -715,7 +766,7 @@ struct aac_nvraminfo { u_int32_t NV_BattNeedsReconditioning; /* boolean */ u_int32_t NV_TotalSize; /* size of all non-volatile * memories in bytes */ -} __attribute__ ((packed)); +} __packed; /* * Data types relating to adapter-initiated FIBs @@ -783,11 +834,11 @@ typedef enum { struct aac_AifContainers { u_int32_t src; /* from/master */ u_int32_t dst; /* to/slave */ -} __attribute__ ((packed)); +} __packed; union aac_AifJobClient { struct aac_AifContainers container; /* For Container and - * file system progress + * filesystem progress * ops; */ int32_t scsi_dh; /* For SCSI progress * ops */ @@ -799,7 +850,7 @@ struct aac_AifJobDesc { AAC_AifJobType type; /* Operation that is being * performed */ union aac_AifJobClient client; /* Details */ -} __attribute__ ((packed)); +} __packed; struct aac_AifJobProgressReport { struct aac_AifJobDesc jd; @@ -808,7 +859,7 @@ struct aac_AifJobProgressReport { u_int32_t currentTick; u_int32_t jobSpecificData1; u_int32_t jobSpecificData2; -} __attribute__ ((packed)); +} __packed; /* * Event Notification @@ -818,7 +869,7 @@ typedef enum { AifEnGeneric = 1, /* Generic notification */ AifEnTaskComplete, /* Task has completed */ AifEnConfigChange, /* Adapter config change occurred */ - AifEnContainerChange, /* Adapter specific container + AifEnContainerChange, /* Adapter specific container * configuration change */ AifEnDeviceFailure, /* SCSI device failed */ AifEnMirrorFailover, /* Mirror failover started */ @@ -832,10 +883,21 @@ typedef enum { AifEnBatteryEvent, /* Significant NV battery event */ AifEnAddContainer, /* A new container was created. */ AifEnDeleteContainer, /* A container was deleted. */ - AifEnSMARTEvent, /* SMART Event */ + AifEnSMARTEvent, /* SMART Event */ AifEnBatteryNeedsRecond, /* The battery needs reconditioning */ AifEnClusterEvent, /* Some cluster event */ AifEnDiskSetEvent, /* A disk set event occured. */ + AifEnContainerScsiEvent, /* a container event with no. and scsi id */ + AifEnPicBatteryEvent, /* An event gen. by pic_battery.c for an ABM */ + AifEnExpEvent, /* Exp. Event Type to replace CTPopUp messages */ + AifEnRAID6RebuildDone, /* RAID6 rebuild finished */ + AifEnSensorOverHeat, /* Heat Sensor indicate overheat */ + AifEnSensorCoolDown, /* Heat Sensor ind. cooled down after overheat */ + AifFeatureKeysModified, /* notif. of updated feature keys */ + AifApplicationExpirationEvent, /* notif. on app. expiration status */ + AifEnBackgroundConsistencyCheck,/* BCC notif. for NEC - DDTS 94700 */ + AifEnAddJBOD, /* A new JBOD type drive was created (30) */ + AifEnDeleteJBOD, /* A JBOD type drive was deleted (31) */ AifDriverNotifyStart=199, /* Notifies for host driver go here */ /* Host driver notifications start here */ AifDenMorphComplete, /* A morph operation completed */ @@ -844,46 +906,51 @@ typedef enum { struct aac_AifEnsGeneric { char text[132]; /* Generic text */ -} __attribute__ ((packed)); +} __packed; struct aac_AifEnsDeviceFailure { u_int32_t deviceHandle; /* SCSI device handle */ -} __attribute__ ((packed)); +} __packed; struct aac_AifEnsMirrorFailover { u_int32_t container; /* Container with failed element */ u_int32_t failedSlice; /* Old slice which failed */ u_int32_t creatingSlice; /* New slice used for auto-create */ -} __attribute__ ((packed)); +} __packed; struct aac_AifEnsContainerChange { u_int32_t container[2]; /* container that changed, -1 if no * container */ -} __attribute__ ((packed)); +} __packed; struct aac_AifEnsContainerEvent { u_int32_t container; /* container number */ u_int32_t eventType; /* event type */ -} __attribute__ ((packed)); +} __packed; struct aac_AifEnsEnclosureEvent { u_int32_t empID; /* enclosure management proc number */ u_int32_t unitID; /* unitId, fan id, power supply id, * slot id, tempsensor id. */ u_int32_t eventType; /* event type */ -} __attribute__ ((packed)); +} __packed; + +typedef enum { + AIF_EM_DRIVE_INSERTION=31, + AIF_EM_DRIVE_REMOVAL +} aac_AifEMEventType; struct aac_AifEnsBatteryEvent { AAC_NVBATT_TRANSITION transition_type; /* eg from low to ok */ AAC_NVBATTSTATUS current_state; /* current batt state */ AAC_NVBATTSTATUS prior_state; /* prev batt state */ -} __attribute__ ((packed)); +} __packed; struct aac_AifEnsDiskSetEvent { u_int32_t eventType; u_int64_t DsNum; u_int64_t CreatorId; -} __attribute__ ((packed)); +} __packed; typedef enum { CLUSTER_NULL_EVENT = 0, @@ -897,7 +964,7 @@ typedef enum { struct aac_AifEnsClusterEvent { AAC_ClusterAifEvent eventType; -} __attribute__ ((packed)); +} __packed; struct aac_AifEventNotify { AAC_AifEventNotifyType type; @@ -913,12 +980,12 @@ struct aac_AifEventNotify { /* struct aac_AifEnsSMARTEvent ES;*/ struct aac_AifEnsClusterEvent ECLE; } data; -} __attribute__ ((packed)); +} __packed; /* * Adapter Initiated FIB command structures. Start with the adapter * initiated FIBs that really come from the adapter, and get responded - * to by the host. + * to by the host. */ #define AAC_AIF_REPORT_MAX_SIZE 64 @@ -951,7 +1018,7 @@ struct aac_aif_command { u_int8_t AR[AAC_AIF_REPORT_MAX_SIZE]; u_int8_t data[AAC_FIB_DATASIZE - 8]; } data; -} __attribute__ ((packed)); +} __packed; /* * Filesystem commands/data @@ -1032,6 +1099,7 @@ typedef enum { ST_DQUOT = 69, ST_STALE = 70, ST_REMOTE = 71, + ST_NOT_READY = 72, ST_BADHANDLE = 10001, ST_NOT_SYNC = 10002, ST_BAD_COOKIE = 10003, @@ -1042,7 +1110,8 @@ typedef enum { ST_JUKEBOX = 10008, ST_NOTMOUNTED = 10009, ST_MAINTMODE = 10010, - ST_STALEACL = 10011 + ST_STALEACL = 10011, + ST_BUS_RESET = 20001 } AAC_FSAStatus; /* @@ -1071,7 +1140,7 @@ typedef enum _VM_COMMANDS { VM_CtHostRead64, VM_CtHostWrite64, VM_DrvErrTblLog, /* drive error table/log type of command */ - VM_NameServe64 + VM_NameServe64 } AAC_VMCommand; /* @@ -1091,20 +1160,21 @@ struct aac_mntobj { u_int32_t pad[8]; } ObjExtension; u_int32_t AlterEgoId; -} __attribute__ ((packed)); + u_int32_t CapacityHigh; +} __packed; struct aac_mntinfo { u_int32_t Command; u_int32_t MntType; u_int32_t MntCount; -} __attribute__ ((packed)); +} __packed; struct aac_mntinforesp { u_int32_t Status; u_int32_t MntType; u_int32_t MntRespCount; struct aac_mntobj MntTable[1]; -} __attribute__ ((packed)); +} __packed; /* * Container shutdown command. @@ -1112,7 +1182,7 @@ struct aac_mntinforesp { struct aac_closecommand { u_int32_t Command; u_int32_t ContainerId; -} __attribute__ ((packed)); +} __packed; /* * Container Config Command @@ -1122,13 +1192,13 @@ struct aac_ctcfg { u_int32_t Command; u_int32_t cmd; u_int32_t param; -} __attribute__ ((packed)); +} __packed; struct aac_ctcfg_resp { u_int32_t Status; u_int32_t resp; u_int32_t param; -} __attribute__ ((packed)); +} __packed; /* * 'Ioctl' commads @@ -1146,7 +1216,7 @@ struct aac_getbusinf { u_int32_t TargetsPerBus; u_int8_t InitiatorBusId[AAC_SCSI_MAX_PORTS]; u_int8_t BusValid[AAC_SCSI_MAX_PORTS]; -} __attribute__ ((packed)); +} __packed; struct aac_vmioctl { u_int32_t Command; @@ -1155,7 +1225,7 @@ struct aac_vmioctl { u_int32_t ObjId; u_int32_t IoctlCmd; u_int32_t IoctlBuf[1]; /* Placeholder? */ -} __attribute__ ((packed)); +} __packed; struct aac_vmi_businf_resp { u_int32_t Status; @@ -1164,7 +1234,7 @@ struct aac_vmi_businf_resp { u_int32_t ObjId; u_int32_t IoctlCmd; struct aac_getbusinf BusInf; -} __attribute__ ((packed)); +} __packed; #if 0 #define AAC_BTL_TO_HANDLE(b, t, l) \ @@ -1250,7 +1320,7 @@ struct aac_blockread { u_int32_t BlockNumber; u_int32_t ByteCount; struct aac_sg_table SgMap; /* variable size */ -} __attribute__ ((packed)); +} __packed; struct aac_blockread64 { u_int32_t Command; @@ -1265,7 +1335,7 @@ struct aac_blockread64 { struct aac_blockread_response { u_int32_t Status; u_int32_t ByteCount; -} __attribute__ ((packed)); +} __packed; struct aac_blockwrite { u_int32_t Command; /* not FSACommand! */ @@ -1274,7 +1344,7 @@ struct aac_blockwrite { u_int32_t ByteCount; u_int32_t Stable; struct aac_sg_table SgMap; /* variable size */ -} __attribute__ ((packed)); +} __packed; struct aac_blockwrite64 { u_int32_t Command; /* not FSACommand! */ @@ -1290,7 +1360,7 @@ struct aac_blockwrite_response { u_int32_t Status; u_int32_t ByteCount; u_int32_t Committed; -} __attribute__ ((packed)); +} __packed; struct aac_raw_io { u_int64_t BlockNumber; @@ -1306,14 +1376,14 @@ struct aac_raw_io { * Container shutdown command. */ struct aac_close_command { - u_int32_t Command; - u_int32_t ContainerId; + u_int32_t Command; + u_int32_t ContainerId; }; /* * SCSI Passthrough structures */ -struct aac_srb32 { +struct aac_srb { u_int32_t function; u_int32_t bus; u_int32_t target; @@ -1324,7 +1394,7 @@ struct aac_srb32 { u_int32_t retry_limit; u_int32_t cdb_len; u_int8_t cdb[16]; - struct aac_sg_table sg_map32; + struct aac_sg_table sg_map; }; enum { @@ -1402,24 +1472,6 @@ enum { AAC_SRB_STS_ERROR_RECOVERY }; -/* - * Register set for adapters based on the Falcon bridge and PPC core - */ - -#define AAC_FA_DOORBELL0_CLEAR 0x00 -#define AAC_FA_DOORBELL1_CLEAR 0x02 -#define AAC_FA_DOORBELL0 0x04 -#define AAC_FA_DOORBELL1 0x06 -#define AAC_FA_MASK0_CLEAR 0x08 -#define AAC_FA_MASK1_CLEAR 0x0a -#define AAC_FA_MASK0 0x0c -#define AAC_FA_MASK1 0x0e -#define AAC_FA_MAILBOX 0x10 -#define AAC_FA_FWSTATUS 0x2c /* Mailbox 7 */ -#define AAC_FA_INTSRC 0x900 - -#define AAC_FA_HACK(sc) (void)AAC_GETREG4(sc, AAC_FA_INTSRC) - /* * Register definitions for the Adaptec AAC-364 'Jalapeno I/II' adapters, based * on the SA110 'StrongArm'. @@ -1445,6 +1497,8 @@ enum { * and other related adapters. */ +#define AAC_RX_OMR0 0x18 /* outbound message register 0 */ +#define AAC_RX_OMR1 0x1c /* outbound message register 1 */ #define AAC_RX_IDBR 0x20 /* inbound doorbell register */ #define AAC_RX_IISR 0x24 /* inbound interrupt status register */ #define AAC_RX_IIMR 0x28 /* inbound interrupt mask register */ @@ -1462,6 +1516,8 @@ enum { * Unsurprisingly, it's quite similar to the i960! */ +#define AAC_RKT_OMR0 0x18 /* outbound message register 0 */ +#define AAC_RKT_OMR1 0x1c /* outbound message register 1 */ #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 */ @@ -1490,7 +1546,7 @@ enum { /* * The adapter can request the host print a message by setting the * DB_PRINTF flag in DOORBELL0. The driver responds by collecting the - * message from the printf buffer, clearing the DB_PRINTF flag in + * message from the printf buffer, clearing the DB_PRINTF flag in * DOORBELL0 and setting it in DOORBELL1. * (ODBR and IDBR respectively for the i960Rx adapters) */ diff --git a/sys/dev/raid/aac/aacvar.h b/sys/dev/raid/aac/aacvar.h index 02e91266b0..58f428c015 100644 --- a/sys/dev/raid/aac/aacvar.h +++ b/sys/dev/raid/aac/aacvar.h @@ -26,23 +26,38 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * $FreeBSD: src/sys/dev/aac/aacvar.h,v 1.4.2.7 2003/04/08 13:22:08 scottl Exp $ + * $FreeBSD: src/sys/dev/aac/aacvar.h,v 1.60 2010/09/29 14:22:00 emaste Exp $ */ -#include -#include -#include +#include +#include #include -#include #include -#include +#include +#include +#include +#include + +#define AAC_TYPE_DEVO 1 +#define AAC_TYPE_ALPHA 2 +#define AAC_TYPE_BETA 3 +#define AAC_TYPE_RELEASE 4 + +#define AAC_DRIVER_MAJOR_VERSION 2 +#define AAC_DRIVER_MINOR_VERSION 1 +#define AAC_DRIVER_BUGFIX_LEVEL 9 +#define AAC_DRIVER_TYPE AAC_TYPE_RELEASE + +#ifndef AAC_DRIVER_BUILD +# define AAC_DRIVER_BUILD 1 +#endif /* * Driver Parameter Definitions */ /* - * The firmware interface allows for a 16-bit s/g list length. We limit + * The firmware interface allows for a 16-bit s/g list length. We limit * ourselves to a reasonable maximum and ensure alignment. */ #define AAC_MAXSGENTRIES 64 /* max S/G entries, limit 65535 */ @@ -52,12 +67,6 @@ */ #define AAC_ADAPTER_FIBS 8 -/* - * FIBs are allocated in page-size chunks and can grow up to the 512 - * limit imposed by the hardware. - */ -#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. @@ -70,7 +79,7 @@ #define AAC_PRINTF_BUFSIZE 256 /* - * We wait this many seconds for the adapter to come ready if it is still + * We wait this many seconds for the adapter to come ready if it is still * booting */ #define AAC_BOOT_TIMEOUT (3 * 60) @@ -83,7 +92,7 @@ /* * Timeout for normal commands */ -#define AAC_CMD_TIMEOUT 30 /* seconds */ +#define AAC_CMD_TIMEOUT 120 /* seconds */ /* * Rate at which we periodically check for timed out commands and kick the @@ -105,6 +114,7 @@ struct aac_container /* * Per-SIM data structure */ +struct aac_cam; struct aac_sim { device_t sim_dev; @@ -112,13 +122,14 @@ struct aac_sim int BusNumber; int InitiatorBusId; struct aac_softc *aac_sc; + struct aac_cam *aac_cam; TAILQ_ENTRY(aac_sim) sim_link; }; /* * Per-disk structure */ -struct aac_disk +struct aac_disk { device_t ad_dev; cdev_t ad_dev_t; @@ -131,7 +142,7 @@ struct aac_disk int ad_cylinders; int ad_heads; int ad_sectors; - u_int32_t ad_size; + u_int64_t ad_size; int unit; }; @@ -147,7 +158,7 @@ struct aac_command struct aac_fib *cm_fib; /* FIB associated with this * command */ u_int64_t cm_fibphys; /* bus address of the FIB */ - struct buf *cm_data; /* pointer to data in kernel + struct bio *cm_data; /* pointer to data in kernel * space */ u_int32_t cm_datalen; /* data length */ bus_dmamap_t cm_datamap; /* DMA map for bio data */ @@ -165,10 +176,9 @@ struct aac_command #define AAC_ON_AACQ_FREE (1<<5) #define AAC_ON_AACQ_READY (1<<6) #define AAC_ON_AACQ_BUSY (1<<7) -#define AAC_ON_AACQ_COMPLETE (1<<8) +#define AAC_ON_AACQ_AIF (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_ON_AACQ_MASK ((1<<5)|(1<<6)|(1<<7)|(1<<8)|(1<<10)) #define AAC_QUEUE_FRZN (1<<9) /* Freeze the processing of * commands on the queue. */ @@ -211,7 +221,7 @@ struct aac_common { AAC_QUEUE_ALIGN]; /* buffer for text messages from the controller */ - char ac_printf[AAC_PRINTF_BUFSIZE]; + char ac_printf[AAC_PRINTF_BUFSIZE]; /* fib for synchronous commands */ struct aac_fib ac_sync_fib; @@ -220,7 +230,7 @@ struct aac_common { /* * Interface operations */ -struct aac_interface +struct aac_interface { int (*aif_get_fwstatus)(struct aac_softc *sc); void (*aif_qnotify)(struct aac_softc *sc, int qbit); @@ -231,9 +241,9 @@ struct aac_interface u_int32_t arg2, u_int32_t arg3); int (*aif_get_mailbox)(struct aac_softc *sc, int mb); void (*aif_set_interrupts)(struct aac_softc *sc, int enable); - int (*aif_send_command)(struct aac_softc *sc, struct aac_command *cm); - int (*aif_get_outb_queue)(struct aac_softc *sc); - void (*aif_set_outb_queue)(struct aac_softc *sc, int index); + 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; @@ -258,38 +268,51 @@ extern struct aac_interface aac_rkt_interface; #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) -#define AAC_GETREG4(sc, reg) bus_space_read_4 (sc->aac_btag, \ - sc->aac_bhandle, reg) -#define AAC_SETREG2(sc, reg, val) bus_space_write_2(sc->aac_btag, \ - sc->aac_bhandle, reg, val) -#define AAC_GETREG2(sc, reg) bus_space_read_2 (sc->aac_btag, \ - sc->aac_bhandle, reg) -#define AAC_SETREG1(sc, reg, val) bus_space_write_1(sc->aac_btag, \ - sc->aac_bhandle, reg, val) -#define AAC_GETREG1(sc, reg) bus_space_read_1 (sc->aac_btag, \ - sc->aac_bhandle, reg) - -/* Define the OS version specific locks */ -typedef struct lock aac_lock_t; -#define AAC_LOCK_INIT(l, s) lockinit(l, s, 0, LK_CANRECURSE) -#define AAC_LOCK_ACQUIRE(l) lockmgr(l, LK_EXCLUSIVE) -#define AAC_LOCK_RELEASE(l) lockmgr(l, LK_RELEASE) +#define AAC_MEM0_SETREG4(sc, reg, val) bus_space_write_4(sc->aac_btag0, \ + sc->aac_bhandle0, reg, val) +#define AAC_MEM0_GETREG4(sc, reg) bus_space_read_4(sc->aac_btag0, \ + sc->aac_bhandle0, reg) +#define AAC_MEM0_SETREG2(sc, reg, val) bus_space_write_2(sc->aac_btag0, \ + sc->aac_bhandle0, reg, val) +#define AAC_MEM0_GETREG2(sc, reg) bus_space_read_2(sc->aac_btag0, \ + sc->aac_bhandle0, reg) +#define AAC_MEM0_SETREG1(sc, reg, val) bus_space_write_1(sc->aac_btag0, \ + sc->aac_bhandle0, reg, val) +#define AAC_MEM0_GETREG1(sc, reg) bus_space_read_1(sc->aac_btag0, \ + sc->aac_bhandle0, reg) + +#define AAC_MEM1_SETREG4(sc, reg, val) bus_space_write_4(sc->aac_btag1, \ + sc->aac_bhandle1, reg, val) +#define AAC_MEM1_GETREG4(sc, reg) bus_space_read_4(sc->aac_btag1, \ + sc->aac_bhandle1, reg) +#define AAC_MEM1_SETREG2(sc, reg, val) bus_space_write_2(sc->aac_btag1, \ + sc->aac_bhandle1, reg, val) +#define AAC_MEM1_GETREG2(sc, reg) bus_space_read_2(sc->aac_btag1, \ + sc->aac_bhandle1, reg) +#define AAC_MEM1_SETREG1(sc, reg, val) bus_space_write_1(sc->aac_btag1, \ + sc->aac_bhandle1, reg, val) +#define AAC_MEM1_GETREG1(sc, reg) bus_space_read_1(sc->aac_btag1, \ + sc->aac_bhandle1, reg) + +/* fib context (IOCTL) */ +struct aac_fib_context { + u_int32_t unique; + int ctx_idx; + int ctx_wrap; + struct aac_fib_context *next, *prev; +}; /* * Per-controller structure. */ -struct aac_softc +struct aac_softc { /* bus connections */ device_t aac_dev; - struct callout aac_watchdog; - struct resource *aac_regs_resource; /* register interface - * window */ - int aac_regs_rid; /* resource ID */ - bus_space_handle_t aac_bhandle; /* bus space handle */ - bus_space_tag_t aac_btag; /* bus space tag */ + struct resource *aac_regs_res0, *aac_regs_res1; /* reg. if. window */ + int aac_regs_rid0, aac_regs_rid1; /* resource ID */ + bus_space_handle_t aac_bhandle0, aac_bhandle1; /* bus space handle */ + bus_space_tag_t aac_btag0, aac_btag1; /* bus space tag */ bus_dma_tag_t aac_parent_dmat; /* parent DMA tag */ bus_dma_tag_t aac_buffer_dmat; /* data buffer/command * DMA tag */ @@ -301,7 +324,7 @@ struct aac_softc /* controller features, limits and status */ int aac_state; #define AAC_STATE_SUSPEND (1<<0) -#define AAC_STATE_OPEN (1<<1) +#define AAC_STATE_UNUSED0 (1<<1) #define AAC_STATE_INTERRUPTS_ON (1<<2) #define AAC_STATE_AIF_SLEEPER (1<<3) struct FsaRevision aac_revision; @@ -310,8 +333,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_RKT 3 +#define AAC_HWIF_NARK 4 #define AAC_HWIF_UNKNOWN -1 bus_dma_tag_t aac_common_dmat; /* common structure * DMA tag */ @@ -328,18 +351,12 @@ struct aac_softc struct aac_command *aac_commands; /* command management */ - TAILQ_HEAD(,aac_command) aac_free; /* command structures + TAILQ_HEAD(,aac_command) aac_free; /* command structures * available for reuse */ TAILQ_HEAD(,aac_command) aac_ready; /* commands on hold for * controller resources */ 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; + 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]; @@ -348,13 +365,13 @@ struct aac_softc /* connected containters */ TAILQ_HEAD(,aac_container) aac_container_tqh; - aac_lock_t aac_container_lock; + struct lock aac_container_lock; /* * The general I/O lock. This protects the sync fib, the lists, the * queues, and the registers. */ - aac_lock_t aac_io_lock; + struct lock aac_io_lock; /* delayed activity infrastructure */ struct task aac_task_complete; /* deferred-completion @@ -362,11 +379,12 @@ struct aac_softc struct intr_config_hook aac_ich; /* management interface */ - cdev_t aac_dev_t; - aac_lock_t aac_aifq_lock; - struct aac_aif_command aac_aifq[AAC_AIFQ_LENGTH]; - int aac_aifq_head; - int aac_aifq_tail; + struct cdev *aac_dev_t; + struct lock aac_aifq_lock; + struct aac_fib aac_aifq[AAC_AIFQ_LENGTH]; + int aifq_idx; + int aifq_filled; + struct aac_fib_context *fibctx; struct kqinfo rcv_kq; struct thread *aifthread; int aifflags; @@ -385,25 +403,31 @@ struct aac_softc #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 */ + * 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_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 */ - +#define AAC_FLAGS_LBA_64BIT (1 << 14) /* 64-bit LBA support */ + u_int32_t supported_options; u_int32_t scsi_method_id; TAILQ_HEAD(,aac_sim) aac_sim_tqh; + struct callout aac_daemontime; /* clock daemon callout */ + 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) */ + 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) */ +#define AAC_CAM_TARGET_WILDCARD ~0 + void (*cam_rescan_cb)(struct aac_softc *, uint32_t, + uint32_t); }; /* @@ -411,7 +435,7 @@ struct aac_softc */ #define AAC_EVENT_NONE 0x00 #define AAC_EVENT_CMFREE 0x01 -#define AAC_EVENT_MASK 0xff +#define AAC_EVENT_MASK 0xff #define AAC_EVENT_REPEAT 0x100 typedef void aac_event_cb_t(struct aac_softc *sc, struct aac_event *event, @@ -423,26 +447,19 @@ struct aac_event { void *ev_arg; }; -#ifndef AAC_DRIVER_BUILD -# define AAC_DRIVER_BUILD 1 -#endif - /* * Public functions */ extern void aac_free(struct aac_softc *sc); 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_shutdown(device_t dev); +extern int aac_suspend(device_t dev); extern int aac_resume(device_t dev); extern void aac_new_intr(void *arg); -extern void aac_fast_intr(void *arg); -extern devclass_t aac_devclass; +extern void aac_filter(void *arg); extern void aac_submit_bio(struct aac_disk *ad, struct bio *bio); extern void aac_biodone(struct bio *bio, const char *code); -extern int aac_dump_enqueue(struct aac_disk *ad, u_int64_t lba, - void *data, int nblks); -extern void aac_dump_complete(struct aac_softc *sc); extern void aac_startio(struct aac_softc *sc); extern int aac_alloc_command(struct aac_softc *sc, struct aac_command **cmp); @@ -453,32 +470,33 @@ extern int aac_sync_fib(struct aac_softc *sc, u_int32_t command, extern void aac_add_event(struct aac_softc *sc, struct aac_event *event); -/* - * Debugging levels: - * 0 - quiet, only emit warnings - * 1 - noisy, emit major function points and things done - * 2 - extremely noisy, emit trace items in loops, etc. - */ #ifdef AAC_DEBUG -# define debug(level, fmt, args...) \ - do { \ - if (level <=AAC_DEBUG) kprintf("%s: " fmt "\n", __func__ , ##args); \ - } while (0) -# define debug_called(level) \ - do { \ - if (level <= AAC_DEBUG) kprintf("%s: called\n", __func__); \ - } while (0) - +extern int aac_debug_enable; +# define fwprintf(sc, flags, fmt, args...) \ +do { \ + if (!aac_debug_enable) \ + break; \ + if (sc != NULL) \ + device_printf(((struct aac_softc *)sc)->aac_dev, \ + "%s: " fmt "\n", __func__, ##args); \ + else \ + kprintf("%s: " fmt "\n", __func__, ##args); \ +} while(0) + +extern void aac_print_queues(struct aac_softc *sc); +extern void aac_panic(struct aac_softc *sc, char *reason); extern void aac_print_fib(struct aac_softc *sc, struct aac_fib *fib, const char *caller); extern void aac_print_aif(struct aac_softc *sc, struct aac_aif_command *aif); -# define AAC_PRINT_FIB(sc, fib) aac_print_fib(sc, fib, __func__) +#define AAC_PRINT_FIB(sc, fib) aac_print_fib(sc, fib, __func__) #else -# define debug(level, fmt, args...) -# define debug_called(level) +# define fwprintf(sc, flags, fmt, args...) + +# define aac_print_queues(sc) +# define aac_panic(sc, reason) # define AAC_PRINT_FIB(sc, fib) # define aac_print_aif(sc, aac_aif_command) @@ -522,7 +540,7 @@ static __inline void \ aac_enqueue_ ## name (struct aac_command *cm) \ { \ if ((cm->cm_flags & AAC_ON_AACQ_MASK) != 0) { \ - kprintf("command %p is on another queue, flags = %#x\n", \ + kprintf("command %p is on another queue, flags = %#x\n", \ cm, cm->cm_flags); \ panic("command is on another queue"); \ } \ @@ -534,7 +552,7 @@ static __inline void \ aac_requeue_ ## name (struct aac_command *cm) \ { \ if ((cm->cm_flags & AAC_ON_AACQ_MASK) != 0) { \ - kprintf("command %p is on another queue, flags = %#x\n", \ + kprintf("command %p is on another queue, flags = %#x\n", \ cm, cm->cm_flags); \ panic("command is on another queue"); \ } \ @@ -549,8 +567,8 @@ aac_dequeue_ ## name (struct aac_softc *sc) \ \ if ((cm = TAILQ_FIRST(&sc->aac_ ## name)) != NULL) { \ if ((cm->cm_flags & AAC_ON_ ## index) == 0) { \ - kprintf("command %p not in queue, flags = %#x, " \ - "bit = %#x\n", cm, cm->cm_flags, \ + kprintf("command %p not in queue, flags = %#x, " \ + "bit = %#x\n", cm, cm->cm_flags, \ AAC_ON_ ## index); \ panic("command not in queue"); \ } \ @@ -564,7 +582,7 @@ static __inline void \ aac_remove_ ## name (struct aac_command *cm) \ { \ if ((cm->cm_flags & AAC_ON_ ## index) == 0) { \ - kprintf("command %p not in queue, flags = %#x, " \ + kprintf("command %p not in queue, flags = %#x, " \ "bit = %#x\n", cm, cm->cm_flags, \ AAC_ON_ ## index); \ panic("command not in queue"); \ @@ -578,7 +596,6 @@ struct hack AACQ_COMMAND_QUEUE(free, AACQ_FREE); AACQ_COMMAND_QUEUE(ready, AACQ_READY); AACQ_COMMAND_QUEUE(busy, AACQ_BUSY); -AACQ_COMMAND_QUEUE(complete, AACQ_COMPLETE); /* * outstanding bio queue @@ -591,22 +608,22 @@ aac_initq_bio(struct aac_softc *sc) } static __inline void -aac_enqueue_bio(struct aac_softc *sc, struct bio *bio) +aac_enqueue_bio(struct aac_softc *sc, struct bio *bp) { - bioqdisksort(&sc->aac_bioq, bio); + bioq_insert_tail(&sc->aac_bioq, bp); AACQ_ADD(sc, AACQ_BIO); } static __inline struct bio * aac_dequeue_bio(struct aac_softc *sc) { - struct bio *bio; + struct bio *bp; - if ((bio = bioq_first(&sc->aac_bioq)) != NULL) { - bioq_remove(&sc->aac_bioq, bio); + if ((bp = bioq_first(&sc->aac_bioq)) != NULL) { + bioq_remove(&sc->aac_bioq, bp); AACQ_REMOVE(sc, AACQ_BIO); } - return(bio); + return(bp); } static __inline void