diff --git a/share/man/man4/amr.4 b/share/man/man4/amr.4 deleted file mode 100644 --- a/share/man/man4/amr.4 +++ /dev/null @@ -1,246 +0,0 @@ -.\" -.\" Copyright (c) 2000 Jeroen Ruigrok van der Werven -.\" 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. The name of the author may not be used to endorse or promote products -.\" derived from this software without specific prior written permission -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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 March 29, 2006 -.Dt AMR 4 -.Os -.Sh NAME -.Nm amr -.Nd MegaRAID SCSI/ATA/SATA RAID 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 scbus" -.Cd "device amr" -.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 -amr_load="YES" -.Ed -.Sh DEPRECATION NOTICE -The -.Nm -driver is not present in -.Fx 13.0 . -.Sh DESCRIPTION -The -.Nm -driver provides support for LSI Logic MegaRAID SCSI, ATA and SATA -RAID controllers and legacy American Megatrends MegaRAID -SCSI RAID controllers, including models relabeled -and sold by Dell and Hewlett-Packard. -.Pp -LSI MegaRAID SAS controllers are supported by -.Xr mfi 4 -and will not work with this driver. -.Sh HARDWARE -Controllers supported by the -.Nm -driver include: -.Pp -.Bl -bullet -compact -.It -MegaRAID SATA 150-4 -.It -MegaRAID SATA 150-6 -.It -MegaRAID SATA 300-4X -.It -MegaRAID SATA 300-8X -.It -MegaRAID SCSI 320-1E -.It -MegaRAID SCSI 320-2E -.It -MegaRAID SCSI 320-4E -.It -MegaRAID SCSI 320-0X -.It -MegaRAID SCSI 320-2X -.It -MegaRAID SCSI 320-4X -.It -MegaRAID SCSI 320-0 -.It -MegaRAID SCSI 320-1 -.It -MegaRAID SCSI 320-2 -.It -MegaRAID SCSI 320-4 -.It -MegaRAID Series 418 -.It -MegaRAID i4 133 RAID -.It -MegaRAID Elite 1500 (Series 467) -.It -MegaRAID Elite 1600 (Series 493) -.It -MegaRAID Elite 1650 (Series 4xx) -.It -MegaRAID Enterprise 1200 (Series 428) -.It -MegaRAID Enterprise 1300 (Series 434) -.It -MegaRAID Enterprise 1400 (Series 438) -.It -MegaRAID Enterprise 1500 (Series 467) -.It -MegaRAID Enterprise 1600 (Series 471) -.It -MegaRAID Express 100 (Series 466WS) -.It -MegaRAID Express 200 (Series 466) -.It -MegaRAID Express 300 (Series 490) -.It -MegaRAID Express 500 (Series 475) -.It -Dell PERC -.It -Dell PERC 2/SC -.It -Dell PERC 2/DC -.It -Dell PERC 3/DCL -.It -Dell PERC 3/QC -.It -Dell PERC 4/DC -.It -Dell PERC 4/IM -.It -Dell PERC 4/SC -.It -Dell PERC 4/Di -.It -Dell PERC 4e/DC -.It -Dell PERC 4e/Di -.It -Dell PERC 4e/Si -.It -Dell PERC 4ei -.It -HP NetRAID-1/Si -.It -HP NetRAID-3/Si (D4943A) -.It -HP Embedded NetRAID -.It -Intel RAID Controller SRCS16 -.It -Intel RAID Controller SRCU42X -.El -.Sh DIAGNOSTICS -.Ss Driver initialisation/shutdown phase -.Bl -diag -.It amr%d: memory window not available -.It amr%d: I/O window not available -.Pp -The PCI BIOS did not allocate resources necessary for the correct operation of -the controller. -The driver cannot attach to this controller. -.It amr%d: busmaster bit not set, enabling -.Pp -The PCI BIOS did not enable busmaster DMA, -which is required for the correct operation of the controller. -The driver has enabled this bit and initialisation will proceed. -.It amr%d: can't allocate register window -.It amr%d: can't allocate interrupt -.It amr%d: can't set up interrupt -.It amr%d: can't allocate parent DMA tag -.It amr%d: can't allocate buffer DMA tag -.It amr%d: can't allocate scatter/gather DMA tag -.It amr%d: can't allocate s/g table -.It amr%d: can't allocate mailbox tag -.It amr%d: can't allocate mailbox memory -.Pp -A resource allocation error occurred while initialising the driver; -initialisation has failed and the driver will not attach to this controller. -.It amr%d: can't obtain configuration data from controller -.It amr%d: can't obtain product data from controller -.Pp -The driver was unable to obtain vital configuration data from the controller. -Initialisation has failed and the driver will not attach to this controller. -.It amr%d: can't establish configuration hook -.It amr%d: can't scan controller for drives -.Pp -The scan for logical drives managed by the controller failed. -No drives will be attached. -.It amr%d: device_add_child failed -.It amr%d: bus_generic_attach returned %d -.Pp -Creation of the logical drive instances failed; -attachment of one or more logical drives may have been aborted. -.It amr%d: flushing cache... -.Pp -The controller cache is being flushed prior to shutdown or detach. -.El -.Ss Operational diagnostics -.Bl -diag -.It amr%d: I/O beyond end of unit (%u,%d > %u) -.Pp -A partitioning error or disk corruption has caused an I/O request -beyond the end of the logical drive. -This may also occur if FlexRAID Virtual Sizing is enabled and -an I/O operation is attempted on a portion of the virtual drive -beyond the actual capacity available. -.It amr%d: polled command timeout -.Pp -An initialisation command timed out. -The initialisation process may fail as a result. -.It amr%d: bad slot %d completed -.Pp -The controller reported completion of a command that the driver did not issue. -This may result in data corruption, -and suggests a hardware or firmware problem with the system or controller. -.It amr%d: I/O error - %x -.Pp -An I/O error has occurred. -.El -.Sh SEE ALSO -.Xr cd 4 , -.Xr da 4 , -.Xr mfi 4 , -.Xr sa 4 , -.Xr scsi 4 -.Sh AUTHORS -.An -nosplit -The -.Nm -driver was written by -.An Mike Smith Aq Mt msmith@FreeBSD.org . -.Pp -This manual page was written by -.An Mike Smith Aq Mt msmith@FreeBSD.org -and -.An Jeroen Ruigrok van der Werven Aq Mt asmodai@FreeBSD.org . diff --git a/sys/amd64/conf/GENERIC b/sys/amd64/conf/GENERIC --- a/sys/amd64/conf/GENERIC +++ b/sys/amd64/conf/GENERIC @@ -180,7 +180,6 @@ #device ctl # CAM Target Layer # RAID controllers interfaced to the SCSI subsystem -device amr # AMI MegaRAID device arcmsr # Areca SATA II RAID device ciss # Compaq Smart RAID 5* device ips # IBM (Adaptec) ServeRAID diff --git a/sys/conf/NOTES b/sys/conf/NOTES --- a/sys/conf/NOTES +++ b/sys/conf/NOTES @@ -1642,8 +1642,6 @@ # device ida # Compaq Smart RAID device mlx # Mylex DAC960 -device amr # AMI MegaRAID -device amrp # SCSI Passthrough interface (optional, CAM req.) device mfi # LSI MegaRAID SAS device mfip # LSI MegaRAID SAS passthrough, requires CAM options MFI_DEBUG diff --git a/sys/conf/files b/sys/conf/files --- a/sys/conf/files +++ b/sys/conf/files @@ -890,10 +890,6 @@ dev/altera/pio/pio_if.m optional altera_pio dev/amdpm/amdpm.c optional amdpm pci | nfpm pci dev/amdsmb/amdsmb.c optional amdsmb pci -dev/amr/amr.c optional amr -dev/amr/amr_cam.c optional amrp amr -dev/amr/amr_disk.c optional amr -dev/amr/amr_pci.c optional amr pci # dev/ata/ata_if.m optional ata | atacore dev/ata/ata-all.c optional ata | atacore diff --git a/sys/dev/amr/amr.c b/sys/dev/amr/amr.c deleted file mode 100644 --- a/sys/dev/amr/amr.c +++ /dev/null @@ -1,2446 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999,2000 Michael Smith - * Copyright (c) 2000 BSDi - * Copyright (c) 2005 Scott Long - * 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. - */ -/*- - * Copyright (c) 2002 Eric Moore - * Copyright (c) 2002, 2004 LSI Logic Corporation - * 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. - * 3. The party using or redistributing the source code and binary forms - * agrees to the disclaimer below and the terms and conditions set forth - * herein. - * - * 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 -__FBSDID("$FreeBSD$"); - -/* - * Driver for the AMI MegaRaid family of controllers. - */ - -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include - -#include -#include -#include -#define AMR_DEFINE_TABLES -#include - -SYSCTL_NODE(_hw, OID_AUTO, amr, CTLFLAG_RD | CTLFLAG_MPSAFE, 0, - "AMR driver parameters"); - -static d_open_t amr_open; -static d_close_t amr_close; -static d_ioctl_t amr_ioctl; - -static struct cdevsw amr_cdevsw = { - .d_version = D_VERSION, - .d_flags = D_NEEDGIANT, - .d_open = amr_open, - .d_close = amr_close, - .d_ioctl = amr_ioctl, - .d_name = "amr", -}; - -int linux_no_adapter = 0; -/* - * Initialisation, bus interface. - */ -static void amr_startup(void *arg); - -/* - * Command wrappers - */ -static int amr_query_controller(struct amr_softc *sc); -static void *amr_enquiry(struct amr_softc *sc, size_t bufsize, - u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual, int *status); -static void amr_completeio(struct amr_command *ac); -static int amr_support_ext_cdb(struct amr_softc *sc); - -/* - * Command buffer allocation. - */ -static void amr_alloccmd_cluster(struct amr_softc *sc); -static void amr_freecmd_cluster(struct amr_command_cluster *acc); - -/* - * Command processing. - */ -static int amr_bio_command(struct amr_softc *sc, struct amr_command **acp); -static int amr_wait_command(struct amr_command *ac) __unused; -static int amr_mapcmd(struct amr_command *ac); -static void amr_unmapcmd(struct amr_command *ac); -static int amr_start(struct amr_command *ac); -static void amr_complete(void *context, ac_qhead_t *head); -static void amr_setup_sg(void *arg, bus_dma_segment_t *segs, int nsegments, int error); -static void amr_setup_data(void *arg, bus_dma_segment_t *segs, int nsegments, int error); -static void amr_setup_ccb(void *arg, bus_dma_segment_t *segs, int nsegments, int error); -static void amr_abort_load(struct amr_command *ac); - -/* - * Interface-specific shims - */ -static int amr_quartz_submit_command(struct amr_command *ac); -static int amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave); -static int amr_quartz_poll_command(struct amr_command *ac); -static int amr_quartz_poll_command1(struct amr_softc *sc, struct amr_command *ac); - -static int amr_std_submit_command(struct amr_command *ac); -static int amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave); -static int amr_std_poll_command(struct amr_command *ac); -static void amr_std_attach_mailbox(struct amr_softc *sc); - -#ifdef AMR_BOARD_INIT -static int amr_quartz_init(struct amr_softc *sc); -static int amr_std_init(struct amr_softc *sc); -#endif - -/* - * Debugging - */ -static void amr_describe_controller(struct amr_softc *sc); -#ifdef AMR_DEBUG -#if 0 -static void amr_printcommand(struct amr_command *ac); -#endif -#endif - -static void amr_init_sysctl(struct amr_softc *sc); -static int amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, - int32_t flag, struct thread *td); - -static MALLOC_DEFINE(M_AMR, "amr", "AMR memory"); - -/******************************************************************************** - ******************************************************************************** - Inline Glue - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - ******************************************************************************** - Public Interfaces - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Initialise the controller and softc. - */ -int -amr_attach(struct amr_softc *sc) -{ - device_t child; - - debug_called(1); - - /* - * Initialise per-controller queues. - */ - amr_init_qhead(&sc->amr_freecmds); - amr_init_qhead(&sc->amr_ready); - TAILQ_INIT(&sc->amr_cmd_clusters); - bioq_init(&sc->amr_bioq); - - debug(2, "queue init done"); - - /* - * Configure for this controller type. - */ - if (AMR_IS_QUARTZ(sc)) { - sc->amr_submit_command = amr_quartz_submit_command; - sc->amr_get_work = amr_quartz_get_work; - sc->amr_poll_command = amr_quartz_poll_command; - sc->amr_poll_command1 = amr_quartz_poll_command1; - } else { - sc->amr_submit_command = amr_std_submit_command; - sc->amr_get_work = amr_std_get_work; - sc->amr_poll_command = amr_std_poll_command; - amr_std_attach_mailbox(sc); - } - -#ifdef AMR_BOARD_INIT - if ((AMR_IS_QUARTZ(sc) ? amr_quartz_init(sc) : amr_std_init(sc))) - return(ENXIO); -#endif - - /* - * Allocate initial commands. - */ - amr_alloccmd_cluster(sc); - - /* - * Quiz controller for features and limits. - */ - if (amr_query_controller(sc)) - return(ENXIO); - - debug(2, "controller query complete"); - - /* - * preallocate the remaining commands. - */ - while (sc->amr_nextslot < sc->amr_maxio) - amr_alloccmd_cluster(sc); - - /* - * Setup sysctls. - */ - amr_init_sysctl(sc); - - /* - * Attach our 'real' SCSI channels to CAM. - */ - child = device_add_child(sc->amr_dev, "amrp", -1); - sc->amr_pass = child; - if (child != NULL) { - device_set_softc(child, sc); - device_set_desc(child, "SCSI Passthrough Bus"); - bus_generic_attach(sc->amr_dev); - } - - /* - * Create the control device. - */ - sc->amr_dev_t = make_dev(&amr_cdevsw, device_get_unit(sc->amr_dev), UID_ROOT, GID_OPERATOR, - S_IRUSR | S_IWUSR, "amr%d", device_get_unit(sc->amr_dev)); - sc->amr_dev_t->si_drv1 = sc; - linux_no_adapter++; - if (device_get_unit(sc->amr_dev) == 0) - make_dev_alias(sc->amr_dev_t, "megadev0"); - - /* - * Schedule ourselves to bring the controller up once interrupts are - * available. - */ - bzero(&sc->amr_ich, sizeof(struct intr_config_hook)); - sc->amr_ich.ich_func = amr_startup; - sc->amr_ich.ich_arg = sc; - if (config_intrhook_establish(&sc->amr_ich) != 0) { - device_printf(sc->amr_dev, "can't establish configuration hook\n"); - return(ENOMEM); - } - - /* - * Print a little information about the controller. - */ - amr_describe_controller(sc); - - debug(2, "attach complete"); - return(0); -} - -/******************************************************************************** - * Locate disk resources and attach children to them. - */ -static void -amr_startup(void *arg) -{ - struct amr_softc *sc = (struct amr_softc *)arg; - struct amr_logdrive *dr; - int i, error; - - debug_called(1); - - /* get up-to-date drive information */ - if (amr_query_controller(sc)) { - device_printf(sc->amr_dev, "can't scan controller for drives\n"); - return; - } - - /* iterate over available drives */ - for (i = 0, dr = &sc->amr_drive[0]; (i < AMR_MAXLD) && (dr->al_size != 0xffffffff); i++, dr++) { - /* are we already attached to this drive? */ - if (dr->al_disk == 0) { - /* generate geometry information */ - if (dr->al_size > 0x200000) { /* extended translation? */ - dr->al_heads = 255; - dr->al_sectors = 63; - } else { - dr->al_heads = 64; - dr->al_sectors = 32; - } - dr->al_cylinders = dr->al_size / (dr->al_heads * dr->al_sectors); - - dr->al_disk = device_add_child(sc->amr_dev, NULL, -1); - if (dr->al_disk == 0) - device_printf(sc->amr_dev, "device_add_child failed\n"); - device_set_ivars(dr->al_disk, dr); - } - } - - if ((error = bus_generic_attach(sc->amr_dev)) != 0) - device_printf(sc->amr_dev, "bus_generic_attach returned %d\n", error); - - /* mark controller back up */ - sc->amr_state &= ~AMR_STATE_SHUTDOWN; - - /* interrupts will be enabled before we do anything more */ - sc->amr_state |= AMR_STATE_INTEN; - - /* pull ourselves off the intrhook chain */ - if (sc->amr_ich.ich_func) - config_intrhook_disestablish(&sc->amr_ich); - sc->amr_ich.ich_func = NULL; - - return; -} - -static void -amr_init_sysctl(struct amr_softc *sc) -{ - - SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->amr_dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(sc->amr_dev)), - OID_AUTO, "allow_volume_configure", CTLFLAG_RW, &sc->amr_allow_vol_config, 0, - ""); - SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->amr_dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(sc->amr_dev)), - OID_AUTO, "nextslot", CTLFLAG_RD, &sc->amr_nextslot, 0, - ""); - SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->amr_dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(sc->amr_dev)), - OID_AUTO, "busyslots", CTLFLAG_RD, &sc->amr_busyslots, 0, - ""); - SYSCTL_ADD_INT(device_get_sysctl_ctx(sc->amr_dev), - SYSCTL_CHILDREN(device_get_sysctl_tree(sc->amr_dev)), - OID_AUTO, "maxio", CTLFLAG_RD, &sc->amr_maxio, 0, - ""); -} - -/******************************************************************************* - * Free resources associated with a controller instance - */ -void -amr_free(struct amr_softc *sc) -{ - struct amr_command_cluster *acc; - - /* detach from CAM */ - if (sc->amr_pass != NULL) - device_delete_child(sc->amr_dev, sc->amr_pass); - - /* throw away any command buffers */ - while ((acc = TAILQ_FIRST(&sc->amr_cmd_clusters)) != NULL) { - TAILQ_REMOVE(&sc->amr_cmd_clusters, acc, acc_link); - amr_freecmd_cluster(acc); - } - - /* destroy control device */ - if( sc->amr_dev_t != (struct cdev *)NULL) - destroy_dev(sc->amr_dev_t); - - if (mtx_initialized(&sc->amr_hw_lock)) - mtx_destroy(&sc->amr_hw_lock); - - if (mtx_initialized(&sc->amr_list_lock)) - mtx_destroy(&sc->amr_list_lock); -} - -/******************************************************************************* - * Receive a bio structure from a child device and queue it on a particular - * disk resource, then poke the disk resource to start as much work as it can. - */ -int -amr_submit_bio(struct amr_softc *sc, struct bio *bio) -{ - debug_called(2); - - mtx_lock(&sc->amr_list_lock); - amr_enqueue_bio(sc, bio); - amr_startio(sc); - mtx_unlock(&sc->amr_list_lock); - return(0); -} - -/******************************************************************************** - * Accept an open operation on the control device. - */ -static int -amr_open(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - int unit = dev2unit(dev); - struct amr_softc *sc = devclass_get_softc(devclass_find("amr"), unit); - - debug_called(1); - - sc->amr_state |= AMR_STATE_OPEN; - return(0); -} - -#ifdef LSI -static int -amr_del_ld(struct amr_softc *sc, int drv_no, int status) -{ - - debug_called(1); - - sc->amr_state &= ~AMR_STATE_QUEUE_FRZN; - sc->amr_state &= ~AMR_STATE_LD_DELETE; - sc->amr_state |= AMR_STATE_REMAP_LD; - debug(1, "State Set"); - - if (!status) { - debug(1, "disk begin destroyed %d",drv_no); - if (--amr_disks_registered == 0) - cdevsw_remove(&amrddisk_cdevsw); - debug(1, "disk begin destroyed success"); - } - return 0; -} - -static int -amr_prepare_ld_delete(struct amr_softc *sc) -{ - - debug_called(1); - if (sc->ld_del_supported == 0) - return(ENOIOCTL); - - sc->amr_state |= AMR_STATE_QUEUE_FRZN; - sc->amr_state |= AMR_STATE_LD_DELETE; - - /* 5 minutes for the all the commands to be flushed.*/ - tsleep((void *)&sc->ld_del_supported, PCATCH | PRIBIO,"delete_logical_drv",hz * 60 * 1); - if ( sc->amr_busyslots ) - return(ENOIOCTL); - - return 0; -} -#endif - -/******************************************************************************** - * Accept the last close on the control device. - */ -static int -amr_close(struct cdev *dev, int flags, int fmt, struct thread *td) -{ - int unit = dev2unit(dev); - struct amr_softc *sc = devclass_get_softc(devclass_find("amr"), unit); - - debug_called(1); - - sc->amr_state &= ~AMR_STATE_OPEN; - return (0); -} - -/******************************************************************************** - * Handle controller-specific control operations. - */ -static void -amr_rescan_drives(struct cdev *dev) -{ - struct amr_softc *sc = (struct amr_softc *)dev->si_drv1; - int i, error = 0; - - sc->amr_state |= AMR_STATE_REMAP_LD; - while (sc->amr_busyslots) { - device_printf(sc->amr_dev, "idle controller\n"); - amr_done(sc); - } - - /* mark ourselves as in-shutdown */ - sc->amr_state |= AMR_STATE_SHUTDOWN; - - /* flush controller */ - device_printf(sc->amr_dev, "flushing cache..."); - printf("%s\n", amr_flush(sc) ? "failed" : "done"); - - /* delete all our child devices */ - for(i = 0 ; i < AMR_MAXLD; i++) { - if(sc->amr_drive[i].al_disk != 0) { - if((error = device_delete_child(sc->amr_dev, - sc->amr_drive[i].al_disk)) != 0) - goto shutdown_out; - - sc->amr_drive[i].al_disk = 0; - } - } - -shutdown_out: - amr_startup(sc); -} - -/* - * Bug-for-bug compatibility with Linux! - * Some apps will send commands with inlen and outlen set to 0, - * even though they expect data to be transferred to them from the - * card. Linux accidentally allows this by allocating a 4KB - * buffer for the transfer anyways, but it then throws it away - * without copying it back to the app. - * - * The amr(4) firmware relies on this feature. In fact, it assumes - * the buffer is always a power of 2 up to a max of 64k. There is - * also at least one case where it assumes a buffer less than 16k is - * greater than 16k. However, forcing all buffers to a size of 32k - * causes stalls in the firmware. Force each command smaller than - * 64k up to the next power of two except that commands between 8k - * and 16k are rounded up to 32k instead of 16k. - */ -static unsigned long -amr_ioctl_buffer_length(unsigned long len) -{ - - if (len <= 4 * 1024) - return (4 * 1024); - if (len <= 8 * 1024) - return (8 * 1024); - if (len <= 32 * 1024) - return (32 * 1024); - if (len <= 64 * 1024) - return (64 * 1024); - return (len); -} - -int -amr_linux_ioctl_int(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, - struct thread *td) -{ - struct amr_softc *sc = (struct amr_softc *)dev->si_drv1; - struct amr_command *ac; - struct amr_mailbox *mb; - struct amr_linux_ioctl ali; - void *dp, *temp; - int error; - int len, ac_flags = 0; - int logical_drives_changed = 0; - u_int32_t linux_version = 0x02100000; - u_int8_t status; - struct amr_passthrough *ap; /* 60 bytes */ - - error = 0; - dp = NULL; - ac = NULL; - ap = NULL; - - if ((error = copyin(addr, &ali, sizeof(ali))) != 0) - return (error); - switch (ali.ui.fcs.opcode) { - case 0x82: - switch(ali.ui.fcs.subopcode) { - case 'e': - copyout(&linux_version, (void *)(uintptr_t)ali.data, - sizeof(linux_version)); - error = 0; - break; - - case 'm': - copyout(&linux_no_adapter, (void *)(uintptr_t)ali.data, - sizeof(linux_no_adapter)); - td->td_retval[0] = linux_no_adapter; - error = 0; - break; - - default: - printf("Unknown subopcode\n"); - error = ENOIOCTL; - break; - } - break; - - case 0x80: - case 0x81: - if (ali.ui.fcs.opcode == 0x80) - len = max(ali.outlen, ali.inlen); - else - len = ali.ui.fcs.length; - - mb = (void *)&ali.mbox[0]; - - if ((ali.mbox[0] == FC_DEL_LOGDRV && ali.mbox[2] == OP_DEL_LOGDRV) || /* delete */ - (ali.mbox[0] == AMR_CMD_CONFIG && ali.mbox[2] == 0x0d)) { /* create */ - if (sc->amr_allow_vol_config == 0) { - error = EPERM; - break; - } - logical_drives_changed = 1; - } - - if (ali.mbox[0] == AMR_CMD_PASS) { - mtx_lock(&sc->amr_list_lock); - while ((ac = amr_alloccmd(sc)) == NULL) - msleep(sc, &sc->amr_list_lock, PPAUSE, "amrioc", hz); - mtx_unlock(&sc->amr_list_lock); - ap = &ac->ac_ccb->ccb_pthru; - - error = copyin((void *)(uintptr_t)mb->mb_physaddr, ap, - sizeof(struct amr_passthrough)); - if (error) - break; - - if (ap->ap_data_transfer_length) - dp = malloc(ap->ap_data_transfer_length, M_AMR, - M_WAITOK | M_ZERO); - - if (ali.inlen) { - error = copyin((void *)(uintptr_t)ap->ap_data_transfer_address, - dp, ap->ap_data_transfer_length); - if (error) - break; - } - - ac_flags = AMR_CMD_DATAIN|AMR_CMD_DATAOUT|AMR_CMD_CCB; - bzero(&ac->ac_mailbox, sizeof(ac->ac_mailbox)); - ac->ac_mailbox.mb_command = AMR_CMD_PASS; - ac->ac_flags = ac_flags; - - ac->ac_data = dp; - ac->ac_length = ap->ap_data_transfer_length; - temp = (void *)(uintptr_t)ap->ap_data_transfer_address; - - mtx_lock(&sc->amr_list_lock); - error = amr_wait_command(ac); - mtx_unlock(&sc->amr_list_lock); - if (error) - break; - - status = ac->ac_status; - error = copyout(&status, &((struct amr_passthrough *)(uintptr_t)mb->mb_physaddr)->ap_scsi_status, sizeof(status)); - if (error) - break; - - if (ali.outlen) { - error = copyout(dp, temp, ap->ap_data_transfer_length); - if (error) - break; - } - error = copyout(ap->ap_request_sense_area, ((struct amr_passthrough *)(uintptr_t)mb->mb_physaddr)->ap_request_sense_area, ap->ap_request_sense_length); - if (error) - break; - - error = 0; - break; - } else if (ali.mbox[0] == AMR_CMD_PASS_64) { - printf("No AMR_CMD_PASS_64\n"); - error = ENOIOCTL; - break; - } else if (ali.mbox[0] == AMR_CMD_EXTPASS) { - printf("No AMR_CMD_EXTPASS\n"); - error = ENOIOCTL; - break; - } else { - len = amr_ioctl_buffer_length(imax(ali.inlen, ali.outlen)); - - dp = malloc(len, M_AMR, M_WAITOK | M_ZERO); - - if (ali.inlen) { - error = copyin((void *)(uintptr_t)mb->mb_physaddr, dp, len); - if (error) - break; - } - - mtx_lock(&sc->amr_list_lock); - while ((ac = amr_alloccmd(sc)) == NULL) - msleep(sc, &sc->amr_list_lock, PPAUSE, "amrioc", hz); - - ac_flags = AMR_CMD_DATAIN|AMR_CMD_DATAOUT; - bzero(&ac->ac_mailbox, sizeof(ac->ac_mailbox)); - bcopy(&ali.mbox[0], &ac->ac_mailbox, sizeof(ali.mbox)); - - ac->ac_length = len; - ac->ac_data = dp; - ac->ac_flags = ac_flags; - - error = amr_wait_command(ac); - mtx_unlock(&sc->amr_list_lock); - if (error) - break; - - status = ac->ac_status; - error = copyout(&status, &((struct amr_mailbox *)&((struct amr_linux_ioctl *)addr)->mbox[0])->mb_status, sizeof(status)); - if (ali.outlen) { - error = copyout(dp, (void *)(uintptr_t)mb->mb_physaddr, ali.outlen); - if (error) - break; - } - - error = 0; - if (logical_drives_changed) - amr_rescan_drives(dev); - break; - } - break; - - default: - debug(1, "unknown linux ioctl 0x%lx", cmd); - printf("unknown linux ioctl 0x%lx\n", cmd); - error = ENOIOCTL; - break; - } - - /* - * At this point, we know that there is a lock held and that these - * objects have been allocated. - */ - mtx_lock(&sc->amr_list_lock); - if (ac != NULL) - amr_releasecmd(ac); - mtx_unlock(&sc->amr_list_lock); - if (dp != NULL) - free(dp, M_AMR); - return(error); -} - -static int -amr_ioctl(struct cdev *dev, u_long cmd, caddr_t addr, int32_t flag, struct thread *td) -{ - struct amr_softc *sc = (struct amr_softc *)dev->si_drv1; - union { - void *_p; - struct amr_user_ioctl *au; -#ifdef AMR_IO_COMMAND32 - struct amr_user_ioctl32 *au32; -#endif - int *result; - } arg; - struct amr_command *ac; - struct amr_mailbox_ioctl *mbi; - void *dp, *au_buffer; - unsigned long au_length, real_length; - unsigned char *au_cmd; - int *au_statusp; - int error; - struct amr_passthrough *ap; /* 60 bytes */ - int logical_drives_changed = 0; - - debug_called(1); - - arg._p = (void *)addr; - - error = 0; - dp = NULL; - ac = NULL; - ap = NULL; - - switch(cmd) { - case AMR_IO_VERSION: - debug(1, "AMR_IO_VERSION"); - *arg.result = AMR_IO_VERSION_NUMBER; - return(0); - -#ifdef AMR_IO_COMMAND32 - /* - * Accept ioctl-s from 32-bit binaries on non-32-bit - * platforms, such as AMD. LSI's MEGAMGR utility is - * the only example known today... -mi - */ - case AMR_IO_COMMAND32: - debug(1, "AMR_IO_COMMAND32 0x%x", arg.au32->au_cmd[0]); - au_cmd = arg.au32->au_cmd; - au_buffer = (void *)(u_int64_t)arg.au32->au_buffer; - au_length = arg.au32->au_length; - au_statusp = &arg.au32->au_status; - break; -#endif - - case AMR_IO_COMMAND: - debug(1, "AMR_IO_COMMAND 0x%x", arg.au->au_cmd[0]); - au_cmd = arg.au->au_cmd; - au_buffer = (void *)arg.au->au_buffer; - au_length = arg.au->au_length; - au_statusp = &arg.au->au_status; - break; - - case 0xc0046d00: - case 0xc06e6d00: /* Linux emulation */ - { - devclass_t devclass; - struct amr_linux_ioctl ali; - int adapter, error; - - devclass = devclass_find("amr"); - if (devclass == NULL) - return (ENOENT); - - error = copyin(addr, &ali, sizeof(ali)); - if (error) - return (error); - if (ali.ui.fcs.opcode == 0x82) - adapter = 0; - else - adapter = (ali.ui.fcs.adapno) ^ 'm' << 8; - - sc = devclass_get_softc(devclass, adapter); - if (sc == NULL) - return (ENOENT); - - return (amr_linux_ioctl_int(sc->amr_dev_t, cmd, addr, 0, td)); - } - default: - debug(1, "unknown ioctl 0x%lx", cmd); - return(ENOIOCTL); - } - - if ((au_cmd[0] == FC_DEL_LOGDRV && au_cmd[1] == OP_DEL_LOGDRV) || /* delete */ - (au_cmd[0] == AMR_CMD_CONFIG && au_cmd[1] == 0x0d)) { /* create */ - if (sc->amr_allow_vol_config == 0) { - error = EPERM; - goto out; - } - logical_drives_changed = 1; -#ifdef LSI - if ((error = amr_prepare_ld_delete(sc)) != 0) - return (error); -#endif - } - - /* handle inbound data buffer */ - real_length = amr_ioctl_buffer_length(au_length); - dp = malloc(real_length, M_AMR, M_WAITOK|M_ZERO); - if (au_length != 0 && au_cmd[0] != 0x06) { - if ((error = copyin(au_buffer, dp, au_length)) != 0) { - free(dp, M_AMR); - return (error); - } - debug(2, "copyin %ld bytes from %p -> %p", au_length, au_buffer, dp); - } - - /* Allocate this now before the mutex gets held */ - - mtx_lock(&sc->amr_list_lock); - while ((ac = amr_alloccmd(sc)) == NULL) - msleep(sc, &sc->amr_list_lock, PPAUSE, "amrioc", hz); - - /* handle SCSI passthrough command */ - if (au_cmd[0] == AMR_CMD_PASS) { - int len; - - ap = &ac->ac_ccb->ccb_pthru; - bzero(ap, sizeof(struct amr_passthrough)); - - /* copy cdb */ - len = au_cmd[2]; - ap->ap_cdb_length = len; - bcopy(au_cmd + 3, ap->ap_cdb, len); - - /* build passthrough */ - ap->ap_timeout = au_cmd[len + 3] & 0x07; - ap->ap_ars = (au_cmd[len + 3] & 0x08) ? 1 : 0; - ap->ap_islogical = (au_cmd[len + 3] & 0x80) ? 1 : 0; - ap->ap_logical_drive_no = au_cmd[len + 4]; - ap->ap_channel = au_cmd[len + 5]; - ap->ap_scsi_id = au_cmd[len + 6]; - ap->ap_request_sense_length = 14; - ap->ap_data_transfer_length = au_length; - /* XXX what about the request-sense area? does the caller want it? */ - - /* build command */ - ac->ac_mailbox.mb_command = AMR_CMD_PASS; - ac->ac_flags = AMR_CMD_CCB; - - } else { - /* direct command to controller */ - mbi = (struct amr_mailbox_ioctl *)&ac->ac_mailbox; - - /* copy pertinent mailbox items */ - mbi->mb_command = au_cmd[0]; - mbi->mb_channel = au_cmd[1]; - mbi->mb_param = au_cmd[2]; - mbi->mb_pad[0] = au_cmd[3]; - mbi->mb_drive = au_cmd[4]; - ac->ac_flags = 0; - } - - /* build the command */ - ac->ac_data = dp; - ac->ac_length = real_length; - ac->ac_flags |= AMR_CMD_DATAIN|AMR_CMD_DATAOUT; - - /* run the command */ - error = amr_wait_command(ac); - mtx_unlock(&sc->amr_list_lock); - if (error) - goto out; - - /* copy out data and set status */ - if (au_length != 0) { - error = copyout(dp, au_buffer, au_length); - } - debug(2, "copyout %ld bytes from %p -> %p", au_length, dp, au_buffer); - debug(2, "%p status 0x%x", dp, ac->ac_status); - *au_statusp = ac->ac_status; - -out: - /* - * At this point, we know that there is a lock held and that these - * objects have been allocated. - */ - mtx_lock(&sc->amr_list_lock); - if (ac != NULL) - amr_releasecmd(ac); - mtx_unlock(&sc->amr_list_lock); - if (dp != NULL) - free(dp, M_AMR); - -#ifndef LSI - if (logical_drives_changed) - amr_rescan_drives(dev); -#endif - - return(error); -} - -/******************************************************************************** - ******************************************************************************** - Command Wrappers - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Interrogate the controller for the operational parameters we require. - */ -static int -amr_query_controller(struct amr_softc *sc) -{ - struct amr_enquiry3 *aex; - struct amr_prodinfo *ap; - struct amr_enquiry *ae; - int ldrv; - int status; - - /* - * Greater than 10 byte cdb support - */ - sc->support_ext_cdb = amr_support_ext_cdb(sc); - - if(sc->support_ext_cdb) { - debug(2,"supports extended CDBs."); - } - - /* - * Try to issue an ENQUIRY3 command - */ - if ((aex = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_ENQ3, - AMR_CONFIG_ENQ3_SOLICITED_FULL, &status)) != NULL) { - /* - * Fetch current state of logical drives. - */ - for (ldrv = 0; ldrv < aex->ae_numldrives; ldrv++) { - sc->amr_drive[ldrv].al_size = aex->ae_drivesize[ldrv]; - sc->amr_drive[ldrv].al_state = aex->ae_drivestate[ldrv]; - sc->amr_drive[ldrv].al_properties = aex->ae_driveprop[ldrv]; - debug(2, " drive %d: %d state %x properties %x\n", ldrv, sc->amr_drive[ldrv].al_size, - sc->amr_drive[ldrv].al_state, sc->amr_drive[ldrv].al_properties); - } - free(aex, M_AMR); - - /* - * Get product info for channel count. - */ - if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0, &status)) == NULL) { - device_printf(sc->amr_dev, "can't obtain product data from controller\n"); - return(1); - } - sc->amr_maxdrives = 40; - sc->amr_maxchan = ap->ap_nschan; - sc->amr_maxio = ap->ap_maxio; - sc->amr_type |= AMR_TYPE_40LD; - free(ap, M_AMR); - - ap = amr_enquiry(sc, 0, FC_DEL_LOGDRV, OP_SUP_DEL_LOGDRV, 0, &status); - if (ap != NULL) - free(ap, M_AMR); - if (!status) { - sc->amr_ld_del_supported = 1; - device_printf(sc->amr_dev, "delete logical drives supported by controller\n"); - } - } else { - /* failed, try the 8LD ENQUIRY commands */ - if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0, &status)) == NULL) { - if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0, &status)) == NULL) { - device_printf(sc->amr_dev, "can't obtain configuration data from controller\n"); - return(1); - } - ae->ae_signature = 0; - } - - /* - * Fetch current state of logical drives. - */ - for (ldrv = 0; ldrv < ae->ae_ldrv.al_numdrives; ldrv++) { - sc->amr_drive[ldrv].al_size = ae->ae_ldrv.al_size[ldrv]; - sc->amr_drive[ldrv].al_state = ae->ae_ldrv.al_state[ldrv]; - sc->amr_drive[ldrv].al_properties = ae->ae_ldrv.al_properties[ldrv]; - debug(2, " drive %d: %d state %x properties %x\n", ldrv, sc->amr_drive[ldrv].al_size, - sc->amr_drive[ldrv].al_state, sc->amr_drive[ldrv].al_properties); - } - - sc->amr_maxdrives = 8; - sc->amr_maxchan = ae->ae_adapter.aa_channels; - sc->amr_maxio = ae->ae_adapter.aa_maxio; - free(ae, M_AMR); - } - - /* - * Mark remaining drives as unused. - */ - for (; ldrv < AMR_MAXLD; ldrv++) - sc->amr_drive[ldrv].al_size = 0xffffffff; - - /* - * Cap the maximum number of outstanding I/Os. AMI's Linux driver doesn't trust - * the controller's reported value, and lockups have been seen when we do. - */ - sc->amr_maxio = imin(sc->amr_maxio, AMR_LIMITCMD); - - return(0); -} - -/******************************************************************************** - * Run a generic enquiry-style command. - */ -static void * -amr_enquiry(struct amr_softc *sc, size_t bufsize, u_int8_t cmd, u_int8_t cmdsub, u_int8_t cmdqual, int *status) -{ - struct amr_command *ac; - void *result; - u_int8_t *mbox; - int error; - - debug_called(1); - - error = 1; - result = NULL; - - /* get ourselves a command buffer */ - mtx_lock(&sc->amr_list_lock); - ac = amr_alloccmd(sc); - mtx_unlock(&sc->amr_list_lock); - if (ac == NULL) - goto out; - /* allocate the response structure */ - if ((result = malloc(bufsize, M_AMR, M_ZERO|M_NOWAIT)) == NULL) - goto out; - /* set command flags */ - - ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAIN; - - /* point the command at our data */ - ac->ac_data = result; - ac->ac_length = bufsize; - - /* build the command proper */ - mbox = (u_int8_t *)&ac->ac_mailbox; /* XXX want a real structure for this? */ - mbox[0] = cmd; - mbox[2] = cmdsub; - mbox[3] = cmdqual; - *status = 0; - - /* can't assume that interrupts are going to work here, so play it safe */ - if (sc->amr_poll_command(ac)) - goto out; - error = ac->ac_status; - *status = ac->ac_status; - - out: - mtx_lock(&sc->amr_list_lock); - if (ac != NULL) - amr_releasecmd(ac); - mtx_unlock(&sc->amr_list_lock); - if ((error != 0) && (result != NULL)) { - free(result, M_AMR); - result = NULL; - } - return(result); -} - -/******************************************************************************** - * Flush the controller's internal cache, return status. - */ -int -amr_flush(struct amr_softc *sc) -{ - struct amr_command *ac; - int error; - - /* get ourselves a command buffer */ - error = 1; - mtx_lock(&sc->amr_list_lock); - ac = amr_alloccmd(sc); - mtx_unlock(&sc->amr_list_lock); - if (ac == NULL) - goto out; - /* set command flags */ - ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; - - /* build the command proper */ - ac->ac_mailbox.mb_command = AMR_CMD_FLUSH; - - /* we have to poll, as the system may be going down or otherwise damaged */ - if (sc->amr_poll_command(ac)) - goto out; - error = ac->ac_status; - - out: - mtx_lock(&sc->amr_list_lock); - if (ac != NULL) - amr_releasecmd(ac); - mtx_unlock(&sc->amr_list_lock); - return(error); -} - -/******************************************************************************** - * Detect extented cdb >> greater than 10 byte cdb support - * returns '1' means this support exist - * returns '0' means this support doesn't exist - */ -static int -amr_support_ext_cdb(struct amr_softc *sc) -{ - struct amr_command *ac; - u_int8_t *mbox; - int error; - - /* get ourselves a command buffer */ - error = 0; - mtx_lock(&sc->amr_list_lock); - ac = amr_alloccmd(sc); - mtx_unlock(&sc->amr_list_lock); - if (ac == NULL) - goto out; - /* set command flags */ - ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; - - /* build the command proper */ - mbox = (u_int8_t *)&ac->ac_mailbox; /* XXX want a real structure for this? */ - mbox[0] = 0xA4; - mbox[2] = 0x16; - - /* we have to poll, as the system may be going down or otherwise damaged */ - if (sc->amr_poll_command(ac)) - goto out; - if( ac->ac_status == AMR_STATUS_SUCCESS ) { - error = 1; - } - -out: - mtx_lock(&sc->amr_list_lock); - if (ac != NULL) - amr_releasecmd(ac); - mtx_unlock(&sc->amr_list_lock); - return(error); -} - -/******************************************************************************** - * Try to find I/O work for the controller from one or more of the work queues. - * - * We make the assumption that if the controller is not ready to take a command - * at some given time, it will generate an interrupt at some later time when - * it is. - */ -void -amr_startio(struct amr_softc *sc) -{ - struct amr_command *ac; - - /* spin until something prevents us from doing any work */ - for (;;) { - /* Don't bother to queue commands no bounce buffers are available. */ - if (sc->amr_state & AMR_STATE_QUEUE_FRZN) - break; - - /* try to get a ready command */ - ac = amr_dequeue_ready(sc); - - /* if that failed, build a command from a bio */ - if (ac == NULL) - (void)amr_bio_command(sc, &ac); - - /* if that failed, build a command from a ccb */ - if ((ac == NULL) && (sc->amr_cam_command != NULL)) - sc->amr_cam_command(sc, &ac); - - /* if we don't have anything to do, give up */ - if (ac == NULL) - break; - - /* try to give the command to the controller; if this fails save it for later and give up */ - if (amr_start(ac)) { - debug(2, "controller busy, command deferred"); - amr_requeue_ready(ac); /* XXX schedule retry very soon? */ - break; - } - } -} - -/******************************************************************************** - * Handle completion of an I/O command. - */ -static void -amr_completeio(struct amr_command *ac) -{ - struct amrd_softc *sc = ac->ac_bio->bio_disk->d_drv1; - static struct timeval lastfail; - static int curfail; - - if (ac->ac_status != AMR_STATUS_SUCCESS) { /* could be more verbose here? */ - ac->ac_bio->bio_error = EIO; - ac->ac_bio->bio_flags |= BIO_ERROR; - - if (ppsratecheck(&lastfail, &curfail, 1)) - device_printf(sc->amrd_dev, "I/O error - 0x%x\n", ac->ac_status); -/* amr_printcommand(ac);*/ - } - amrd_intr(ac->ac_bio); - mtx_lock(&ac->ac_sc->amr_list_lock); - amr_releasecmd(ac); - mtx_unlock(&ac->ac_sc->amr_list_lock); -} - -/******************************************************************************** - ******************************************************************************** - Command Processing - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Convert a bio off the top of the bio queue into a command. - */ -static int -amr_bio_command(struct amr_softc *sc, struct amr_command **acp) -{ - struct amr_command *ac; - struct amrd_softc *amrd; - struct bio *bio; - int error; - int blkcount; - int driveno; - int cmd; - - ac = NULL; - error = 0; - - /* get a command */ - if ((ac = amr_alloccmd(sc)) == NULL) - return (ENOMEM); - - /* get a bio to work on */ - if ((bio = amr_dequeue_bio(sc)) == NULL) { - amr_releasecmd(ac); - return (0); - } - - /* connect the bio to the command */ - ac->ac_complete = amr_completeio; - ac->ac_bio = bio; - ac->ac_data = bio->bio_data; - ac->ac_length = bio->bio_bcount; - cmd = 0; - switch (bio->bio_cmd) { - case BIO_READ: - ac->ac_flags |= AMR_CMD_DATAIN; - if (AMR_IS_SG64(sc)) { - cmd = AMR_CMD_LREAD64; - ac->ac_flags |= AMR_CMD_SG64; - } else - cmd = AMR_CMD_LREAD; - break; - case BIO_WRITE: - ac->ac_flags |= AMR_CMD_DATAOUT; - if (AMR_IS_SG64(sc)) { - cmd = AMR_CMD_LWRITE64; - ac->ac_flags |= AMR_CMD_SG64; - } else - cmd = AMR_CMD_LWRITE; - break; - case BIO_FLUSH: - ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; - cmd = AMR_CMD_FLUSH; - break; - default: - biofinish(bio, NULL, EOPNOTSUPP); - amr_releasecmd(ac); - return (0); - } - amrd = (struct amrd_softc *)bio->bio_disk->d_drv1; - driveno = amrd->amrd_drive - sc->amr_drive; - blkcount = howmany(bio->bio_bcount, AMR_BLKSIZE); - - ac->ac_mailbox.mb_command = cmd; - if (bio->bio_cmd == BIO_READ || bio->bio_cmd == BIO_WRITE) { - ac->ac_mailbox.mb_blkcount = blkcount; - ac->ac_mailbox.mb_lba = bio->bio_pblkno; - if ((bio->bio_pblkno + blkcount) > sc->amr_drive[driveno].al_size) { - device_printf(sc->amr_dev, - "I/O beyond end of unit (%lld,%d > %lu)\n", - (long long)bio->bio_pblkno, blkcount, - (u_long)sc->amr_drive[driveno].al_size); - } - } - ac->ac_mailbox.mb_drive = driveno; - if (sc->amr_state & AMR_STATE_REMAP_LD) - ac->ac_mailbox.mb_drive |= 0x80; - - /* we fill in the s/g related data when the command is mapped */ - - *acp = ac; - return(error); -} - -/******************************************************************************** - * Take a command, submit it to the controller and sleep until it completes - * or fails. Interrupts must be enabled, returns nonzero on error. - */ -static int -amr_wait_command(struct amr_command *ac) -{ - int error = 0; - struct amr_softc *sc = ac->ac_sc; - - debug_called(1); - - ac->ac_complete = NULL; - ac->ac_flags |= AMR_CMD_SLEEP; - if ((error = amr_start(ac)) != 0) { - return(error); - } - - while ((ac->ac_flags & AMR_CMD_BUSY) && (error != EWOULDBLOCK)) { - error = msleep(ac,&sc->amr_list_lock, PRIBIO, "amrwcmd", 0); - } - - return(error); -} - -/******************************************************************************** - * Take a command, submit it to the controller and busy-wait for it to return. - * Returns nonzero on error. Can be safely called with interrupts enabled. - */ -static int -amr_std_poll_command(struct amr_command *ac) -{ - struct amr_softc *sc = ac->ac_sc; - int error, count; - - debug_called(2); - - ac->ac_complete = NULL; - if ((error = amr_start(ac)) != 0) - return(error); - - count = 0; - do { - /* - * Poll for completion, although the interrupt handler may beat us to it. - * Note that the timeout here is somewhat arbitrary. - */ - amr_done(sc); - DELAY(1000); - } while ((ac->ac_flags & AMR_CMD_BUSY) && (count++ < 1000)); - if (!(ac->ac_flags & AMR_CMD_BUSY)) { - error = 0; - } else { - /* XXX the slot is now marked permanently busy */ - error = EIO; - device_printf(sc->amr_dev, "polled command timeout\n"); - } - return(error); -} - -static void -amr_setup_polled_dmamap(void *arg, bus_dma_segment_t *segs, int nsegs, int err) -{ - struct amr_command *ac = arg; - struct amr_softc *sc = ac->ac_sc; - int mb_channel; - - if (err) { - device_printf(sc->amr_dev, "error %d in %s", err, __FUNCTION__); - ac->ac_status = AMR_STATUS_ABORTED; - return; - } - - amr_setup_sg(arg, segs, nsegs, err); - - /* for AMR_CMD_CONFIG Read/Write the s/g count goes elsewhere */ - mb_channel = ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel; - if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG && - ((mb_channel == AMR_CONFIG_READ_NVRAM_CONFIG) || - (mb_channel == AMR_CONFIG_WRITE_NVRAM_CONFIG))) - ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param = ac->ac_nsegments; - - ac->ac_mailbox.mb_nsgelem = ac->ac_nsegments; - ac->ac_mailbox.mb_physaddr = ac->ac_mb_physaddr; - if (AC_IS_SG64(ac)) { - ac->ac_sg64_hi = 0; - ac->ac_sg64_lo = ac->ac_sgbusaddr; - } - - sc->amr_poll_command1(sc, ac); -} - -/******************************************************************************** - * Take a command, submit it to the controller and busy-wait for it to return. - * Returns nonzero on error. Can be safely called with interrupts enabled. - */ -static int -amr_quartz_poll_command(struct amr_command *ac) -{ - struct amr_softc *sc = ac->ac_sc; - int error; - - debug_called(2); - - error = 0; - - if (AC_IS_SG64(ac)) { - ac->ac_tag = sc->amr_buffer64_dmat; - ac->ac_datamap = ac->ac_dma64map; - } else { - ac->ac_tag = sc->amr_buffer_dmat; - ac->ac_datamap = ac->ac_dmamap; - } - - /* now we have a slot, we can map the command (unmapped in amr_complete) */ - if (ac->ac_data != 0) { - if (bus_dmamap_load(ac->ac_tag, ac->ac_datamap, ac->ac_data, - ac->ac_length, amr_setup_polled_dmamap, ac, BUS_DMA_NOWAIT) != 0) { - error = 1; - } - } else { - error = amr_quartz_poll_command1(sc, ac); - } - - return (error); -} - -static int -amr_quartz_poll_command1(struct amr_softc *sc, struct amr_command *ac) -{ - int count, error; - - mtx_lock(&sc->amr_hw_lock); - if ((sc->amr_state & AMR_STATE_INTEN) == 0) { - count=0; - while (sc->amr_busyslots) { - msleep(sc, &sc->amr_hw_lock, PRIBIO | PCATCH, "amrpoll", hz); - if(count++>10) { - break; - } - } - - if(sc->amr_busyslots) { - device_printf(sc->amr_dev, "adapter is busy\n"); - mtx_unlock(&sc->amr_hw_lock); - if (ac->ac_data != NULL) { - bus_dmamap_unload(ac->ac_tag, ac->ac_datamap); - } - ac->ac_status=0; - return(1); - } - } - - bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, AMR_MBOX_CMDSIZE); - - /* clear the poll/ack fields in the mailbox */ - sc->amr_mailbox->mb_ident = 0xFE; - sc->amr_mailbox->mb_nstatus = 0xFF; - sc->amr_mailbox->mb_status = 0xFF; - sc->amr_mailbox->mb_poll = 0; - sc->amr_mailbox->mb_ack = 0; - sc->amr_mailbox->mb_busy = 1; - - AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT); - - while(sc->amr_mailbox->mb_nstatus == 0xFF) - DELAY(1); - while(sc->amr_mailbox->mb_status == 0xFF) - DELAY(1); - ac->ac_status=sc->amr_mailbox->mb_status; - error = (ac->ac_status !=AMR_STATUS_SUCCESS) ? 1:0; - while(sc->amr_mailbox->mb_poll != 0x77) - DELAY(1); - sc->amr_mailbox->mb_poll = 0; - sc->amr_mailbox->mb_ack = 0x77; - - /* acknowledge that we have the commands */ - AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_ACK); - while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK) - DELAY(1); - mtx_unlock(&sc->amr_hw_lock); - - /* unmap the command's data buffer */ - if (ac->ac_flags & AMR_CMD_DATAIN) { - bus_dmamap_sync(ac->ac_tag, ac->ac_datamap, BUS_DMASYNC_POSTREAD); - } - if (ac->ac_flags & AMR_CMD_DATAOUT) { - bus_dmamap_sync(ac->ac_tag, ac->ac_datamap, BUS_DMASYNC_POSTWRITE); - } - bus_dmamap_unload(ac->ac_tag, ac->ac_datamap); - - return(error); -} - -static __inline int -amr_freeslot(struct amr_command *ac) -{ - struct amr_softc *sc = ac->ac_sc; - int slot; - - debug_called(3); - - slot = ac->ac_slot; - if (sc->amr_busycmd[slot] == NULL) - panic("amr: slot %d not busy?\n", slot); - - sc->amr_busycmd[slot] = NULL; - atomic_subtract_int(&sc->amr_busyslots, 1); - - return (0); -} - -/******************************************************************************** - * Map/unmap (ac)'s data in the controller's addressable space as required. - * - * These functions may be safely called multiple times on a given command. - */ -static void -amr_setup_sg(void *arg, bus_dma_segment_t *segs, int nsegments, int error) -{ - struct amr_command *ac = (struct amr_command *)arg; - struct amr_sgentry *sg; - struct amr_sg64entry *sg64; - int flags, i; - - debug_called(3); - - /* get base address of s/g table */ - sg = ac->ac_sg.sg32; - sg64 = ac->ac_sg.sg64; - - if (AC_IS_SG64(ac)) { - ac->ac_nsegments = nsegments; - ac->ac_mb_physaddr = 0xffffffff; - for (i = 0; i < nsegments; i++, sg64++) { - sg64->sg_addr = segs[i].ds_addr; - sg64->sg_count = segs[i].ds_len; - } - } else { - /* decide whether we need to populate the s/g table */ - if (nsegments < 2) { - ac->ac_nsegments = 0; - ac->ac_mb_physaddr = segs[0].ds_addr; - } else { - ac->ac_nsegments = nsegments; - ac->ac_mb_physaddr = ac->ac_sgbusaddr; - for (i = 0; i < nsegments; i++, sg++) { - sg->sg_addr = segs[i].ds_addr; - sg->sg_count = segs[i].ds_len; - } - } - } - - flags = 0; - if (ac->ac_flags & AMR_CMD_DATAIN) - flags |= BUS_DMASYNC_PREREAD; - if (ac->ac_flags & AMR_CMD_DATAOUT) - flags |= BUS_DMASYNC_PREWRITE; - bus_dmamap_sync(ac->ac_tag, ac->ac_datamap, flags); - ac->ac_flags |= AMR_CMD_MAPPED; -} - -static void -amr_setup_data(void *arg, bus_dma_segment_t *segs, int nsegs, int err) -{ - struct amr_command *ac = arg; - struct amr_softc *sc = ac->ac_sc; - int mb_channel; - - if (err) { - device_printf(sc->amr_dev, "error %d in %s", err, __FUNCTION__); - amr_abort_load(ac); - return; - } - - amr_setup_sg(arg, segs, nsegs, err); - - /* for AMR_CMD_CONFIG Read/Write the s/g count goes elsewhere */ - mb_channel = ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_channel; - if (ac->ac_mailbox.mb_command == AMR_CMD_CONFIG && - ((mb_channel == AMR_CONFIG_READ_NVRAM_CONFIG) || - (mb_channel == AMR_CONFIG_WRITE_NVRAM_CONFIG))) - ((struct amr_mailbox_ioctl *)&ac->ac_mailbox)->mb_param = ac->ac_nsegments; - - ac->ac_mailbox.mb_nsgelem = ac->ac_nsegments; - ac->ac_mailbox.mb_physaddr = ac->ac_mb_physaddr; - if (AC_IS_SG64(ac)) { - ac->ac_sg64_hi = 0; - ac->ac_sg64_lo = ac->ac_sgbusaddr; - } - - if (sc->amr_submit_command(ac) == EBUSY) { - amr_freeslot(ac); - amr_requeue_ready(ac); - } -} - -static void -amr_setup_ccb(void *arg, bus_dma_segment_t *segs, int nsegs, int err) -{ - struct amr_command *ac = arg; - struct amr_softc *sc = ac->ac_sc; - struct amr_passthrough *ap = &ac->ac_ccb->ccb_pthru; - struct amr_ext_passthrough *aep = &ac->ac_ccb->ccb_epthru; - - if (err) { - device_printf(sc->amr_dev, "error %d in %s", err, __FUNCTION__); - amr_abort_load(ac); - return; - } - - /* Set up the mailbox portion of the command to point at the ccb */ - ac->ac_mailbox.mb_nsgelem = 0; - ac->ac_mailbox.mb_physaddr = ac->ac_ccb_busaddr; - - amr_setup_sg(arg, segs, nsegs, err); - - switch (ac->ac_mailbox.mb_command) { - case AMR_CMD_EXTPASS: - aep->ap_no_sg_elements = ac->ac_nsegments; - aep->ap_data_transfer_address = ac->ac_mb_physaddr; - break; - case AMR_CMD_PASS: - ap->ap_no_sg_elements = ac->ac_nsegments; - ap->ap_data_transfer_address = ac->ac_mb_physaddr; - break; - default: - panic("Unknown ccb command"); - } - - if (sc->amr_submit_command(ac) == EBUSY) { - amr_freeslot(ac); - amr_requeue_ready(ac); - } -} - -static int -amr_mapcmd(struct amr_command *ac) -{ - bus_dmamap_callback_t *cb; - struct amr_softc *sc = ac->ac_sc; - - debug_called(3); - - if (AC_IS_SG64(ac)) { - ac->ac_tag = sc->amr_buffer64_dmat; - ac->ac_datamap = ac->ac_dma64map; - } else { - ac->ac_tag = sc->amr_buffer_dmat; - ac->ac_datamap = ac->ac_dmamap; - } - - if (ac->ac_flags & AMR_CMD_CCB) - cb = amr_setup_ccb; - else - cb = amr_setup_data; - - /* if the command involves data at all, and hasn't been mapped */ - if ((ac->ac_flags & AMR_CMD_MAPPED) == 0 && (ac->ac_data != NULL)) { - /* map the data buffers into bus space and build the s/g list */ - if (bus_dmamap_load(ac->ac_tag, ac->ac_datamap, ac->ac_data, - ac->ac_length, cb, ac, 0) == EINPROGRESS) { - sc->amr_state |= AMR_STATE_QUEUE_FRZN; - } - } else { - if (sc->amr_submit_command(ac) == EBUSY) { - amr_freeslot(ac); - amr_requeue_ready(ac); - } - } - - return (0); -} - -static void -amr_unmapcmd(struct amr_command *ac) -{ - int flag; - - debug_called(3); - - /* if the command involved data at all and was mapped */ - if (ac->ac_flags & AMR_CMD_MAPPED) { - if (ac->ac_data != NULL) { - flag = 0; - if (ac->ac_flags & AMR_CMD_DATAIN) - flag |= BUS_DMASYNC_POSTREAD; - if (ac->ac_flags & AMR_CMD_DATAOUT) - flag |= BUS_DMASYNC_POSTWRITE; - - bus_dmamap_sync(ac->ac_tag, ac->ac_datamap, flag); - bus_dmamap_unload(ac->ac_tag, ac->ac_datamap); - } - - ac->ac_flags &= ~AMR_CMD_MAPPED; - } -} - -static void -amr_abort_load(struct amr_command *ac) -{ - ac_qhead_t head; - struct amr_softc *sc = ac->ac_sc; - - mtx_assert(&sc->amr_list_lock, MA_OWNED); - - ac->ac_status = AMR_STATUS_ABORTED; - amr_init_qhead(&head); - amr_enqueue_completed(ac, &head); - - mtx_unlock(&sc->amr_list_lock); - amr_complete(sc, &head); - mtx_lock(&sc->amr_list_lock); -} - -/******************************************************************************** - * Take a command and give it to the controller, returns 0 if successful, or - * EBUSY if the command should be retried later. - */ -static int -amr_start(struct amr_command *ac) -{ - struct amr_softc *sc; - int error = 0; - int slot; - - debug_called(3); - - /* mark command as busy so that polling consumer can tell */ - sc = ac->ac_sc; - ac->ac_flags |= AMR_CMD_BUSY; - - /* get a command slot (freed in amr_done) */ - slot = ac->ac_slot; - if (sc->amr_busycmd[slot] != NULL) - panic("amr: slot %d busy?\n", slot); - sc->amr_busycmd[slot] = ac; - atomic_add_int(&sc->amr_busyslots, 1); - - /* Now we have a slot, we can map the command (unmapped in amr_complete). */ - if ((error = amr_mapcmd(ac)) == ENOMEM) { - /* - * Memory resources are short, so free the slot and let this be tried - * later. - */ - amr_freeslot(ac); - } - - return (error); -} - -/******************************************************************************** - * Extract one or more completed commands from the controller (sc) - * - * Returns nonzero if any commands on the work queue were marked as completed. - */ - -int -amr_done(struct amr_softc *sc) -{ - ac_qhead_t head; - struct amr_command *ac; - struct amr_mailbox mbox; - int i, idx, result; - - debug_called(3); - - /* See if there's anything for us to do */ - result = 0; - amr_init_qhead(&head); - - /* loop collecting completed commands */ - for (;;) { - /* poll for a completed command's identifier and status */ - if (sc->amr_get_work(sc, &mbox)) { - result = 1; - - /* iterate over completed commands in this result */ - for (i = 0; i < mbox.mb_nstatus; i++) { - /* get pointer to busy command */ - idx = mbox.mb_completed[i] - 1; - ac = sc->amr_busycmd[idx]; - - /* really a busy command? */ - if (ac != NULL) { - /* pull the command from the busy index */ - amr_freeslot(ac); - - /* save status for later use */ - ac->ac_status = mbox.mb_status; - amr_enqueue_completed(ac, &head); - debug(3, "completed command with status %x", mbox.mb_status); - } else { - device_printf(sc->amr_dev, "bad slot %d completed\n", idx); - } - } - } else - break; /* no work */ - } - - /* handle completion and timeouts */ - amr_complete(sc, &head); - - return(result); -} - -/******************************************************************************** - * Do completion processing on done commands on (sc) - */ - -static void -amr_complete(void *context, ac_qhead_t *head) -{ - struct amr_softc *sc = (struct amr_softc *)context; - struct amr_command *ac; - - debug_called(3); - - /* pull completed commands off the queue */ - for (;;) { - ac = amr_dequeue_completed(sc, head); - if (ac == NULL) - break; - - /* unmap the command's data buffer */ - amr_unmapcmd(ac); - - /* - * Is there a completion handler? - */ - if (ac->ac_complete != NULL) { - /* unbusy the command */ - ac->ac_flags &= ~AMR_CMD_BUSY; - ac->ac_complete(ac); - - /* - * Is someone sleeping on this one? - */ - } else { - mtx_lock(&sc->amr_list_lock); - ac->ac_flags &= ~AMR_CMD_BUSY; - if (ac->ac_flags & AMR_CMD_SLEEP) { - /* unbusy the command */ - wakeup(ac); - } - mtx_unlock(&sc->amr_list_lock); - } - - if(!sc->amr_busyslots) { - wakeup(sc); - } - } - - mtx_lock(&sc->amr_list_lock); - sc->amr_state &= ~AMR_STATE_QUEUE_FRZN; - amr_startio(sc); - mtx_unlock(&sc->amr_list_lock); -} - -/******************************************************************************** - ******************************************************************************** - Command Buffer Management - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Get a new command buffer. - * - * This may return NULL in low-memory cases. - * - * If possible, we recycle a command buffer that's been used before. - */ -struct amr_command * -amr_alloccmd(struct amr_softc *sc) -{ - struct amr_command *ac; - - debug_called(3); - - ac = amr_dequeue_free(sc); - if (ac == NULL) { - sc->amr_state |= AMR_STATE_QUEUE_FRZN; - return(NULL); - } - - /* clear out significant fields */ - ac->ac_status = 0; - bzero(&ac->ac_mailbox, sizeof(struct amr_mailbox)); - ac->ac_flags = 0; - ac->ac_bio = NULL; - ac->ac_data = NULL; - ac->ac_complete = NULL; - ac->ac_retries = 0; - ac->ac_tag = NULL; - ac->ac_datamap = NULL; - return(ac); -} - -/******************************************************************************** - * Release a command buffer for recycling. - */ -void -amr_releasecmd(struct amr_command *ac) -{ - debug_called(3); - - amr_enqueue_free(ac); -} - -/******************************************************************************** - * Allocate a new command cluster and initialise it. - */ -static void -amr_alloccmd_cluster(struct amr_softc *sc) -{ - struct amr_command_cluster *acc; - struct amr_command *ac; - int i, nextslot; - - /* - * If we haven't found the real limit yet, let us have a couple of - * commands in order to be able to probe. - */ - if (sc->amr_maxio == 0) - sc->amr_maxio = 2; - - if (sc->amr_nextslot > sc->amr_maxio) - return; - acc = malloc(AMR_CMD_CLUSTERSIZE, M_AMR, M_NOWAIT | M_ZERO); - if (acc != NULL) { - nextslot = sc->amr_nextslot; - mtx_lock(&sc->amr_list_lock); - TAILQ_INSERT_TAIL(&sc->amr_cmd_clusters, acc, acc_link); - mtx_unlock(&sc->amr_list_lock); - for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++) { - ac = &acc->acc_command[i]; - ac->ac_sc = sc; - ac->ac_slot = nextslot; - - /* - * The SG table for each slot is a fixed size and is assumed to - * to hold 64-bit s/g objects when the driver is configured to do - * 64-bit DMA. 32-bit DMA commands still use the same table, but - * cast down to 32-bit objects. - */ - if (AMR_IS_SG64(sc)) { - ac->ac_sgbusaddr = sc->amr_sgbusaddr + - (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sg64entry)); - ac->ac_sg.sg64 = sc->amr_sg64table + (ac->ac_slot * AMR_NSEG); - } else { - ac->ac_sgbusaddr = sc->amr_sgbusaddr + - (ac->ac_slot * AMR_NSEG * sizeof(struct amr_sgentry)); - ac->ac_sg.sg32 = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG); - } - - ac->ac_ccb = sc->amr_ccb + ac->ac_slot; - ac->ac_ccb_busaddr = sc->amr_ccb_busaddr + - (ac->ac_slot * sizeof(union amr_ccb)); - - if (bus_dmamap_create(sc->amr_buffer_dmat, 0, &ac->ac_dmamap)) - break; - if (AMR_IS_SG64(sc) && - (bus_dmamap_create(sc->amr_buffer64_dmat, 0,&ac->ac_dma64map))) - break; - amr_releasecmd(ac); - if (++nextslot > sc->amr_maxio) - break; - } - sc->amr_nextslot = nextslot; - } -} - -/******************************************************************************** - * Free a command cluster - */ -static void -amr_freecmd_cluster(struct amr_command_cluster *acc) -{ - struct amr_softc *sc = acc->acc_command[0].ac_sc; - int i; - - for (i = 0; i < AMR_CMD_CLUSTERCOUNT; i++) { - if (acc->acc_command[i].ac_sc == NULL) - break; - bus_dmamap_destroy(sc->amr_buffer_dmat, acc->acc_command[i].ac_dmamap); - if (AMR_IS_SG64(sc)) - bus_dmamap_destroy(sc->amr_buffer64_dmat, acc->acc_command[i].ac_dma64map); - } - free(acc, M_AMR); -} - -/******************************************************************************** - ******************************************************************************** - Interface-specific Shims - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Tell the controller that the mailbox contains a valid command - */ -static int -amr_quartz_submit_command(struct amr_command *ac) -{ - struct amr_softc *sc = ac->ac_sc; - static struct timeval lastfail; - static int curfail; - int i = 0; - - mtx_lock(&sc->amr_hw_lock); - while (sc->amr_mailbox->mb_busy && (i++ < 10)) { - DELAY(1); - /* This is a no-op read that flushes pending mailbox updates */ - AMR_QGET_ODB(sc); - } - if (sc->amr_mailbox->mb_busy) { - mtx_unlock(&sc->amr_hw_lock); - if (ac->ac_retries++ > 1000) { - if (ppsratecheck(&lastfail, &curfail, 1)) - device_printf(sc->amr_dev, "Too many retries on command %p. " - "Controller is likely dead\n", ac); - ac->ac_retries = 0; - } - return (EBUSY); - } - - /* - * Save the slot number so that we can locate this command when complete. - * Note that ident = 0 seems to be special, so we don't use it. - */ - ac->ac_mailbox.mb_ident = ac->ac_slot + 1; /* will be coppied into mbox */ - bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, 14); - sc->amr_mailbox->mb_busy = 1; - sc->amr_mailbox->mb_poll = 0; - sc->amr_mailbox->mb_ack = 0; - sc->amr_mailbox64->sg64_hi = ac->ac_sg64_hi; - sc->amr_mailbox64->sg64_lo = ac->ac_sg64_lo; - - AMR_QPUT_IDB(sc, sc->amr_mailboxphys | AMR_QIDB_SUBMIT); - mtx_unlock(&sc->amr_hw_lock); - return(0); -} - -static int -amr_std_submit_command(struct amr_command *ac) -{ - struct amr_softc *sc = ac->ac_sc; - static struct timeval lastfail; - static int curfail; - - mtx_lock(&sc->amr_hw_lock); - if (AMR_SGET_MBSTAT(sc) & AMR_SMBOX_BUSYFLAG) { - mtx_unlock(&sc->amr_hw_lock); - if (ac->ac_retries++ > 1000) { - if (ppsratecheck(&lastfail, &curfail, 1)) - device_printf(sc->amr_dev, "Too many retries on command %p. " - "Controller is likely dead\n", ac); - ac->ac_retries = 0; - } - return (EBUSY); - } - - /* - * Save the slot number so that we can locate this command when complete. - * Note that ident = 0 seems to be special, so we don't use it. - */ - ac->ac_mailbox.mb_ident = ac->ac_slot + 1; /* will be coppied into mbox */ - bcopy(&ac->ac_mailbox, (void *)(uintptr_t)(volatile void *)sc->amr_mailbox, 14); - sc->amr_mailbox->mb_busy = 1; - sc->amr_mailbox->mb_poll = 0; - sc->amr_mailbox->mb_ack = 0; - - AMR_SPOST_COMMAND(sc); - mtx_unlock(&sc->amr_hw_lock); - return(0); -} - -/******************************************************************************** - * Claim any work that the controller has completed; acknowledge completion, - * save details of the completion in (mbsave) - */ -static int -amr_quartz_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave) -{ - int worked, i; - u_int32_t outd; - u_int8_t nstatus; - u_int8_t completed[46]; - - debug_called(3); - - worked = 0; - - /* work waiting for us? */ - if ((outd = AMR_QGET_ODB(sc)) == AMR_QODB_READY) { - /* acknowledge interrupt */ - AMR_QPUT_ODB(sc, AMR_QODB_READY); - - while ((nstatus = sc->amr_mailbox->mb_nstatus) == 0xff) - DELAY(1); - sc->amr_mailbox->mb_nstatus = 0xff; - - /* wait until fw wrote out all completions */ - for (i = 0; i < nstatus; i++) { - while ((completed[i] = sc->amr_mailbox->mb_completed[i]) == 0xff) - DELAY(1); - sc->amr_mailbox->mb_completed[i] = 0xff; - } - - /* Save information for later processing */ - mbsave->mb_nstatus = nstatus; - mbsave->mb_status = sc->amr_mailbox->mb_status; - sc->amr_mailbox->mb_status = 0xff; - - for (i = 0; i < nstatus; i++) - mbsave->mb_completed[i] = completed[i]; - - /* acknowledge that we have the commands */ - AMR_QPUT_IDB(sc, AMR_QIDB_ACK); - -#if 0 -#ifndef AMR_QUARTZ_GOFASTER - /* - * This waits for the controller to notice that we've taken the - * command from it. It's very inefficient, and we shouldn't do it, - * but if we remove this code, we stop completing commands under - * load. - * - * Peter J says we shouldn't do this. The documentation says we - * should. Who is right? - */ - while(AMR_QGET_IDB(sc) & AMR_QIDB_ACK) - ; /* XXX aiee! what if it dies? */ -#endif -#endif - - worked = 1; /* got some work */ - } - - return(worked); -} - -static int -amr_std_get_work(struct amr_softc *sc, struct amr_mailbox *mbsave) -{ - int worked; - u_int8_t istat; - - debug_called(3); - - worked = 0; - - /* check for valid interrupt status */ - istat = AMR_SGET_ISTAT(sc); - if ((istat & AMR_SINTR_VALID) != 0) { - AMR_SPUT_ISTAT(sc, istat); /* ack interrupt status */ - - /* save mailbox, which contains a list of completed commands */ - bcopy((void *)(uintptr_t)(volatile void *)sc->amr_mailbox, mbsave, sizeof(*mbsave)); - - AMR_SACK_INTERRUPT(sc); /* acknowledge we have the mailbox */ - worked = 1; - } - - return(worked); -} - -/******************************************************************************** - * Notify the controller of the mailbox location. - */ -static void -amr_std_attach_mailbox(struct amr_softc *sc) -{ - - /* program the mailbox physical address */ - AMR_SBYTE_SET(sc, AMR_SMBOX_0, sc->amr_mailboxphys & 0xff); - AMR_SBYTE_SET(sc, AMR_SMBOX_1, (sc->amr_mailboxphys >> 8) & 0xff); - AMR_SBYTE_SET(sc, AMR_SMBOX_2, (sc->amr_mailboxphys >> 16) & 0xff); - AMR_SBYTE_SET(sc, AMR_SMBOX_3, (sc->amr_mailboxphys >> 24) & 0xff); - AMR_SBYTE_SET(sc, AMR_SMBOX_ENABLE, AMR_SMBOX_ADDR); - - /* clear any outstanding interrupt and enable interrupts proper */ - AMR_SACK_INTERRUPT(sc); - AMR_SENABLE_INTR(sc); -} - -#ifdef AMR_BOARD_INIT -/******************************************************************************** - * Initialise the controller - */ -static int -amr_quartz_init(struct amr_softc *sc) -{ - int status, ostatus; - - device_printf(sc->amr_dev, "initial init status %x\n", AMR_QGET_INITSTATUS(sc)); - - AMR_QRESET(sc); - - ostatus = 0xff; - while ((status = AMR_QGET_INITSTATUS(sc)) != AMR_QINIT_DONE) { - if (status != ostatus) { - device_printf(sc->amr_dev, "(%x) %s\n", status, amr_describe_code(amr_table_qinit, status)); - ostatus = status; - } - switch (status) { - case AMR_QINIT_NOMEM: - return(ENOMEM); - - case AMR_QINIT_SCAN: - /* XXX we could print channel/target here */ - break; - } - } - return(0); -} - -static int -amr_std_init(struct amr_softc *sc) -{ - int status, ostatus; - - device_printf(sc->amr_dev, "initial init status %x\n", AMR_SGET_INITSTATUS(sc)); - - AMR_SRESET(sc); - - ostatus = 0xff; - while ((status = AMR_SGET_INITSTATUS(sc)) != AMR_SINIT_DONE) { - if (status != ostatus) { - device_printf(sc->amr_dev, "(%x) %s\n", status, amr_describe_code(amr_table_sinit, status)); - ostatus = status; - } - switch (status) { - case AMR_SINIT_NOMEM: - return(ENOMEM); - - case AMR_SINIT_INPROG: - /* XXX we could print channel/target here? */ - break; - } - } - return(0); -} -#endif - -/******************************************************************************** - ******************************************************************************** - Debugging - ******************************************************************************** - ********************************************************************************/ - -/******************************************************************************** - * Identify the controller and print some information about it. - */ -static void -amr_describe_controller(struct amr_softc *sc) -{ - struct amr_prodinfo *ap; - struct amr_enquiry *ae; - char *prod; - int status; - - /* - * Try to get 40LD product info, which tells us what the card is labelled as. - */ - if ((ap = amr_enquiry(sc, 2048, AMR_CMD_CONFIG, AMR_CONFIG_PRODUCT_INFO, 0, &status)) != NULL) { - device_printf(sc->amr_dev, " Firmware %.16s, BIOS %.16s, %dMB RAM\n", - ap->ap_product, ap->ap_firmware, ap->ap_bios, - ap->ap_memsize); - - free(ap, M_AMR); - return; - } - - /* - * Try 8LD extended ENQUIRY to get controller signature, and use lookup table. - */ - if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_EXT_ENQUIRY2, 0, 0, &status)) != NULL) { - prod = amr_describe_code(amr_table_adaptertype, ae->ae_signature); - - } else if ((ae = (struct amr_enquiry *)amr_enquiry(sc, 2048, AMR_CMD_ENQUIRY, 0, 0, &status)) != NULL) { - /* - * Try to work it out based on the PCI signatures. - */ - switch (pci_get_device(sc->amr_dev)) { - case 0x9010: - prod = "Series 428"; - break; - case 0x9060: - prod = "Series 434"; - break; - default: - prod = "unknown controller"; - break; - } - } else { - device_printf(sc->amr_dev, "\n"); - return; - } - - /* - * HP NetRaid controllers have a special encoding of the firmware and - * BIOS versions. The AMI version seems to have it as strings whereas - * the HP version does it with a leading uppercase character and two - * binary numbers. - */ - - if(ae->ae_adapter.aa_firmware[2] >= 'A' && - ae->ae_adapter.aa_firmware[2] <= 'Z' && - ae->ae_adapter.aa_firmware[1] < ' ' && - ae->ae_adapter.aa_firmware[0] < ' ' && - ae->ae_adapter.aa_bios[2] >= 'A' && - ae->ae_adapter.aa_bios[2] <= 'Z' && - ae->ae_adapter.aa_bios[1] < ' ' && - ae->ae_adapter.aa_bios[0] < ' ') { - /* this looks like we have an HP NetRaid version of the MegaRaid */ - - if(ae->ae_signature == AMR_SIG_438) { - /* the AMI 438 is a NetRaid 3si in HP-land */ - prod = "HP NetRaid 3si"; - } - - device_printf(sc->amr_dev, "<%s> Firmware %c.%02d.%02d, BIOS %c.%02d.%02d, %dMB RAM\n", - prod, ae->ae_adapter.aa_firmware[2], - ae->ae_adapter.aa_firmware[1], - ae->ae_adapter.aa_firmware[0], - ae->ae_adapter.aa_bios[2], - ae->ae_adapter.aa_bios[1], - ae->ae_adapter.aa_bios[0], - ae->ae_adapter.aa_memorysize); - } else { - device_printf(sc->amr_dev, "<%s> Firmware %.4s, BIOS %.4s, %dMB RAM\n", - prod, ae->ae_adapter.aa_firmware, ae->ae_adapter.aa_bios, - ae->ae_adapter.aa_memorysize); - } - free(ae, M_AMR); -} - -int -amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks) -{ - struct amr_command *ac; - int error = EIO; - - debug_called(1); - - sc->amr_state |= AMR_STATE_INTEN; - - /* get ourselves a command buffer */ - if ((ac = amr_alloccmd(sc)) == NULL) - goto out; - /* set command flags */ - ac->ac_flags |= AMR_CMD_PRIORITY | AMR_CMD_DATAOUT; - - /* point the command at our data */ - ac->ac_data = data; - ac->ac_length = blks * AMR_BLKSIZE; - - /* build the command proper */ - ac->ac_mailbox.mb_command = AMR_CMD_LWRITE; - ac->ac_mailbox.mb_blkcount = blks; - ac->ac_mailbox.mb_lba = lba; - ac->ac_mailbox.mb_drive = unit; - - /* can't assume that interrupts are going to work here, so play it safe */ - if (sc->amr_poll_command(ac)) - goto out; - error = ac->ac_status; - - out: - if (ac != NULL) - amr_releasecmd(ac); - - sc->amr_state &= ~AMR_STATE_INTEN; - return (error); -} - -#ifdef AMR_DEBUG -/******************************************************************************** - * Print the command (ac) in human-readable format - */ -#if 0 -static void -amr_printcommand(struct amr_command *ac) -{ - struct amr_softc *sc = ac->ac_sc; - struct amr_sgentry *sg; - int i; - - device_printf(sc->amr_dev, "cmd %x ident %d drive %d\n", - ac->ac_mailbox.mb_command, ac->ac_mailbox.mb_ident, ac->ac_mailbox.mb_drive); - device_printf(sc->amr_dev, "blkcount %d lba %d\n", - ac->ac_mailbox.mb_blkcount, ac->ac_mailbox.mb_lba); - device_printf(sc->amr_dev, "virtaddr %p length %lu\n", ac->ac_data, (unsigned long)ac->ac_length); - device_printf(sc->amr_dev, "sg physaddr %08x nsg %d\n", - ac->ac_mailbox.mb_physaddr, ac->ac_mailbox.mb_nsgelem); - device_printf(sc->amr_dev, "ccb %p bio %p\n", ac->ac_ccb_data, ac->ac_bio); - - /* get base address of s/g table */ - sg = sc->amr_sgtable + (ac->ac_slot * AMR_NSEG); - for (i = 0; i < ac->ac_mailbox.mb_nsgelem; i++, sg++) - device_printf(sc->amr_dev, " %x/%d\n", sg->sg_addr, sg->sg_count); -} -#endif -#endif diff --git a/sys/dev/amr/amr_cam.c b/sys/dev/amr/amr_cam.c deleted file mode 100644 --- a/sys/dev/amr/amr_cam.c +++ /dev/null @@ -1,627 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2000 Michael Smith - * Copyright (c) 2000 BSDi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/*- - * Copyright (c) 2002 Eric Moore - * Copyright (c) 2002 LSI Logic Corporation - * 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. - * 3. The party using or redistributing the source code and binary forms - * agrees to the disclaimer below and the terms and conditions set forth - * herein. - * - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include - -#include -#include - -static int amr_cam_probe(device_t dev); -static int amr_cam_attach(device_t dev); -static int amr_cam_detach(device_t dev); -static void amr_cam_action(struct cam_sim *sim, union ccb *ccb); -static void amr_cam_poll(struct cam_sim *sim); -static void amr_cam_complete(struct amr_command *ac); -static int amr_cam_command(struct amr_softc *sc, struct amr_command **acp); - -static devclass_t amr_pass_devclass; - -static device_method_t amr_pass_methods[] = { - DEVMETHOD(device_probe, amr_cam_probe), - DEVMETHOD(device_attach, amr_cam_attach), - DEVMETHOD(device_detach, amr_cam_detach), - { 0, 0 } -}; - -static driver_t amr_pass_driver = { - "amrp", - amr_pass_methods, - 0 -}; - -DRIVER_MODULE(amrp, amr, amr_pass_driver, amr_pass_devclass, 0, 0); -MODULE_DEPEND(amrp, cam, 1, 1, 1); - -static MALLOC_DEFINE(M_AMRCAM, "amrcam", "AMR CAM memory"); - -/*********************************************************************** - * Enqueue/dequeue functions - */ -static __inline void -amr_enqueue_ccb(struct amr_softc *sc, union ccb *ccb) -{ - - TAILQ_INSERT_TAIL(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe); -} - -static __inline void -amr_requeue_ccb(struct amr_softc *sc, union ccb *ccb) -{ - - TAILQ_INSERT_HEAD(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe); -} - -static __inline union ccb * -amr_dequeue_ccb(struct amr_softc *sc) -{ - union ccb *ccb; - - if ((ccb = (union ccb *)TAILQ_FIRST(&sc->amr_cam_ccbq)) != NULL) - TAILQ_REMOVE(&sc->amr_cam_ccbq, &ccb->ccb_h, sim_links.tqe); - return(ccb); -} - -static int -amr_cam_probe(device_t dev) -{ - return (0); -} - -/******************************************************************************** - * Attach our 'real' SCSI channels to CAM - */ -static int -amr_cam_attach(device_t dev) -{ - struct amr_softc *sc; - struct cam_devq *devq; - int chn, error; - - sc = device_get_softc(dev); - - /* initialise the ccb queue */ - TAILQ_INIT(&sc->amr_cam_ccbq); - - /* - * Allocate a devq for all our channels combined. This should - * allow for the maximum number of SCSI commands we will accept - * at one time. Save the pointer in the softc so we can find it later - * during detach. - */ - if ((devq = cam_simq_alloc(AMR_MAX_SCSI_CMDS)) == NULL) - return(ENOMEM); - sc->amr_cam_devq = devq; - - /* - * Iterate over our channels, registering them with CAM - */ - for (chn = 0; chn < sc->amr_maxchan; chn++) { - /* allocate a sim */ - if ((sc->amr_cam_sim[chn] = cam_sim_alloc(amr_cam_action, - amr_cam_poll, "amr", sc, device_get_unit(sc->amr_dev), - &sc->amr_list_lock, 1, AMR_MAX_SCSI_CMDS, devq)) == NULL) { - cam_simq_free(devq); - device_printf(sc->amr_dev, "CAM SIM attach failed\n"); - return(ENOMEM); - } - - /* register the bus ID so we can get it later */ - mtx_lock(&sc->amr_list_lock); - error = xpt_bus_register(sc->amr_cam_sim[chn], sc->amr_dev,chn); - mtx_unlock(&sc->amr_list_lock); - if (error) { - device_printf(sc->amr_dev, - "CAM XPT bus registration failed\n"); - return(ENXIO); - } - } - /* - * XXX we should scan the config and work out which devices are - * actually protected. - */ - sc->amr_cam_command = amr_cam_command; - return(0); -} - -/******************************************************************************** - * Disconnect ourselves from CAM - */ -static int -amr_cam_detach(device_t dev) -{ - struct amr_softc *sc; - int chn; - - sc = device_get_softc(dev); - mtx_lock(&sc->amr_list_lock); - for (chn = 0; chn < sc->amr_maxchan; chn++) { - /* - * If a sim was allocated for this channel, free it - */ - if (sc->amr_cam_sim[chn] != NULL) { - xpt_bus_deregister(cam_sim_path(sc->amr_cam_sim[chn])); - cam_sim_free(sc->amr_cam_sim[chn], FALSE); - } - } - mtx_unlock(&sc->amr_list_lock); - - /* Now free the devq */ - if (sc->amr_cam_devq != NULL) - cam_simq_free(sc->amr_cam_devq); - - return (0); -} - -/*********************************************************************** - *********************************************************************** - CAM passthrough interface - *********************************************************************** - ***********************************************************************/ - -/*********************************************************************** - * Handle a request for action from CAM - */ -static void -amr_cam_action(struct cam_sim *sim, union ccb *ccb) -{ - struct amr_softc *sc = cam_sim_softc(sim); - - switch(ccb->ccb_h.func_code) { - /* - * Perform SCSI I/O to a physical device. - */ - case XPT_SCSI_IO: - { - struct ccb_hdr *ccbh = &ccb->ccb_h; - struct ccb_scsiio *csio = &ccb->csio; - - /* Validate the CCB */ - ccbh->status = CAM_REQ_INPROG; - - /* check the CDB length */ - if (csio->cdb_len > AMR_MAX_EXTCDB_LEN) - ccbh->status = CAM_REQ_INVALID; - - if ((csio->cdb_len > AMR_MAX_CDB_LEN) && - (sc->support_ext_cdb == 0)) - ccbh->status = CAM_REQ_INVALID; - - /* check that the CDB pointer is not to a physical address */ - if ((ccbh->flags & CAM_CDB_POINTER) && - (ccbh->flags & CAM_CDB_PHYS)) - ccbh->status = CAM_REQ_INVALID; - /* - * if there is data transfer, it must be to/from a virtual - * address - */ - if ((ccbh->flags & CAM_DIR_MASK) != CAM_DIR_NONE) { - if ((ccbh->flags & CAM_DATA_MASK) != CAM_DATA_VADDR) - /* we can't map it */ - ccbh->status = CAM_REQ_INVALID; - } - - /* - * If the command is to a LUN other than 0, fail it. - * This is probably incorrect, but during testing the - * firmware did not seem to respect the LUN field, and thus - * devices appear echoed. - */ - if (csio->ccb_h.target_lun != 0) - ccbh->status = CAM_DEV_NOT_THERE; - - /* if we're happy with the request, queue it for attention */ - if (ccbh->status == CAM_REQ_INPROG) { - /* save the channel number in the ccb */ - csio->ccb_h.sim_priv.entries[0].field= cam_sim_bus(sim); - - amr_enqueue_ccb(sc, ccb); - amr_startio(sc); - return; - } - break; - } - - case XPT_CALC_GEOMETRY: - { - cam_calc_geometry(&ccb->ccg, /*extended*/1); - break; - } - - /* - * Return path stats. Some of these should probably be amended. - */ - case XPT_PATH_INQ: - { - struct ccb_pathinq *cpi = & ccb->cpi; - - debug(3, "XPT_PATH_INQ"); - cpi->version_num = 1; /* XXX??? */ - cpi->hba_inquiry = PI_SDTR_ABLE|PI_TAG_ABLE|PI_WIDE_16; - cpi->target_sprt = 0; - cpi->hba_misc = PIM_NOBUSRESET|PIM_SEQSCAN; - cpi->hba_eng_cnt = 0; - cpi->max_target = AMR_MAX_TARGETS; - cpi->max_lun = 0 /* AMR_MAX_LUNS*/; - cpi->initiator_id = 7; /* XXX variable? */ - strlcpy(cpi->sim_vid, "FreeBSD", SIM_IDLEN); - strlcpy(cpi->hba_vid, "LSI", HBA_IDLEN); - strlcpy(cpi->dev_name, cam_sim_name(sim), DEV_IDLEN); - cpi->unit_number = cam_sim_unit(sim); - cpi->bus_id = cam_sim_bus(sim); - cpi->base_transfer_speed = 132 * 1024; /* XXX */ - cpi->transport = XPORT_SPI; - cpi->transport_version = 2; - cpi->protocol = PROTO_SCSI; - cpi->protocol_version = SCSI_REV_2; - cpi->ccb_h.status = CAM_REQ_CMP; - - break; - } - - case XPT_RESET_BUS: - { - struct ccb_pathinq *cpi = & ccb->cpi; - - debug(1, "XPT_RESET_BUS"); - cpi->ccb_h.status = CAM_REQ_CMP; - break; - } - - case XPT_RESET_DEV: - { - debug(1, "XPT_RESET_DEV"); - ccb->ccb_h.status = CAM_REQ_CMP; - break; - } - - case XPT_GET_TRAN_SETTINGS: - { - struct ccb_trans_settings *cts = &(ccb->cts); - - debug(3, "XPT_GET_TRAN_SETTINGS"); - - struct ccb_trans_settings_scsi *scsi; - struct ccb_trans_settings_spi *spi; - - scsi = &cts->proto_specific.scsi; - spi = &cts->xport_specific.spi; - - cts->protocol = PROTO_SCSI; - cts->protocol_version = SCSI_REV_2; - cts->transport = XPORT_SPI; - cts->transport_version = 2; - - if (cts->type == CTS_TYPE_USER_SETTINGS) { - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - break; - } - - spi->flags = CTS_SPI_FLAGS_DISC_ENB; - spi->bus_width = MSG_EXT_WDTR_BUS_32_BIT; - spi->sync_period = 6; /* 40MHz how wide is this bus? */ - spi->sync_offset = 31; /* How to extract this from board? */ - - spi->valid = CTS_SPI_VALID_SYNC_RATE - | CTS_SPI_VALID_SYNC_OFFSET - | CTS_SPI_VALID_BUS_WIDTH - | CTS_SPI_VALID_DISC; - scsi->valid = CTS_SCSI_VALID_TQ; - ccb->ccb_h.status = CAM_REQ_CMP; - break; - } - - case XPT_SET_TRAN_SETTINGS: - debug(3, "XPT_SET_TRAN_SETTINGS"); - ccb->ccb_h.status = CAM_FUNC_NOTAVAIL; - break; - - /* - * Reject anything else as unsupported. - */ - default: - /* we can't do this */ - ccb->ccb_h.status = CAM_REQ_INVALID; - break; - } - - mtx_assert(&sc->amr_list_lock, MA_OWNED); - xpt_done(ccb); -} - -/*********************************************************************** - * Convert a CAM CCB off the top of the CCB queue to a passthrough SCSI - * command. - */ -static int -amr_cam_command(struct amr_softc *sc, struct amr_command **acp) -{ - struct amr_command *ac; - struct amr_passthrough *ap; - struct amr_ext_passthrough *aep; - struct ccb_scsiio *csio; - int bus, target, error; - - error = 0; - ac = NULL; - ap = NULL; - aep = NULL; - - /* check to see if there is a ccb for us to work with */ - if ((csio = (struct ccb_scsiio *)amr_dequeue_ccb(sc)) == NULL) - goto out; - - /* get bus/target, XXX validate against protected devices? */ - bus = csio->ccb_h.sim_priv.entries[0].field; - target = csio->ccb_h.target_id; - - /* - * Build a passthrough command. - */ - - /* construct command */ - if ((ac = amr_alloccmd(sc)) == NULL) { - error = ENOMEM; - goto out; - } - - /* construct passthrough */ - if (sc->support_ext_cdb ) { - aep = &ac->ac_ccb->ccb_epthru; - aep->ap_timeout = 2; - aep->ap_ars = 1; - aep->ap_request_sense_length = 14; - aep->ap_islogical = 0; - aep->ap_channel = bus; - aep->ap_scsi_id = target; - aep->ap_logical_drive_no = csio->ccb_h.target_lun; - aep->ap_cdb_length = csio->cdb_len; - aep->ap_data_transfer_length = csio->dxfer_len; - if (csio->ccb_h.flags & CAM_CDB_POINTER) { - bcopy(csio->cdb_io.cdb_ptr, aep->ap_cdb, csio->cdb_len); - } else { - bcopy(csio->cdb_io.cdb_bytes, aep->ap_cdb, - csio->cdb_len); - } - /* - * we leave the data s/g list and s/g count to the map routine - * later - */ - - debug(2, " COMMAND %x/%d+%d to %d:%d:%d", aep->ap_cdb[0], - aep->ap_cdb_length, csio->dxfer_len, aep->ap_channel, - aep->ap_scsi_id, aep->ap_logical_drive_no); - - } else { - ap = &ac->ac_ccb->ccb_pthru; - ap->ap_timeout = 0; - ap->ap_ars = 1; - ap->ap_request_sense_length = 14; - ap->ap_islogical = 0; - ap->ap_channel = bus; - ap->ap_scsi_id = target; - ap->ap_logical_drive_no = csio->ccb_h.target_lun; - ap->ap_cdb_length = csio->cdb_len; - ap->ap_data_transfer_length = csio->dxfer_len; - if (csio->ccb_h.flags & CAM_CDB_POINTER) { - bcopy(csio->cdb_io.cdb_ptr, ap->ap_cdb, csio->cdb_len); - } else { - bcopy(csio->cdb_io.cdb_bytes, ap->ap_cdb, - csio->cdb_len); - } - /* - * we leave the data s/g list and s/g count to the map routine - * later - */ - - debug(2, " COMMAND %x/%d+%d to %d:%d:%d", ap->ap_cdb[0], - ap->ap_cdb_length, csio->dxfer_len, ap->ap_channel, - ap->ap_scsi_id, ap->ap_logical_drive_no); - } - - ac->ac_flags |= AMR_CMD_CCB; - - ac->ac_data = csio->data_ptr; - ac->ac_length = csio->dxfer_len; - if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_IN) - ac->ac_flags |= AMR_CMD_DATAIN; - if ((csio->ccb_h.flags & CAM_DIR_MASK) == CAM_DIR_OUT) - ac->ac_flags |= AMR_CMD_DATAOUT; - - ac->ac_private = csio; - ac->ac_complete = amr_cam_complete; - if ( sc->support_ext_cdb ) { - ac->ac_mailbox.mb_command = AMR_CMD_EXTPASS; - } else { - ac->ac_mailbox.mb_command = AMR_CMD_PASS; - } - -out: - if (error != 0) { - if (ac != NULL) - amr_releasecmd(ac); - if (csio != NULL) - /* put it back and try again later */ - amr_requeue_ccb(sc, (union ccb *)csio); - } - *acp = ac; - return(error); -} - -/*********************************************************************** - * Check for interrupt status - */ -static void -amr_cam_poll(struct cam_sim *sim) -{ - - amr_done(cam_sim_softc(sim)); -} - - /********************************************************************** - * Handle completion of a command submitted via CAM. - */ -static void -amr_cam_complete(struct amr_command *ac) -{ - struct amr_passthrough *ap; - struct amr_ext_passthrough *aep; - struct ccb_scsiio *csio; - struct scsi_inquiry_data *inq; - int scsi_status, cdb0; - - ap = &ac->ac_ccb->ccb_pthru; - aep = &ac->ac_ccb->ccb_epthru; - csio = (struct ccb_scsiio *)ac->ac_private; - inq = (struct scsi_inquiry_data *)csio->data_ptr; - - if (ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS) - scsi_status = aep->ap_scsi_status; - else - scsi_status = ap->ap_scsi_status; - debug(1, "status 0x%x AP scsi_status 0x%x", ac->ac_status, - scsi_status); - - /* Make sure the status is sane */ - if ((ac->ac_status != AMR_STATUS_SUCCESS) && (scsi_status == 0)) { - csio->ccb_h.status = CAM_REQ_CMP_ERR; - goto out; - } - - /* - * Hide disks from CAM so that they're not picked up and treated as - * 'normal' disks. - * - * If the configuration provides a mechanism to mark a disk a "not - * managed", we could add handling for that to allow disks to be - * selectively visible. - */ - - /* handle passthrough SCSI status */ - switch(scsi_status) { - case 0: /* completed OK */ - if (ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS) - cdb0 = aep->ap_cdb[0]; - else - cdb0 = ap->ap_cdb[0]; - if ((cdb0 == INQUIRY) && (SID_TYPE(inq) == T_DIRECT)) - inq->device = (inq->device & 0xe0) | T_NODEVICE; - csio->ccb_h.status = CAM_REQ_CMP; - break; - - case 0x02: - csio->ccb_h.status = CAM_SCSI_STATUS_ERROR; - csio->scsi_status = SCSI_STATUS_CHECK_COND; - if (ac->ac_mailbox.mb_command == AMR_CMD_EXTPASS) - bcopy(aep->ap_request_sense_area, &csio->sense_data, - AMR_MAX_REQ_SENSE_LEN); - else - bcopy(ap->ap_request_sense_area, &csio->sense_data, - AMR_MAX_REQ_SENSE_LEN); - csio->sense_len = AMR_MAX_REQ_SENSE_LEN; - csio->ccb_h.status |= CAM_AUTOSNS_VALID; - break; - - case 0x08: - csio->ccb_h.status = CAM_SCSI_BUSY; - break; - - case 0xf0: - case 0xf4: - default: - /* - * Non-zero LUNs are already filtered, so there's no need - * to return CAM_DEV_NOT_THERE. - */ - csio->ccb_h.status = CAM_SEL_TIMEOUT; - break; - } - -out: - if ((csio->ccb_h.flags & CAM_DIR_MASK) != CAM_DIR_NONE) - debug(2, "%*D\n", imin(csio->dxfer_len, 16), csio->data_ptr, - " "); - - mtx_lock(&ac->ac_sc->amr_list_lock); - xpt_done((union ccb *)csio); - amr_releasecmd(ac); - mtx_unlock(&ac->ac_sc->amr_list_lock); -} diff --git a/sys/dev/amr/amr_disk.c b/sys/dev/amr/amr_disk.c deleted file mode 100644 --- a/sys/dev/amr/amr_disk.c +++ /dev/null @@ -1,267 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 1999 Jonathan Lemon - * Copyright (c) 1999, 2000 Michael Smith - * Copyright (c) 2000 BSDi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/*- - * Copyright (c) 2002 Eric Moore - * Copyright (c) 2002 LSI Logic Corporation - * 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. - * 3. The party using or redistributing the source code and binary forms - * agrees to the disclaimer below and the terms and conditions set forth - * herein. - * - * 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 -__FBSDID("$FreeBSD$"); - -/* - * Disk driver for AMI MegaRaid controllers - */ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include -#include - -/* prototypes */ -static int amrd_probe(device_t dev); -static int amrd_attach(device_t dev); -static int amrd_detach(device_t dev); - -static disk_open_t amrd_open; -static disk_strategy_t amrd_strategy; - -static devclass_t amrd_devclass; -#ifdef FREEBSD_4 -int amr_disks_registered = 0; -#endif - -static device_method_t amrd_methods[] = { - DEVMETHOD(device_probe, amrd_probe), - DEVMETHOD(device_attach, amrd_attach), - DEVMETHOD(device_detach, amrd_detach), - { 0, 0 } -}; - -static driver_t amrd_driver = { - "amrd", - amrd_methods, - sizeof(struct amrd_softc) -}; - -DRIVER_MODULE(amrd, amr, amrd_driver, amrd_devclass, 0, 0); - -static int -amrd_open(struct disk *dp) -{ - struct amrd_softc *sc = (struct amrd_softc *)dp->d_drv1; - - debug_called(1); - - if (sc == NULL) - return (ENXIO); - - /* controller not active? */ - if (sc->amrd_controller->amr_state & AMR_STATE_SHUTDOWN) - return(ENXIO); - - return (0); -} -/******************************************************************************** - * System crashdump support - */ - -static int -amrd_dump(void *arg, void *virtual, vm_offset_t physical, off_t offset, size_t length) -{ - - struct amrd_softc *amrd_sc; - struct amr_softc *amr_sc; - int error; - struct disk *dp; - - dp = arg; - amrd_sc = (struct amrd_softc *)dp->d_drv1; - if (amrd_sc == NULL) - return(ENXIO); - amr_sc = (struct amr_softc *)amrd_sc->amrd_controller; - - if (length > 0) { - int driveno = amrd_sc->amrd_drive - amr_sc->amr_drive; - if ((error = amr_dump_blocks(amr_sc,driveno,offset / AMR_BLKSIZE ,(void *)virtual,(int) length / AMR_BLKSIZE )) != 0) - return(error); - } - return(0); -} - -/* - * Read/write routine for a buffer. Finds the proper unit, range checks - * arguments, and schedules the transfer. Does not wait for the transfer - * to complete. Multi-page transfers are supported. All I/O requests must - * be a multiple of a sector in length. - */ -static void -amrd_strategy(struct bio *bio) -{ - struct amrd_softc *sc = (struct amrd_softc *)bio->bio_disk->d_drv1; - - /* bogus disk? */ - if (sc == NULL) { - bio->bio_error = EINVAL; - goto bad; - } - - amr_submit_bio(sc->amrd_controller, bio); - return; - - bad: - bio->bio_flags |= BIO_ERROR; - - /* - * Correctly set the buf to indicate a completed transfer - */ - bio->bio_resid = bio->bio_bcount; - biodone(bio); - return; -} - -void -amrd_intr(void *data) -{ - struct bio *bio = (struct bio *)data; - - debug_called(2); - - if (bio->bio_flags & BIO_ERROR) { - bio->bio_error = EIO; - debug(1, "i/o error\n"); - } else { - bio->bio_resid = 0; - } - - biodone(bio); -} - -static int -amrd_probe(device_t dev) -{ - - debug_called(1); - - device_set_desc(dev, "LSILogic MegaRAID logical drive"); - return (0); -} - -static int -amrd_attach(device_t dev) -{ - struct amrd_softc *sc = (struct amrd_softc *)device_get_softc(dev); - device_t parent; - - debug_called(1); - - parent = device_get_parent(dev); - sc->amrd_controller = (struct amr_softc *)device_get_softc(parent); - sc->amrd_unit = device_get_unit(dev); - sc->amrd_drive = device_get_ivars(dev); - sc->amrd_dev = dev; - - device_printf(dev, "%uMB (%u sectors) RAID %d (%s)\n", - sc->amrd_drive->al_size / ((1024 * 1024) / AMR_BLKSIZE), - sc->amrd_drive->al_size, sc->amrd_drive->al_properties & AMR_DRV_RAID_MASK, - amr_describe_code(amr_table_drvstate, AMR_DRV_CURSTATE(sc->amrd_drive->al_state))); - - sc->amrd_disk = disk_alloc(); - sc->amrd_disk->d_drv1 = sc; - sc->amrd_disk->d_maxsize = (AMR_NSEG - 1) * PAGE_SIZE; - sc->amrd_disk->d_open = amrd_open; - sc->amrd_disk->d_strategy = amrd_strategy; - sc->amrd_disk->d_name = "amrd"; - sc->amrd_disk->d_dump = (dumper_t *)amrd_dump; - sc->amrd_disk->d_unit = sc->amrd_unit; - sc->amrd_disk->d_flags = DISKFLAG_CANFLUSHCACHE; - sc->amrd_disk->d_sectorsize = AMR_BLKSIZE; - sc->amrd_disk->d_mediasize = (off_t)sc->amrd_drive->al_size * AMR_BLKSIZE; - sc->amrd_disk->d_fwsectors = sc->amrd_drive->al_sectors; - sc->amrd_disk->d_fwheads = sc->amrd_drive->al_heads; - disk_create(sc->amrd_disk, DISK_VERSION); - - return (0); -} - -static int -amrd_detach(device_t dev) -{ - struct amrd_softc *sc = (struct amrd_softc *)device_get_softc(dev); - - debug_called(1); - - if (sc->amrd_disk->d_flags & DISKFLAG_OPEN) - return(EBUSY); - -#ifdef FREEBSD_4 - if (--amr_disks_registered == 0) - cdevsw_remove(&amrddisk_cdevsw); -#else - disk_destroy(sc->amrd_disk); -#endif - return(0); -} diff --git a/sys/dev/amr/amr_linux.c b/sys/dev/amr/amr_linux.c deleted file mode 100644 --- a/sys/dev/amr/amr_linux.c +++ /dev/null @@ -1,87 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD - * - * Copyright (c) 2005 Paul Saab - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include -#include -#include -#include - -#if defined(__amd64__) /* Assume amd64 wants 32 bit Linux */ -#include -#include -#else -#include -#include -#endif -#include - -/* There are multiple ioctl number ranges that need to be handled */ -#define AMR_LINUX_IOCTL_MIN 0x6d00 -#define AMR_LINUX_IOCTL_MAX 0x6d01 - -static linux_ioctl_function_t amr_linux_ioctl; -static struct linux_ioctl_handler amr_linux_handler = {amr_linux_ioctl, - AMR_LINUX_IOCTL_MIN, - AMR_LINUX_IOCTL_MAX}; - -SYSINIT (amr_register, SI_SUB_KLD, SI_ORDER_MIDDLE, - linux_ioctl_register_handler, &amr_linux_handler); -SYSUNINIT(amr_unregister, SI_SUB_KLD, SI_ORDER_MIDDLE, - linux_ioctl_unregister_handler, &amr_linux_handler); - -static int -amr_linux_modevent(module_t mod, int cmd, void *data) -{ - return (0); -} - -DEV_MODULE(amr_linux, amr_linux_modevent, NULL); -MODULE_DEPEND(amr, linux, 1, 1, 1); - -static int -amr_linux_ioctl(struct thread *p, struct linux_ioctl_args *args) -{ - cap_rights_t rights; - struct file *fp; - int error; - - error = fget(p, args->fd, cap_rights_init_one(&rights, CAP_IOCTL), &fp); - if (error != 0) - return (error); - error = fo_ioctl(fp, args->cmd, (caddr_t)args->arg, p->td_ucred, p); - fdrop(fp, p); - return (error); -} diff --git a/sys/dev/amr/amr_pci.c b/sys/dev/amr/amr_pci.c deleted file mode 100644 --- a/sys/dev/amr/amr_pci.c +++ /dev/null @@ -1,705 +0,0 @@ -/*- - * Copyright (c) 1999,2000 Michael Smith - * Copyright (c) 2000 BSDi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ -/*- - * SPDX-License-Identifier: BSD-3-Clause - * - * Copyright (c) 2002 Eric Moore - * Copyright (c) 2002, 2004 LSI Logic Corporation - * 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. - * 3. The party using or redistributing the source code and binary forms - * agrees to the disclaimer below and the terms and conditions set forth - * herein. - * - * 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 -__FBSDID("$FreeBSD$"); - -#include -#include -#include -#include -#include - -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include -#include -#include - -static int amr_pci_probe(device_t dev); -static int amr_pci_attach(device_t dev); -static int amr_pci_detach(device_t dev); -static int amr_pci_shutdown(device_t dev); -static int amr_pci_suspend(device_t dev); -static int amr_pci_resume(device_t dev); -static void amr_pci_intr(void *arg); -static void amr_pci_free(struct amr_softc *sc); -static void amr_sglist_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error); -static int amr_sglist_map(struct amr_softc *sc); -static int amr_setup_mbox(struct amr_softc *sc); -static int amr_ccb_map(struct amr_softc *sc); - -static u_int amr_force_sg32 = 0; -SYSCTL_DECL(_hw_amr); -SYSCTL_UINT(_hw_amr, OID_AUTO, force_sg32, CTLFLAG_RDTUN, &amr_force_sg32, 0, - "Force the AMR driver to use 32bit scatter gather"); - -static device_method_t amr_methods[] = { - /* Device interface */ - DEVMETHOD(device_probe, amr_pci_probe), - DEVMETHOD(device_attach, amr_pci_attach), - DEVMETHOD(device_detach, amr_pci_detach), - DEVMETHOD(device_shutdown, amr_pci_shutdown), - DEVMETHOD(device_suspend, amr_pci_suspend), - DEVMETHOD(device_resume, amr_pci_resume), - - DEVMETHOD_END -}; - -static driver_t amr_pci_driver = { - "amr", - amr_methods, - sizeof(struct amr_softc) -}; - -static struct amr_ident -{ - uint16_t vendor; - uint16_t device; - int flags; -#define AMR_ID_PROBE_SIG (1<<0) /* generic i960RD, check signature */ -#define AMR_ID_DO_SG64 (1<<1) -#define AMR_ID_QUARTZ (1<<2) -} amr_device_ids[] = { - {0x101e, 0x9010, 0}, - {0x101e, 0x9060, 0}, - {0x8086, 0x1960, AMR_ID_QUARTZ | AMR_ID_PROBE_SIG}, - {0x101e, 0x1960, AMR_ID_QUARTZ}, - {0x1000, 0x1960, AMR_ID_QUARTZ | AMR_ID_DO_SG64 | AMR_ID_PROBE_SIG}, - {0x1000, 0x0407, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, - {0x1000, 0x0408, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, - {0x1000, 0x0409, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, - {0x1028, 0x000e, AMR_ID_QUARTZ | AMR_ID_DO_SG64 | AMR_ID_PROBE_SIG}, /* perc4/di i960 */ - {0x1028, 0x000f, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, /* perc4/di Verde*/ - {0x1028, 0x0013, AMR_ID_QUARTZ | AMR_ID_DO_SG64}, /* perc4/di */ - {0, 0, 0} -}; - -static devclass_t amr_devclass; -DRIVER_MODULE(amr, pci, amr_pci_driver, amr_devclass, 0, 0); -MODULE_PNP_INFO("U16:vendor;U16:device", pci, amr, amr_device_ids, - nitems(amr_device_ids) - 1); -MODULE_DEPEND(amr, pci, 1, 1, 1); -MODULE_DEPEND(amr, cam, 1, 1, 1); - -static struct amr_ident * -amr_find_ident(device_t dev) -{ - struct amr_ident *id; - int sig; - - for (id = amr_device_ids; id->vendor != 0; id++) { - if ((pci_get_vendor(dev) == id->vendor) && - (pci_get_device(dev) == id->device)) { - /* do we need to test for a signature? */ - if (id->flags & AMR_ID_PROBE_SIG) { - sig = pci_read_config(dev, AMR_CFG_SIG, 2); - if ((sig != AMR_SIGNATURE_1) && (sig != AMR_SIGNATURE_2)) - continue; - } - return (id); - } - } - return (NULL); -} - -static int -amr_pci_probe(device_t dev) -{ - - debug_called(1); - - if (amr_find_ident(dev) != NULL) { - device_set_desc(dev, LSI_DESC_PCI); - return(BUS_PROBE_DEFAULT); - } - return(ENXIO); -} - -static int -amr_pci_attach(device_t dev) -{ - struct amr_softc *sc; - struct amr_ident *id; - int rid, rtype, error; - - debug_called(1); - - /* - * Initialise softc. - */ - sc = device_get_softc(dev); - bzero(sc, sizeof(*sc)); - sc->amr_dev = dev; - - /* assume failure is 'not configured' */ - error = ENXIO; - - /* - * Determine board type. - */ - if ((id = amr_find_ident(dev)) == NULL) - return (ENXIO); - - if (id->flags & AMR_ID_QUARTZ) { - sc->amr_type |= AMR_TYPE_QUARTZ; - } - - if ((amr_force_sg32 == 0) && (id->flags & AMR_ID_DO_SG64) && - (sizeof(vm_paddr_t) > 4)) { - device_printf(dev, "Using 64-bit DMA\n"); - sc->amr_type |= AMR_TYPE_SG64; - } - - /* force the busmaster enable bit on */ - pci_enable_busmaster(dev); - - /* - * Allocate the PCI register window. - */ - rid = PCIR_BAR(0); - rtype = AMR_IS_QUARTZ(sc) ? SYS_RES_MEMORY : SYS_RES_IOPORT; - sc->amr_reg = bus_alloc_resource_any(dev, rtype, &rid, RF_ACTIVE); - if (sc->amr_reg == NULL) { - device_printf(sc->amr_dev, "can't allocate register window\n"); - goto out; - } - sc->amr_btag = rman_get_bustag(sc->amr_reg); - sc->amr_bhandle = rman_get_bushandle(sc->amr_reg); - - /* - * Allocate and connect our interrupt. - */ - rid = 0; - sc->amr_irq = bus_alloc_resource_any(sc->amr_dev, SYS_RES_IRQ, &rid, - RF_SHAREABLE | RF_ACTIVE); - if (sc->amr_irq == NULL) { - device_printf(sc->amr_dev, "can't allocate interrupt\n"); - goto out; - } - if (bus_setup_intr(sc->amr_dev, sc->amr_irq, - INTR_TYPE_BIO | INTR_ENTROPY | INTR_MPSAFE, NULL, amr_pci_intr, - sc, &sc->amr_intr)) { - device_printf(sc->amr_dev, "can't set up interrupt\n"); - goto out; - } - - debug(2, "interrupt attached"); - - /* assume failure is 'out of memory' */ - error = ENOMEM; - - /* - * Allocate the parent bus DMA tag appropriate for PCI. - */ - if (bus_dma_tag_create(bus_get_dma_tag(dev), /* PCI parent */ - 1, 0, /* alignment,boundary */ - AMR_IS_SG64(sc) ? - BUS_SPACE_MAXADDR : - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - BUS_SPACE_MAXSIZE, /* maxsize */ - BUS_SPACE_UNRESTRICTED, /* nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->amr_parent_dmat)) { - device_printf(dev, "can't allocate parent DMA tag\n"); - goto out; - } - - /* - * Create DMA tag for mapping buffers into controller-addressable space. - */ - if (bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ - 1, 0, /* alignment,boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - DFLTPHYS, /* maxsize */ - AMR_NSEG, /* nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - 0, /* flags */ - busdma_lock_mutex, /* lockfunc */ - &sc->amr_list_lock, /* lockarg */ - &sc->amr_buffer_dmat)) { - device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n"); - goto out; - } - - if (bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ - 1, 0, /* alignment,boundary */ - BUS_SPACE_MAXADDR, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - DFLTPHYS, /* maxsize */ - AMR_NSEG, /* nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - 0, /* flags */ - busdma_lock_mutex, /* lockfunc */ - &sc->amr_list_lock, /* lockarg */ - &sc->amr_buffer64_dmat)) { - device_printf(sc->amr_dev, "can't allocate buffer DMA tag\n"); - goto out; - } - - debug(2, "dma tag done"); - - /* - * Allocate and set up mailbox in a bus-visible fashion. - */ - mtx_init(&sc->amr_list_lock, "AMR List Lock", NULL, MTX_DEF); - mtx_init(&sc->amr_hw_lock, "AMR HW Lock", NULL, MTX_DEF); - if ((error = amr_setup_mbox(sc)) != 0) - goto out; - - debug(2, "mailbox setup"); - - /* - * Build the scatter/gather buffers. - */ - if ((error = amr_sglist_map(sc)) != 0) - goto out; - debug(2, "s/g list mapped"); - - if ((error = amr_ccb_map(sc)) != 0) - goto out; - debug(2, "ccb mapped"); - - /* - * Do bus-independant initialisation, bring controller online. - */ - error = amr_attach(sc); - -out: - if (error) - amr_pci_free(sc); - else - gone_in_dev(dev, 13, "amr(4) driver"); - return(error); -} - -/******************************************************************************** - * Disconnect from the controller completely, in preparation for unload. - */ -static int -amr_pci_detach(device_t dev) -{ - struct amr_softc *sc = device_get_softc(dev); - int error; - - debug_called(1); - - if (sc->amr_state & AMR_STATE_OPEN) - return(EBUSY); - - if ((error = amr_pci_shutdown(dev))) - return(error); - - amr_pci_free(sc); - - return(0); -} - -/******************************************************************************** - * Bring the controller down to a dormant state and detach all child devices. - * - * This function is called before detach, system shutdown, or before performing - * an operation which may add or delete system disks. (Call amr_startup to - * resume normal operation.) - * - * 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 -amr_pci_shutdown(device_t dev) -{ - struct amr_softc *sc = device_get_softc(dev); - int i,error; - - debug_called(1); - - /* mark ourselves as in-shutdown */ - sc->amr_state |= AMR_STATE_SHUTDOWN; - - /* flush controller */ - device_printf(sc->amr_dev, "flushing cache..."); - printf("%s\n", amr_flush(sc) ? "failed" : "done"); - - error = 0; - - /* delete all our child devices */ - for(i = 0 ; i < AMR_MAXLD; i++) { - if( sc->amr_drive[i].al_disk != 0) { - if((error = device_delete_child(sc->amr_dev,sc->amr_drive[i].al_disk)) != 0) - goto shutdown_out; - sc->amr_drive[i].al_disk = 0; - } - } - - /* XXX disable interrupts? */ - -shutdown_out: - return(error); -} - -/******************************************************************************** - * Bring the controller to a quiescent state, ready for system suspend. - */ -static int -amr_pci_suspend(device_t dev) -{ - struct amr_softc *sc = device_get_softc(dev); - - debug_called(1); - - sc->amr_state |= AMR_STATE_SUSPEND; - - /* flush controller */ - device_printf(sc->amr_dev, "flushing cache..."); - printf("%s\n", amr_flush(sc) ? "failed" : "done"); - - /* XXX disable interrupts? */ - - return(0); -} - -/******************************************************************************** - * Bring the controller back to a state ready for operation. - */ -static int -amr_pci_resume(device_t dev) -{ - struct amr_softc *sc = device_get_softc(dev); - - debug_called(1); - - sc->amr_state &= ~AMR_STATE_SUSPEND; - - /* XXX enable interrupts? */ - - return(0); -} - -/******************************************************************************* - * Take an interrupt, or be poked by other code to look for interrupt-worthy - * status. - */ -static void -amr_pci_intr(void *arg) -{ - struct amr_softc *sc = (struct amr_softc *)arg; - - debug_called(3); - - /* collect finished commands, queue anything waiting */ - amr_done(sc); -} - -/******************************************************************************** - * Free all of the resources associated with (sc) - * - * Should not be called if the controller is active. - */ -static void -amr_pci_free(struct amr_softc *sc) -{ - void *p; - - debug_called(1); - - amr_free(sc); - - /* destroy data-transfer DMA tag */ - if (sc->amr_buffer_dmat) - bus_dma_tag_destroy(sc->amr_buffer_dmat); - if (sc->amr_buffer64_dmat) - bus_dma_tag_destroy(sc->amr_buffer64_dmat); - - /* free and destroy DMA memory and tag for passthrough pool */ - if (sc->amr_ccb) { - bus_dmamap_unload(sc->amr_ccb_dmat, sc->amr_ccb_dmamap); - bus_dmamem_free(sc->amr_ccb_dmat, sc->amr_ccb, sc->amr_ccb_dmamap); - } - if (sc->amr_ccb_dmat) - bus_dma_tag_destroy(sc->amr_ccb_dmat); - - /* free and destroy DMA memory and tag for s/g lists */ - if (sc->amr_sgtable) { - bus_dmamap_unload(sc->amr_sg_dmat, sc->amr_sg_dmamap); - bus_dmamem_free(sc->amr_sg_dmat, sc->amr_sgtable, sc->amr_sg_dmamap); - } - if (sc->amr_sg_dmat) - bus_dma_tag_destroy(sc->amr_sg_dmat); - - /* free and destroy DMA memory and tag for mailbox */ - p = (void *)(uintptr_t)(volatile void *)sc->amr_mailbox64; - if (sc->amr_mailbox) { - bus_dmamap_unload(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap); - bus_dmamem_free(sc->amr_mailbox_dmat, p, sc->amr_mailbox_dmamap); - } - if (sc->amr_mailbox_dmat) - bus_dma_tag_destroy(sc->amr_mailbox_dmat); - - /* disconnect the interrupt handler */ - if (sc->amr_intr) - bus_teardown_intr(sc->amr_dev, sc->amr_irq, sc->amr_intr); - if (sc->amr_irq != NULL) - bus_release_resource(sc->amr_dev, SYS_RES_IRQ, 0, sc->amr_irq); - - /* destroy the parent DMA tag */ - if (sc->amr_parent_dmat) - bus_dma_tag_destroy(sc->amr_parent_dmat); - - /* release the register window mapping */ - if (sc->amr_reg != NULL) - bus_release_resource(sc->amr_dev, - AMR_IS_QUARTZ(sc) ? SYS_RES_MEMORY : SYS_RES_IOPORT, - PCIR_BAR(0), sc->amr_reg); -} - -/******************************************************************************** - * Allocate and map the scatter/gather table in bus space. - */ -static void -amr_sglist_helper(void *arg, bus_dma_segment_t *segs, int nseg, int error) -{ - uint32_t *addr; - - debug_called(1); - - addr = arg; - *addr = segs[0].ds_addr; -} - -static int -amr_sglist_map(struct amr_softc *sc) -{ - size_t segsize; - void *p; - int error; - - debug_called(1); - - /* - * Create a single tag describing a region large enough to hold all of - * the s/g lists we will need. - * - * Note that we could probably use AMR_LIMITCMD here, but that may become - * tunable. - */ - if (AMR_IS_SG64(sc)) - segsize = sizeof(struct amr_sg64entry) * AMR_NSEG * AMR_MAXCMD; - else - segsize = sizeof(struct amr_sgentry) * AMR_NSEG * AMR_MAXCMD; - - error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ - 512, 0, /* alignment,boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - segsize, 1, /* maxsize, nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->amr_sg_dmat); - if (error != 0) { - device_printf(sc->amr_dev, "can't allocate scatter/gather DMA tag\n"); - return(ENOMEM); - } - - /* - * Allocate enough s/g maps for all commands and permanently map them into - * controller-visible space. - * - * XXX this assumes we can get enough space for all the s/g maps in one - * contiguous slab. We may need to switch to a more complex arrangement - * where we allocate in smaller chunks and keep a lookup table from slot - * to bus address. - * - * XXX HACK ALERT: at least some controllers don't like the s/g memory - * being allocated below 0x2000. We leak some memory if - * we get some below this mark and allocate again. We - * should be able to avoid this with the tag setup, but - * that does't seem to work. - */ -retry: - error = bus_dmamem_alloc(sc->amr_sg_dmat, (void **)&p, BUS_DMA_NOWAIT, &sc->amr_sg_dmamap); - if (error) { - device_printf(sc->amr_dev, "can't allocate s/g table\n"); - return(ENOMEM); - } - bus_dmamap_load(sc->amr_sg_dmat, sc->amr_sg_dmamap, p, segsize, amr_sglist_helper, &sc->amr_sgbusaddr, 0); - if (sc->amr_sgbusaddr < 0x2000) { - debug(1, "s/g table too low (0x%x), reallocating\n", sc->amr_sgbusaddr); - goto retry; - } - - if (AMR_IS_SG64(sc)) - sc->amr_sg64table = (struct amr_sg64entry *)p; - sc->amr_sgtable = (struct amr_sgentry *)p; - - return(0); -} - -/******************************************************************************** - * Allocate and set up mailbox areas for the controller (sc) - * - * The basic mailbox structure should be 16-byte aligned. - */ -static int -amr_setup_mbox(struct amr_softc *sc) -{ - int error; - void *p; - uint32_t baddr; - - debug_called(1); - - /* - * Create a single tag describing a region large enough to hold the entire - * mailbox. - */ - error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ - 16, 0, /* alignment,boundary */ - BUS_SPACE_MAXADDR_32BIT, /* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - sizeof(struct amr_mailbox64), /* maxsize */ - 1, /* nsegments */ - BUS_SPACE_MAXSIZE_32BIT, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->amr_mailbox_dmat); - if (error != 0) { - device_printf(sc->amr_dev, "can't allocate mailbox tag\n"); - return(ENOMEM); - } - - /* - * Allocate the mailbox structure and permanently map it into - * controller-visible space. - */ - error = bus_dmamem_alloc(sc->amr_mailbox_dmat, (void **)&p, BUS_DMA_NOWAIT, - &sc->amr_mailbox_dmamap); - if (error) { - device_printf(sc->amr_dev, "can't allocate mailbox memory\n"); - return(ENOMEM); - } - bus_dmamap_load(sc->amr_mailbox_dmat, sc->amr_mailbox_dmamap, p, - sizeof(struct amr_mailbox64), amr_sglist_helper, &baddr, 0); - /* - * Conventional mailbox is inside the mailbox64 region. - */ - /* save physical base of the basic mailbox structure */ - sc->amr_mailboxphys = baddr + offsetof(struct amr_mailbox64, mb); - bzero(p, sizeof(struct amr_mailbox64)); - sc->amr_mailbox64 = (struct amr_mailbox64 *)p; - sc->amr_mailbox = &sc->amr_mailbox64->mb; - - return(0); -} - -static int -amr_ccb_map(struct amr_softc *sc) -{ - int ccbsize, error; - - /* - * Passthrough and Extended passthrough structures will share the same - * memory. - */ - ccbsize = sizeof(union amr_ccb) * AMR_MAXCMD; - error = bus_dma_tag_create(sc->amr_parent_dmat, /* parent */ - 128, 0, /* alignment,boundary */ - BUS_SPACE_MAXADDR_32BIT,/* lowaddr */ - BUS_SPACE_MAXADDR, /* highaddr */ - NULL, NULL, /* filter, filterarg */ - ccbsize, /* maxsize */ - 1, /* nsegments */ - ccbsize, /* maxsegsize */ - 0, /* flags */ - NULL, NULL, /* lockfunc, lockarg */ - &sc->amr_ccb_dmat); - if (error != 0) { - device_printf(sc->amr_dev, "can't allocate ccb tag\n"); - return (ENOMEM); - } - - error = bus_dmamem_alloc(sc->amr_ccb_dmat, (void **)&sc->amr_ccb, - BUS_DMA_NOWAIT, &sc->amr_ccb_dmamap); - if (error) { - device_printf(sc->amr_dev, "can't allocate ccb memory\n"); - return (ENOMEM); - } - bus_dmamap_load(sc->amr_ccb_dmat, sc->amr_ccb_dmamap, sc->amr_ccb, - ccbsize, amr_sglist_helper, &sc->amr_ccb_busaddr, 0); - bzero(sc->amr_ccb, ccbsize); - - return (0); -} diff --git a/sys/dev/amr/amr_tables.h b/sys/dev/amr/amr_tables.h deleted file mode 100644 --- a/sys/dev/amr/amr_tables.h +++ /dev/null @@ -1,141 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-3-Clause - * - * Copyright (c) 2000 Michael Smith - * Copyright (c) 2000 BSDi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Copyright (c) 2002 Eric Moore - * Copyright (c) 2002 LSI Logic Corporation - * 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. - * 3. The party using or redistributing the source code and binary forms - * agrees to the disclaimer below and the terms and conditions set forth - * herein. - * - * 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$ - */ - -/* - * Lookup table for code-to-text translations. - */ -struct amr_code_lookup { - char *string; - u_int32_t code; -}; - -extern char *amr_describe_code(struct amr_code_lookup *table, u_int32_t code); - -#ifndef AMR_DEFINE_TABLES -extern struct amr_code_lookup amr_table_qinit[]; -extern struct amr_code_lookup amr_table_sinit[]; -extern struct amr_code_lookup amr_table_drvstate[]; - -#else /* AMR_DEFINE_TABLES */ - -/******************************************************************************** - * Look up a text description of a numeric code and return a pointer to same. - */ -char * -amr_describe_code(struct amr_code_lookup *table, u_int32_t code) -{ - int i; - - for (i = 0; table[i].string != NULL; i++) - if (table[i].code == code) - return(table[i].string); - return(table[i+1].string); -} - -struct amr_code_lookup amr_table_qinit[] = { - {"init scanning drives", AMR_QINIT_SCAN}, - {"init scanning initialising", AMR_QINIT_SCANINIT}, - {"init firmware initing", AMR_QINIT_FIRMWARE}, - {"init in progress", AMR_QINIT_INPROG}, - {"init spinning drives", AMR_QINIT_SPINUP}, - {"insufficient memory", AMR_QINIT_NOMEM}, - {"init flushing cache", AMR_QINIT_CACHEFLUSH}, - {"init successfully done", AMR_QINIT_DONE}, - {NULL, 0}, - {"unknown init code", 0} -}; - -struct amr_code_lookup amr_table_sinit[] = { - {"init abnormal terminated", AMR_SINIT_ABEND}, - {"insufficient memory", AMR_SINIT_NOMEM}, - {"firmware flushing cache", AMR_SINIT_CACHEFLUSH}, - {"init in progress", AMR_SINIT_INPROG}, - {"firmware spinning drives", AMR_SINIT_SPINUP}, - {"init successfully done", AMR_SINIT_DONE}, - {NULL, 0}, - {"unknown init code", 0} -}; - -struct amr_code_lookup amr_table_drvstate[] = { - {"offline", AMR_DRV_OFFLINE}, - {"degraded", AMR_DRV_DEGRADED}, - {"optimal", AMR_DRV_OPTIMAL}, - {"online", AMR_DRV_ONLINE}, - {"failed", AMR_DRV_FAILED}, - {"rebuild", AMR_DRV_REBUILD}, - {"hot spare", AMR_DRV_HOTSPARE}, - {NULL, 0}, - {"unknown", 0} -}; - -struct amr_code_lookup amr_table_adaptertype[] = { - {"Series 431", AMR_SIG_431}, - {"Series 438", AMR_SIG_438}, - {"Series 762", AMR_SIG_762}, - {"Integrated HP NetRAID (T5)", AMR_SIG_T5}, - {"Series 466", AMR_SIG_466}, - {"Series 467", AMR_SIG_467}, - {"Integrated HP NetRAID (T7)", AMR_SIG_T7}, - {"Series 490", AMR_SIG_490}, - {NULL, 0}, - {"unknown adapter", 0} -}; - -#endif diff --git a/sys/dev/amr/amrio.h b/sys/dev/amr/amrio.h deleted file mode 100644 --- a/sys/dev/amr/amrio.h +++ /dev/null @@ -1,124 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-3-Clause - * - * Copyright (c) 1999 Michael Smith - * 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. - * - * Copyright (c) 2002 Eric Moore - * Copyright (c) 2002 LSI Logic Corporation - * 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. - * 3. The party using or redistributing the source code and binary forms - * agrees to the disclaimer below and the terms and conditions set forth - * herein. - * - * 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$ - */ - -/* - * ioctl interface - */ - -#include -#include - -/* - * Fetch the driver's interface version. - */ -#define AMR_IO_VERSION_NUMBER 153 -#define AMR_IO_VERSION _IOR('A', 0x200, int) - -/* - * Pass a command from userspace through to the adapter. - * - * Note that in order to be code-compatible with the Linux - * interface where possible, the formatting of the au_cmd field is - * somewhat Interesting. - * - * For normal commands, the layout is (fields from struct amr_mailbox_ioctl): - * - * 0 mb_command - * 1 mb_channel - * 2 mb_param - * 3 mb_pad[0] - * 4 mb_drive - * - * For SCSI passthrough commands, the layout is: - * - * 0 AMR_CMD_PASS (0x3) - * 1 reserved, 0 - * 2 cdb length - * 3 cdb data - * 3+cdb_len passthrough control byte (timeout, ars, islogical) - * 4+cdb_len reserved, 0 - * 5+cdb_len channel - * 6+cdb_len target - */ - -struct amr_user_ioctl { - unsigned char au_cmd[32]; /* command text from userspace */ - void *au_buffer; /* data buffer in userspace */ - unsigned long au_length; /* data buffer size (0 == no data) */ - int au_direction; /* data transfer direction */ -#define AMR_IO_NODATA 0 -#define AMR_IO_READ 1 -#define AMR_IO_WRITE 2 - int au_status; /* command status returned by adapter */ -}; - -#define AMR_IO_COMMAND _IOWR('A', 0x201, struct amr_user_ioctl) - -#if defined(__amd64__) - -struct amr_user_ioctl32 { - unsigned char au_cmd[32]; /* command text from userspace */ - u_int32_t au_buffer; /* 32-bit pointer to uspace buf */ - u_int32_t au_length; /* length of the uspace buffer */ - int32_t au_direction; /* data transfer direction */ - int32_t au_status; /* command status returned by adapter */ -}; - -# define AMR_IO_COMMAND32 _IOWR('A', 0x201, struct amr_user_ioctl32) -#endif diff --git a/sys/dev/amr/amrreg.h b/sys/dev/amr/amrreg.h deleted file mode 100644 --- a/sys/dev/amr/amrreg.h +++ /dev/null @@ -1,657 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-3-Clause - * - * Copyright (c) 1999,2000 Michael Smith - * Copyright (c) 2000 BSDi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Copyright (c) 2002 Eric Moore - * Copyright (c) 2002 LSI Logic Corporation - * 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. - * 3. The party using or redistributing the source code and binary forms - * agrees to the disclaimer below and the terms and conditions set forth - * herein. - * - * 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$ - */ - -/******************************************************************************** - ******************************************************************************** - Driver parameters - ******************************************************************************** - ********************************************************************************/ - -/* - * We could actually use all 17 segments, but using only 16 means that - * each scatter/gather map is 128 bytes in size, and thus we don't have to worry about - * maps crossing page boundaries. - * - * The AMI documentation says that the limit is 26. Unfortunately, there's no way to - * cleanly fit more than 16 entries in without a page boundary. But is this a concern, - * since we allocate the s/g maps contiguously anyway? - */ -/* - * emoore - Oct 21, 2002 - * firmware doesn't have sglist boundary restrictions. - * The sgelem can be set to 26 - */ -#define AMR_NSEG 26 - -#define AMR_MAXCMD 255 /* ident = 0 not allowed */ -#define AMR_LIMITCMD 120 /* maximum count of outstanding commands */ -#define AMR_MAXLD 40 - -#define AMR_MAX_CHANNELS 8 -#define AMR_MAX_TARGETS 15 -#define AMR_MAX_LUNS 7 -#define AMR_MAX_SCSI_CMDS (15 * AMR_MAX_CHANNELS) /* one for every target? */ - -#define AMR_MAX_CDB_LEN 0x0a -#define AMR_MAX_EXTCDB_LEN 0x10 -#define AMR_MAX_REQ_SENSE_LEN 0x20 - -#define AMR_BLKSIZE 512 /* constant for all controllers */ - -/* - * Perform at-startup board initialisation. - * At this point in time, this code doesn't work correctly, so leave it disabled. - */ -/*#define AMR_BOARD_INIT*/ - -/******************************************************************************** - ******************************************************************************** - Interface Magic Numbers - ******************************************************************************** - ********************************************************************************/ - -/* - * Mailbox commands - */ -#define AMR_CMD_LREAD 0x01 -#define AMR_CMD_LWRITE 0x02 -#define AMR_CMD_PASS 0x03 -#define AMR_CMD_EXT_ENQUIRY 0x04 -#define AMR_CMD_ENQUIRY 0x05 -#define AMR_CMD_FLUSH 0x0a -#define AMR_CMD_EXT_ENQUIRY2 0x0c -#define AMR_CONFIG_PRODINFO 0x0e -#define AMR_CMD_GET_MACHINEID 0x36 -#define AMR_CMD_GET_INITIATOR 0x7d /* returns one byte */ -#define AMR_CMD_CONFIG 0xa1 -#define AMR_CMD_LREAD64 0xa7 -#define AMR_CMD_LWRITE64 0xa8 -#define AMR_CMD_PASS_64 0xc3 -#define AMR_CMD_EXTPASS 0xe3 - -#define AMR_CONFIG_READ_NVRAM_CONFIG 0x04 -#define AMR_CONFIG_WRITE_NVRAM_CONFIG 0x0d -#define AMR_CONFIG_PRODUCT_INFO 0x0e -#define AMR_CONFIG_ENQ3 0x0f -#define AMR_CONFIG_ENQ3_SOLICITED_NOTIFY 0x01 -#define AMR_CONFIG_ENQ3_SOLICITED_FULL 0x02 -#define AMR_CONFIG_ENQ3_UNSOLICITED 0x03 - -/* - * Command for random deletion of logical drives - */ -#define FC_DEL_LOGDRV 0xA4 -#define OP_SUP_DEL_LOGDRV 0x2A -#define OP_GET_LDID_MAP 0x18 -#define OP_DEL_LOGDRV 0x1C - -/* - * Command for random deletion of logical drives - */ -#define FC_DEL_LOGDRV 0xA4 -#define OP_SUP_DEL_LOGDRV 0x2A -#define OP_GET_LDID_MAP 0x18 -#define OP_DEL_LOGDRV 0x1C - -/* - * Command results - */ -#define AMR_STATUS_SUCCESS 0x00 -#define AMR_STATUS_ABORTED 0x02 -#define AMR_STATUS_FAILED 0x80 - -/* - * Physical/logical drive states - */ -#define AMR_DRV_CURSTATE(x) ((x) & 0x0f) -#define AMR_DRV_PREVSTATE(x) (((x) >> 4) & 0x0f) -#define AMR_DRV_OFFLINE 0x00 -#define AMR_DRV_DEGRADED 0x01 -#define AMR_DRV_OPTIMAL 0x02 -#define AMR_DRV_ONLINE 0x03 -#define AMR_DRV_FAILED 0x04 -#define AMR_DRV_REBUILD 0x05 -#define AMR_DRV_HOTSPARE 0x06 - -/* - * Logical drive properties - */ -#define AMR_DRV_RAID_MASK 0x0f /* RAID level 0, 1, 3, 5, etc. */ -#define AMR_DRV_WRITEBACK 0x10 /* write-back enabled */ -#define AMR_DRV_READHEAD 0x20 /* readhead policy enabled */ -#define AMR_DRV_ADAPTIVE 0x40 /* adaptive I/O policy enabled */ - -/* - * Battery status - */ -#define AMR_BATT_MODULE_MISSING 0x01 -#define AMR_BATT_LOW_VOLTAGE 0x02 -#define AMR_BATT_TEMP_HIGH 0x04 -#define AMR_BATT_PACK_MISSING 0x08 -#define AMR_BATT_CHARGE_MASK 0x30 -#define AMR_BATT_CHARGE_DONE 0x00 -#define AMR_BATT_CHARGE_INPROG 0x10 -#define AMR_BATT_CHARGE_FAIL 0x20 -#define AMR_BATT_CYCLES_EXCEEDED 0x40 - -/******************************************************************************** - ******************************************************************************** - 8LD Firmware Interface - ******************************************************************************** - ********************************************************************************/ - -/* - * Array constraints - */ -#define AMR_8LD_MAXDRIVES 8 -#define AMR_8LD_MAXCHAN 5 -#define AMR_8LD_MAXTARG 15 -#define AMR_8LD_MAXPHYSDRIVES (AMR_8LD_MAXCHAN * AMR_8LD_MAXTARG) - -/* - * Adapter Info structure - */ -struct amr_adapter_info -{ - u_int8_t aa_maxio; - u_int8_t aa_rebuild_rate; - u_int8_t aa_maxtargchan; - u_int8_t aa_channels; - u_int8_t aa_firmware[4]; - u_int16_t aa_flashage; - u_int8_t aa_chipsetvalue; - u_int8_t aa_memorysize; - u_int8_t aa_cacheflush; - u_int8_t aa_bios[4]; - u_int8_t aa_boardtype; - u_int8_t aa_scsisensealert; - u_int8_t aa_writeconfigcount; - u_int8_t aa_driveinsertioncount; - u_int8_t aa_inserteddrive; - u_int8_t aa_batterystatus; - u_int8_t res1; -} __packed; - -/* - * Logical Drive info structure - */ -struct amr_logdrive_info -{ - u_int8_t al_numdrives; - u_int8_t res1[3]; - u_int32_t al_size[AMR_8LD_MAXDRIVES]; - u_int8_t al_properties[AMR_8LD_MAXDRIVES]; - u_int8_t al_state[AMR_8LD_MAXDRIVES]; -} __packed; - -/* - * Physical Drive info structure - */ -struct amr_physdrive_info -{ - u_int8_t ap_state[AMR_8LD_MAXPHYSDRIVES]; /* low nibble current state, high nibble previous state */ - u_int8_t ap_predictivefailure; -} __packed; - -/* - * Enquiry response structure for AMR_CMD_ENQUIRY, AMR_CMD_EXT_ENQUIRY and - * AMR_CMD_EXT_ENQUIRY2. - * ENQUIRY EXT_ENQUIRY EXT_ENQUIRY2 - */ -struct amr_enquiry -{ - struct amr_adapter_info ae_adapter; /* X X X */ - struct amr_logdrive_info ae_ldrv; /* X X X */ - struct amr_physdrive_info ae_pdrv; /* X X X */ - u_int8_t ae_formatting[AMR_8LD_MAXDRIVES];/* X X */ - u_int8_t res1[AMR_8LD_MAXDRIVES]; /* X X */ - u_int32_t ae_extlen; /* X */ - u_int16_t ae_subsystem; /* X */ - u_int16_t ae_subvendor; /* X */ - u_int32_t ae_signature; /* X */ -#define AMR_SIG_431 0xfffe0001 -#define AMR_SIG_438 0xfffd0002 -#define AMR_SIG_762 0xfffc0003 -#define AMR_SIG_T5 0xfffb0004 -#define AMR_SIG_466 0xfffa0005 -#define AMR_SIG_467 0xfff90006 -#define AMR_SIG_T7 0xfff80007 -#define AMR_SIG_490 0xfff70008 - u_int8_t res2[844]; /* X */ -} __packed; - -/******************************************************************************** - ******************************************************************************** - 40LD Firmware Interface - ******************************************************************************** - ********************************************************************************/ - -/* - * Array constraints - */ -#define AMR_40LD_MAXDRIVES 40 -#define AMR_40LD_MAXCHAN 16 -#define AMR_40LD_MAXTARG 16 -#define AMR_40LD_MAXPHYSDRIVES 256 - -/* - * Product Info structure - */ -struct amr_prodinfo -{ - u_int32_t ap_size; /* current size in bytes (not including resvd) */ - u_int32_t ap_configsig; /* default is 0x00282008, indicating 0x28 maximum - * logical drives, 0x20 maximum stripes and 0x08 - * maximum spans */ - u_int8_t ap_firmware[16]; /* printable identifiers */ - u_int8_t ap_bios[16]; - u_int8_t ap_product[80]; - u_int8_t ap_maxio; /* maximum number of concurrent commands supported */ - u_int8_t ap_nschan; /* number of SCSI channels present */ - u_int8_t ap_fcloops; /* number of fibre loops present */ - u_int8_t ap_memtype; /* memory type */ - u_int32_t ap_signature; - u_int16_t ap_memsize; /* onboard memory in MB */ - u_int16_t ap_subsystem; /* subsystem identifier */ - u_int16_t ap_subvendor; /* subsystem vendor ID */ - u_int8_t ap_numnotifyctr; /* number of notify counters */ -} __packed; - -/* - * Notify structure - */ -struct amr_notify -{ - u_int32_t an_globalcounter; /* change counter */ - - u_int8_t an_paramcounter; /* parameter change counter */ - u_int8_t an_paramid; -#define AMR_PARAM_REBUILD_RATE 0x01 /* value = new rebuild rate */ -#define AMR_PARAM_FLUSH_INTERVAL 0x02 /* value = new flush interval */ -#define AMR_PARAM_SENSE_ALERT 0x03 /* value = last physical drive with check condition set */ -#define AMR_PARAM_DRIVE_INSERTED 0x04 /* value = last physical drive inserted */ -#define AMR_PARAM_BATTERY_STATUS 0x05 /* value = battery status */ - u_int16_t an_paramval; - - u_int8_t an_writeconfigcounter; /* write config occurred */ - u_int8_t res1[3]; - - u_int8_t an_ldrvopcounter; /* logical drive operation started/completed */ - u_int8_t an_ldrvopid; - u_int8_t an_ldrvopcmd; -#define AMR_LDRVOP_CHECK 0x01 -#define AMR_LDRVOP_INIT 0x02 -#define AMR_LDRVOP_REBUILD 0x03 - u_int8_t an_ldrvopstatus; -#define AMR_LDRVOP_SUCCESS 0x00 -#define AMR_LDRVOP_FAILED 0x01 -#define AMR_LDRVOP_ABORTED 0x02 -#define AMR_LDRVOP_CORRECTED 0x03 -#define AMR_LDRVOP_STARTED 0x04 - - u_int8_t an_ldrvstatecounter; /* logical drive state change occurred */ - u_int8_t an_ldrvstateid; - u_int8_t an_ldrvstatenew; - u_int8_t an_ldrvstateold; - - u_int8_t an_pdrvstatecounter; /* physical drive state change occurred */ - u_int8_t an_pdrvstateid; - u_int8_t an_pdrvstatenew; - u_int8_t an_pdrvstateold; - - u_int8_t an_pdrvfmtcounter; - u_int8_t an_pdrvfmtid; - u_int8_t an_pdrvfmtval; -#define AMR_FORMAT_START 0x01 -#define AMR_FORMAT_COMPLETE 0x02 - u_int8_t res2; - - u_int8_t an_targxfercounter; /* scsi xfer rate change */ - u_int8_t an_targxferid; - u_int8_t an_targxferval; - u_int8_t res3; - - u_int8_t an_fcloopidcounter; /* FC/AL loop ID changed */ - u_int8_t an_fcloopidpdrvid; - u_int8_t an_fcloopid0; - u_int8_t an_fcloopid1; - - u_int8_t an_fcloopstatecounter; /* FC/AL loop status changed */ - u_int8_t an_fcloopstate0; - u_int8_t an_fcloopstate1; - u_int8_t res4; -} __packed; - -/* - * Enquiry3 structure - */ -struct amr_enquiry3 -{ - u_int32_t ae_datasize; /* valid data size in this structure */ - union { /* event notify structure */ - struct amr_notify n; - u_int8_t pad[0x80]; - } ae_notify; - u_int8_t ae_rebuildrate; /* current rebuild rate in % */ - u_int8_t ae_cacheflush; /* flush interval in seconds */ - u_int8_t ae_sensealert; - u_int8_t ae_driveinsertcount; /* count of inserted drives */ - u_int8_t ae_batterystatus; - u_int8_t ae_numldrives; - u_int8_t ae_reconstate[AMR_40LD_MAXDRIVES / 8]; /* reconstruction state */ - u_int16_t ae_opstatus[AMR_40LD_MAXDRIVES / 8]; /* operation status per drive */ - u_int32_t ae_drivesize[AMR_40LD_MAXDRIVES]; /* logical drive size */ - u_int8_t ae_driveprop[AMR_40LD_MAXDRIVES]; /* logical drive properties */ - u_int8_t ae_drivestate[AMR_40LD_MAXDRIVES]; /* logical drive state */ - u_int8_t ae_pdrivestate[AMR_40LD_MAXPHYSDRIVES]; /* physical drive state */ - u_int16_t ae_pdriveformat[AMR_40LD_MAXPHYSDRIVES / 16]; - u_int8_t ae_targxfer[80]; /* physical drive transfer rates */ - - u_int8_t res1[263]; /* pad to 1024 bytes */ -} __packed; - -/******************************************************************************** - ******************************************************************************** - Mailbox and Command Structures - ******************************************************************************** - ********************************************************************************/ - -#define AMR_MBOX_CMDSIZE 0x10 /* portion worth copying for controller */ - -struct amr_mailbox -{ - u_int8_t mb_command; - u_int8_t mb_ident; - u_int16_t mb_blkcount; /* u_int8_t opcode */ - /* u_int8_t subopcode */ - u_int32_t mb_lba; - u_int32_t mb_physaddr; - u_int8_t mb_drive; - u_int8_t mb_nsgelem; /* u_int8_t rserv[0] */ - u_int8_t res1; /* u_int8_t rserv[1] */ - u_int8_t mb_busy; /* u_int8_t rserv[2] */ - u_int8_t mb_nstatus; - u_int8_t mb_status; - u_int8_t mb_completed[46]; - u_int8_t mb_poll; - u_int8_t mb_ack; - u_int8_t res2[16]; -} __packed; - -struct amr_mailbox64 -{ - u_int8_t pad[8]; /* Needed for alignment */ - u_int32_t sg64_lo; /* S/G pointer for 64-bit commands */ - u_int32_t sg64_hi; /* S/G pointer for 64-bit commands */ - struct amr_mailbox mb; -} __packed; - -struct amr_mailbox_ioctl -{ - u_int8_t mb_command; - u_int8_t mb_ident; - u_int8_t mb_channel; - u_int8_t mb_param; - u_int8_t mb_pad[4]; - u_int32_t mb_physaddr; - u_int8_t mb_drive; - u_int8_t mb_nsgelem; - u_int8_t res1; - u_int8_t mb_busy; - u_int8_t mb_nstatus; - u_int8_t mb_completed[46]; - u_int8_t mb_poll; - u_int8_t mb_ack; - u_int8_t res4[16]; -} __packed; - -struct amr_sgentry -{ - u_int32_t sg_addr; - u_int32_t sg_count; -} __packed; - -struct amr_sg64entry -{ - u_int64_t sg_addr; - u_int32_t sg_count; -} __packed; - -struct amr_passthrough -{ - u_int8_t ap_timeout:3; - u_int8_t ap_ars:1; - u_int8_t ap_dummy:3; - u_int8_t ap_islogical:1; - u_int8_t ap_logical_drive_no; - u_int8_t ap_channel; - u_int8_t ap_scsi_id; - u_int8_t ap_queue_tag; - u_int8_t ap_queue_action; - u_int8_t ap_cdb[AMR_MAX_CDB_LEN]; - u_int8_t ap_cdb_length; - u_int8_t ap_request_sense_length; - u_int8_t ap_request_sense_area[AMR_MAX_REQ_SENSE_LEN]; - u_int8_t ap_no_sg_elements; - u_int8_t ap_scsi_status; - u_int32_t ap_data_transfer_address; - u_int32_t ap_data_transfer_length; -} __packed; - -struct amr_ext_passthrough -{ - u_int8_t ap_timeout:3; - u_int8_t ap_ars:1; - u_int8_t ap_rsvd1:1; - u_int8_t ap_cd_rom:1; - u_int8_t ap_rsvd2:1; - u_int8_t ap_islogical:1; - u_int8_t ap_logical_drive_no; - u_int8_t ap_channel; - u_int8_t ap_scsi_id; - u_int8_t ap_queue_tag; - u_int8_t ap_queue_action; - u_int8_t ap_cdb_length; - u_int8_t ap_rsvd3; - u_int8_t ap_cdb[AMR_MAX_EXTCDB_LEN]; - u_int8_t ap_no_sg_elements; - u_int8_t ap_scsi_status; - u_int8_t ap_request_sense_length; - u_int8_t ap_request_sense_area[AMR_MAX_REQ_SENSE_LEN]; - u_int8_t ap_rsvd4; - u_int32_t ap_data_transfer_address; - u_int32_t ap_data_transfer_length; -} __packed; - -struct amr_linux_ioctl { - u_int32_t inlen; - u_int32_t outlen; - union { - u_int8_t fca[16]; - struct { - u_int8_t opcode; - u_int8_t subopcode; - u_int16_t adapno; - u_int32_t buffer; - u_int8_t pad[4]; - u_int32_t length; - } __packed fcs; - } __packed ui; - u_int8_t mbox[18]; - struct amr_passthrough pthru; - u_int32_t data; - u_int8_t pad[4]; -} __packed; - -#ifdef _KERNEL -/******************************************************************************** - ******************************************************************************** - "Quartz" i960 PCI bridge interface - ******************************************************************************** - ********************************************************************************/ - -#define AMR_CFG_SIG 0xa0 /* PCI config register for signature */ -#define AMR_SIGNATURE_1 0xCCCC /* i960 signature (older adapters) */ -#define AMR_SIGNATURE_2 0x3344 /* i960 signature (newer adapters) */ - -/* - * Doorbell registers - */ -#define AMR_QIDB 0x20 -#define AMR_QODB 0x2c -#define AMR_QIDB_SUBMIT 0x00000001 /* mailbox ready for work */ -#define AMR_QIDB_ACK 0x00000002 /* mailbox done */ -#define AMR_QODB_READY 0x10001234 /* work ready to be processed */ - -/* - * Initialisation status - */ -#define AMR_QINIT_SCAN 0x01 /* init scanning drives */ -#define AMR_QINIT_SCANINIT 0x02 /* init scanning initialising */ -#define AMR_QINIT_FIRMWARE 0x03 /* init firmware initing */ -#define AMR_QINIT_INPROG 0xdc /* init in progress */ -#define AMR_QINIT_SPINUP 0x2c /* init spinning drives */ -#define AMR_QINIT_NOMEM 0xac /* insufficient memory */ -#define AMR_QINIT_CACHEFLUSH 0xbc /* init flushing cache */ -#define AMR_QINIT_DONE 0x9c /* init successfully done */ - -/* - * I/O primitives - */ -#define AMR_QPUT_IDB(sc, val) bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QIDB, val) -#define AMR_QGET_IDB(sc) bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QIDB) -#define AMR_QPUT_ODB(sc, val) bus_space_write_4(sc->amr_btag, sc->amr_bhandle, AMR_QODB, val) -#define AMR_QGET_ODB(sc) bus_space_read_4 (sc->amr_btag, sc->amr_bhandle, AMR_QODB) - -#ifdef AMR_BOARD_INIT -#define AMR_QRESET(sc) \ - do { \ - pci_write_config((sc)->amr_dev, 0x40, pci_read_config((sc)->amr_dev, 0x40, 1) | 0x20, 1); \ - pci_write_config((sc)->amr_dev, 0x64, 0x1122, 1); \ - } while (0) -#define AMR_QGET_INITSTATUS(sc) pci_read_config((sc)->amr_dev, 0x9c, 1) -#define AMR_QGET_INITCHAN(sc) pci_read_config((sc)->amr_dev, 0x9f, 1) -#define AMR_QGET_INITTARG(sc) pci_read_config((sc)->amr_dev, 0x9e, 1) -#endif - -/******************************************************************************** - ******************************************************************************** - "Standard" old-style ASIC bridge interface - ******************************************************************************** - ********************************************************************************/ - -/* - * I/O registers - */ -#define AMR_SCMD 0x10 /* command/ack register (write) */ -#define AMR_SMBOX_BUSY 0x10 /* mailbox status (read) */ -#define AMR_STOGGLE 0x11 /* interrupt enable bit here */ -#define AMR_SMBOX_0 0x14 /* mailbox physical address low byte */ -#define AMR_SMBOX_1 0x15 -#define AMR_SMBOX_2 0x16 -#define AMR_SMBOX_3 0x17 /* high byte */ -#define AMR_SMBOX_ENABLE 0x18 /* atomic mailbox address enable */ -#define AMR_SINTR 0x1a /* interrupt status */ - -/* - * I/O magic numbers - */ -#define AMR_SCMD_POST 0x10 /* -> SCMD to initiate action on mailbox */ -#define AMR_SCMD_ACKINTR 0x08 /* -> SCMD to ack mailbox retrieved */ -#define AMR_STOGL_IENABLE 0xc0 /* in STOGGLE */ -#define AMR_SINTR_VALID 0x40 /* in SINTR */ -#define AMR_SMBOX_BUSYFLAG 0x10 /* in SMBOX_BUSY */ -#define AMR_SMBOX_ADDR 0x00 /* -> SMBOX_ENABLE */ - -/* - * Initialisation status - */ -#define AMR_SINIT_ABEND 0xee /* init abnormal terminated */ -#define AMR_SINIT_NOMEM 0xca /* insufficient memory */ -#define AMR_SINIT_CACHEFLUSH 0xbb /* firmware flushing cache */ -#define AMR_SINIT_INPROG 0x11 /* init in progress */ -#define AMR_SINIT_SPINUP 0x22 /* firmware spinning drives */ -#define AMR_SINIT_DONE 0x99 /* init successfully done */ - -/* - * I/O primitives - */ -#define AMR_SPUT_ISTAT(sc, val) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SINTR, val) -#define AMR_SGET_ISTAT(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SINTR) -#define AMR_SACK_INTERRUPT(sc) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_ACKINTR) -#define AMR_SPOST_COMMAND(sc) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_SCMD, AMR_SCMD_POST) -#define AMR_SGET_MBSTAT(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_BUSY) -#define AMR_SENABLE_INTR(sc) \ - bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, \ - bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) | AMR_STOGL_IENABLE) -#define AMR_SDISABLE_INTR(sc) \ - bus_space_write_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE, \ - bus_space_read_1(sc->amr_btag, sc->amr_bhandle, AMR_STOGGLE) & ~AMR_STOGL_IENABLE) -#define AMR_SBYTE_SET(sc, reg, val) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, reg, val) - -#ifdef AMR_BOARD_INIT -#define AMR_SRESET(sc) bus_space_write_1(sc->amr_btag, sc->amr_bhandle, 0, 0x80) -#define AMR_SGET_INITSTATUS(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_ENABLE) -#define AMR_SGET_FAILDRIVE(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_ENABLE + 1) -#define AMR_SGET_INITCHAN(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_ENABLE + 2) -#define AMR_SGET_INITTARG(sc) bus_space_read_1 (sc->amr_btag, sc->amr_bhandle, AMR_SMBOX_ENABLE + 3) -#endif - -#endif /* _KERNEL */ diff --git a/sys/dev/amr/amrvar.h b/sys/dev/amr/amrvar.h deleted file mode 100644 --- a/sys/dev/amr/amrvar.h +++ /dev/null @@ -1,384 +0,0 @@ -/*- - * SPDX-License-Identifier: BSD-2-Clause-FreeBSD AND BSD-3-Clause - * - * Copyright (c) 1999,2000 Michael Smith - * Copyright (c) 2000 BSDi - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * Copyright (c) 2002 Eric Moore - * Copyright (c) 2002 LSI Logic Corporation - * 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. - * 3. The party using or redistributing the source code and binary forms - * agrees to the disclaimer below and the terms and conditions set forth - * herein. - * - * 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$ - */ - -#include -#include -#include - -#define LSI_DESC_PCI "LSILogic MegaRAID 1.53" - -#ifdef AMR_DEBUG -# define debug(level, fmt, args...) do {if (level <= AMR_DEBUG) printf("%s: " fmt "\n", __func__ , ##args);} while(0) -# define debug_called(level) do {if (level <= AMR_DEBUG) printf("%s: called\n", __func__);} while(0) -#else -# define debug(level, fmt, args...) do {} while (0) -# define debug_called(level) do {} while (0) -#endif -#define xdebug(fmt, args...) printf("%s: " fmt "\n", __func__ , ##args) - -/* - * Per-logical-drive datastructure - */ -struct amr_logdrive -{ - u_int32_t al_size; - int al_state; - int al_properties; - - /* synthetic geometry */ - int al_cylinders; - int al_heads; - int al_sectors; - - /* driver */ - device_t al_disk; -}; - -/* - * Due to the difficulty of using the zone allocator to create a new - * zone from within a module, we use our own clustering to reduce - * memory wastage due to allocating lots of these small structures. - * - * 16k gives us a little under 200 command structures, which should - * normally be plenty. We will grab more if we need them. - */ - -#define AMR_CMD_CLUSTERSIZE (16 * 1024) - -typedef STAILQ_HEAD(, amr_command) ac_qhead_t; -typedef STAILQ_ENTRY(amr_command) ac_link_t; - -union amr_ccb { - struct amr_passthrough ccb_pthru; - struct amr_ext_passthrough ccb_epthru; - uint8_t bytes[128]; -}; - -/* - * Per-command control structure. - */ -struct amr_command -{ - ac_link_t ac_link; - - struct amr_softc *ac_sc; - u_int8_t ac_slot; - int ac_status; /* command completion status */ - union { - struct amr_sgentry *sg32; - struct amr_sg64entry *sg64; - } ac_sg; - u_int32_t ac_sgbusaddr; - u_int32_t ac_sg64_lo; - u_int32_t ac_sg64_hi; - struct amr_mailbox ac_mailbox; - int ac_flags; -#define AMR_CMD_DATAIN (1<<0) -#define AMR_CMD_DATAOUT (1<<1) -#define AMR_CMD_CCB (1<<2) -#define AMR_CMD_PRIORITY (1<<4) -#define AMR_CMD_MAPPED (1<<5) -#define AMR_CMD_SLEEP (1<<6) -#define AMR_CMD_BUSY (1<<7) -#define AMR_CMD_SG64 (1<<8) -#define AC_IS_SG64(ac) ((ac)->ac_flags & AMR_CMD_SG64) - u_int ac_retries; - - struct bio *ac_bio; - void (* ac_complete)(struct amr_command *ac); - void *ac_private; - - void *ac_data; - size_t ac_length; - bus_dmamap_t ac_dmamap; - bus_dmamap_t ac_dma64map; - - bus_dma_tag_t ac_tag; - bus_dmamap_t ac_datamap; - int ac_nsegments; - uint32_t ac_mb_physaddr; - - union amr_ccb *ac_ccb; - uint32_t ac_ccb_busaddr; -}; - -struct amr_command_cluster -{ - TAILQ_ENTRY(amr_command_cluster) acc_link; - struct amr_command acc_command[0]; -}; - -#define AMR_CMD_CLUSTERCOUNT ((AMR_CMD_CLUSTERSIZE - sizeof(struct amr_command_cluster)) / \ - sizeof(struct amr_command)) - -/* - * Per-controller-instance data - */ -struct amr_softc -{ - /* bus attachments */ - device_t amr_dev; - struct resource *amr_reg; /* control registers */ - bus_space_handle_t amr_bhandle; - bus_space_tag_t amr_btag; - bus_dma_tag_t amr_parent_dmat; /* parent DMA tag */ - bus_dma_tag_t amr_buffer_dmat; /* data buffer DMA tag */ - bus_dma_tag_t amr_buffer64_dmat; - struct resource *amr_irq; /* interrupt */ - void *amr_intr; - - /* mailbox */ - volatile struct amr_mailbox *amr_mailbox; - volatile struct amr_mailbox64 *amr_mailbox64; - u_int32_t amr_mailboxphys; - bus_dma_tag_t amr_mailbox_dmat; - bus_dmamap_t amr_mailbox_dmamap; - - /* scatter/gather lists and their controller-visible mappings */ - struct amr_sgentry *amr_sgtable; /* s/g lists */ - struct amr_sg64entry *amr_sg64table; /* 64bit s/g lists */ - u_int32_t amr_sgbusaddr; /* s/g table base address in bus space */ - bus_dma_tag_t amr_sg_dmat; /* s/g buffer DMA tag */ - bus_dmamap_t amr_sg_dmamap; /* map for s/g buffers */ - - union amr_ccb *amr_ccb; - uint32_t amr_ccb_busaddr; - bus_dma_tag_t amr_ccb_dmat; - bus_dmamap_t amr_ccb_dmamap; - - /* controller limits and features */ - int amr_nextslot; /* Next slot to use for newly allocated commands */ - int amr_maxio; /* maximum number of I/O transactions */ - int amr_maxdrives; /* max number of logical drives */ - int amr_maxchan; /* count of SCSI channels */ - - /* connected logical drives */ - struct amr_logdrive amr_drive[AMR_MAXLD]; - - /* controller state */ - int amr_state; -#define AMR_STATE_OPEN (1<<0) -#define AMR_STATE_SUSPEND (1<<1) -#define AMR_STATE_INTEN (1<<2) -#define AMR_STATE_SHUTDOWN (1<<3) -#define AMR_STATE_CRASHDUMP (1<<4) -#define AMR_STATE_QUEUE_FRZN (1<<5) -#define AMR_STATE_LD_DELETE (1<<6) -#define AMR_STATE_REMAP_LD (1<<7) - - /* per-controller queues */ - struct bio_queue_head amr_bioq; /* pending I/O with no commands */ - ac_qhead_t amr_ready; /* commands ready to be submitted */ - struct amr_command *amr_busycmd[AMR_MAXCMD]; - int amr_busyslots; - ac_qhead_t amr_freecmds; - TAILQ_HEAD(,amr_command_cluster) amr_cmd_clusters; - - /* CAM attachments for passthrough */ - struct cam_sim *amr_cam_sim[AMR_MAX_CHANNELS]; - TAILQ_HEAD(, ccb_hdr) amr_cam_ccbq; - struct cam_devq *amr_cam_devq; - - /* control device */ - struct cdev *amr_dev_t; - struct mtx amr_list_lock; - - /* controller type-specific support */ - int amr_type; -#define AMR_TYPE_QUARTZ (1<<0) -#define AMR_IS_QUARTZ(sc) ((sc)->amr_type & AMR_TYPE_QUARTZ) -#define AMR_TYPE_40LD (1<<1) -#define AMR_IS_40LD(sc) ((sc)->amr_type & AMR_TYPE_40LD) -#define AMR_TYPE_SG64 (1<<2) -#define AMR_IS_SG64(sc) ((sc)->amr_type & AMR_TYPE_SG64) - int (* amr_submit_command)(struct amr_command *ac); - int (* amr_get_work)(struct amr_softc *sc, struct amr_mailbox *mbsave); - int (*amr_poll_command)(struct amr_command *ac); - int (*amr_poll_command1)(struct amr_softc *sc, struct amr_command *ac); - int support_ext_cdb; /* greater than 10 byte cdb support */ - - /* misc glue */ - device_t amr_pass; - int (*amr_cam_command)(struct amr_softc *sc, struct amr_command **acp); - struct intr_config_hook amr_ich; /* wait-for-interrupts probe hook */ - int amr_allow_vol_config; - int amr_linux_no_adapters; - int amr_ld_del_supported; - struct mtx amr_hw_lock; -}; - -/* - * Interface between bus connections and driver core. - */ -extern int amr_attach(struct amr_softc *sc); -extern void amr_free(struct amr_softc *sc); -extern int amr_flush(struct amr_softc *sc); -extern int amr_done(struct amr_softc *sc); -extern void amr_startio(struct amr_softc *sc); - -/* - * Command buffer allocation. - */ -extern struct amr_command *amr_alloccmd(struct amr_softc *sc); -extern void amr_releasecmd(struct amr_command *ac); - -/* - * MegaRAID logical disk driver - */ -struct amrd_softc -{ - device_t amrd_dev; - struct amr_softc *amrd_controller; - struct amr_logdrive *amrd_drive; - struct disk *amrd_disk; - int amrd_unit; -}; - -/* - * Interface between driver core and disk driver (should be using a bus?) - */ -extern int amr_submit_bio(struct amr_softc *sc, struct bio *bio); -extern int amr_dump_blocks(struct amr_softc *sc, int unit, u_int32_t lba, void *data, int blks); -extern void amrd_intr(void *data); - -/******************************************************************************** - * Enqueue/dequeue functions - */ -static __inline void -amr_enqueue_bio(struct amr_softc *sc, struct bio *bio) -{ - - bioq_insert_tail(&sc->amr_bioq, bio); -} - -static __inline struct bio * -amr_dequeue_bio(struct amr_softc *sc) -{ - struct bio *bio; - - if ((bio = bioq_first(&sc->amr_bioq)) != NULL) - bioq_remove(&sc->amr_bioq, bio); - return(bio); -} - -static __inline void -amr_init_qhead(ac_qhead_t *head) -{ - - STAILQ_INIT(head); -} - -static __inline void -amr_enqueue_ready(struct amr_command *ac) -{ - - STAILQ_INSERT_TAIL(&ac->ac_sc->amr_ready, ac, ac_link); -} - -static __inline void -amr_requeue_ready(struct amr_command *ac) -{ - - STAILQ_INSERT_HEAD(&ac->ac_sc->amr_ready, ac, ac_link); -} - -static __inline struct amr_command * -amr_dequeue_ready(struct amr_softc *sc) -{ - struct amr_command *ac; - - if ((ac = STAILQ_FIRST(&sc->amr_ready)) != NULL) - STAILQ_REMOVE_HEAD(&sc->amr_ready, ac_link); - return(ac); -} - -static __inline void -amr_enqueue_completed(struct amr_command *ac, ac_qhead_t *head) -{ - - STAILQ_INSERT_TAIL(head, ac, ac_link); -} - -static __inline struct amr_command * -amr_dequeue_completed(struct amr_softc *sc, ac_qhead_t *head) -{ - struct amr_command *ac; - - if ((ac = STAILQ_FIRST(head)) != NULL) - STAILQ_REMOVE_HEAD(head, ac_link); - return(ac); -} - -static __inline void -amr_enqueue_free(struct amr_command *ac) -{ - - STAILQ_INSERT_HEAD(&ac->ac_sc->amr_freecmds, ac, ac_link); -} - -static __inline struct amr_command * -amr_dequeue_free(struct amr_softc *sc) -{ - struct amr_command *ac; - - if ((ac = STAILQ_FIRST(&sc->amr_freecmds)) != NULL) - STAILQ_REMOVE_HEAD(&sc->amr_freecmds, ac_link); - return(ac); -} diff --git a/sys/i386/conf/GENERIC b/sys/i386/conf/GENERIC --- a/sys/i386/conf/GENERIC +++ b/sys/i386/conf/GENERIC @@ -154,7 +154,6 @@ #device ctl # CAM Target Layer # RAID controllers interfaced to the SCSI subsystem -device amr # AMI MegaRAID device arcmsr # Areca SATA II RAID device ciss # Compaq Smart RAID 5* device ips # IBM (Adaptec) ServeRAID diff --git a/sys/modules/Makefile b/sys/modules/Makefile --- a/sys/modules/Makefile +++ b/sys/modules/Makefile @@ -38,7 +38,6 @@ ${_amdsbwd} \ ${_amdsmn} \ ${_amdtemp} \ - amr \ ${_aout} \ ${_arcmsr} \ ${_allwinner} \ diff --git a/sys/modules/amr/Makefile b/sys/modules/amr/Makefile deleted file mode 100644 --- a/sys/modules/amr/Makefile +++ /dev/null @@ -1,21 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/amr - -SUBDIR= amr_cam -.if ${MACHINE_CPUARCH} == "i386" || ${MACHINE_CPUARCH} == "amd64" -SUBDIR+= amr_linux -.endif - -KMOD= amr -SRCS= amr.c amr_pci.c amr_disk.c device_if.h bus_if.h pci_if.h - -# Enable a questionable optimisation for newer adapters -#CFLAGS+= -DAMR_QUARTZ_GOFASTER - -# Debugging -#CFLAGS+= -DAMR_DEBUG=3 - -EXPORT_SYMS= YES - -.include diff --git a/sys/modules/amr/amr_cam/Makefile b/sys/modules/amr/amr_cam/Makefile deleted file mode 100644 --- a/sys/modules/amr/amr_cam/Makefile +++ /dev/null @@ -1,9 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/amr - -KMOD= amr_cam -SRCS= amr_cam.c device_if.h bus_if.h -SRCS+= opt_cam.h opt_scsi.h - -.include diff --git a/sys/modules/amr/amr_linux/Makefile b/sys/modules/amr/amr_linux/Makefile deleted file mode 100644 --- a/sys/modules/amr/amr_linux/Makefile +++ /dev/null @@ -1,8 +0,0 @@ -# $FreeBSD$ - -.PATH: ${SRCTOP}/sys/dev/amr - -KMOD= amr_linux -SRCS= amr_linux.c device_if.h bus_if.h - -.include diff --git a/tools/kerneldoc/subsys/Doxyfile-dev_amr b/tools/kerneldoc/subsys/Doxyfile-dev_amr deleted file mode 100644 --- a/tools/kerneldoc/subsys/Doxyfile-dev_amr +++ /dev/null @@ -1,21 +0,0 @@ -# Doxyfile 1.5.2 - -# $FreeBSD$ - -#--------------------------------------------------------------------------- -# Project related configuration options -#--------------------------------------------------------------------------- -PROJECT_NAME = "FreeBSD kernel AMR device code" -OUTPUT_DIRECTORY = $(DOXYGEN_DEST_PATH)/dev_amr/ -EXTRACT_ALL = YES # for undocumented src, no warnings enabled -#--------------------------------------------------------------------------- -# configuration options related to the input files -#--------------------------------------------------------------------------- -INPUT = $(DOXYGEN_SRC_PATH)/dev/amr/ \ - $(NOTREVIEWED) - -GENERATE_TAGFILE = dev_amr/dev_amr.tag - -@INCLUDE_PATH = $(DOXYGEN_INCLUDE_PATH) -@INCLUDE = common-Doxyfile -