svn commit: r250963 - in head: share/man/man4 sys/amd64/conf sys/conf sys/dev/aacraid sys/i386/conf sys/ia64/conf sys/modules sys/modules/aacraid sys/modules/aacraid/aacraid_linux
Achim Leubner
achim at FreeBSD.org
Fri May 24 09:22:44 UTC 2013
Author: achim
Date: Fri May 24 09:22:43 2013
New Revision: 250963
URL: http://svnweb.freebsd.org/changeset/base/250963
Log:
Driver 'aacraid' added. Supports Adaptec by PMC RAID controller families Series 6, 7, 8 and upcoming products. Older Adaptec RAID controller families are supported by the 'aac' driver.
Approved by: scottl (mentor)
Added:
head/share/man/man4/aacraid.4 (contents, props changed)
head/sys/dev/aacraid/
head/sys/dev/aacraid/aacraid.c (contents, props changed)
head/sys/dev/aacraid/aacraid_cam.c (contents, props changed)
head/sys/dev/aacraid/aacraid_debug.c (contents, props changed)
head/sys/dev/aacraid/aacraid_debug.h (contents, props changed)
head/sys/dev/aacraid/aacraid_linux.c (contents, props changed)
head/sys/dev/aacraid/aacraid_pci.c (contents, props changed)
head/sys/dev/aacraid/aacraid_reg.h (contents, props changed)
head/sys/dev/aacraid/aacraid_var.h (contents, props changed)
head/sys/modules/aacraid/
head/sys/modules/aacraid/Makefile (contents, props changed)
head/sys/modules/aacraid/Makefile.inc (contents, props changed)
head/sys/modules/aacraid/aacraid_linux/
head/sys/modules/aacraid/aacraid_linux/Makefile (contents, props changed)
Modified:
head/share/man/man4/Makefile
head/sys/amd64/conf/GENERIC
head/sys/amd64/conf/NOTES
head/sys/conf/files
head/sys/conf/options
head/sys/i386/conf/GENERIC
head/sys/i386/conf/NOTES
head/sys/ia64/conf/GENERIC
head/sys/modules/Makefile
Modified: head/share/man/man4/Makefile
==============================================================================
--- head/share/man/man4/Makefile Fri May 24 09:21:18 2013 (r250962)
+++ head/share/man/man4/Makefile Fri May 24 09:22:43 2013 (r250963)
@@ -4,6 +4,7 @@
.include <bsd.own.mk>
MAN= aac.4 \
+ aacraid.4 \
acpi.4 \
${_acpi_asus.4} \
${_acpi_asus_wmi.4} \
Added: head/share/man/man4/aacraid.4
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/share/man/man4/aacraid.4 Fri May 24 09:22:43 2013 (r250963)
@@ -0,0 +1,139 @@
+.\" Copyright (c) 2013 Achim Leubner
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+.\" SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.Dd April 09, 2013
+.Dt AACRAID 4
+.Os
+.Sh NAME
+.Nm aacraid
+.Nd Adaptec AACRAID Controller driver
+.Sh SYNOPSIS
+To compile this driver into the kernel,
+place the following lines in your
+kernel configuration file:
+.Bd -ragged -offset indent
+.Cd device pci
+.Cd device aacraid
+.Pp
+To compile in debugging code:
+.Cd options AACRAID_DEBUG=N
+.Ed
+.Pp
+Alternatively, to load the driver as a
+module at boot time, place the following line in
+.Xr loader.conf 5 :
+.Bd -literal -offset indent
+aacraid_load="YES"
+.Ed
+.Sh DESCRIPTION
+The
+.Nm
+driver provides support for the Adaptec by PMC RAID controllers,
+including Series 6/7/8 and upcoming families.
+.Pp
+The RAID containers are handled via the
+.Nm aacraidp0
+bus.
+The physical buses are represented by the
+.Nm aacraidp?
+devices (beginning with aacraidp1). These devices enable the
+SCSI pass-thru interface and allows devices connected
+to the card such as CD-ROMs to be available via the CAM
+.Xr scsi 4
+subsystem.
+Note that not all cards allow this interface to be enabled.
+.Pp
+The
+.Pa /dev/aacraid?
+device nodes provide access to the management interface of the controller.
+One node exists per installed card.
+If the kernel is compiled with the
+.Dv COMPAT_LINUX
+option, or the
+.Pa aacraid_linux.ko
+and
+.Pa linux.ko
+modules are loaded, the
+Linux-compatible
+.Xr ioctl 2
+interface for the management device will be enabled and will allow
+Linux-based management applications to control the card.
+.Sh HARDWARE
+Controllers supported by the
+.Nm
+driver include:
+.Pp
+.Bl -bullet -compact
+.It
+Adaptec ASR-6405(T|E)
+.It
+Adaptec ASR-6445
+.It
+Adaptec ASR-6805(T|E|Q|TQ)
+.It
+Adaptec ASR-7085
+.It
+Adaptec ASR-7805(Q)
+.It
+Adaptec ASR-70165
+.It
+Adaptec ASR-71605(E|Q)
+.It
+Adaptec ASR-71685
+.It
+Adaptec ASR-72405
+.It
+Adaptec Series 8 cards
+.El
+.Sh FILES
+.Bl -tag -width /boot/kernel/aacraid.ko -compact
+.It Pa /dev/aacraid?
+aacraid management interface
+.El
+.Sh DIAGNOSTICS
+Compiling with
+.Dv AACRAID_DEBUG
+set to a number between 0 and 3
+will enable increasingly verbose debug messages.
+.Pp
+The adapter can send status and alert messages asynchronously
+to the driver.
+These messages are printed on the system console,
+and are also queued for retrieval by a management application.
+.Sh SEE ALSO
+.Xr kld 4 ,
+.Xr linux 4 ,
+.Xr scsi 4 ,
+.Xr kldload 8
+.Sh AUTHORS
+.An Achim Leubner
+.Aq achim at FreeBSD.org
+.An Ed Maste
+.Aq emaste at FreeBSD.org
+.An Scott Long
+.Aq scottl at FreeBSD.org
+.Sh BUGS
+.Pp
+The controller is not actually paused on suspend/resume.
Modified: head/sys/amd64/conf/GENERIC
==============================================================================
--- head/sys/amd64/conf/GENERIC Fri May 24 09:21:18 2013 (r250962)
+++ head/sys/amd64/conf/GENERIC Fri May 24 09:22:43 2013 (r250963)
@@ -158,6 +158,7 @@ device tws # LSI 3ware 9750 SATA+SAS 6
# RAID controllers
device aac # Adaptec FSA RAID
device aacp # SCSI passthrough for aac (requires CAM)
+device aacraid # Adaptec by PMC RAID
device ida # Compaq Smart RAID
device mfi # LSI MegaRAID SAS
device mlx # Mylex DAC960 family
Modified: head/sys/amd64/conf/NOTES
==============================================================================
--- head/sys/amd64/conf/NOTES Fri May 24 09:21:18 2013 (r250962)
+++ head/sys/amd64/conf/NOTES Fri May 24 09:22:43 2013 (r250963)
@@ -406,6 +406,10 @@ device aac
device aacp # SCSI Passthrough interface (optional, CAM required)
#
+# Adaptec by PMC RAID controllers, Series 6/7/8 and upcoming families
+device aacraid # Container interface, CAM required
+
+#
# Highpoint RocketRAID 27xx.
device hpt27xx
Modified: head/sys/conf/files
==============================================================================
--- head/sys/conf/files Fri May 24 09:21:18 2013 (r250962)
+++ head/sys/conf/files Fri May 24 09:22:43 2013 (r250963)
@@ -573,6 +573,11 @@ dev/aac/aac_debug.c optional aac
dev/aac/aac_disk.c optional aac
dev/aac/aac_linux.c optional aac compat_linux
dev/aac/aac_pci.c optional aac pci
+dev/aacraid/aacraid.c optional aacraid
+dev/aacraid/aacraid_cam.c optional aacraid scbus
+dev/aacraid/aacraid_debug.c optional aacraid
+dev/aacraid/aacraid_linux.c optional aacraid compat_linux
+dev/aacraid/aacraid_pci.c optional aacraid pci
dev/acpi_support/acpi_wmi.c optional acpi_wmi acpi
dev/acpi_support/acpi_asus.c optional acpi_asus acpi
dev/acpi_support/acpi_asus_wmi.c optional acpi_asus_wmi acpi
Modified: head/sys/conf/options
==============================================================================
--- head/sys/conf/options Fri May 24 09:21:18 2013 (r250962)
+++ head/sys/conf/options Fri May 24 09:22:43 2013 (r250963)
@@ -31,6 +31,7 @@
# opt_<name-of-option-in-lower-case>.h
AAC_DEBUG opt_aac.h
+AACRAID_DEBUG opt_aacraid.h
AHC_ALLOW_MEMIO opt_aic7xxx.h
AHC_TMODE_ENABLE opt_aic7xxx.h
AHC_DUMP_EEPROM opt_aic7xxx.h
Added: head/sys/dev/aacraid/aacraid.c
==============================================================================
--- /dev/null 00:00:00 1970 (empty, because file is newly added)
+++ head/sys/dev/aacraid/aacraid.c Fri May 24 09:22:43 2013 (r250963)
@@ -0,0 +1,3501 @@
+/*-
+ * Copyright (c) 2000 Michael Smith
+ * Copyright (c) 2001 Scott Long
+ * Copyright (c) 2000 BSDi
+ * Copyright (c) 2001-2010 Adaptec, Inc.
+ * Copyright (c) 2010-2012 PMC-Sierra, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * Driver for the Adaptec by PMC Series 6,7,8,... families of RAID controllers
+ */
+#define AAC_DRIVERNAME "aacraid"
+
+#include "opt_aacraid.h"
+
+/* #include <stddef.h> */
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/malloc.h>
+#include <sys/kernel.h>
+#include <sys/kthread.h>
+#include <sys/sysctl.h>
+#include <sys/poll.h>
+#include <sys/ioccom.h>
+
+#include <sys/bus.h>
+#include <sys/conf.h>
+#include <sys/signalvar.h>
+#include <sys/time.h>
+#include <sys/eventhandler.h>
+#include <sys/rman.h>
+
+#include <machine/bus.h>
+#include <sys/bus_dma.h>
+#include <machine/resource.h>
+
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <dev/aacraid/aacraid_reg.h>
+#include <sys/aac_ioctl.h>
+#include <dev/aacraid/aacraid_debug.h>
+#include <dev/aacraid/aacraid_var.h>
+
+#ifndef FILTER_HANDLED
+#define FILTER_HANDLED 0x02
+#endif
+
+static void aac_add_container(struct aac_softc *sc,
+ struct aac_mntinforesp *mir, int f,
+ u_int32_t uid);
+static void aac_get_bus_info(struct aac_softc *sc);
+static void aac_container_bus(struct aac_softc *sc);
+static void aac_daemon(void *arg);
+static int aac_convert_sgraw2(struct aac_softc *sc, struct aac_raw_io2 *raw,
+ int pages, int nseg, int nseg_new);
+
+/* Command Processing */
+static void aac_timeout(struct aac_softc *sc);
+static void aac_command_thread(struct aac_softc *sc);
+static int aac_sync_fib(struct aac_softc *sc, u_int32_t command,
+ u_int32_t xferstate, struct aac_fib *fib,
+ u_int16_t datasize);
+/* Command Buffer Management */
+static void aac_map_command_helper(void *arg, bus_dma_segment_t *segs,
+ int nseg, int error);
+static int aac_alloc_commands(struct aac_softc *sc);
+static void aac_free_commands(struct aac_softc *sc);
+static void aac_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);
+static int aac_init(struct aac_softc *sc);
+static int aac_setup_intr(struct aac_softc *sc);
+
+/* PMC SRC interface */
+static int aac_src_get_fwstatus(struct aac_softc *sc);
+static void aac_src_qnotify(struct aac_softc *sc, int qbit);
+static int aac_src_get_istatus(struct aac_softc *sc);
+static void aac_src_clear_istatus(struct aac_softc *sc, int mask);
+static void aac_src_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_src_get_mailbox(struct aac_softc *sc, int mb);
+static void aac_src_set_interrupts(struct aac_softc *sc, int enable);
+static int aac_src_send_command(struct aac_softc *sc, struct aac_command *cm);
+static int aac_src_get_outb_queue(struct aac_softc *sc);
+static void aac_src_set_outb_queue(struct aac_softc *sc, int index);
+
+struct aac_interface aacraid_src_interface = {
+ aac_src_get_fwstatus,
+ aac_src_qnotify,
+ aac_src_get_istatus,
+ aac_src_clear_istatus,
+ aac_src_set_mailbox,
+ aac_src_get_mailbox,
+ aac_src_set_interrupts,
+ aac_src_send_command,
+ aac_src_get_outb_queue,
+ aac_src_set_outb_queue
+};
+
+/* PMC SRCv interface */
+static void aac_srcv_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_srcv_get_mailbox(struct aac_softc *sc, int mb);
+
+struct aac_interface aacraid_srcv_interface = {
+ aac_src_get_fwstatus,
+ aac_src_qnotify,
+ aac_src_get_istatus,
+ aac_src_clear_istatus,
+ aac_srcv_set_mailbox,
+ aac_srcv_get_mailbox,
+ aac_src_set_interrupts,
+ aac_src_send_command,
+ aac_src_get_outb_queue,
+ aac_src_set_outb_queue
+};
+
+/* Debugging and Diagnostics */
+static struct aac_code_lookup aac_cpu_variant[] = {
+ {"i960JX", CPUI960_JX},
+ {"i960CX", CPUI960_CX},
+ {"i960HX", CPUI960_HX},
+ {"i960RX", CPUI960_RX},
+ {"i960 80303", CPUI960_80303},
+ {"StrongARM SA110", CPUARM_SA110},
+ {"PPC603e", CPUPPC_603e},
+ {"XScale 80321", CPU_XSCALE_80321},
+ {"MIPS 4KC", CPU_MIPS_4KC},
+ {"MIPS 5KC", CPU_MIPS_5KC},
+ {"Unknown StrongARM", CPUARM_xxx},
+ {"Unknown PowerPC", CPUPPC_xxx},
+ {NULL, 0},
+ {"Unknown processor", 0}
+};
+
+static struct aac_code_lookup aac_battery_platform[] = {
+ {"required battery present", PLATFORM_BAT_REQ_PRESENT},
+ {"REQUIRED BATTERY NOT PRESENT", PLATFORM_BAT_REQ_NOTPRESENT},
+ {"optional battery present", PLATFORM_BAT_OPT_PRESENT},
+ {"optional battery not installed", PLATFORM_BAT_OPT_NOTPRESENT},
+ {"no battery support", PLATFORM_BAT_NOT_SUPPORTED},
+ {NULL, 0},
+ {"unknown battery platform", 0}
+};
+static void aac_describe_controller(struct aac_softc *sc);
+static char *aac_describe_code(struct aac_code_lookup *table,
+ u_int32_t code);
+
+/* Management Interface */
+static d_open_t aac_open;
+static d_ioctl_t aac_ioctl;
+static d_poll_t aac_poll;
+#if __FreeBSD_version >= 702000
+static void aac_cdevpriv_dtor(void *arg);
+#else
+static d_close_t aac_close;
+#endif
+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 void aac_request_aif(struct aac_softc *sc);
+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,
+ 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);
+static int aac_reset_adapter(struct aac_softc *sc);
+static int aac_get_container_info(struct aac_softc *sc,
+ struct aac_fib *fib, int cid,
+ struct aac_mntinforesp *mir,
+ u_int32_t *uid);
+static u_int32_t
+ aac_check_adapter_health(struct aac_softc *sc, u_int8_t *bled);
+
+static struct cdevsw aacraid_cdevsw = {
+ .d_version = D_VERSION,
+ .d_flags = D_NEEDGIANT,
+ .d_open = aac_open,
+#if __FreeBSD_version < 702000
+ .d_close = aac_close,
+#endif
+ .d_ioctl = aac_ioctl,
+ .d_poll = aac_poll,
+ .d_name = "aacraid",
+};
+
+MALLOC_DEFINE(M_AACRAIDBUF, "aacraid_buf", "Buffers for the AACRAID driver");
+
+/* sysctl node */
+SYSCTL_NODE(_hw, OID_AUTO, aacraid, CTLFLAG_RD, 0, "AACRAID driver parameters");
+
+/*
+ * Device Interface
+ */
+
+/*
+ * Initialize the controller and softc
+ */
+int
+aacraid_attach(struct aac_softc *sc)
+{
+ int error, unit;
+ struct aac_fib *fib;
+ struct aac_mntinforesp mir;
+ int count = 0, i = 0;
+ u_int32_t uid;
+
+ fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+ sc->hint_flags = device_get_flags(sc->aac_dev);
+ /*
+ * Initialize per-controller queues.
+ */
+ aac_initq_free(sc);
+ aac_initq_ready(sc);
+ aac_initq_busy(sc);
+
+ /* mark controller as suspended until we get ourselves organised */
+ sc->aac_state |= AAC_STATE_SUSPEND;
+
+ /*
+ * Check that the firmware on the card is supported.
+ */
+ if ((error = aac_check_firmware(sc)) != 0)
+ return(error);
+
+ /*
+ * Initialize locks
+ */
+ mtx_init(&sc->aac_io_lock, "AACRAID I/O lock", NULL, MTX_DEF);
+ TAILQ_INIT(&sc->aac_container_tqh);
+ TAILQ_INIT(&sc->aac_ev_cmfree);
+
+#if __FreeBSD_version >= 800000
+ /* Initialize the clock daemon callout. */
+ callout_init_mtx(&sc->aac_daemontime, &sc->aac_io_lock, 0);
+#endif
+ /*
+ * Initialize the adapter.
+ */
+ if ((error = aac_alloc(sc)) != 0)
+ return(error);
+ if (!(sc->flags & AAC_FLAGS_SYNC_MODE)) {
+ if ((error = aac_init(sc)) != 0)
+ return(error);
+ }
+
+ /*
+ * Allocate and connect our interrupt.
+ */
+ if ((error = aac_setup_intr(sc)) != 0)
+ return(error);
+
+ /*
+ * Print a little information about the controller.
+ */
+ aac_describe_controller(sc);
+
+ /*
+ * Make the control device.
+ */
+ unit = device_get_unit(sc->aac_dev);
+ sc->aac_dev_t = make_dev(&aacraid_cdevsw, unit, UID_ROOT, GID_OPERATOR,
+ 0640, "aacraid%d", unit);
+ sc->aac_dev_t->si_drv1 = sc;
+
+ /* Create the AIF thread */
+ if (aac_kthread_create((void(*)(void *))aac_command_thread, sc,
+ &sc->aifthread, 0, 0, "aacraid%daif", unit))
+ panic("Could not create AIF thread");
+
+ /* Register the shutdown method to only be called post-dump */
+ if ((sc->eh = EVENTHANDLER_REGISTER(shutdown_final, aacraid_shutdown,
+ sc->aac_dev, SHUTDOWN_PRI_DEFAULT)) == NULL)
+ device_printf(sc->aac_dev,
+ "shutdown event registration failed\n");
+
+ /* Find containers */
+ mtx_lock(&sc->aac_io_lock);
+ aac_alloc_sync_fib(sc, &fib);
+ /* loop over possible containers */
+ do {
+ if ((aac_get_container_info(sc, fib, i, &mir, &uid)) != 0)
+ continue;
+ if (i == 0)
+ count = mir.MntRespCount;
+ aac_add_container(sc, &mir, 0, uid);
+ i++;
+ } while ((i < count) && (i < AAC_MAX_CONTAINERS));
+ aac_release_sync_fib(sc);
+ mtx_unlock(&sc->aac_io_lock);
+
+ /* Register with CAM for the containers */
+ TAILQ_INIT(&sc->aac_sim_tqh);
+ aac_container_bus(sc);
+ /* Register with CAM for the non-DASD devices */
+ if ((sc->flags & AAC_FLAGS_ENABLE_CAM) != 0)
+ aac_get_bus_info(sc);
+
+ /* poke the bus to actually attach the child devices */
+ bus_generic_attach(sc->aac_dev);
+
+ /* mark the controller up */
+ sc->aac_state &= ~AAC_STATE_SUSPEND;
+
+ /* enable interrupts now */
+ AAC_UNMASK_INTERRUPTS(sc);
+
+#if __FreeBSD_version >= 800000
+ mtx_lock(&sc->aac_io_lock);
+ callout_reset(&sc->aac_daemontime, 60 * hz, aac_daemon, sc);
+ mtx_unlock(&sc->aac_io_lock);
+#else
+ {
+ struct timeval tv;
+ tv.tv_sec = 60;
+ tv.tv_usec = 0;
+ sc->timeout_id = timeout(aac_daemon, (void *)sc, tvtohz(&tv));
+ }
+#endif
+
+ return(0);
+}
+
+static void
+aac_daemon(void *arg)
+{
+ struct aac_softc *sc;
+ struct timeval tv;
+ struct aac_command *cm;
+ struct aac_fib *fib;
+
+ sc = arg;
+ fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+#if __FreeBSD_version >= 800000
+ mtx_assert(&sc->aac_io_lock, MA_OWNED);
+ if (callout_pending(&sc->aac_daemontime) ||
+ callout_active(&sc->aac_daemontime) == 0)
+ return;
+#else
+ mtx_lock(&sc->aac_io_lock);
+#endif
+ getmicrotime(&tv);
+
+ if (!aacraid_alloc_command(sc, &cm)) {
+ fib = cm->cm_fib;
+ cm->cm_timestamp = time_uptime;
+ cm->cm_datalen = 0;
+ cm->cm_flags |= AAC_CMD_WAIT;
+
+ fib->Header.Size =
+ sizeof(struct aac_fib_header) + sizeof(u_int32_t);
+ 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 = SendHostTime;
+ *(uint32_t *)fib->data = tv.tv_sec;
+
+ aacraid_map_command_sg(cm, NULL, 0, 0);
+ aacraid_release_command(cm);
+ }
+
+#if __FreeBSD_version >= 800000
+ callout_schedule(&sc->aac_daemontime, 30 * 60 * hz);
+#else
+ mtx_unlock(&sc->aac_io_lock);
+ tv.tv_sec = 30 * 60;
+ tv.tv_usec = 0;
+ sc->timeout_id = timeout(aac_daemon, (void *)sc, tvtohz(&tv));
+#endif
+}
+
+void
+aacraid_add_event(struct aac_softc *sc, struct aac_event *event)
+{
+
+ switch (event->ev_type & AAC_EVENT_MASK) {
+ case AAC_EVENT_CMFREE:
+ TAILQ_INSERT_TAIL(&sc->aac_ev_cmfree, event, ev_links);
+ break;
+ default:
+ device_printf(sc->aac_dev, "aac_add event: unknown event %d\n",
+ event->ev_type);
+ break;
+ }
+
+ return;
+}
+
+/*
+ * Request information of container #cid
+ */
+static int
+aac_get_container_info(struct aac_softc *sc, struct aac_fib *sync_fib, int cid,
+ struct aac_mntinforesp *mir, u_int32_t *uid)
+{
+ struct aac_command *cm;
+ struct aac_fib *fib;
+ struct aac_mntinfo *mi;
+ struct aac_cnt_config *ccfg;
+
+ if (sync_fib == NULL) {
+ if (aacraid_alloc_command(sc, &cm)) {
+ device_printf(sc->aac_dev,
+ "Warning, no free command available\n");
+ return (-1);
+ }
+ fib = cm->cm_fib;
+ } else {
+ fib = sync_fib;
+ }
+
+ mi = (struct aac_mntinfo *)&fib->data[0];
+ /* 4KB support?, 64-bit LBA? */
+ if (sc->aac_support_opt2 & AAC_SUPPORTED_VARIABLE_BLOCK_SIZE)
+ mi->Command = VM_NameServeAllBlk;
+ else if (sc->flags & AAC_FLAGS_LBA_64BIT)
+ mi->Command = VM_NameServe64;
+ else
+ mi->Command = VM_NameServe;
+ mi->MntType = FT_FILESYS;
+ mi->MntCount = cid;
+
+ if (sync_fib) {
+ if (aac_sync_fib(sc, ContainerCommand, 0, fib,
+ sizeof(struct aac_mntinfo))) {
+ device_printf(sc->aac_dev, "Error probing container %d\n", cid);
+ return (-1);
+ }
+ } else {
+ cm->cm_timestamp = time_uptime;
+ cm->cm_datalen = 0;
+
+ fib->Header.Size =
+ sizeof(struct aac_fib_header) + sizeof(struct aac_mntinfo);
+ fib->Header.XferState =
+ AAC_FIBSTATE_HOSTOWNED |
+ AAC_FIBSTATE_INITIALISED |
+ AAC_FIBSTATE_EMPTY |
+ AAC_FIBSTATE_FROMHOST |
+ AAC_FIBSTATE_REXPECTED |
+ AAC_FIBSTATE_NORM |
+ AAC_FIBSTATE_ASYNC |
+ AAC_FIBSTATE_FAST_RESPONSE;
+ fib->Header.Command = ContainerCommand;
+ if (aacraid_wait_command(cm) != 0) {
+ device_printf(sc->aac_dev, "Error probing container %d\n", cid);
+ aacraid_release_command(cm);
+ return (-1);
+ }
+ }
+ bcopy(&fib->data[0], mir, sizeof(struct aac_mntinforesp));
+
+ /* UID */
+ *uid = cid;
+ if (mir->MntTable[0].VolType != CT_NONE &&
+ !(mir->MntTable[0].ContentState & AAC_FSCS_HIDDEN)) {
+ if (!(sc->aac_support_opt2 & AAC_SUPPORTED_VARIABLE_BLOCK_SIZE))
+ mir->MntTable[0].ObjExtension.BlockSize = 0x200;
+
+ ccfg = (struct aac_cnt_config *)&fib->data[0];
+ bzero(ccfg, sizeof (*ccfg) - CT_PACKET_SIZE);
+ ccfg->Command = VM_ContainerConfig;
+ ccfg->CTCommand.command = CT_CID_TO_32BITS_UID;
+ ccfg->CTCommand.param[0] = cid;
+
+ if (sync_fib) {
+ if (aac_sync_fib(sc, ContainerCommand, 0, fib,
+ sizeof(struct aac_cnt_config) == 0) &&
+ ccfg->CTCommand.param[0] == ST_OK &&
+ mir->MntTable[0].VolType != CT_PASSTHRU)
+ *uid = ccfg->CTCommand.param[1];
+ } else {
+ fib->Header.Size =
+ sizeof(struct aac_fib_header) + sizeof(struct aac_cnt_config);
+ fib->Header.XferState =
+ AAC_FIBSTATE_HOSTOWNED |
+ AAC_FIBSTATE_INITIALISED |
+ AAC_FIBSTATE_EMPTY |
+ AAC_FIBSTATE_FROMHOST |
+ AAC_FIBSTATE_REXPECTED |
+ AAC_FIBSTATE_NORM |
+ AAC_FIBSTATE_ASYNC |
+ AAC_FIBSTATE_FAST_RESPONSE;
+ fib->Header.Command = ContainerCommand;
+ if (aacraid_wait_command(cm) == 0 &&
+ ccfg->CTCommand.param[0] == ST_OK &&
+ mir->MntTable[0].VolType != CT_PASSTHRU)
+ *uid = ccfg->CTCommand.param[1];
+ aacraid_release_command(cm);
+ }
+ }
+
+ return (0);
+}
+
+/*
+ * Create a device to represent a new container
+ */
+static void
+aac_add_container(struct aac_softc *sc, struct aac_mntinforesp *mir, int f,
+ u_int32_t uid)
+{
+ struct aac_container *co;
+
+ fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+ /*
+ * Check container volume type for validity. Note that many of
+ * the possible types may never show up.
+ */
+ if ((mir->Status == ST_OK) && (mir->MntTable[0].VolType != CT_NONE)) {
+ co = (struct aac_container *)malloc(sizeof *co, M_AACRAIDBUF,
+ M_NOWAIT | M_ZERO);
+ if (co == NULL) {
+ panic("Out of memory?!");
+ }
+
+ co->co_found = f;
+ bcopy(&mir->MntTable[0], &co->co_mntobj,
+ sizeof(struct aac_mntobj));
+ co->co_uid = uid;
+ TAILQ_INSERT_TAIL(&sc->aac_container_tqh, co, co_link);
+ }
+}
+
+/*
+ * Allocate resources associated with (sc)
+ */
+static int
+aac_alloc(struct aac_softc *sc)
+{
+ bus_size_t maxsize;
+
+ 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 */
+ busdma_lock_mutex, /* lockfunc */
+ &sc->aac_io_lock, /* lockfuncarg */
+ &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 (sc->flags & AAC_FLAGS_NEW_COMM_TYPE1)
+ maxsize = sc->aac_max_fibs_alloc * (sc->aac_max_fib_size +
+ sizeof(struct aac_fib_xporthdr) + 31);
+ else
+ maxsize = sc->aac_max_fibs_alloc * (sc->aac_max_fib_size + 31);
+ 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 */
+ maxsize, /* maxsize */
+ 1, /* nsegments */
+ maxsize, /* maxsize */
+ 0, /* flags */
+ NULL, NULL, /* No locking needed */
+ &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.
+ */
+ maxsize = sizeof(struct aac_common);
+ maxsize += sc->aac_max_fibs * sizeof(u_int32_t);
+ 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 */
+ maxsize, /* maxsize */
+ 1, /* nsegments */
+ maxsize, /* maxsegsize */
+ 0, /* flags */
+ NULL, NULL, /* No locking needed */
+ &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);
+ }
+
+ (void)bus_dmamap_load(sc->aac_common_dmat, sc->aac_common_dmamap,
+ sc->aac_common, maxsize,
+ aac_common_map, sc, 0);
+ bzero(sc->aac_common, maxsize);
+
+ /* Allocate some FIBs and associated command structs */
+ TAILQ_INIT(&sc->aac_fibmap_tqh);
+ sc->aac_commands = malloc(sc->aac_max_fibs * sizeof(struct aac_command),
+ M_AACRAIDBUF, M_WAITOK|M_ZERO);
+ mtx_lock(&sc->aac_io_lock);
+ while (sc->total_fibs < sc->aac_max_fibs) {
+ if (aac_alloc_commands(sc) != 0)
+ break;
+ }
+ mtx_unlock(&sc->aac_io_lock);
+ if (sc->total_fibs == 0)
+ return (ENOMEM);
+
+ return (0);
+}
+
+/*
+ * Free all of the resources associated with (sc)
+ *
+ * Should not be called if the controller is active.
+ */
+void
+aacraid_free(struct aac_softc *sc)
+{
+ fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+ /* remove the control device */
+ if (sc->aac_dev_t != NULL)
+ destroy_dev(sc->aac_dev_t);
+
+ /* throw away any FIB buffers, discard the FIB DMA tag */
+ aac_free_commands(sc);
+ if (sc->aac_fib_dmat)
+ bus_dma_tag_destroy(sc->aac_fib_dmat);
+
+ free(sc->aac_commands, M_AACRAIDBUF);
+
+ /* destroy the common area */
+ if (sc->aac_common) {
+ bus_dmamap_unload(sc->aac_common_dmat, sc->aac_common_dmamap);
+ bus_dmamem_free(sc->aac_common_dmat, sc->aac_common,
+ sc->aac_common_dmamap);
+ }
+ if (sc->aac_common_dmat)
+ bus_dma_tag_destroy(sc->aac_common_dmat);
+
+ /* disconnect the interrupt handler */
+ if (sc->aac_intr)
+ bus_teardown_intr(sc->aac_dev, sc->aac_irq, sc->aac_intr);
+ if (sc->aac_irq != NULL)
+ bus_release_resource(sc->aac_dev, SYS_RES_IRQ, sc->aac_irq_rid,
+ sc->aac_irq);
+
+ /* destroy data-transfer DMA tag */
+ if (sc->aac_buffer_dmat)
+ bus_dma_tag_destroy(sc->aac_buffer_dmat);
+
+ /* destroy the parent DMA tag */
+ if (sc->aac_parent_dmat)
+ bus_dma_tag_destroy(sc->aac_parent_dmat);
+
+ /* release the register window mapping */
+ if (sc->aac_regs_res0 != NULL)
+ bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
+ sc->aac_regs_rid0, sc->aac_regs_res0);
+ if (sc->aac_regs_res1 != NULL)
+ bus_release_resource(sc->aac_dev, SYS_RES_MEMORY,
+ sc->aac_regs_rid1, sc->aac_regs_res1);
+}
+
+/*
+ * Disconnect from the controller completely, in preparation for unload.
+ */
+int
+aacraid_detach(device_t dev)
+{
+ struct aac_softc *sc;
+ struct aac_container *co;
+ struct aac_sim *sim;
+ int error;
+
+ sc = device_get_softc(dev);
+ fwprintf(sc, HBA_FLAGS_DBG_FUNCTION_ENTRY_B, "");
+
+#if __FreeBSD_version >= 800000
+ callout_drain(&sc->aac_daemontime);
+#else
+ untimeout(aac_daemon, (void *)sc, sc->timeout_id);
+#endif
+ /* Remove the child containers */
+ while ((co = TAILQ_FIRST(&sc->aac_container_tqh)) != NULL) {
+ TAILQ_REMOVE(&sc->aac_container_tqh, co, co_link);
+ free(co, M_AACRAIDBUF);
+ }
+
+ /* Remove the CAM SIMs */
+ while ((sim = TAILQ_FIRST(&sc->aac_sim_tqh)) != NULL) {
+ TAILQ_REMOVE(&sc->aac_sim_tqh, sim, sim_link);
+ error = device_delete_child(dev, sim->sim_dev);
+ if (error)
+ return (error);
+ free(sim, M_AACRAIDBUF);
+ }
+
+ if (sc->aifflags & AAC_AIFFLAGS_RUNNING) {
+ sc->aifflags |= AAC_AIFFLAGS_EXIT;
+ wakeup(sc->aifthread);
+ tsleep(sc->aac_dev, PUSER | PCATCH, "aac_dch", 30 * hz);
+ }
+
+ if (sc->aifflags & AAC_AIFFLAGS_RUNNING)
+ panic("Cannot shutdown AIF thread");
+
+ if ((error = aacraid_shutdown(dev)))
+ return(error);
+
+ EVENTHANDLER_DEREGISTER(shutdown_final, sc->eh);
+
+ aacraid_free(sc);
+
+ mtx_destroy(&sc->aac_io_lock);
+
+ return(0);
+}
+
+/*
+ * Bring the controller down to a dormant state and detach all child devices.
+ *
+ * This function is called before detach or system shutdown.
+ *
+ * Note that we can assume that the bioq on the controller is empty, as we won't
+ * allow shutdown if any device is open.
+ */
+int
+aacraid_shutdown(device_t dev)
+{
+ struct aac_softc *sc;
+ struct aac_fib *fib;
+ struct aac_close_command *cc;
*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
More information about the svn-src-all
mailing list